forked from openlp/openlp
Fix code so values saved
This commit is contained in:
commit
9648e0c81b
@ -384,6 +384,7 @@ def create_separated_list(stringlist):
|
||||
|
||||
|
||||
from eventreceiver import Receiver
|
||||
from filedialog import FileDialog
|
||||
from listwidgetwithdnd import ListWidgetWithDnD
|
||||
from formattingtags import FormattingTags
|
||||
from spelltextedit import SpellTextEdit
|
||||
|
63
openlp/core/lib/filedialog.py
Normal file
63
openlp/core/lib/filedialog.py
Normal file
@ -0,0 +1,63 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2013 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# 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, Martin Zibricky #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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 #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
Provide a work around for a bug in QFileDialog
|
||||
<https://bugs.launchpad.net/openlp/+bug/1209515>
|
||||
"""
|
||||
import os
|
||||
import urllib
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib.ui import UiStrings
|
||||
|
||||
class FileDialog(QtGui.QFileDialog):
|
||||
"""
|
||||
Subclass QFileDialog to work round a bug
|
||||
"""
|
||||
@staticmethod
|
||||
def getOpenFileNames(parent, title, path, filters):
|
||||
"""
|
||||
Reimplement getOpenFileNames to fix the way it returns some file
|
||||
names that url encoded when selecting multiple files/
|
||||
"""
|
||||
files = QtGui.QFileDialog.getOpenFileNames(parent, title, path, filters)
|
||||
file_list = QtCore.QStringList()
|
||||
for file in files:
|
||||
file = unicode(file)
|
||||
if not os.path.exists(file):
|
||||
file = urllib.unquote(file)
|
||||
if not os.path.exists(file):
|
||||
QtGui.QMessageBox.information(parent,
|
||||
UiStrings().FileNotFound,
|
||||
UiStrings().FileNotFoundMessage % file)
|
||||
continue
|
||||
file_list.append(QtCore.QString(file))
|
||||
return file_list
|
@ -35,7 +35,7 @@ import re
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import SettingsManager, OpenLPToolbar, ServiceItem, \
|
||||
from openlp.core.lib import FileDialog, SettingsManager, OpenLPToolbar, ServiceItem, \
|
||||
StringContent, build_icon, translate, Receiver, ListWidgetWithDnD
|
||||
from openlp.core.lib.searchedit import SearchEdit
|
||||
from openlp.core.lib.ui import UiStrings, create_widget_action, \
|
||||
@ -337,7 +337,7 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
"""
|
||||
Add a file to the list widget to make it available for showing
|
||||
"""
|
||||
files = QtGui.QFileDialog.getOpenFileNames(
|
||||
files = FileDialog.getOpenFileNames(
|
||||
self, self.onNewPrompt,
|
||||
SettingsManager.get_last_dir(self.settingsSection),
|
||||
self.onNewFileMasks)
|
||||
|
@ -77,6 +77,10 @@ class UiStrings(object):
|
||||
self.Error = translate('OpenLP.Ui', 'Error')
|
||||
self.Export = translate('OpenLP.Ui', 'Export')
|
||||
self.File = translate('OpenLP.Ui', 'File')
|
||||
self.FileNotFound = unicode(translate('OpenLP.Ui',
|
||||
'File Not Found'))
|
||||
self.FileNotFoundMessage = unicode(translate('OpenLP.Ui',
|
||||
'File %s not found.\nPlease try selecting it individually.'))
|
||||
self.FontSizePtUnit = translate('OpenLP.Ui', 'pt',
|
||||
'Abbreviated font pointsize unit')
|
||||
self.Help = translate('OpenLP.Ui', 'Help')
|
||||
|
@ -26,7 +26,9 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The First Time Wizard
|
||||
"""
|
||||
import io
|
||||
import logging
|
||||
import os
|
||||
@ -48,6 +50,7 @@ from firsttimewizard import Ui_FirstTimeWizard, FirstTimePage
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ThemeScreenshotThread(QtCore.QThread):
|
||||
"""
|
||||
This thread downloads the theme screenshots.
|
||||
@ -56,6 +59,9 @@ class ThemeScreenshotThread(QtCore.QThread):
|
||||
QtCore.QThread.__init__(self, parent)
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
Run the thread.
|
||||
"""
|
||||
themes = self.parent().config.get(u'themes', u'files')
|
||||
themes = themes.split(u',')
|
||||
themes_dir = self.parent().config.get(u'themes', u'directory')
|
||||
@ -180,15 +186,28 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
Determine the next page in the Wizard to go to.
|
||||
"""
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
# If we are currently on the plugins page
|
||||
if self.currentId() == FirstTimePage.Plugins:
|
||||
# But we don't have Internet access
|
||||
if not self.webAccess:
|
||||
return FirstTimePage.NoInternet
|
||||
else:
|
||||
# The songs plugin is enabled
|
||||
elif self.songsCheckBox.isChecked():
|
||||
return FirstTimePage.Songs
|
||||
# The Bibles plugin is enabled
|
||||
elif self.bibleCheckBox.isChecked():
|
||||
return FirstTimePage.Bibles
|
||||
else:
|
||||
return FirstTimePage.Themes
|
||||
elif self.currentId() == FirstTimePage.Progress:
|
||||
return -1
|
||||
elif self.currentId() == FirstTimePage.NoInternet:
|
||||
return FirstTimePage.Progress
|
||||
elif self.currentId() == FirstTimePage.Songs:
|
||||
if self.bibleCheckBox.isChecked():
|
||||
return FirstTimePage.Bibles
|
||||
else:
|
||||
return FirstTimePage.Themes
|
||||
elif self.currentId() == FirstTimePage.Themes:
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
@ -395,7 +414,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
self.max_progress += size
|
||||
if self.max_progress:
|
||||
# Add on 2 for plugins status setting plus a "finished" point.
|
||||
self.max_progress = self.max_progress + 2
|
||||
self.max_progress += 2
|
||||
self.progressBar.setValue(0)
|
||||
self.progressBar.setMinimum(0)
|
||||
self.progressBar.setMaximum(self.max_progress)
|
||||
|
@ -34,7 +34,11 @@ import sys
|
||||
from openlp.core.lib import translate
|
||||
from openlp.core.lib.ui import add_welcome_page
|
||||
|
||||
|
||||
class FirstTimePage(object):
|
||||
"""
|
||||
An enumeration object to make it easy for a developer to determine which page is which by index
|
||||
"""
|
||||
Welcome = 0
|
||||
Plugins = 1
|
||||
NoInternet = 2
|
||||
|
@ -109,6 +109,7 @@ class FormattingTagForm(QtGui.QDialog, Ui_FormattingTagDialog):
|
||||
has been changed.
|
||||
"""
|
||||
self.savePushButton.setEnabled(True)
|
||||
self.savePushButton.setDefault(True)
|
||||
|
||||
def onNewClicked(self):
|
||||
"""
|
||||
|
@ -89,7 +89,8 @@ VIDEO_EXT = [
|
||||
u'*.xa',
|
||||
u'*.iso',
|
||||
u'*.vob',
|
||||
u'*.webm'
|
||||
u'*.webm',
|
||||
u'*.divx'
|
||||
]
|
||||
|
||||
|
||||
|
@ -229,32 +229,32 @@ FLASH_HTML = u"""
|
||||
"""
|
||||
|
||||
VIDEO_EXT = [
|
||||
u'*.3gp'
|
||||
, u'*.3gpp'
|
||||
, u'*.3g2'
|
||||
, u'*.3gpp2'
|
||||
, u'*.aac'
|
||||
, u'*.flv'
|
||||
, u'*.f4a'
|
||||
, u'*.f4b'
|
||||
, u'*.f4p'
|
||||
, u'*.f4v'
|
||||
, u'*.mov'
|
||||
, u'*.m4a'
|
||||
, u'*.m4b'
|
||||
, u'*.m4p'
|
||||
, u'*.m4v'
|
||||
, u'*.mkv'
|
||||
, u'*.mp4'
|
||||
, u'*.ogv'
|
||||
, u'*.webm'
|
||||
, u'*.mpg', u'*.wmv', u'*.mpeg', u'*.avi'
|
||||
, u'*.swf'
|
||||
u'*.3gp',
|
||||
u'*.3gpp',
|
||||
u'*.3g2',
|
||||
u'*.3gpp2',
|
||||
u'*.aac',
|
||||
u'*.flv',
|
||||
u'*.f4a',
|
||||
u'*.f4b',
|
||||
u'*.f4p',
|
||||
u'*.f4v',
|
||||
u'*.mov',
|
||||
u'*.m4a',
|
||||
u'*.m4b',
|
||||
u'*.m4p',
|
||||
u'*.m4v',
|
||||
u'*.mkv',
|
||||
u'*.mp4',
|
||||
u'*.ogv',
|
||||
u'*.webm',
|
||||
u'*.mpg', u'*.wmv', u'*.mpeg', u'*.avi',
|
||||
u'*.swf'
|
||||
]
|
||||
|
||||
AUDIO_EXT = [
|
||||
u'*.mp3'
|
||||
, u'*.ogg'
|
||||
u'*.mp3',
|
||||
u'*.ogg'
|
||||
]
|
||||
|
||||
|
||||
|
@ -78,6 +78,8 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
||||
QtCore.SIGNAL(u'clicked()'), self.onGradientEndButtonClicked)
|
||||
QtCore.QObject.connect(self.imageBrowseButton,
|
||||
QtCore.SIGNAL(u'clicked()'), self.onImageBrowseButtonClicked)
|
||||
QtCore.QObject.connect(self.imageFileEdit,
|
||||
QtCore.SIGNAL(u'editingFinished()'), self.onImageFileEditEditingFinished)
|
||||
QtCore.QObject.connect(self.mainColorButton,
|
||||
QtCore.SIGNAL(u'clicked()'), self.onMainColorButtonClicked)
|
||||
QtCore.QObject.connect(self.outlineColorButton,
|
||||
@ -233,7 +235,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
||||
background_image = BackgroundType.to_string(BackgroundType.Image)
|
||||
if self.page(self.currentId()) == self.backgroundPage and \
|
||||
self.theme.background_type == background_image and \
|
||||
is_not_image_file(self.imageFileEdit.text()):
|
||||
is_not_image_file(self.theme.background_filename):
|
||||
QtGui.QMessageBox.critical(self,
|
||||
translate('OpenLP.ThemeWizard', 'Background Image Empty'),
|
||||
translate('OpenLP.ThemeWizard', 'You have not selected a '
|
||||
@ -545,6 +547,12 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
||||
self.theme.background_filename = unicode(filename)
|
||||
self.setBackgroundPageValues()
|
||||
|
||||
def onImageFileEditEditingFinished(self):
|
||||
"""
|
||||
Background image path edited
|
||||
"""
|
||||
self.theme.background_filename = unicode(self.imageFileEdit.text())
|
||||
|
||||
def onMainColorButtonClicked(self):
|
||||
self.theme.font_main_color = \
|
||||
self._colorButton(self.theme.font_main_color)
|
||||
|
@ -36,7 +36,7 @@ import re
|
||||
from xml.etree.ElementTree import ElementTree, XML
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import OpenLPToolbar, get_text_file_string, build_icon, \
|
||||
from openlp.core.lib import FileDialog, OpenLPToolbar, get_text_file_string, build_icon, \
|
||||
Receiver, SettingsManager, translate, check_item_selected, \
|
||||
check_directory_exists, create_thumb, validate_thumb, ImageSource
|
||||
from openlp.core.lib.theme import ThemeXML, BackgroundType, VerticalType, \
|
||||
@ -420,7 +420,7 @@ class ThemeManager(QtGui.QWidget):
|
||||
attempting to extract OpenLP themes from those files. This process
|
||||
will load both OpenLP version 1 and version 2 themes.
|
||||
"""
|
||||
files = QtGui.QFileDialog.getOpenFileNames(self,
|
||||
files = FileDialog.getOpenFileNames(self,
|
||||
translate('OpenLP.ThemeManager', 'Select Theme Import File'),
|
||||
SettingsManager.get_last_dir(self.settingsSection),
|
||||
unicode(translate('OpenLP.ThemeManager',
|
||||
|
@ -371,15 +371,14 @@ def is_not_image_file(file_name):
|
||||
``file_name``
|
||||
File name to be checked.
|
||||
"""
|
||||
if file_name.isEmpty():
|
||||
return True
|
||||
else:
|
||||
formats = [unicode(fmt).lower()
|
||||
for fmt in QtGui.QImageReader.supportedImageFormats()]
|
||||
file_part, file_extension = os.path.splitext(unicode(file_name))
|
||||
if file_extension[1:].lower() in formats and os.path.exists(file_name):
|
||||
return False
|
||||
if not file_name:
|
||||
return True
|
||||
formats = [unicode(fmt).lower()
|
||||
for fmt in QtGui.QImageReader.supportedImageFormats()]
|
||||
file_part, file_extension = os.path.splitext(unicode(file_name))
|
||||
if file_extension[1:].lower() in formats and os.path.exists(file_name):
|
||||
return False
|
||||
return True
|
||||
|
||||
def join_url(base, *args):
|
||||
"""
|
||||
|
@ -862,6 +862,26 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
||||
return book[0]
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def get_language_by_id(language_id):
|
||||
"""
|
||||
Return a dict containing the language id, name and code by id.
|
||||
|
||||
``id``
|
||||
The id of the language in the database.
|
||||
"""
|
||||
log.debug(u'BiblesResourcesDB.get_language_by_id(%d)', language_id)
|
||||
language = BiblesResourcesDB.run_sql(u'SELECT id, name, code FROM '
|
||||
u'language WHERE id = ?', (language_id,))
|
||||
if language:
|
||||
return {
|
||||
u'id': language[0][0],
|
||||
u'name': unicode(language[0][1]),
|
||||
u'code': unicode(language[0][2])
|
||||
}
|
||||
else:
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def get_language(name):
|
||||
"""
|
||||
|
@ -245,6 +245,8 @@ class BGExtract(object):
|
||||
return None
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
div = soup.find('div', 'result-text-style-normal')
|
||||
if not div:
|
||||
return None
|
||||
self._clean_soup(div)
|
||||
span_list = div.findAll('span', 'text')
|
||||
log.debug('Span list: %s', span_list)
|
||||
@ -375,6 +377,7 @@ class BSExtract(object):
|
||||
content = content.findAll(u'li')
|
||||
return [
|
||||
book.contents[0].contents[0] for book in content
|
||||
if len(book.contents[0].contents)
|
||||
]
|
||||
|
||||
|
||||
|
@ -34,7 +34,7 @@ import codecs
|
||||
import re
|
||||
|
||||
from openlp.core.lib import Receiver, translate
|
||||
from openlp.core.utils import AppLocation
|
||||
from openlp.core.utils import AppLocation, LanguageManager
|
||||
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -148,10 +148,22 @@ class OSISBible(BibleDB):
|
||||
self.filename)
|
||||
return False
|
||||
book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
|
||||
if not db_book or db_book.name != book_details[u'name']:
|
||||
log.debug(u'New book: "%s"' % book_details[u'name'])
|
||||
bible_language = BiblesResourcesDB.get_language_by_id(language_id)
|
||||
if bible_language is not None:
|
||||
# The language of this bible was found, so we can
|
||||
# translate the name of this book
|
||||
custom_translator = LanguageManager.get_translator(
|
||||
bible_language['code'])[0]
|
||||
book_name_localized = unicode(custom_translator.translate(
|
||||
'BiblesPlugin', book_details[u'name']))
|
||||
else:
|
||||
# The language of this bible was not found, so we just
|
||||
# use the English name for this book
|
||||
book_name_localized = book_details[u'name']
|
||||
if not db_book or db_book.name != book_name_localized:
|
||||
log.debug(u'New book: "%s"' % book_name_localized)
|
||||
db_book = self.create_book(
|
||||
book_details[u'name'],
|
||||
book_name_localized,
|
||||
book_ref_id,
|
||||
book_details[u'testament_id'])
|
||||
if last_chapter == 0:
|
||||
@ -162,7 +174,7 @@ class OSISBible(BibleDB):
|
||||
self.wizard.incrementProgressBar(unicode(translate(
|
||||
'BiblesPlugin.OsisImport', 'Importing %s %s...',
|
||||
'Importing <book name> <chapter>...')) %
|
||||
(book_details[u'name'], chapter))
|
||||
(book_name_localized, chapter))
|
||||
last_chapter = chapter
|
||||
# All of this rigmarol below is because the mod2osis
|
||||
# tool from the Sword library embeds XML in the OSIS
|
||||
|
@ -44,6 +44,7 @@ import time
|
||||
if os.name == u'nt':
|
||||
from win32com.client import Dispatch
|
||||
import pywintypes
|
||||
|
||||
# Declare an empty exception to match the exception imported from UNO
|
||||
class ErrorCodeIOException(Exception):
|
||||
pass
|
||||
@ -63,6 +64,7 @@ from presentationcontroller import PresentationController, PresentationDocument
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ImpressController(PresentationController):
|
||||
"""
|
||||
Class to control interactions with Impress presentations.
|
||||
@ -79,7 +81,7 @@ class ImpressController(PresentationController):
|
||||
PresentationController.__init__(self, plugin, u'Impress',
|
||||
ImpressDocument)
|
||||
self.supports = [u'odp']
|
||||
self.alsosupports = [u'ppt', u'pps', u'pptx', u'ppsx']
|
||||
self.alsosupports = [u'ppt', u'pps', u'pptx', u'ppsx', u'pptm']
|
||||
self.process = None
|
||||
self.desktop = None
|
||||
self.manager = None
|
||||
|
@ -45,6 +45,7 @@ log = logging.getLogger(__name__)
|
||||
|
||||
ERROR = QtGui.QImage(u':/general/general_delete.png')
|
||||
|
||||
|
||||
class PresentationMediaItem(MediaManagerItem):
|
||||
"""
|
||||
This is the Presentation media manager item for Presentation Items.
|
||||
@ -88,10 +89,10 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
if self.controllers[controller].enabled():
|
||||
types = self.controllers[controller].supports + \
|
||||
self.controllers[controller].alsosupports
|
||||
for type in types:
|
||||
if fileType.find(type) == -1:
|
||||
fileType += u'*.%s ' % type
|
||||
self.plugin.serviceManager.supportedSuffixes(type)
|
||||
for type_ in types:
|
||||
if fileType.find(type_) == -1:
|
||||
fileType += u'*.%s ' % type_
|
||||
self.plugin.serviceManager.supportedSuffixes(type_)
|
||||
self.onNewFileMasks = unicode(translate('PresentationPlugin.MediaItem',
|
||||
'Presentations (%s)')) % fileType
|
||||
|
||||
|
@ -43,6 +43,7 @@ log = logging.getLogger(__name__)
|
||||
# PPT API documentation:
|
||||
# http://msdn.microsoft.com/en-us/library/aa269321(office.10).aspx
|
||||
|
||||
|
||||
class PowerpointController(PresentationController):
|
||||
"""
|
||||
Class to control interactions with PowerPoint Presentations
|
||||
@ -58,7 +59,7 @@ class PowerpointController(PresentationController):
|
||||
log.debug(u'Initialising')
|
||||
PresentationController.__init__(self, plugin, u'Powerpoint',
|
||||
PowerpointDocument)
|
||||
self.supports = [u'ppt', u'pps', u'pptx', u'ppsx']
|
||||
self.supports = [u'ppt', u'pps', u'pptx', u'ppsx', u'pptm']
|
||||
self.process = None
|
||||
|
||||
def check_available(self):
|
||||
|
@ -38,6 +38,7 @@ from presentationcontroller import PresentationController, PresentationDocument
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PptviewController(PresentationController):
|
||||
"""
|
||||
Class to control interactions with PowerPOint Viewer Presentations
|
||||
@ -54,7 +55,7 @@ class PptviewController(PresentationController):
|
||||
self.process = None
|
||||
PresentationController.__init__(self, plugin, u'Powerpoint Viewer',
|
||||
PptviewDocument)
|
||||
self.supports = [u'ppt', u'pps', u'pptx', u'ppsx']
|
||||
self.supports = [u'ppt', u'pps', u'pptx', u'ppsx', u'pptm']
|
||||
|
||||
def check_available(self):
|
||||
"""
|
||||
|
@ -34,7 +34,7 @@ import shutil
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import PluginStatus, Receiver, MediaType, translate, \
|
||||
from openlp.core.lib import FileDialog, PluginStatus, Receiver, MediaType, translate, \
|
||||
create_separated_list, check_directory_exists
|
||||
from openlp.core.lib.ui import UiStrings, set_case_insensitive_completer, \
|
||||
critical_error_message_box, find_and_set_in_combo_box
|
||||
@ -47,6 +47,7 @@ from editsongdialog import Ui_EditSongDialog
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
"""
|
||||
Class to manage the editing of a song
|
||||
@ -229,6 +230,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
self.loadTopics()
|
||||
self.loadBooks()
|
||||
self.loadMediaFiles()
|
||||
self.themeComboBox.setEditText(u'')
|
||||
self.themeComboBox.setCurrentIndex(0)
|
||||
# it's a new song to preview is not possible
|
||||
self.previewButton.setVisible(False)
|
||||
@ -261,6 +263,9 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
if self.song.theme_name:
|
||||
find_and_set_in_combo_box(
|
||||
self.themeComboBox, unicode(self.song.theme_name))
|
||||
else:
|
||||
self.themeComboBox.setEditText(u'')
|
||||
self.themeComboBox.setCurrentIndex(0)
|
||||
self.copyrightEdit.setText(
|
||||
self.song.copyright if self.song.copyright else u'')
|
||||
self.commentsEdit.setPlainText(
|
||||
@ -757,7 +762,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
Loads file(s) from the filesystem.
|
||||
"""
|
||||
filters = u'%s (*)' % UiStrings().AllFiles
|
||||
filenames = QtGui.QFileDialog.getOpenFileNames(self,
|
||||
filenames = FileDialog.getOpenFileNames(self,
|
||||
translate('SongsPlugin.EditSongForm', 'Open File(s)'),
|
||||
QtCore.QString(), filters)
|
||||
for filename in filenames:
|
||||
|
@ -35,7 +35,7 @@ import os
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Receiver, SettingsManager, translate
|
||||
from openlp.core.lib import FileDialog, Receiver, SettingsManager, translate
|
||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
||||
from openlp.core.lib.settings import Settings
|
||||
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
|
||||
@ -281,7 +281,7 @@ class SongImportForm(OpenLPWizard):
|
||||
if filters:
|
||||
filters += u';;'
|
||||
filters += u'%s (*)' % UiStrings().AllFiles
|
||||
filenames = QtGui.QFileDialog.getOpenFileNames(self, title,
|
||||
filenames = FileDialog.getOpenFileNames(self, title,
|
||||
SettingsManager.get_last_dir(self.plugin.settingsSection, 1),
|
||||
filters)
|
||||
if filenames:
|
||||
|
@ -96,6 +96,7 @@ import os
|
||||
|
||||
from lxml import etree, objectify
|
||||
|
||||
from openlp.core.lib import translate
|
||||
from openlp.core.ui.wizard import WizardStrings
|
||||
from openlp.plugins.songs.lib import clean_song, VerseType
|
||||
from openlp.plugins.songs.lib.songimport import SongImport
|
||||
@ -115,7 +116,7 @@ class FoilPresenterImport(SongImport):
|
||||
"""
|
||||
log.debug(u'initialise FoilPresenterImport')
|
||||
SongImport.__init__(self, manager, **kwargs)
|
||||
self.FoilPresenter = FoilPresenter(self.manager)
|
||||
self.FoilPresenter = FoilPresenter(self.manager, self)
|
||||
|
||||
def doImport(self):
|
||||
"""
|
||||
@ -202,8 +203,9 @@ class FoilPresenter(object):
|
||||
<copyright> tag.
|
||||
|
||||
"""
|
||||
def __init__(self, manager):
|
||||
def __init__(self, manager, importer):
|
||||
self.manager = manager
|
||||
self.importer = importer
|
||||
|
||||
def xml_to_song(self, xml):
|
||||
"""
|
||||
@ -222,6 +224,7 @@ class FoilPresenter(object):
|
||||
song.search_lyrics = u''
|
||||
song.verse_order = u''
|
||||
song.search_title = u''
|
||||
self.save_song = True
|
||||
# Because "text" seems to be an reserverd word, we have to recompile it.
|
||||
xml = re.compile(u'<text>').sub(u'<text_>', xml)
|
||||
xml = re.compile(u'</text>').sub(u'</text_>', xml)
|
||||
@ -236,8 +239,9 @@ class FoilPresenter(object):
|
||||
self._process_authors(foilpresenterfolie, song)
|
||||
self._process_songbooks(foilpresenterfolie, song)
|
||||
self._process_topics(foilpresenterfolie, song)
|
||||
clean_song(self.manager, song)
|
||||
self.manager.save_object(song)
|
||||
if self.save_song:
|
||||
clean_song(self.manager, song)
|
||||
self.manager.save_object(song)
|
||||
|
||||
def _child(self, element):
|
||||
"""
|
||||
@ -424,6 +428,12 @@ class FoilPresenter(object):
|
||||
VerseType.Tags[VerseType.Intro]: 1,
|
||||
VerseType.Tags[VerseType.PreChorus]: 1
|
||||
}
|
||||
if not hasattr(foilpresenterfolie.strophen, u'strophe'):
|
||||
self.importer.logError(self._child(foilpresenterfolie.titel),
|
||||
unicode(translate('SongsPlugin.FoilPresenterSongImport',
|
||||
'Invalid Foilpresenter song file. No verses found.')))
|
||||
self.save_song = False
|
||||
return
|
||||
for strophe in foilpresenterfolie.strophen.strophe:
|
||||
text = self._child(strophe.text_) if hasattr(strophe, u'text_') \
|
||||
else u''
|
||||
|
@ -49,6 +49,9 @@ class OpenSongImport(SongImport):
|
||||
the OpenSong web site. However, it doesn't describe the <lyrics> section,
|
||||
so here's an attempt:
|
||||
|
||||
If the first charachter of a line is a space, then the rest of that line
|
||||
is lyrics. If it is not a space the following applies.
|
||||
|
||||
Verses can be expressed in one of 2 ways, either in complete verses, or by
|
||||
line grouping, i.e. grouping all line 1's of a verse together, all line 2's
|
||||
of a verse together, and so on.
|
||||
@ -171,13 +174,11 @@ class OpenSongImport(SongImport):
|
||||
else:
|
||||
lyrics = u''
|
||||
for this_line in lyrics.split(u'\n'):
|
||||
# remove comments
|
||||
semicolon = this_line.find(u';')
|
||||
if semicolon >= 0:
|
||||
this_line = this_line[:semicolon]
|
||||
this_line = this_line.strip()
|
||||
if not this_line:
|
||||
continue
|
||||
# skip this line if it is a comment
|
||||
if this_line.startswith(u';'):
|
||||
continue
|
||||
# skip guitar chords and page and column breaks
|
||||
if this_line.startswith(u'.') or this_line.startswith(u'---') \
|
||||
or this_line.startswith(u'-!!'):
|
||||
@ -212,7 +213,6 @@ class OpenSongImport(SongImport):
|
||||
if this_line[0].isdigit():
|
||||
verse_num = this_line[0]
|
||||
this_line = this_line[1:].strip()
|
||||
our_verse_order.append([verse_tag, verse_num, inst])
|
||||
verses.setdefault(verse_tag, {})
|
||||
verses[verse_tag].setdefault(verse_num, {})
|
||||
if inst not in verses[verse_tag][verse_num]:
|
||||
@ -222,6 +222,7 @@ class OpenSongImport(SongImport):
|
||||
this_line = self.tidyText(this_line)
|
||||
this_line = this_line.replace(u'_', u'')
|
||||
this_line = this_line.replace(u'|', u'\n')
|
||||
this_line = this_line.strip()
|
||||
verses[verse_tag][verse_num][inst].append(this_line)
|
||||
# done parsing
|
||||
# add verses in original order
|
||||
|
@ -30,13 +30,14 @@
|
||||
The :mod:`songshowplusimport` module provides the functionality for importing
|
||||
SongShow Plus songs into the OpenLP database.
|
||||
"""
|
||||
import chardet
|
||||
import os
|
||||
import logging
|
||||
import re
|
||||
import struct
|
||||
|
||||
from openlp.core.ui.wizard import WizardStrings
|
||||
from openlp.plugins.songs.lib import VerseType
|
||||
from openlp.plugins.songs.lib import VerseType, retrieve_windows_encoding
|
||||
from openlp.plugins.songs.lib.songimport import SongImport
|
||||
|
||||
TITLE = 1
|
||||
@ -142,44 +143,44 @@ class SongShowPlusImport(SongImport):
|
||||
log.debug(length_descriptor_size)
|
||||
data = song_data.read(length_descriptor)
|
||||
if block_key == TITLE:
|
||||
self.title = unicode(data, u'cp1252')
|
||||
self.title = self.decode(data)
|
||||
elif block_key == AUTHOR:
|
||||
authors = data.split(" / ")
|
||||
for author in authors:
|
||||
if author.find(",") !=-1:
|
||||
authorParts = author.split(", ")
|
||||
author = authorParts[1] + " " + authorParts[0]
|
||||
self.parseAuthor(unicode(author, u'cp1252'))
|
||||
self.parseAuthor(self.decode(author))
|
||||
elif block_key == COPYRIGHT:
|
||||
self.addCopyright(unicode(data, u'cp1252'))
|
||||
self.addCopyright(self.decode(data))
|
||||
elif block_key == CCLI_NO:
|
||||
self.ccliNumber = int(data)
|
||||
elif block_key == VERSE:
|
||||
self.addVerse(unicode(data, u'cp1252'),
|
||||
self.addVerse(self.decode(data),
|
||||
"%s%s" % (VerseType.Tags[VerseType.Verse], verse_no))
|
||||
elif block_key == CHORUS:
|
||||
self.addVerse(unicode(data, u'cp1252'),
|
||||
self.addVerse(self.decode(data),
|
||||
"%s%s" % (VerseType.Tags[VerseType.Chorus], verse_no))
|
||||
elif block_key == BRIDGE:
|
||||
self.addVerse(unicode(data, u'cp1252'),
|
||||
self.addVerse(self.decode(data),
|
||||
"%s%s" % (VerseType.Tags[VerseType.Bridge], verse_no))
|
||||
elif block_key == TOPIC:
|
||||
self.topics.append(unicode(data, u'cp1252'))
|
||||
self.topics.append(self.decode(data))
|
||||
elif block_key == COMMENTS:
|
||||
self.comments = unicode(data, u'cp1252')
|
||||
self.comments = self.decode(data)
|
||||
elif block_key == VERSE_ORDER:
|
||||
verse_tag = self.toOpenLPVerseTag(data, True)
|
||||
if verse_tag:
|
||||
if not isinstance(verse_tag, unicode):
|
||||
verse_tag = unicode(verse_tag, u'cp1252')
|
||||
verse_tag = self.decode(verse_tag)
|
||||
self.sspVerseOrderList.append(verse_tag)
|
||||
elif block_key == SONG_BOOK:
|
||||
self.songBookName = unicode(data, u'cp1252')
|
||||
self.songBookName = self.decode(data)
|
||||
elif block_key == SONG_NUMBER:
|
||||
self.songNumber = ord(data)
|
||||
elif block_key == CUSTOM_VERSE:
|
||||
verse_tag = self.toOpenLPVerseTag(verse_name)
|
||||
self.addVerse(unicode(data, u'cp1252'), verse_tag)
|
||||
self.addVerse(self.decode(data), verse_tag)
|
||||
else:
|
||||
log.debug("Unrecognised blockKey: %s, data: %s"
|
||||
% (block_key, data))
|
||||
@ -221,3 +222,9 @@ class SongShowPlusImport(SongImport):
|
||||
verse_tag = VerseType.Tags[VerseType.Other]
|
||||
verse_number = self.otherList[verse_name]
|
||||
return verse_tag + verse_number
|
||||
|
||||
def decode(self, data):
|
||||
try:
|
||||
return unicode(data, chardet.detect(data)['encoding'])
|
||||
except:
|
||||
return unicode(data, retrieve_windows_encoding())
|
||||
|
@ -68,7 +68,7 @@ class SundayPlusImport(SongImport):
|
||||
for filename in self.importSource:
|
||||
if self.stopImportFlag:
|
||||
return
|
||||
song_file = open(filename)
|
||||
song_file = open(filename, 'rb')
|
||||
self.doImportFile(song_file)
|
||||
song_file.close()
|
||||
|
||||
@ -96,7 +96,7 @@ class SundayPlusImport(SongImport):
|
||||
# Now we are looking for the name.
|
||||
if data[i:i + 1] == '#':
|
||||
name_end = data.find(':', i + 1)
|
||||
name = data[i + 1:name_end]
|
||||
name = data[i + 1:name_end].upper()
|
||||
i = name_end + 1
|
||||
while data[i:i + 1] == ' ':
|
||||
i += 1
|
||||
@ -122,13 +122,13 @@ class SundayPlusImport(SongImport):
|
||||
value = data[i:end]
|
||||
# If we are in the main group.
|
||||
if cell == False:
|
||||
if name == 'title':
|
||||
if name == 'TITLE':
|
||||
self.title = self.decode(self.unescape(value))
|
||||
elif name == 'Author':
|
||||
elif name == 'AUTHOR':
|
||||
author = self.decode(self.unescape(value))
|
||||
if len(author):
|
||||
self.addAuthor(author)
|
||||
elif name == 'Copyright':
|
||||
elif name == 'COPYRIGHT':
|
||||
self.copyright = self.decode(self.unescape(value))
|
||||
elif name[0:4] == 'CELL':
|
||||
self.parse(value, cell = name[4:])
|
||||
@ -142,13 +142,13 @@ class SundayPlusImport(SongImport):
|
||||
if len(value) >= 2 and value[-1] in ['0', '1', '2',
|
||||
'3', '4', '5', '6', '7', '8', '9']:
|
||||
verse_type = "%s%s" % (verse_type, value[-1])
|
||||
elif name == 'Hotkey':
|
||||
elif name == 'HOTKEY':
|
||||
# Hotkey always appears after MARKER_NAME, so it
|
||||
# effectively overrides MARKER_NAME, if present.
|
||||
if len(value) and \
|
||||
value in HOTKEY_TO_VERSE_TYPE.keys():
|
||||
verse_type = HOTKEY_TO_VERSE_TYPE[value]
|
||||
if name == 'rtf':
|
||||
if name == 'RTF':
|
||||
value = self.unescape(value)
|
||||
result = strip_rtf(value, self.encoding)
|
||||
if result is None:
|
||||
|
@ -79,6 +79,33 @@ NAMESPACE = u'http://openlyrics.info/namespace/2009/song'
|
||||
NSMAP = '{' + NAMESPACE + '}' + '%s'
|
||||
|
||||
|
||||
def clean_xml_string(xml):
|
||||
"""
|
||||
Filter out invalid characters in xml
|
||||
Source <http://stackoverflow.com/questions/8733233/filtering-out-certain-bytes-in-python>
|
||||
|
||||
``xml``
|
||||
The actual text to be checked.
|
||||
|
||||
"""
|
||||
return ''.join(char for char in xml if valid_XML_char_ordinal(ord(char)))
|
||||
|
||||
|
||||
def valid_XML_char_ordinal(char):
|
||||
"""
|
||||
Undertake the filter test.
|
||||
|
||||
``char``
|
||||
The individual character to be checked.
|
||||
"""
|
||||
return (
|
||||
0x20 <= char <= 0xD7FF
|
||||
or char in (0x9, 0xA, 0xD)
|
||||
or 0xE000 <= char <= 0xFFFD
|
||||
or 0x10000 <= char <= 0x10FFFF
|
||||
)
|
||||
|
||||
|
||||
class SongXML(object):
|
||||
"""
|
||||
This class builds and parses the XML used to describe songs.
|
||||
@ -112,6 +139,7 @@ class SongXML(object):
|
||||
The verse's language code (ISO-639). This is not required, but
|
||||
should be added if available.
|
||||
"""
|
||||
content = clean_xml_string(content)
|
||||
verse = etree.Element(u'verse', type=unicode(type),
|
||||
label=unicode(number))
|
||||
if lang:
|
||||
|
Loading…
Reference in New Issue
Block a user