forked from openlp/openlp
trunk
This commit is contained in:
commit
4bacaab205
@ -36,10 +36,9 @@ if __name__ == '__main__':
|
||||
"""
|
||||
Instantiate and run the application.
|
||||
"""
|
||||
# Mac OS X passes arguments like '-psn_XXXX' to gui application.
|
||||
# This argument is process serial number. However, this causes
|
||||
# conflict with other OpenLP arguments. Since we do not use this
|
||||
# argument we can delete it to avoid any potential conflicts.
|
||||
# Mac OS X passes arguments like '-psn_XXXX' to the application. This argument is actually a process serial number.
|
||||
# However, this causes a conflict with other OpenLP arguments. Since we do not use this argument we can delete it
|
||||
# to avoid any potential conflicts.
|
||||
if sys.platform.startswith('darwin'):
|
||||
sys.argv = [x for x in sys.argv if not x.startswith('-psn')]
|
||||
main()
|
||||
|
@ -59,7 +59,7 @@ __all__ = ['OpenLP', 'main']
|
||||
|
||||
log = logging.getLogger()
|
||||
|
||||
NT_REPAIR_STYLESHEET = """
|
||||
WIN_REPAIR_STYLESHEET = """
|
||||
QMainWindow::separator
|
||||
{
|
||||
border: none;
|
||||
@ -127,7 +127,7 @@ class OpenLP(OpenLPMixin, QtGui.QApplication):
|
||||
'QTableWidget, QListWidget, QTreeWidget {alternate-background-color: ' + base_color.name() + ';}\n'
|
||||
application_stylesheet += alternate_rows_repair_stylesheet
|
||||
if is_win():
|
||||
application_stylesheet += NT_REPAIR_STYLESHEET
|
||||
application_stylesheet += WIN_REPAIR_STYLESHEET
|
||||
if application_stylesheet:
|
||||
self.setStyleSheet(application_stylesheet)
|
||||
show_splash = Settings().value('core/show splash')
|
||||
|
@ -33,6 +33,7 @@ import logging
|
||||
import inspect
|
||||
|
||||
from openlp.core.common import trace_error_handler
|
||||
|
||||
DO_NOT_TRACE_EVENTS = ['timerEvent', 'paintEvent', 'drag_enter_event', 'drop_event', 'on_controller_size_changed',
|
||||
'preview_size_changed', 'resizeEvent']
|
||||
|
||||
@ -41,11 +42,8 @@ class OpenLPMixin(object):
|
||||
"""
|
||||
Base Calling object for OpenLP classes.
|
||||
"""
|
||||
def __init__(self, parent):
|
||||
try:
|
||||
super(OpenLPMixin, self).__init__(parent)
|
||||
except TypeError:
|
||||
super(OpenLPMixin, self).__init__()
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(OpenLPMixin, self).__init__(*args, **kwargs)
|
||||
self.logger = logging.getLogger("%s.%s" % (self.__module__, self.__class__.__name__))
|
||||
if self.logger.getEffectiveLevel() == logging.DEBUG:
|
||||
for name, m in inspect.getmembers(self, inspect.ismethod):
|
||||
|
@ -33,7 +33,7 @@ import logging
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.common import Registry, UiStrings, translate
|
||||
from openlp.core.common import Registry, UiStrings, translate, is_macosx
|
||||
from openlp.core.lib import build_icon
|
||||
from openlp.core.utils.actions import ActionList
|
||||
|
||||
@ -247,6 +247,8 @@ def create_action(parent, name, **kwargs):
|
||||
"""
|
||||
action = QtGui.QAction(parent)
|
||||
action.setObjectName(name)
|
||||
if is_macosx():
|
||||
action.setIconVisibleInMenu(False)
|
||||
if kwargs.get('text'):
|
||||
action.setText(kwargs.pop('text'))
|
||||
if kwargs.get('icon'):
|
||||
|
@ -387,17 +387,21 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard, RegistryProperties):
|
||||
self.progress_bar.setValue(self.progress_bar.maximum())
|
||||
if self.has_run_wizard:
|
||||
self.progress_label.setText(translate('OpenLP.FirstTimeWizard',
|
||||
'Download complete. Click the finish button to return to OpenLP.'))
|
||||
'Download complete. Click the %s button to return to OpenLP.') %
|
||||
self.buttonText(QtGui.QWizard.FinishButton))
|
||||
else:
|
||||
self.progress_label.setText(translate('OpenLP.FirstTimeWizard',
|
||||
'Download complete. Click the finish button to start OpenLP.'))
|
||||
'Download complete. Click the %s button to start OpenLP.') %
|
||||
self.buttonText(QtGui.QWizard.FinishButton))
|
||||
else:
|
||||
if self.has_run_wizard:
|
||||
self.progress_label.setText(translate('OpenLP.FirstTimeWizard',
|
||||
'Click the finish button to return to OpenLP.'))
|
||||
'Click the %s button to return to OpenLP.') %
|
||||
self.buttonText(QtGui.QWizard.FinishButton))
|
||||
else:
|
||||
self.progress_label.setText(translate('OpenLP.FirstTimeWizard',
|
||||
'Click the finish button to start OpenLP.'))
|
||||
'Click the %s button to start OpenLP.') %
|
||||
self.buttonText(QtGui.QWizard.FinishButton))
|
||||
self.finish_button.setVisible(True)
|
||||
self.finish_button.setEnabled(True)
|
||||
self.cancel_button.setVisible(False)
|
||||
|
@ -31,9 +31,7 @@ The UI widgets for the first time wizard.
|
||||
"""
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
import sys
|
||||
|
||||
from openlp.core.common import translate
|
||||
from openlp.core.common import translate, is_macosx
|
||||
from openlp.core.lib import build_icon
|
||||
from openlp.core.lib.ui import add_welcome_page
|
||||
|
||||
@ -64,9 +62,12 @@ class Ui_FirstTimeWizard(object):
|
||||
first_time_wizard.setWindowIcon(build_icon(u':/icon/openlp-logo.svg'))
|
||||
first_time_wizard.resize(550, 386)
|
||||
first_time_wizard.setModal(True)
|
||||
first_time_wizard.setWizardStyle(QtGui.QWizard.ModernStyle)
|
||||
first_time_wizard.setOptions(QtGui.QWizard.IndependentPages | QtGui.QWizard.NoBackButtonOnStartPage |
|
||||
QtGui.QWizard.NoBackButtonOnLastPage | QtGui.QWizard.HaveCustomButton1)
|
||||
if is_macosx():
|
||||
first_time_wizard.setPixmap(QtGui.QWizard.BackgroundPixmap,
|
||||
QtGui.QPixmap(':/wizards/openlp-osx-wizard.png'))
|
||||
first_time_wizard.resize(634, 386)
|
||||
self.finish_button = self.button(QtGui.QWizard.FinishButton)
|
||||
self.no_internet_finish_button = self.button(QtGui.QWizard.CustomButton1)
|
||||
self.cancel_button = self.button(QtGui.QWizard.CancelButton)
|
||||
@ -212,7 +213,8 @@ class Ui_FirstTimeWizard(object):
|
||||
translate('OpenLP.FirstTimeWizard', 'Welcome to the First Time Wizard'))
|
||||
self.information_label.setText(
|
||||
translate('OpenLP.FirstTimeWizard', 'This wizard will help you to configure OpenLP for initial use. '
|
||||
'Click the next button below to start.'))
|
||||
'Click the %s button below to start.') %
|
||||
self.buttonText(QtGui.QWizard.NextButton))
|
||||
self.plugin_page.setTitle(translate('OpenLP.FirstTimeWizard', 'Activate required Plugins'))
|
||||
self.plugin_page.setSubTitle(translate('OpenLP.FirstTimeWizard', 'Select the Plugins you wish to use. '))
|
||||
self.songs_check_box.setText(translate('OpenLP.FirstTimeWizard', 'Songs'))
|
||||
@ -236,7 +238,7 @@ class Ui_FirstTimeWizard(object):
|
||||
'wizard by selecting "Tools/Re-run First Time Wizard" from OpenLP.')
|
||||
self.cancelWizardText = translate('OpenLP.FirstTimeWizard',
|
||||
'\n\nTo cancel the First Time Wizard completely (and not start OpenLP), '
|
||||
'click the Cancel button now.')
|
||||
'click the %s button now.') % self.buttonText(QtGui.QWizard.CancelButton)
|
||||
self.songs_page.setTitle(translate('OpenLP.FirstTimeWizard', 'Sample Songs'))
|
||||
self.songs_page.setSubTitle(translate('OpenLP.FirstTimeWizard', 'Select and download public domain songs.'))
|
||||
self.bibles_page.setTitle(translate('OpenLP.FirstTimeWizard', 'Sample Bibles'))
|
||||
|
@ -60,6 +60,12 @@ class FormattingTagForm(QtGui.QDialog, Ui_FormattingTagDialog, FormattingTagCont
|
||||
"""
|
||||
super(FormattingTagForm, self).__init__(parent)
|
||||
self.setupUi(self)
|
||||
self._setup()
|
||||
|
||||
def _setup(self):
|
||||
"""
|
||||
Set up the class. This method is mocked out by the tests.
|
||||
"""
|
||||
self.services = FormattingTagController()
|
||||
self.tag_table_widget.itemSelectionChanged.connect(self.on_row_selected)
|
||||
self.new_button.clicked.connect(self.on_new_clicked)
|
||||
|
@ -92,6 +92,8 @@ class Ui_MainWindow(object):
|
||||
main_window.setObjectName('MainWindow')
|
||||
main_window.setWindowIcon(build_icon(':/icon/openlp-logo.svg'))
|
||||
main_window.setDockNestingEnabled(True)
|
||||
if is_macosx():
|
||||
main_window.setDocumentMode(True)
|
||||
# Set up the main container, which contains all the other form widgets.
|
||||
self.main_content = QtGui.QWidget(main_window)
|
||||
self.main_content.setObjectName('main_content')
|
||||
@ -118,9 +120,11 @@ class Ui_MainWindow(object):
|
||||
self.recent_files_menu = QtGui.QMenu(self.file_menu)
|
||||
self.recent_files_menu.setObjectName('recentFilesMenu')
|
||||
self.file_import_menu = QtGui.QMenu(self.file_menu)
|
||||
if not is_macosx():
|
||||
self.file_import_menu.setIcon(build_icon(u':/general/general_import.png'))
|
||||
self.file_import_menu.setObjectName('file_import_menu')
|
||||
self.file_export_menu = QtGui.QMenu(self.file_menu)
|
||||
if not is_macosx():
|
||||
self.file_export_menu.setIcon(build_icon(u':/general/general_export.png'))
|
||||
self.file_export_menu.setObjectName('file_export_menu')
|
||||
# View Menu
|
||||
|
@ -31,7 +31,7 @@ The Create/Edit theme wizard
|
||||
"""
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.common import UiStrings, translate
|
||||
from openlp.core.common import UiStrings, translate, is_macosx
|
||||
from openlp.core.lib import build_icon
|
||||
from openlp.core.lib.theme import HorizontalType, BackgroundType, BackgroundGradientType
|
||||
from openlp.core.lib.ui import add_welcome_page, create_valign_selection_widgets
|
||||
@ -41,19 +41,21 @@ class Ui_ThemeWizard(object):
|
||||
"""
|
||||
The Create/Edit theme wizard
|
||||
"""
|
||||
def setupUi(self, themeWizard):
|
||||
def setupUi(self, theme_wizard):
|
||||
"""
|
||||
Set up the UI
|
||||
"""
|
||||
themeWizard.setObjectName('OpenLP.ThemeWizard')
|
||||
themeWizard.setWindowIcon(build_icon(u':/icon/openlp-logo.svg'))
|
||||
themeWizard.setModal(True)
|
||||
themeWizard.setWizardStyle(QtGui.QWizard.ModernStyle)
|
||||
themeWizard.setOptions(QtGui.QWizard.IndependentPages |
|
||||
theme_wizard.setObjectName('OpenLP.ThemeWizard')
|
||||
theme_wizard.setWindowIcon(build_icon(u':/icon/openlp-logo.svg'))
|
||||
theme_wizard.setModal(True)
|
||||
theme_wizard.setOptions(QtGui.QWizard.IndependentPages |
|
||||
QtGui.QWizard.NoBackButtonOnStartPage | QtGui.QWizard.HaveCustomButton1)
|
||||
if is_macosx():
|
||||
theme_wizard.setPixmap(QtGui.QWizard.BackgroundPixmap, QtGui.QPixmap(':/wizards/openlp-osx-wizard.png'))
|
||||
theme_wizard.resize(646, 400)
|
||||
self.spacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum)
|
||||
# Welcome Page
|
||||
add_welcome_page(themeWizard, ':/wizards/wizard_createtheme.bmp')
|
||||
add_welcome_page(theme_wizard, ':/wizards/wizard_createtheme.bmp')
|
||||
# Background Page
|
||||
self.background_page = QtGui.QWizardPage()
|
||||
self.background_page.setObjectName('background_page')
|
||||
@ -137,7 +139,7 @@ class Ui_ThemeWizard(object):
|
||||
self.transparent_layout.setObjectName('Transparent_layout')
|
||||
self.background_stack.addWidget(self.transparent_widget)
|
||||
self.background_layout.addLayout(self.background_stack)
|
||||
themeWizard.addPage(self.background_page)
|
||||
theme_wizard.addPage(self.background_page)
|
||||
# Main Area Page
|
||||
self.main_area_page = QtGui.QWizardPage()
|
||||
self.main_area_page.setObjectName('main_area_page')
|
||||
@ -218,7 +220,7 @@ class Ui_ThemeWizard(object):
|
||||
self.shadow_size_spin_box.setObjectName('shadow_size_spin_box')
|
||||
self.shadow_layout.addWidget(self.shadow_size_spin_box)
|
||||
self.main_area_layout.addRow(self.shadow_check_box, self.shadow_layout)
|
||||
themeWizard.addPage(self.main_area_page)
|
||||
theme_wizard.addPage(self.main_area_page)
|
||||
# Footer Area Page
|
||||
self.footer_area_page = QtGui.QWizardPage()
|
||||
self.footer_area_page.setObjectName('footer_area_page')
|
||||
@ -242,7 +244,7 @@ class Ui_ThemeWizard(object):
|
||||
self.footer_size_spin_box.setObjectName('FooterSizeSpinBox')
|
||||
self.footer_area_layout.addRow(self.footer_size_label, self.footer_size_spin_box)
|
||||
self.footer_area_layout.setItem(3, QtGui.QFormLayout.LabelRole, self.spacer)
|
||||
themeWizard.addPage(self.footer_area_page)
|
||||
theme_wizard.addPage(self.footer_area_page)
|
||||
# Alignment Page
|
||||
self.alignment_page = QtGui.QWizardPage()
|
||||
self.alignment_page.setObjectName('alignment_page')
|
||||
@ -264,7 +266,7 @@ class Ui_ThemeWizard(object):
|
||||
self.transitions_check_box.setObjectName('transitions_check_box')
|
||||
self.alignment_layout.addRow(self.transitions_label, self.transitions_check_box)
|
||||
self.alignment_layout.setItem(3, QtGui.QFormLayout.LabelRole, self.spacer)
|
||||
themeWizard.addPage(self.alignment_page)
|
||||
theme_wizard.addPage(self.alignment_page)
|
||||
# Area Position Page
|
||||
self.area_position_page = QtGui.QWizardPage()
|
||||
self.area_position_page.setObjectName('area_position_page')
|
||||
@ -334,7 +336,7 @@ class Ui_ThemeWizard(object):
|
||||
self.footer_height_spin_box.setObjectName('footer_height_spin_box')
|
||||
self.footer_position_layout.addRow(self.footer_height_label, self.footer_height_spin_box)
|
||||
self.area_position_layout.addWidget(self.footer_position_group_box)
|
||||
themeWizard.addPage(self.area_position_page)
|
||||
theme_wizard.addPage(self.area_position_page)
|
||||
# Preview Page
|
||||
self.preview_page = QtGui.QWizardPage()
|
||||
self.preview_page.setObjectName('preview_page')
|
||||
@ -362,8 +364,8 @@ class Ui_ThemeWizard(object):
|
||||
self.preview_box_label.setObjectName('preview_box_label')
|
||||
self.preview_area_layout.addWidget(self.preview_box_label)
|
||||
self.preview_layout.addWidget(self.preview_area)
|
||||
themeWizard.addPage(self.preview_page)
|
||||
self.retranslateUi(themeWizard)
|
||||
theme_wizard.addPage(self.preview_page)
|
||||
self.retranslateUi(theme_wizard)
|
||||
QtCore.QObject.connect(self.background_combo_box, QtCore.SIGNAL('currentIndexChanged(int)'),
|
||||
self.background_stack, QtCore.SLOT('setCurrentIndex(int)'))
|
||||
QtCore.QObject.connect(self.outline_check_box, QtCore.SIGNAL('toggled(bool)'), self.outline_color_button,
|
||||
@ -391,11 +393,11 @@ class Ui_ThemeWizard(object):
|
||||
QtCore.QObject.connect(self.footer_position_check_box, QtCore.SIGNAL('toggled(bool)'),
|
||||
self.footer_height_spin_box, QtCore.SLOT('setDisabled(bool)'))
|
||||
|
||||
def retranslateUi(self, themeWizard):
|
||||
def retranslateUi(self, theme_wizard):
|
||||
"""
|
||||
Translate the UI on the fly
|
||||
"""
|
||||
themeWizard.setWindowTitle(translate('OpenLP.ThemeWizard', 'Theme Wizard'))
|
||||
theme_wizard.setWindowTitle(translate('OpenLP.ThemeWizard', 'Theme Wizard'))
|
||||
self.title_label.setText('<span style="font-size:14pt; font-weight:600;">%s</span>' %
|
||||
translate('OpenLP.ThemeWizard', 'Welcome to the Theme Wizard'))
|
||||
self.information_label.setText(
|
||||
@ -484,8 +486,8 @@ class Ui_ThemeWizard(object):
|
||||
self.footer_height_label.setText(translate('OpenLP.ThemeWizard', 'Height:'))
|
||||
self.footer_height_spin_box.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
|
||||
self.footer_position_check_box.setText(translate('OpenLP.ThemeWizard', 'Use default location'))
|
||||
themeWizard.setOption(QtGui.QWizard.HaveCustomButton1, False)
|
||||
themeWizard.setButtonText(QtGui.QWizard.CustomButton1, translate('OpenLP.ThemeWizard', 'Layout Preview'))
|
||||
theme_wizard.setOption(QtGui.QWizard.HaveCustomButton1, False)
|
||||
theme_wizard.setButtonText(QtGui.QWizard.CustomButton1, translate('OpenLP.ThemeWizard', 'Layout Preview'))
|
||||
self.preview_page.setTitle(translate('OpenLP.ThemeWizard', 'Preview and Save'))
|
||||
self.preview_page.setSubTitle(translate('OpenLP.ThemeWizard', 'Preview the theme and save it.'))
|
||||
self.theme_name_label.setText(translate('OpenLP.ThemeWizard', 'Theme name:'))
|
||||
|
@ -34,7 +34,7 @@ import os
|
||||
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from openlp.core.common import Registry, RegistryProperties, Settings, UiStrings, translate
|
||||
from openlp.core.common import Registry, RegistryProperties, Settings, UiStrings, translate, is_macosx
|
||||
from openlp.core.lib import build_icon
|
||||
from openlp.core.lib.ui import add_welcome_page
|
||||
|
||||
@ -121,9 +121,10 @@ class OpenLPWizard(QtGui.QWizard, RegistryProperties):
|
||||
"""
|
||||
self.setWindowIcon(build_icon(u':/icon/openlp-logo.svg'))
|
||||
self.setModal(True)
|
||||
self.setWizardStyle(QtGui.QWizard.ModernStyle)
|
||||
self.setOptions(QtGui.QWizard.IndependentPages |
|
||||
QtGui.QWizard.NoBackButtonOnStartPage | QtGui.QWizard.NoBackButtonOnLastPage)
|
||||
if is_macosx():
|
||||
self.setPixmap(QtGui.QWizard.BackgroundPixmap, QtGui.QPixmap(':/wizards/openlp-osx-wizard.png'))
|
||||
add_welcome_page(self, image)
|
||||
self.add_custom_pages()
|
||||
if self.with_progress_page:
|
||||
|
@ -30,7 +30,7 @@
|
||||
import logging
|
||||
from lxml import etree, objectify
|
||||
|
||||
from openlp.core.common import translate
|
||||
from openlp.core.common import translate, trace_error_handler
|
||||
from openlp.core.lib.ui import critical_error_message_box
|
||||
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB
|
||||
|
||||
@ -88,6 +88,7 @@ class OpenSongBible(BibleDB):
|
||||
'Incorrect Bible file type supplied. This looks like a Zefania XML bible, '
|
||||
'please use the Zefania import option.'))
|
||||
return False
|
||||
# No language info in the opensong format, so ask the user
|
||||
language_id = self.get_language(bible_name)
|
||||
if not language_id:
|
||||
log.error('Importing books from "%s" failed' % self.filename)
|
||||
@ -134,6 +135,7 @@ class OpenSongBible(BibleDB):
|
||||
self.session.commit()
|
||||
self.application.process_events()
|
||||
except etree.XMLSyntaxError as inst:
|
||||
trace_error_handler(log)
|
||||
critical_error_message_box(
|
||||
message=translate('BiblesPlugin.OpenSongImport',
|
||||
'Incorrect Bible file type supplied. OpenSong Bibles may be '
|
||||
|
@ -27,14 +27,12 @@
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
import os
|
||||
import logging
|
||||
import chardet
|
||||
import codecs
|
||||
import re
|
||||
from lxml import etree
|
||||
|
||||
from openlp.core.common import AppLocation, translate
|
||||
from openlp.core.common import translate, trace_error_handler
|
||||
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB
|
||||
from openlp.core.lib.ui import critical_error_message_box
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -53,143 +51,151 @@ class OSISBible(BibleDB):
|
||||
log.debug(self.__class__.__name__)
|
||||
BibleDB.__init__(self, parent, **kwargs)
|
||||
self.filename = kwargs['filename']
|
||||
self.language_regex = re.compile(r'<language.*>(.*?)</language>')
|
||||
self.verse_regex = re.compile(r'<verse osisID="([a-zA-Z0-9 ]*).([0-9]*).([0-9]*)">(.*?)</verse>')
|
||||
self.note_regex = re.compile(r'<note(.*?)>(.*?)</note>')
|
||||
self.title_regex = re.compile(r'<title(.*?)>(.*?)</title>')
|
||||
self.milestone_regex = re.compile(r'<milestone(.*?)/>')
|
||||
self.fi_regex = re.compile(r'<FI>(.*?)<Fi>')
|
||||
self.rf_regex = re.compile(r'<RF>(.*?)<Rf>')
|
||||
self.lb_regex = re.compile(r'<lb(.*?)>')
|
||||
self.lg_regex = re.compile(r'<lg(.*?)>')
|
||||
self.l_regex = re.compile(r'<l (.*?)>')
|
||||
self.w_regex = re.compile(r'<w (.*?)>')
|
||||
self.q_regex = re.compile(r'<q(.*?)>')
|
||||
self.q1_regex = re.compile(r'<q(.*?)level="1"(.*?)>')
|
||||
self.q2_regex = re.compile(r'<q(.*?)level="2"(.*?)>')
|
||||
self.trans_regex = re.compile(r'<transChange(.*?)>(.*?)</transChange>')
|
||||
self.divine_name_regex = re.compile(r'<divineName(.*?)>(.*?)</divineName>')
|
||||
self.spaces_regex = re.compile(r'([ ]{2,})')
|
||||
filepath = os.path.join(
|
||||
AppLocation.get_directory(AppLocation.PluginsDir), 'bibles', 'resources', 'osisbooks.csv')
|
||||
|
||||
def do_import(self, bible_name=None):
|
||||
"""
|
||||
Loads a Bible from file.
|
||||
"""
|
||||
log.debug('Starting OSIS import from "%s"' % self.filename)
|
||||
detect_file = None
|
||||
db_book = None
|
||||
osis = None
|
||||
if not isinstance(self.filename, str):
|
||||
self.filename = str(self.filename, 'utf8')
|
||||
import_file = None
|
||||
success = True
|
||||
last_chapter = 0
|
||||
match_count = 0
|
||||
self.wizard.increment_progress_bar(
|
||||
translate('BiblesPlugin.OsisImport', 'Detecting encoding (this may take a few minutes)...'))
|
||||
try:
|
||||
detect_file = open(self.filename, 'r')
|
||||
details = chardet.detect(detect_file.read(1048576))
|
||||
detect_file.seek(0)
|
||||
lines_in_file = int(len(detect_file.readlines()))
|
||||
except IOError:
|
||||
log.exception('Failed to detect OSIS file encoding')
|
||||
return
|
||||
finally:
|
||||
if detect_file:
|
||||
detect_file.close()
|
||||
try:
|
||||
osis = codecs.open(self.filename, 'r', details['encoding'])
|
||||
repl = replacement
|
||||
language_id = False
|
||||
# Decide if the bible probably contains only NT or AT and NT or
|
||||
# AT, NT and Apocrypha
|
||||
if lines_in_file < 11500:
|
||||
book_count = 27
|
||||
chapter_count = 260
|
||||
elif lines_in_file < 34200:
|
||||
book_count = 66
|
||||
chapter_count = 1188
|
||||
else:
|
||||
book_count = 67
|
||||
chapter_count = 1336
|
||||
for file_record in osis:
|
||||
if self.stop_import_flag:
|
||||
break
|
||||
# Try to find the bible language
|
||||
if not language_id:
|
||||
language_match = self.language_regex.search(file_record)
|
||||
if language_match:
|
||||
language = BiblesResourcesDB.get_language(
|
||||
language_match.group(1))
|
||||
# NOTE: We don't need to do any of the normal encoding detection here, because lxml does it's own encoding
|
||||
# detection, and the two mechanisms together interfere with each other.
|
||||
import_file = open(self.filename, 'rb')
|
||||
osis_bible_tree = etree.parse(import_file)
|
||||
namespace = {'ns': 'http://www.bibletechnologies.net/2003/OSIS/namespace'}
|
||||
# Find bible language
|
||||
language_id = None
|
||||
language = osis_bible_tree.xpath("//ns:osisText/@xml:lang", namespaces=namespace)
|
||||
if language:
|
||||
language_id = language['id']
|
||||
self.save_meta('language_id', language_id)
|
||||
continue
|
||||
match = self.verse_regex.search(file_record)
|
||||
if match:
|
||||
# Set meta language_id if not detected till now
|
||||
language_id = BiblesResourcesDB.get_language(language[0])
|
||||
# The language couldn't be detected, ask the user
|
||||
if not language_id:
|
||||
language_id = self.get_language(bible_name)
|
||||
if not language_id:
|
||||
log.error('Importing books from "%s" failed' % self.filename)
|
||||
return False
|
||||
match_count += 1
|
||||
book = str(match.group(1))
|
||||
chapter = int(match.group(2))
|
||||
verse = int(match.group(3))
|
||||
verse_text = match.group(4)
|
||||
book_ref_id = self.get_book_ref_id_by_name(book, book_count, language_id)
|
||||
num_books = int(osis_bible_tree.xpath("count(//ns:div[@type='book'])", namespaces=namespace))
|
||||
self.wizard.increment_progress_bar(translate('BiblesPlugin.OsisImport',
|
||||
'Removing unused tags (this may take a few minutes)...'))
|
||||
# We strip unused tags from the XML, this should leave us with only chapter, verse and div tags.
|
||||
# Strip tags we don't use - remove content
|
||||
etree.strip_elements(osis_bible_tree, ('{http://www.bibletechnologies.net/2003/OSIS/namespace}note',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}milestone',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}title',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}abbr',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}catchWord',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}index',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}rdg',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}rdgGroup',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}figure'),
|
||||
with_tail=False)
|
||||
# Strip tags we don't use - keep content
|
||||
etree.strip_tags(osis_bible_tree, ('{http://www.bibletechnologies.net/2003/OSIS/namespace}p',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}l',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}lg',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}q',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}a',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}w',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}divineName',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}foreign',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}hi',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}inscription',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}mentioned',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}name',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}reference',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}seg',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}transChange',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}salute',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}signed',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}closer',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}speech',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}speaker',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}list',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}item',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}table',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}head',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}row',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}cell',
|
||||
'{http://www.bibletechnologies.net/2003/OSIS/namespace}caption'))
|
||||
# Precompile a few xpath-querys
|
||||
verse_in_chapter = etree.XPath('count(//ns:chapter[1]/ns:verse)', namespaces=namespace)
|
||||
text_in_verse = etree.XPath('count(//ns:verse[1]/text())', namespaces=namespace)
|
||||
# Find books in the bible
|
||||
bible_books = osis_bible_tree.xpath("//ns:div[@type='book']", namespaces=namespace)
|
||||
for book in bible_books:
|
||||
if self.stop_import_flag:
|
||||
break
|
||||
# Remove div-tags in the book
|
||||
etree.strip_tags(book, ('{http://www.bibletechnologies.net/2003/OSIS/namespace}div'))
|
||||
book_ref_id = self.get_book_ref_id_by_name(book.get('osisID'), num_books)
|
||||
if not book_ref_id:
|
||||
book_ref_id = self.get_book_ref_id_by_localised_name(book.get('osisID'))
|
||||
if not book_ref_id:
|
||||
log.error('Importing books from "%s" failed' % self.filename)
|
||||
return False
|
||||
book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
|
||||
if not db_book or db_book.name != book_details['name']:
|
||||
log.debug('New book: "%s"' % book_details['name'])
|
||||
db_book = self.create_book(
|
||||
book_details['name'],
|
||||
book_ref_id,
|
||||
book_details['testament_id'])
|
||||
if last_chapter == 0:
|
||||
self.wizard.progress_bar.setMaximum(chapter_count)
|
||||
if last_chapter != chapter:
|
||||
if last_chapter != 0:
|
||||
self.session.commit()
|
||||
db_book = self.create_book(book_details['name'], book_ref_id, book_details['testament_id'])
|
||||
# Find out if chapter-tags contains the verses, or if it is used as milestone/anchor
|
||||
if int(verse_in_chapter(book)) > 0:
|
||||
# The chapter tags contains the verses
|
||||
for chapter in book:
|
||||
chapter_number = chapter.get("osisID").split('.')[1]
|
||||
# Find out if verse-tags contains the text, or if it is used as milestone/anchor
|
||||
if int(text_in_verse(chapter)) == 0:
|
||||
# verse-tags are used as milestone
|
||||
for verse in chapter:
|
||||
# If this tag marks the start of a verse, the verse text is between this tag and
|
||||
# the next tag, which the "tail" attribute gives us.
|
||||
if verse.get('sID'):
|
||||
verse_number = verse.get("osisID").split('.')[2]
|
||||
verse_text = verse.tail
|
||||
if verse_text:
|
||||
self.create_verse(db_book.id, chapter_number, verse_number, verse_text.strip())
|
||||
else:
|
||||
# Verse-tags contains the text
|
||||
for verse in chapter:
|
||||
verse_number = verse.get("osisID").split('.')[2]
|
||||
self.create_verse(db_book.id, chapter_number, verse_number, verse.text.strip())
|
||||
self.wizard.increment_progress_bar(
|
||||
translate('BiblesPlugin.OsisImport', 'Importing %s %s...',
|
||||
'Importing <book name> <chapter>...') % (book_details['name'], chapter))
|
||||
last_chapter = chapter
|
||||
# All of this rigmarole below is because the mod2osis tool from the Sword library embeds XML in the
|
||||
# OSIS but neglects to enclose the verse text (with XML) in <[CDATA[ ]]> tags.
|
||||
verse_text = self.note_regex.sub('', verse_text)
|
||||
verse_text = self.title_regex.sub('', verse_text)
|
||||
verse_text = self.milestone_regex.sub('', verse_text)
|
||||
verse_text = self.fi_regex.sub('', verse_text)
|
||||
verse_text = self.rf_regex.sub('', verse_text)
|
||||
verse_text = self.lb_regex.sub(' ', verse_text)
|
||||
verse_text = self.lg_regex.sub('', verse_text)
|
||||
verse_text = self.l_regex.sub(' ', verse_text)
|
||||
verse_text = self.w_regex.sub('', verse_text)
|
||||
verse_text = self.q1_regex.sub('"', verse_text)
|
||||
verse_text = self.q2_regex.sub('\'', verse_text)
|
||||
verse_text = self.q_regex.sub('', verse_text)
|
||||
verse_text = self.divine_name_regex.sub(repl, verse_text)
|
||||
verse_text = self.trans_regex.sub('', verse_text)
|
||||
verse_text = verse_text.replace('</lb>', '') \
|
||||
.replace('</l>', '').replace('<lg>', '') \
|
||||
.replace('</lg>', '').replace('</q>', '') \
|
||||
.replace('</div>', '').replace('</w>', '')
|
||||
verse_text = self.spaces_regex.sub(' ', verse_text)
|
||||
self.create_verse(db_book.id, chapter, verse, verse_text)
|
||||
self.application.process_events()
|
||||
translate('BiblesPlugin.OsisImport', 'Importing %(bookname)s %(chapter)s...' %
|
||||
{'bookname': db_book.name, 'chapter': chapter_number}))
|
||||
else:
|
||||
# The chapter tags is used as milestones. For now we assume verses is also milestones
|
||||
chapter_number = 0
|
||||
for element in book:
|
||||
if element.tag == '{http://www.bibletechnologies.net/2003/OSIS/namespace}chapter' \
|
||||
and element.get('sID'):
|
||||
chapter_number = element.get("osisID").split('.')[1]
|
||||
self.wizard.increment_progress_bar(
|
||||
translate('BiblesPlugin.OsisImport', 'Importing %(bookname)s %(chapter)s...' %
|
||||
{'bookname': db_book.name, 'chapter': chapter_number}))
|
||||
elif element.tag == '{http://www.bibletechnologies.net/2003/OSIS/namespace}verse' \
|
||||
and element.get('sID'):
|
||||
# If this tag marks the start of a verse, the verse text is between this tag and
|
||||
# the next tag, which the "tail" attribute gives us.
|
||||
verse_number = element.get("osisID").split('.')[2]
|
||||
verse_text = element.tail
|
||||
if verse_text:
|
||||
self.create_verse(db_book.id, chapter_number, verse_number, verse_text.strip())
|
||||
self.session.commit()
|
||||
if match_count == 0:
|
||||
success = False
|
||||
self.application.process_events()
|
||||
except (ValueError, IOError):
|
||||
log.exception('Loading bible from OSIS file failed')
|
||||
trace_error_handler(log)
|
||||
success = False
|
||||
except etree.XMLSyntaxError as e:
|
||||
log.exception('Loading bible from OSIS file failed')
|
||||
trace_error_handler(log)
|
||||
success = False
|
||||
critical_error_message_box(message=translate('BiblesPlugin.OsisImport',
|
||||
'The file is not a valid OSIS-XML file: \n%s' % e.msg))
|
||||
finally:
|
||||
if osis:
|
||||
osis.close()
|
||||
if import_file:
|
||||
import_file.close()
|
||||
if self.stop_import_flag:
|
||||
return False
|
||||
else:
|
||||
|
@ -64,11 +64,18 @@ class ZefaniaBible(BibleDB):
|
||||
# NOTE: We don't need to do any of the normal encoding detection here, because lxml does it's own encoding
|
||||
# detection, and the two mechanisms together interfere with each other.
|
||||
import_file = open(self.filename, 'rb')
|
||||
zefania_bible_tree = etree.parse(import_file)
|
||||
# Find bible language
|
||||
language_id = None
|
||||
language = zefania_bible_tree.xpath("/XMLBIBLE/INFORMATION/language/text()")
|
||||
if language:
|
||||
language_id = BiblesResourcesDB.get_language(language[0])
|
||||
# The language couldn't be detected, ask the user
|
||||
if not language_id:
|
||||
language_id = self.get_language(bible_name)
|
||||
if not language_id:
|
||||
log.error('Importing books from "%s" failed' % self.filename)
|
||||
return False
|
||||
zefania_bible_tree = etree.parse(import_file)
|
||||
num_books = int(zefania_bible_tree.xpath("count(//BIBLEBOOK)"))
|
||||
# Strip tags we don't use - keep content
|
||||
etree.strip_tags(zefania_bible_tree, ('STYLE', 'GRAM', 'NOTE', 'SUP', 'XREF'))
|
||||
@ -97,7 +104,6 @@ class ZefaniaBible(BibleDB):
|
||||
self.session.commit()
|
||||
self.application.process_events()
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
critical_error_message_box(
|
||||
message=translate('BiblesPlugin.ZefaniaImport',
|
||||
'Incorrect Bible file type supplied. Zefania Bibles may be '
|
||||
|
@ -28,31 +28,29 @@
|
||||
###############################################################################
|
||||
|
||||
import os
|
||||
if os.name == 'nt':
|
||||
from win32com.client import Dispatch
|
||||
import string
|
||||
import sys
|
||||
|
||||
if sys.platform.startswith('linux'):
|
||||
import dbus
|
||||
import logging
|
||||
import re
|
||||
from time import sleep
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.common import translate
|
||||
from openlp.core.common import translate, is_win, is_linux, is_macosx, RegistryProperties
|
||||
from openlp.plugins.media.forms.mediaclipselectordialog import Ui_MediaClipSelector
|
||||
from openlp.core.lib.ui import critical_error_message_box
|
||||
from openlp.core.ui.media import format_milliseconds
|
||||
|
||||
if is_win():
|
||||
from win32com.client import Dispatch
|
||||
|
||||
if is_linux():
|
||||
import dbus
|
||||
|
||||
try:
|
||||
from openlp.core.ui.media.vendor import vlc
|
||||
except (ImportError, NameError, NotImplementedError):
|
||||
pass
|
||||
except OSError as e:
|
||||
if sys.platform.startswith('win'):
|
||||
if is_win():
|
||||
if not isinstance(e, WindowsError) and e.winerror != 126:
|
||||
raise
|
||||
else:
|
||||
@ -61,7 +59,7 @@ except OSError as e:
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
|
||||
class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector, RegistryProperties):
|
||||
"""
|
||||
Class to manage the clip selection
|
||||
"""
|
||||
@ -144,9 +142,9 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
|
||||
# You have to give the id of the QFrame (or similar object)
|
||||
# to vlc, different platforms have different functions for this.
|
||||
win_id = int(self.preview_frame.winId())
|
||||
if sys.platform == "win32":
|
||||
if is_win():
|
||||
self.vlc_media_player.set_hwnd(win_id)
|
||||
elif sys.platform == "darwin":
|
||||
elif is_macosx():
|
||||
# We have to use 'set_nsobject' since Qt4 on OSX uses Cocoa
|
||||
# framework and not the old Carbon.
|
||||
self.vlc_media_player.set_nsobject(win_id)
|
||||
@ -190,7 +188,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
|
||||
self.audio_cd = True
|
||||
self.titles_combo_box.setDisabled(False)
|
||||
self.titles_combo_box.setCurrentIndex(0)
|
||||
self.on_title_combo_box_currentIndexChanged(0)
|
||||
self.on_titles_combo_box_currentIndexChanged(0)
|
||||
|
||||
return True
|
||||
|
||||
@ -203,18 +201,21 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
|
||||
"""
|
||||
log.debug('on_load_disc_button_clicked')
|
||||
self.disable_all()
|
||||
self.application.set_busy_cursor()
|
||||
path = self.media_path_combobox.currentText()
|
||||
# Check if given path is non-empty and exists before starting VLC
|
||||
if not path:
|
||||
log.debug('no given path')
|
||||
critical_error_message_box(message=translate('MediaPlugin.MediaClipSelectorForm', 'No path was given'))
|
||||
self.toggle_disable_load_media(False)
|
||||
self.application.set_normal_cursor()
|
||||
return
|
||||
if not os.path.exists(path):
|
||||
log.debug('Given path does not exists')
|
||||
critical_error_message_box(message=translate('MediaPlugin.MediaClipSelectorForm',
|
||||
'Given path does not exists'))
|
||||
self.toggle_disable_load_media(False)
|
||||
self.application.set_normal_cursor()
|
||||
return
|
||||
# VLC behaves a bit differently on windows and linux when loading, which creates problems when trying to
|
||||
# detect if we're dealing with a DVD or CD, so we use different loading approaches depending on the OS.
|
||||
@ -231,6 +232,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
|
||||
critical_error_message_box(message=translate('MediaPlugin.MediaClipSelectorForm',
|
||||
'An error happened during initialization of VLC player'))
|
||||
self.toggle_disable_load_media(False)
|
||||
self.application.set_normal_cursor()
|
||||
return
|
||||
# put the media in the media player
|
||||
self.vlc_media_player.set_media(self.vlc_media)
|
||||
@ -241,6 +243,8 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
|
||||
critical_error_message_box(message=translate('MediaPlugin.MediaClipSelectorForm',
|
||||
'VLC player failed playing the media'))
|
||||
self.toggle_disable_load_media(False)
|
||||
self.application.set_normal_cursor()
|
||||
self.vlc_media_player.audio_set_mute(False)
|
||||
return
|
||||
self.vlc_media_player.audio_set_mute(True)
|
||||
if not self.media_state_wait(vlc.State.Playing):
|
||||
@ -249,23 +253,32 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
|
||||
critical_error_message_box(message=translate('MediaPlugin.MediaClipSelectorForm',
|
||||
'VLC player failed playing the media'))
|
||||
self.toggle_disable_load_media(False)
|
||||
self.application.set_normal_cursor()
|
||||
self.vlc_media_player.audio_set_mute(False)
|
||||
return
|
||||
self.vlc_media_player.audio_set_mute(True)
|
||||
# pause
|
||||
self.vlc_media_player.set_time(0)
|
||||
self.vlc_media_player.set_pause(1)
|
||||
self.media_state_wait(vlc.State.Paused)
|
||||
self.toggle_disable_load_media(False)
|
||||
self.application.set_normal_cursor()
|
||||
self.vlc_media_player.audio_set_mute(False)
|
||||
if not self.audio_cd:
|
||||
# Temporarily disable signals
|
||||
self.blockSignals(True)
|
||||
# Get titles, insert in combobox
|
||||
titles = self.vlc_media_player.video_get_title_description()
|
||||
self.titles_combo_box.clear()
|
||||
for title in titles:
|
||||
self.titles_combo_box.addItem(title[1].decode(), title[0])
|
||||
# Re-enable signals
|
||||
self.blockSignals(False)
|
||||
# Main title is usually title #1
|
||||
if len(titles) > 1:
|
||||
self.titles_combo_box.setCurrentIndex(1)
|
||||
else:
|
||||
self.titles_combo_box.setCurrentIndex(0)
|
||||
# Enable audio track combobox if anything is in it
|
||||
if len(titles) > 0:
|
||||
self.titles_combo_box.setDisabled(False)
|
||||
self.toggle_disable_load_media(False)
|
||||
log.debug('load_disc_button end - vlc_media_player state: %s' % self.vlc_media_player.get_state())
|
||||
|
||||
@QtCore.pyqtSlot(bool)
|
||||
@ -378,6 +391,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
|
||||
if not self.vlc_media_player:
|
||||
log.error('vlc_media_player was None')
|
||||
return
|
||||
self.application.set_busy_cursor()
|
||||
if self.audio_cd:
|
||||
self.vlc_media = self.audio_cd_tracks.item_at_index(index)
|
||||
self.vlc_media_player.set_media(self.vlc_media)
|
||||
@ -385,14 +399,14 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
|
||||
self.vlc_media_player.play()
|
||||
if not self.media_state_wait(vlc.State.Playing):
|
||||
log.error('Could not start playing audio cd, needed to get track info')
|
||||
self.application.set_normal_cursor()
|
||||
return
|
||||
self.vlc_media_player.audio_set_mute(True)
|
||||
# Sleep 1 second to make sure VLC has the needed metadata
|
||||
sleep(1)
|
||||
# pause
|
||||
self.vlc_media_player.set_time(0)
|
||||
self.vlc_media_player.set_pause(1)
|
||||
self.vlc_media_player.audio_set_mute(False)
|
||||
self.application.set_normal_cursor()
|
||||
self.toggle_disable_player(False)
|
||||
else:
|
||||
self.vlc_media_player.set_title(index)
|
||||
@ -400,13 +414,13 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
|
||||
self.vlc_media_player.play()
|
||||
if not self.media_state_wait(vlc.State.Playing):
|
||||
log.error('Could not start playing dvd, needed to get track info')
|
||||
self.application.set_normal_cursor()
|
||||
return
|
||||
self.vlc_media_player.audio_set_mute(True)
|
||||
# Sleep 1 second to make sure VLC has the needed metadata
|
||||
sleep(1)
|
||||
self.vlc_media_player.set_time(0)
|
||||
# Get audio tracks, insert in combobox
|
||||
# Get audio tracks
|
||||
audio_tracks = self.vlc_media_player.audio_get_track_description()
|
||||
log.debug('number of audio tracks: %d' % len(audio_tracks))
|
||||
# Clear the audio track combobox, insert new tracks
|
||||
self.audio_tracks_combobox.clear()
|
||||
for audio_track in audio_tracks:
|
||||
self.audio_tracks_combobox.addItem(audio_track[1].decode(), audio_track[0])
|
||||
@ -447,6 +461,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
|
||||
self.vlc_media_player.set_pause(1)
|
||||
loop_count += 1
|
||||
log.debug('titles_combo_box end - vlc_media_player state: %s' % self.vlc_media_player.get_state())
|
||||
self.application.set_normal_cursor()
|
||||
|
||||
@QtCore.pyqtSlot(int)
|
||||
def on_audio_tracks_combobox_currentIndexChanged(self, index):
|
||||
@ -535,7 +550,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
|
||||
"""
|
||||
Saves the current media and trackinfo as a clip to the mediamanager
|
||||
"""
|
||||
log.debug('in on_save_button_clicked')
|
||||
log.debug('in MediaClipSelectorForm.accept')
|
||||
start_time = self.start_position_edit.time()
|
||||
start_time_ms = start_time.hour() * 60 * 60 * 1000 + \
|
||||
start_time.minute() * 60 * 1000 + \
|
||||
@ -550,10 +565,23 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
|
||||
path = self.media_path_combobox.currentText()
|
||||
optical = ''
|
||||
if self.audio_cd:
|
||||
# Check for load problems
|
||||
if start_time_ms is None or end_time_ms is None or title is None:
|
||||
critical_error_message_box(translate('MediaPlugin.MediaClipSelectorForm', 'CD not loaded correctly'),
|
||||
translate('MediaPlugin.MediaClipSelectorForm',
|
||||
'The CD was not loaded correctly, please re-load and try again.'))
|
||||
return
|
||||
optical = 'optical:%d:-1:-1:%d:%d:' % (title, start_time_ms, end_time_ms)
|
||||
else:
|
||||
audio_track = self.audio_tracks_combobox.itemData(self.audio_tracks_combobox.currentIndex())
|
||||
subtitle_track = self.subtitle_tracks_combobox.itemData(self.subtitle_tracks_combobox.currentIndex())
|
||||
# Check for load problems
|
||||
if start_time_ms is None or end_time_ms is None or title is None or audio_track is None\
|
||||
or subtitle_track is None:
|
||||
critical_error_message_box(translate('MediaPlugin.MediaClipSelectorForm', 'DVD not loaded correctly'),
|
||||
translate('MediaPlugin.MediaClipSelectorForm',
|
||||
'The DVD was not loaded correctly, please re-load and try again.'))
|
||||
return
|
||||
optical = 'optical:%d:%d:%d:%d:%d:' % (title, audio_track, subtitle_track, start_time_ms, end_time_ms)
|
||||
# Ask for an alternative name for the mediaclip
|
||||
while True:
|
||||
@ -595,7 +623,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
|
||||
while media_state != self.vlc_media_player.get_state():
|
||||
if self.vlc_media_player.get_state() == vlc.State.Error:
|
||||
return False
|
||||
if (datetime.now() - start).seconds > 30:
|
||||
if (datetime.now() - start).seconds > 15:
|
||||
return False
|
||||
return True
|
||||
|
||||
@ -606,7 +634,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
|
||||
"""
|
||||
# Clear list first
|
||||
self.media_path_combobox.clear()
|
||||
if os.name == 'nt':
|
||||
if is_win():
|
||||
# use win api to find optical drives
|
||||
fso = Dispatch('scripting.filesystemobject')
|
||||
for drive in fso.Drives:
|
||||
@ -614,7 +642,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
|
||||
# if type is 4, it is a cd-rom drive
|
||||
if drive.DriveType == 4:
|
||||
self.media_path_combobox.addItem('%s:\\' % drive.DriveLetter)
|
||||
elif sys.platform.startswith('linux'):
|
||||
elif is_linux():
|
||||
# Get disc devices from dbus and find the ones that are optical
|
||||
bus = dbus.SystemBus()
|
||||
try:
|
||||
@ -646,7 +674,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
|
||||
if chr(c) != '\x00':
|
||||
block_file += chr(c)
|
||||
self.media_path_combobox.addItem(block_file)
|
||||
elif sys.platform.startswith('darwin'):
|
||||
elif is_macosx():
|
||||
# Look for DVD folders in devices to find optical devices
|
||||
volumes = os.listdir('/Volumes')
|
||||
candidates = list()
|
||||
|
@ -31,8 +31,6 @@ The :mod:`db` module provides the database and schema that is the backend for
|
||||
the Songs plugin
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
from sqlalchemy import Column, ForeignKey, Table, types
|
||||
from sqlalchemy.orm import mapper, relation, reconstructor
|
||||
from sqlalchemy.sql.expression import func, text
|
||||
@ -329,7 +327,9 @@ def init_schema(url):
|
||||
Column('topic_id', types.Integer(), ForeignKey('topics.id'), primary_key=True)
|
||||
)
|
||||
|
||||
mapper(Author, authors_table)
|
||||
mapper(Author, authors_table, properties={
|
||||
'songs': relation(Song, secondary=authors_songs_table, viewonly=True)
|
||||
})
|
||||
mapper(AuthorSong, authors_songs_table, properties={
|
||||
'author': relation(Author)
|
||||
})
|
||||
@ -339,7 +339,8 @@ def init_schema(url):
|
||||
# Use the authors_songs relation when you need access to the 'author_type' attribute
|
||||
# or when creating new relations
|
||||
'authors_songs': relation(AuthorSong, cascade="all, delete-orphan"),
|
||||
'authors': relation(Author, secondary=authors_songs_table, viewonly=True),
|
||||
# Use lazy='joined' to always load authors when the song is fetched from the database (bug 1366198)
|
||||
'authors': relation(Author, secondary=authors_songs_table, viewonly=True, lazy='joined'),
|
||||
'book': relation(Book, backref='songs'),
|
||||
'media_files': relation(MediaFile, backref='songs', order_by=media_files_table.c.weight),
|
||||
'topics': relation(Topic, backref='songs', secondary=songs_topics_table)
|
||||
|
@ -99,6 +99,7 @@
|
||||
<file>export_load.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="wizards">
|
||||
<file>openlp-osx-wizard.png</file>
|
||||
<file>wizard_exportsong.bmp</file>
|
||||
<file>wizard_importsong.bmp</file>
|
||||
<file>wizard_importbible.bmp</file>
|
||||
|
BIN
resources/images/openlp-osx-wizard.png
Normal file
BIN
resources/images/openlp-osx-wizard.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
@ -51,7 +51,7 @@ class TestTheme(TestCase):
|
||||
"""
|
||||
pass
|
||||
|
||||
def test_new_theme(self):
|
||||
def new_theme_test(self):
|
||||
"""
|
||||
Test the theme creation - basic test
|
||||
"""
|
||||
|
@ -29,10 +29,14 @@
|
||||
"""
|
||||
Package to test the openlp.core.lib.ui package.
|
||||
"""
|
||||
from PyQt4 import QtGui
|
||||
from PyQt4 import QtCore, QtGui
|
||||
from unittest import TestCase
|
||||
|
||||
from openlp.core.lib.ui import *
|
||||
from openlp.core.common import UiStrings, translate
|
||||
from openlp.core.lib.ui import add_welcome_page, create_button_box, create_horizontal_adjusting_combo_box, \
|
||||
create_button, create_action, create_valign_selection_widgets, find_and_set_in_combo_box, create_widget_action, \
|
||||
set_case_insensitive_completer
|
||||
from tests.functional import MagicMock, patch
|
||||
|
||||
|
||||
class TestUi(TestCase):
|
||||
@ -40,7 +44,7 @@ class TestUi(TestCase):
|
||||
Test the functions in the ui module
|
||||
"""
|
||||
|
||||
def test_add_welcome_page(self):
|
||||
def add_welcome_page_test(self):
|
||||
"""
|
||||
Test appending a welcome page to a wizard
|
||||
"""
|
||||
@ -54,7 +58,7 @@ class TestUi(TestCase):
|
||||
self.assertEqual(1, len(wizard.pageIds()), 'The wizard should have one page.')
|
||||
self.assertIsInstance(wizard.page(0).pixmap(QtGui.QWizard.WatermarkPixmap), QtGui.QPixmap)
|
||||
|
||||
def test_create_button_box(self):
|
||||
def create_button_box_test(self):
|
||||
"""
|
||||
Test creating a button box for a dialog
|
||||
"""
|
||||
@ -82,7 +86,7 @@ class TestUi(TestCase):
|
||||
self.assertEqual(1, len(btnbox.buttons()))
|
||||
self.assertEqual(QtGui.QDialogButtonBox.HelpRole, btnbox.buttonRole(btnbox.buttons()[0]))
|
||||
|
||||
def test_create_horizontal_adjusting_combo_box(self):
|
||||
def create_horizontal_adjusting_combo_box_test(self):
|
||||
"""
|
||||
Test creating a horizontal adjusting combo box
|
||||
"""
|
||||
@ -97,7 +101,7 @@ class TestUi(TestCase):
|
||||
self.assertEqual('combo1', combo.objectName())
|
||||
self.assertEqual(QtGui.QComboBox.AdjustToMinimumContentsLength, combo.sizeAdjustPolicy())
|
||||
|
||||
def test_create_button(self):
|
||||
def create_button_test(self):
|
||||
"""
|
||||
Test creating a button
|
||||
"""
|
||||
@ -129,7 +133,7 @@ class TestUi(TestCase):
|
||||
self.assertEqual('my_btn', btn.objectName())
|
||||
self.assertTrue(btn.isEnabled())
|
||||
|
||||
def test_create_action(self):
|
||||
def create_action_test(self):
|
||||
"""
|
||||
Test creating an action
|
||||
"""
|
||||
@ -154,9 +158,46 @@ class TestUi(TestCase):
|
||||
self.assertEqual('my tooltip', action.toolTip())
|
||||
self.assertEqual('my statustip', action.statusTip())
|
||||
|
||||
def test_create_checked_enabled_visible_action(self):
|
||||
def create_action_on_mac_osx_test(self):
|
||||
"""
|
||||
Test creating an action with the 'checked', 'enabled' and 'visible' properties.
|
||||
Test creating an action on OS X calls the correct method
|
||||
"""
|
||||
# GIVEN: A dialog and a mocked out is_macosx() method to always return True
|
||||
with patch('openlp.core.lib.ui.is_macosx') as mocked_is_macosx, \
|
||||
patch('openlp.core.lib.ui.QtGui.QAction') as MockedQAction:
|
||||
mocked_is_macosx.return_value = True
|
||||
mocked_action = MagicMock()
|
||||
MockedQAction.return_value = mocked_action
|
||||
dialog = QtGui.QDialog()
|
||||
|
||||
# WHEN: An action is created
|
||||
create_action(dialog, 'my_action')
|
||||
|
||||
# THEN: setIconVisibleInMenu should be called
|
||||
mocked_action.setIconVisibleInMenu.assert_called_with(False)
|
||||
|
||||
def create_action_not_on_mac_osx_test(self):
|
||||
"""
|
||||
Test creating an action on something other than OS X doesn't call the method
|
||||
"""
|
||||
# GIVEN: A dialog and a mocked out is_macosx() method to always return True
|
||||
with patch('openlp.core.lib.ui.is_macosx') as mocked_is_macosx, \
|
||||
patch('openlp.core.lib.ui.QtGui.QAction') as MockedQAction:
|
||||
mocked_is_macosx.return_value = False
|
||||
mocked_action = MagicMock()
|
||||
MockedQAction.return_value = mocked_action
|
||||
dialog = QtGui.QDialog()
|
||||
|
||||
# WHEN: An action is created
|
||||
create_action(dialog, 'my_action')
|
||||
|
||||
# THEN: setIconVisibleInMenu should not be called
|
||||
self.assertEqual(0, mocked_action.setIconVisibleInMenu.call_count,
|
||||
'setIconVisibleInMenu should not have been called')
|
||||
|
||||
def create_checked_disabled_invisible_action_test(self):
|
||||
"""
|
||||
Test that an invisible, disabled, checked action is created correctly
|
||||
"""
|
||||
# GIVEN: A dialog
|
||||
dialog = QtGui.QDialog()
|
||||
@ -165,11 +206,24 @@ class TestUi(TestCase):
|
||||
action = create_action(dialog, 'my_action', checked=True, enabled=False, visible=False)
|
||||
|
||||
# THEN: These properties should be set
|
||||
self.assertEqual(True, action.isChecked())
|
||||
self.assertEqual(False, action.isEnabled())
|
||||
self.assertEqual(False, action.isVisible())
|
||||
self.assertTrue(action.isChecked(), 'The action should be checked')
|
||||
self.assertFalse(action.isEnabled(), 'The action should be disabled')
|
||||
self.assertFalse(action.isVisible(), 'The action should be invisble')
|
||||
|
||||
def test_create_valign_selection_widgets(self):
|
||||
def create_action_separator_test(self):
|
||||
"""
|
||||
Test creating an action as separator
|
||||
"""
|
||||
# GIVEN: A dialog
|
||||
dialog = QtGui.QDialog()
|
||||
|
||||
# WHEN: We create an action as a separator
|
||||
action = create_action(dialog, 'my_action', separator=True)
|
||||
|
||||
# THEN: The action should be a separator
|
||||
self.assertTrue(action.isSeparator(), 'The action should be a separator')
|
||||
|
||||
def create_valign_selection_widgets_test(self):
|
||||
"""
|
||||
Test creating a combo box for valign selection
|
||||
"""
|
||||
@ -186,7 +240,7 @@ class TestUi(TestCase):
|
||||
for text in [UiStrings().Top, UiStrings().Middle, UiStrings().Bottom]:
|
||||
self.assertTrue(combo.findText(text) >= 0)
|
||||
|
||||
def test_find_and_set_in_combo_box(self):
|
||||
def find_and_set_in_combo_box_test(self):
|
||||
"""
|
||||
Test finding a string in a combo box and setting it as the selected item if present
|
||||
"""
|
||||
@ -213,7 +267,7 @@ class TestUi(TestCase):
|
||||
# THEN: The index should have changed
|
||||
self.assertEqual(2, combo.currentIndex())
|
||||
|
||||
def test_create_widget_action(self):
|
||||
def create_widget_action_test(self):
|
||||
"""
|
||||
Test creating an action for a widget
|
||||
"""
|
||||
@ -227,7 +281,7 @@ class TestUi(TestCase):
|
||||
self.assertIsInstance(action, QtGui.QAction)
|
||||
self.assertEqual(action.objectName(), 'some action')
|
||||
|
||||
def test_set_case_insensitive_completer(self):
|
||||
def set_case_insensitive_completer_test(self):
|
||||
"""
|
||||
Test setting a case insensitive completer on a widget
|
||||
"""
|
||||
|
@ -47,7 +47,7 @@ class TestFirstTimeForm(TestCase, TestMixin):
|
||||
Registry().register('application', self.app)
|
||||
self.first_time_form = FirstTimeForm(screens)
|
||||
|
||||
def test_access_to_config(self):
|
||||
def access_to_config_test(self):
|
||||
"""
|
||||
Test if we can access the First Time Form's config file
|
||||
"""
|
||||
@ -59,7 +59,7 @@ class TestFirstTimeForm(TestCase, TestMixin):
|
||||
self.assertTrue(self.first_time_form.web_access,
|
||||
'First Time Wizard\'s web configuration file should be available')
|
||||
|
||||
def test_parsable_config(self):
|
||||
def parsable_config_test(self):
|
||||
"""
|
||||
Test if the First Time Form's config file is parsable
|
||||
"""
|
||||
|
@ -39,7 +39,7 @@ class TestFormattingTagController(TestCase):
|
||||
def setUp(self):
|
||||
self.services = FormattingTagController()
|
||||
|
||||
def test_strip(self):
|
||||
def strip_test(self):
|
||||
"""
|
||||
Test that the _strip strips the correct chars
|
||||
"""
|
||||
@ -52,7 +52,7 @@ class TestFormattingTagController(TestCase):
|
||||
# THEN: The tag should be returned with the wrappers removed.
|
||||
self.assertEqual(result, 'tag', 'FormattingTagForm._strip should return u\'tag\' when called with u\'{tag}\'')
|
||||
|
||||
def test_end_tag_changed_processes_correctly(self):
|
||||
def end_tag_changed_processes_correctly_test(self):
|
||||
"""
|
||||
Test that the end html tags are generated correctly
|
||||
"""
|
||||
@ -77,7 +77,7 @@ class TestFormattingTagController(TestCase):
|
||||
self.assertTrue(error == test['valid'], 'Function should not generate unexpected error messages : %s ' %
|
||||
error)
|
||||
|
||||
def test_start_tag_changed_processes_correctly(self):
|
||||
def start_tag_changed_processes_correctly_test(self):
|
||||
"""
|
||||
Test that the end html tags are generated correctly
|
||||
"""
|
||||
@ -100,7 +100,7 @@ class TestFormattingTagController(TestCase):
|
||||
self.assertTrue(error == test['valid'], 'Function should not generate unexpected error messages : %s ' %
|
||||
error)
|
||||
|
||||
def test_start_html_to_end_html(self):
|
||||
def start_html_to_end_html_test(self):
|
||||
"""
|
||||
Test that the end html tags are generated correctly
|
||||
"""
|
||||
|
@ -29,17 +29,17 @@
|
||||
"""
|
||||
Package to test the openlp.core.ui.formattingtagsform package.
|
||||
"""
|
||||
from PyQt4 import QtGui
|
||||
from unittest import TestCase
|
||||
from openlp.core.common import translate
|
||||
|
||||
from tests.functional import MagicMock, patch
|
||||
from tests.functional import MagicMock, patch, call
|
||||
|
||||
from openlp.core.ui.formattingtagform import FormattingTagForm
|
||||
|
||||
# TODO: Tests Still TODO
|
||||
# __init__
|
||||
# exec_
|
||||
# on_new_clicked
|
||||
# on_delete_clicked
|
||||
# on_saved_clicked
|
||||
# _reloadTable
|
||||
|
||||
@ -47,30 +47,60 @@ from openlp.core.ui.formattingtagform import FormattingTagForm
|
||||
class TestFormattingTagForm(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.init_patcher = patch('openlp.core.ui.formattingtagform.FormattingTagForm.__init__')
|
||||
self.qdialog_patcher = patch('openlp.core.ui.formattingtagform.QtGui.QDialog')
|
||||
self.ui_formatting_tag_dialog_patcher = patch('openlp.core.ui.formattingtagform.Ui_FormattingTagDialog')
|
||||
self.mocked_init = self.init_patcher.start()
|
||||
self.mocked_qdialog = self.qdialog_patcher.start()
|
||||
self.mocked_ui_formatting_tag_dialog = self.ui_formatting_tag_dialog_patcher.start()
|
||||
self.mocked_init.return_value = None
|
||||
"""
|
||||
Mock out stuff for all the tests
|
||||
"""
|
||||
self.setup_patcher = patch('openlp.core.ui.formattingtagform.FormattingTagForm._setup')
|
||||
self.setup_patcher.start()
|
||||
|
||||
def tearDown(self):
|
||||
self.init_patcher.stop()
|
||||
self.qdialog_patcher.stop()
|
||||
self.ui_formatting_tag_dialog_patcher.stop()
|
||||
|
||||
def test_on_text_edited(self):
|
||||
"""
|
||||
Test that the appropriate actions are preformed when on_text_edited is called
|
||||
Remove the mocks
|
||||
"""
|
||||
self.setup_patcher.stop()
|
||||
|
||||
def on_row_selected_test(self):
|
||||
"""
|
||||
Test that the appropriate actions are preformed when on_row_selected is called
|
||||
"""
|
||||
# GIVEN: An instance of the Formatting Tag Form and a mocked delete_button
|
||||
form = FormattingTagForm(None)
|
||||
form.delete_button = MagicMock()
|
||||
|
||||
# WHEN: on_row_selected is called
|
||||
form.on_row_selected()
|
||||
|
||||
# THEN: setEnabled and should have been called on delete_button
|
||||
form.delete_button.setEnabled.assert_called_with(True)
|
||||
|
||||
def on_new_clicked_test(self):
|
||||
"""
|
||||
Test that clicking the Add a new tag button does the right thing
|
||||
"""
|
||||
|
||||
# GIVEN: An instance of the Formatting Tag Form and a mocked save_push_button
|
||||
form = FormattingTagForm()
|
||||
form.save_button = MagicMock()
|
||||
# GIVEN: A formatting tag form and a mocked out tag table widget
|
||||
form = FormattingTagForm(None)
|
||||
form.tag_table_widget = MagicMock()
|
||||
row_count = 5
|
||||
form.tag_table_widget.rowCount.return_value = row_count
|
||||
|
||||
# WHEN: on_text_edited is called with an arbitrary value
|
||||
# form.on_text_edited('text')
|
||||
# WHEN: on_new_clicked is run (i.e. the Add new button was clicked)
|
||||
with patch('openlp.core.ui.formattingtagform.QtGui.QTableWidgetItem') as MockedQTableWidgetItem:
|
||||
mocked_table_widget = MagicMock()
|
||||
MockedQTableWidgetItem.return_value = mocked_table_widget
|
||||
form.on_new_clicked()
|
||||
|
||||
# THEN: setEnabled and setDefault should have been called on save_push_button
|
||||
# form.save_button.setEnabled.assert_called_with(True)
|
||||
# THEN: A new row should be added to the table
|
||||
form.tag_table_widget.rowCount.assert_called_with()
|
||||
form.tag_table_widget.insertRow.assert_called_with(row_count)
|
||||
expected_set_item_calls = [
|
||||
call(row_count, 0, mocked_table_widget),
|
||||
call(row_count, 1, mocked_table_widget),
|
||||
call(row_count, 2, mocked_table_widget),
|
||||
call(row_count, 3, mocked_table_widget)
|
||||
]
|
||||
self.assertEqual(expected_set_item_calls, form.tag_table_widget.setItem.call_args_list,
|
||||
'setItem should have been called correctly')
|
||||
form.tag_table_widget.resizeRowsToContents.assert_called_with()
|
||||
form.tag_table_widget.scrollToBottom.assert_called_with()
|
||||
form.tag_table_widget.selectRow.assert_called_with(row_count)
|
||||
|
@ -31,6 +31,7 @@ This module contains tests for the OpenSong Bible importer.
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
from unittest import TestCase
|
||||
|
||||
from tests.functional import MagicMock, patch
|
||||
@ -39,29 +40,6 @@ from openlp.plugins.bibles.lib.db import BibleDB
|
||||
|
||||
TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
'..', '..', '..', 'resources', 'bibles'))
|
||||
OPENSONG_TEST_DATA = {
|
||||
'opensong-dk1933.xml': {
|
||||
'book': 'Genesis',
|
||||
'chapter': 1,
|
||||
'verses': [
|
||||
(1, 'I Begyndelsen skabte Gud Himmelen og Jorden.'),
|
||||
(2, 'Og Jorden var øde og tom, og der var Mørke over Verdensdybet. '
|
||||
'Men Guds Ånd svævede over Vandene.'),
|
||||
(3, 'Og Gud sagde: "Der blive Lys!" Og der blev Lys.'),
|
||||
(4, 'Og Gud så, at Lyset var godt, og Gud satte Skel mellem Lyset og Mørket,'),
|
||||
(5, 'og Gud kaldte Lyset Dag, og Mørket kaldte han Nat. Og det blev Aften, '
|
||||
'og det blev Morgen, første Dag.'),
|
||||
(6, 'Derpå sagde Gud: "Der blive en Hvælving midt i Vandene til at skille Vandene ad!"'),
|
||||
(7, 'Og således skete det: Gud gjorde Hvælvingen og skilte Vandet under Hvælvingen '
|
||||
'fra Vandet over Hvælvingen;'),
|
||||
(8, 'og Gud kaldte Hvælvingen Himmel. Og det blev Aften, og det blev Morgen, anden Dag.'),
|
||||
(9, 'Derpå sagde Gud: "Vandet under Himmelen samle sig på eet Sted, så det faste Land kommer til Syne!" '
|
||||
'Og således skete det;'),
|
||||
(10, 'og Gud kaldte det faste Land Jord, og Stedet, hvor Vandet samlede sig, kaldte han Hav. Og Gud så, '
|
||||
'at det var godt.')
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TestOpenSongImport(TestCase):
|
||||
@ -94,12 +72,14 @@ class TestOpenSongImport(TestCase):
|
||||
|
||||
def file_import_test(self):
|
||||
"""
|
||||
Test the actual import of real song files
|
||||
Test the actual import of OpenSong Bible file
|
||||
"""
|
||||
# GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions
|
||||
# get_book_ref_id_by_name, create_verse, create_book, session and get_language.
|
||||
result_file = open(os.path.join(TEST_PATH, 'dk1933.json'), 'rb')
|
||||
test_data = json.loads(result_file.read().decode())
|
||||
bible_file = 'opensong-dk1933.xml'
|
||||
with patch('openlp.plugins.bibles.lib.opensong.OpenSongBible.application'):
|
||||
for bible_file in OPENSONG_TEST_DATA:
|
||||
mocked_manager = MagicMock()
|
||||
mocked_import_wizard = MagicMock()
|
||||
importer = OpenSongBible(mocked_manager, path='.', name='.', filename='')
|
||||
@ -117,8 +97,8 @@ class TestOpenSongImport(TestCase):
|
||||
|
||||
# THEN: The create_verse() method should have been called with each verse in the file.
|
||||
self.assertTrue(importer.create_verse.called)
|
||||
for verse_tag, verse_text in OPENSONG_TEST_DATA[bible_file]['verses']:
|
||||
importer.create_verse.assert_any_call(importer.create_book().id, 1, verse_tag, verse_text)
|
||||
for verse_tag, verse_text in test_data['verses']:
|
||||
importer.create_verse.assert_any_call(importer.create_book().id, 1, int(verse_tag), verse_text)
|
||||
|
||||
def zefania_import_error_test(self):
|
||||
"""
|
||||
|
161
tests/functional/openlp_plugins/bibles/test_osisimport.py
Normal file
161
tests/functional/openlp_plugins/bibles/test_osisimport.py
Normal file
@ -0,0 +1,161 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2014 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2014 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, Patrick Zimmermann #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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 #
|
||||
###############################################################################
|
||||
"""
|
||||
This module contains tests for the OSIS Bible importer.
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
from unittest import TestCase
|
||||
|
||||
from tests.functional import MagicMock, patch
|
||||
from openlp.plugins.bibles.lib.osis import OSISBible
|
||||
from openlp.plugins.bibles.lib.db import BibleDB
|
||||
|
||||
TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
'..', '..', '..', 'resources', 'bibles'))
|
||||
|
||||
|
||||
class TestOsisImport(TestCase):
|
||||
"""
|
||||
Test the functions in the :mod:`osisimport` module.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.registry_patcher = patch('openlp.plugins.bibles.lib.db.Registry')
|
||||
self.registry_patcher.start()
|
||||
self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager')
|
||||
self.manager_patcher.start()
|
||||
|
||||
def tearDown(self):
|
||||
self.registry_patcher.stop()
|
||||
self.manager_patcher.stop()
|
||||
|
||||
def create_importer_test(self):
|
||||
"""
|
||||
Test creating an instance of the OSIS file importer
|
||||
"""
|
||||
# GIVEN: A mocked out "manager"
|
||||
mocked_manager = MagicMock()
|
||||
|
||||
# WHEN: An importer object is created
|
||||
importer = OSISBible(mocked_manager, path='.', name='.', filename='')
|
||||
|
||||
# THEN: The importer should be an instance of BibleDB
|
||||
self.assertIsInstance(importer, BibleDB)
|
||||
|
||||
def file_import_nested_tags_test(self):
|
||||
"""
|
||||
Test the actual import of OSIS Bible file, with nested chapter and verse tags
|
||||
"""
|
||||
# GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions
|
||||
# get_book_ref_id_by_name, create_verse, create_book, session and get_language.
|
||||
result_file = open(os.path.join(TEST_PATH, 'dk1933.json'), 'rb')
|
||||
test_data = json.loads(result_file.read().decode())
|
||||
bible_file = 'osis-dk1933.xml'
|
||||
with patch('openlp.plugins.bibles.lib.osis.OSISBible.application'):
|
||||
mocked_manager = MagicMock()
|
||||
mocked_import_wizard = MagicMock()
|
||||
importer = OSISBible(mocked_manager, path='.', name='.', filename='')
|
||||
importer.wizard = mocked_import_wizard
|
||||
importer.get_book_ref_id_by_name = MagicMock()
|
||||
importer.create_verse = MagicMock()
|
||||
importer.create_book = MagicMock()
|
||||
importer.session = MagicMock()
|
||||
importer.get_language = MagicMock()
|
||||
importer.get_language.return_value = 'Danish'
|
||||
|
||||
# WHEN: Importing bible file
|
||||
importer.filename = os.path.join(TEST_PATH, bible_file)
|
||||
importer.do_import()
|
||||
|
||||
# THEN: The create_verse() method should have been called with each verse in the file.
|
||||
self.assertTrue(importer.create_verse.called)
|
||||
for verse_tag, verse_text in test_data['verses']:
|
||||
importer.create_verse.assert_any_call(importer.create_book().id, '1', verse_tag, verse_text)
|
||||
|
||||
def file_import_mixed_tags_test(self):
|
||||
"""
|
||||
Test the actual import of OSIS Bible file, with chapter tags containing milestone verse tags.
|
||||
"""
|
||||
# GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions
|
||||
# get_book_ref_id_by_name, create_verse, create_book, session and get_language.
|
||||
result_file = open(os.path.join(TEST_PATH, 'kjv.json'), 'rb')
|
||||
test_data = json.loads(result_file.read().decode())
|
||||
bible_file = 'osis-kjv.xml'
|
||||
with patch('openlp.plugins.bibles.lib.osis.OSISBible.application'):
|
||||
mocked_manager = MagicMock()
|
||||
mocked_import_wizard = MagicMock()
|
||||
importer = OSISBible(mocked_manager, path='.', name='.', filename='')
|
||||
importer.wizard = mocked_import_wizard
|
||||
importer.get_book_ref_id_by_name = MagicMock()
|
||||
importer.create_verse = MagicMock()
|
||||
importer.create_book = MagicMock()
|
||||
importer.session = MagicMock()
|
||||
importer.get_language = MagicMock()
|
||||
importer.get_language.return_value = 'English'
|
||||
|
||||
# WHEN: Importing bible file
|
||||
importer.filename = os.path.join(TEST_PATH, bible_file)
|
||||
importer.do_import()
|
||||
|
||||
# THEN: The create_verse() method should have been called with each verse in the file.
|
||||
self.assertTrue(importer.create_verse.called)
|
||||
for verse_tag, verse_text in test_data['verses']:
|
||||
importer.create_verse.assert_any_call(importer.create_book().id, '1', verse_tag, verse_text)
|
||||
|
||||
def file_import_milestone_tags_test(self):
|
||||
"""
|
||||
Test the actual import of OSIS Bible file, with milestone chapter and verse tags.
|
||||
"""
|
||||
# GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions
|
||||
# get_book_ref_id_by_name, create_verse, create_book, session and get_language.
|
||||
result_file = open(os.path.join(TEST_PATH, 'web.json'), 'rb')
|
||||
test_data = json.loads(result_file.read().decode())
|
||||
bible_file = 'osis-web.xml'
|
||||
with patch('openlp.plugins.bibles.lib.osis.OSISBible.application'):
|
||||
mocked_manager = MagicMock()
|
||||
mocked_import_wizard = MagicMock()
|
||||
importer = OSISBible(mocked_manager, path='.', name='.', filename='')
|
||||
importer.wizard = mocked_import_wizard
|
||||
importer.get_book_ref_id_by_name = MagicMock()
|
||||
importer.create_verse = MagicMock()
|
||||
importer.create_book = MagicMock()
|
||||
importer.session = MagicMock()
|
||||
importer.get_language = MagicMock()
|
||||
importer.get_language.return_value = 'English'
|
||||
|
||||
# WHEN: Importing bible file
|
||||
importer.filename = os.path.join(TEST_PATH, bible_file)
|
||||
importer.do_import()
|
||||
|
||||
# THEN: The create_verse() method should have been called with each verse in the file.
|
||||
self.assertTrue(importer.create_verse.called)
|
||||
for verse_tag, verse_text in test_data['verses']:
|
||||
importer.create_verse.assert_any_call(importer.create_book().id, '1', verse_tag, verse_text)
|
@ -31,6 +31,7 @@ This module contains tests for the Zefania Bible importer.
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
from unittest import TestCase
|
||||
|
||||
from tests.functional import MagicMock, patch
|
||||
@ -39,29 +40,6 @@ from openlp.plugins.bibles.lib.db import BibleDB
|
||||
|
||||
TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
'..', '..', '..', 'resources', 'bibles'))
|
||||
ZEFANIA_TEST_DATA = {
|
||||
'zefania-dk1933.xml': {
|
||||
'book': 'Genesis',
|
||||
'chapter': 1,
|
||||
'verses': [
|
||||
('1', 'I Begyndelsen skabte Gud Himmelen og Jorden.'),
|
||||
('2', 'Og Jorden var øde og tom, og der var Mørke over Verdensdybet. '
|
||||
'Men Guds Ånd svævede over Vandene.'),
|
||||
('3', 'Og Gud sagde: "Der blive Lys!" Og der blev Lys.'),
|
||||
('4', 'Og Gud så, at Lyset var godt, og Gud satte Skel mellem Lyset og Mørket,'),
|
||||
('5', 'og Gud kaldte Lyset Dag, og Mørket kaldte han Nat. Og det blev Aften, '
|
||||
'og det blev Morgen, første Dag.'),
|
||||
('6', 'Derpå sagde Gud: "Der blive en Hvælving midt i Vandene til at skille Vandene ad!"'),
|
||||
('7', 'Og således skete det: Gud gjorde Hvælvingen og skilte Vandet under Hvælvingen '
|
||||
'fra Vandet over Hvælvingen;'),
|
||||
('8', 'og Gud kaldte Hvælvingen Himmel. Og det blev Aften, og det blev Morgen, anden Dag.'),
|
||||
('9', 'Derpå sagde Gud: "Vandet under Himmelen samle sig på eet Sted, så det faste Land kommer til Syne!" '
|
||||
'Og således skete det;'),
|
||||
('10', 'og Gud kaldte det faste Land Jord, og Stedet, hvor Vandet samlede sig, kaldte han Hav. Og Gud så, '
|
||||
'at det var godt.')
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TestZefaniaImport(TestCase):
|
||||
@ -94,12 +72,14 @@ class TestZefaniaImport(TestCase):
|
||||
|
||||
def file_import_test(self):
|
||||
"""
|
||||
Test the actual import of real song files
|
||||
Test the actual import of Zefania Bible file
|
||||
"""
|
||||
# GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions
|
||||
# get_book_ref_id_by_name, create_verse, create_book, session and get_language.
|
||||
result_file = open(os.path.join(TEST_PATH, 'dk1933.json'), 'rb')
|
||||
test_data = json.loads(result_file.read().decode())
|
||||
bible_file = 'zefania-dk1933.xml'
|
||||
with patch('openlp.plugins.bibles.lib.zefania.ZefaniaBible.application'):
|
||||
for bible_file in ZEFANIA_TEST_DATA:
|
||||
mocked_manager = MagicMock()
|
||||
mocked_import_wizard = MagicMock()
|
||||
importer = ZefaniaBible(mocked_manager, path='.', name='.', filename='')
|
||||
@ -117,5 +97,5 @@ class TestZefaniaImport(TestCase):
|
||||
|
||||
# THEN: The create_verse() method should have been called with each verse in the file.
|
||||
self.assertTrue(importer.create_verse.called)
|
||||
for verse_tag, verse_text in ZEFANIA_TEST_DATA[bible_file]['verses']:
|
||||
for verse_tag, verse_text in test_data['verses']:
|
||||
importer.create_verse.assert_any_call(importer.create_book().id, '1', verse_tag, verse_text)
|
||||
|
@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2014 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2014 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, Patrick Zimmermann #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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 #
|
||||
###############################################################################
|
28
tests/interfaces/openlp_plugins/media/forms/__init__.py
Normal file
28
tests/interfaces/openlp_plugins/media/forms/__init__.py
Normal file
@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2014 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2014 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, Patrick Zimmermann #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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 #
|
||||
###############################################################################
|
@ -60,6 +60,7 @@ class TestMediaClipSelectorForm(TestCase, TestMixin):
|
||||
# Mock VLC so we don't actually use it
|
||||
self.vlc_patcher = patch('openlp.plugins.media.forms.mediaclipselectorform.vlc')
|
||||
self.vlc_patcher.start()
|
||||
Registry().register('application', self.app)
|
||||
# Mock the media item
|
||||
self.mock_media_item = MagicMock()
|
||||
# create form to test
|
||||
@ -67,6 +68,9 @@ class TestMediaClipSelectorForm(TestCase, TestMixin):
|
||||
mock_media_state_wait = MagicMock()
|
||||
mock_media_state_wait.return_value = True
|
||||
self.form.media_state_wait = mock_media_state_wait
|
||||
self.form.application.set_busy_cursor = MagicMock()
|
||||
self.form.application.set_normal_cursor = MagicMock()
|
||||
self.form.find_optical_devices = MagicMock()
|
||||
|
||||
def tearDown(self):
|
||||
"""
|
||||
@ -155,3 +159,21 @@ class TestMediaClipSelectorForm(TestCase, TestMixin):
|
||||
self.form.audio_tracks_combobox.itemData.assert_any_call(0)
|
||||
self.form.audio_tracks_combobox.itemData.assert_any_call(1)
|
||||
self.form.subtitle_tracks_combobox.itemData.assert_any_call(0)
|
||||
|
||||
def click_save_button_test(self):
|
||||
"""
|
||||
Test that the correct function is called when save is clicked, and that it behaves as expected.
|
||||
"""
|
||||
# GIVEN: Mocked methods.
|
||||
with patch('openlp.plugins.media.forms.mediaclipselectorform.critical_error_message_box') as \
|
||||
mocked_critical_error_message_box,\
|
||||
patch('PyQt4.QtGui.QDialog.exec_') as mocked_exec:
|
||||
self.form.exec_()
|
||||
|
||||
# WHEN: The save button is clicked with a NoneType in start_time_ms or end_time_ms
|
||||
self.form.accept()
|
||||
|
||||
# THEN: we should get an error message
|
||||
mocked_critical_error_message_box.assert_called_with('DVD not loaded correctly',
|
||||
'The DVD was not loaded correctly, '
|
||||
'please re-load and try again.')
|
||||
|
16
tests/resources/bibles/dk1933.json
Normal file
16
tests/resources/bibles/dk1933.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"book": "Genesis",
|
||||
"chapter": 1,
|
||||
"verses": [
|
||||
[ "1", "I Begyndelsen skabte Gud Himmelen og Jorden."],
|
||||
[ "2", "Og Jorden var øde og tom, og der var Mørke over Verdensdybet. Men Guds Ånd svævede over Vandene." ],
|
||||
[ "3", "Og Gud sagde: \"Der blive Lys!\" Og der blev Lys." ],
|
||||
[ "4", "Og Gud så, at Lyset var godt, og Gud satte Skel mellem Lyset og Mørket," ],
|
||||
[ "5", "og Gud kaldte Lyset Dag, og Mørket kaldte han Nat. Og det blev Aften, og det blev Morgen, første Dag." ],
|
||||
[ "6", "Derpå sagde Gud: \"Der blive en Hvælving midt i Vandene til at skille Vandene ad!\"" ],
|
||||
[ "7", "Og således skete det: Gud gjorde Hvælvingen og skilte Vandet under Hvælvingen fra Vandet over Hvælvingen;" ],
|
||||
[ "8", "og Gud kaldte Hvælvingen Himmel. Og det blev Aften, og det blev Morgen, anden Dag." ],
|
||||
[ "9", "Derpå sagde Gud: \"Vandet under Himmelen samle sig på eet Sted, så det faste Land kommer til Syne!\" Og således skete det;" ],
|
||||
[ "10", "og Gud kaldte det faste Land Jord, og Stedet, hvor Vandet samlede sig, kaldte han Hav. Og Gud så, at det var godt." ]
|
||||
]
|
||||
}
|
16
tests/resources/bibles/kjv.json
Normal file
16
tests/resources/bibles/kjv.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"book": "Genesis",
|
||||
"chapter": 1,
|
||||
"verses": [
|
||||
[ "1", "In the beginning God created the heaven and the earth."],
|
||||
[ "2", "And the earth was without form, and void; and darkness was upon the face of the deep. And the Spirit of God moved upon the face of the waters." ],
|
||||
[ "3", "And God said, Let there be light: and there was light." ],
|
||||
[ "4", "And God saw the light, that it was good: and God divided the light from the darkness." ],
|
||||
[ "5", "And God called the light Day, and the darkness he called Night. And the evening and the morning were the first day." ],
|
||||
[ "6", "And God said, Let there be a firmament in the midst of the waters, and let it divide the waters from the waters." ],
|
||||
[ "7", "And God made the firmament, and divided the waters which were under the firmament from the waters which were above the firmament: and it was so." ],
|
||||
[ "8", "And God called the firmament Heaven. And the evening and the morning were the second day." ],
|
||||
[ "9", "And God said, Let the waters under the heaven be gathered together unto one place, and let the dry land appear: and it was so." ],
|
||||
[ "10", "And God called the dry land Earth; and the gathering together of the waters called he Seas: and God saw that it was good." ]
|
||||
]
|
||||
}
|
32
tests/resources/bibles/osis-dk1933.xml
Normal file
32
tests/resources/bibles/osis-dk1933.xml
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<osis xmlns="http://www.bibletechnologies.net/2003/OSIS/namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.bibletechnologies.net/2003/OSIS/namespace http://www.bibletechnologies.net/osisCore.2.1.1.xsd">
|
||||
<osisText osisIDWork="DanDetteBiblen" osisRefWork="defaultReferenceScheme" xml:lang="da">
|
||||
<header>
|
||||
<work osisWork="DanDetteBiblen">
|
||||
<title>Dette er Biblen</title>
|
||||
<identifier type="OSIS">Bible.DanDetteBiblen</identifier>
|
||||
<refSystem>Bible.KJV</refSystem>
|
||||
</work>
|
||||
<work osisWork="defaultReferenceScheme">
|
||||
<refSystem>Bible.KJV</refSystem>
|
||||
</work>
|
||||
</header>
|
||||
<div type="x-testament">
|
||||
<div type="book" osisID="Gen">
|
||||
<chapter osisID="Gen.1">
|
||||
<verse osisID="Gen.1.1">I Begyndelsen skabte Gud Himmelen og Jorden.</verse>
|
||||
<verse osisID="Gen.1.2">Og Jorden var øde og tom, og der var Mørke over Verdensdybet. Men Guds Ånd svævede over Vandene.<p /></verse>
|
||||
<verse osisID="Gen.1.3">Og Gud sagde: "Der blive Lys!" Og der blev Lys.</verse>
|
||||
<verse osisID="Gen.1.4">Og Gud så, at Lyset var godt, og Gud satte Skel mellem Lyset og Mørket,</verse>
|
||||
<verse osisID="Gen.1.5">og Gud kaldte Lyset Dag, og Mørket kaldte han Nat. Og det blev Aften, og det blev Morgen, første Dag.<p /></verse>
|
||||
<verse osisID="Gen.1.6">Derpå sagde Gud: "Der blive en Hvælving midt i Vandene til at skille Vandene ad!"</verse>
|
||||
<verse osisID="Gen.1.7">Og således skete det: Gud gjorde Hvælvingen og skilte Vandet under Hvælvingen fra Vandet over Hvælvingen;</verse>
|
||||
<verse osisID="Gen.1.8">og Gud kaldte Hvælvingen Himmel. Og det blev Aften, og det blev Morgen, anden Dag.<p /></verse>
|
||||
<verse osisID="Gen.1.9">Derpå sagde Gud: "Vandet under Himmelen samle sig på eet Sted, så det faste Land kommer til Syne!" Og således skete det;</verse>
|
||||
<verse osisID="Gen.1.10">og Gud kaldte det faste Land Jord, og Stedet, hvor Vandet samlede sig, kaldte han Hav. Og Gud så, at det var godt.</verse>
|
||||
</chapter>
|
||||
</div>
|
||||
</div>
|
||||
</osisText>
|
||||
</osis>
|
41
tests/resources/bibles/osis-kjv.xml
Normal file
41
tests/resources/bibles/osis-kjv.xml
Normal file
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<osis xmlns="http://www.bibletechnologies.net/2003/OSIS/namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.bibletechnologies.net/2003/OSIS/namespace http://www.bibletechnologies.net/osisCore.2.1.1.xsd">
|
||||
<osisText osisIDWork="KJV" osisRefWork="defaultReferenceScheme" xml:lang="en">
|
||||
<header>
|
||||
<work osisWork="KJV">
|
||||
<title>King James Version (1769) with Strongs Numbers and Morphology</title>
|
||||
<identifier type="OSIS">Bible.KJV</identifier>
|
||||
<scope>Gen-Rev</scope>
|
||||
<refSystem>Bible.KJV</refSystem>
|
||||
</work>
|
||||
<work osisWork="defaultReferenceScheme">
|
||||
<refSystem>Bible.KJV</refSystem>
|
||||
</work>
|
||||
<work osisWork="strong">
|
||||
<refSystem>Dict.Strongs</refSystem>
|
||||
</work>
|
||||
<work osisWork="robinson">
|
||||
<refSystem>Dict.Robinsons</refSystem>
|
||||
</work>
|
||||
<work osisWork="strongMorph">
|
||||
<refSystem>Dict.strongMorph</refSystem>
|
||||
</work>
|
||||
</header>
|
||||
<div type="book" osisID="Gen" canonical="true">
|
||||
<title type="main">THE FIRST BOOK OF MOSES CALLED GENESIS</title>
|
||||
<chapter osisID="Gen.1" chapterTitle="CHAPTER 1.">
|
||||
<title type="chapter">CHAPTER 1.</title>
|
||||
<verse osisID="Gen.1.1" sID="Gen.1.1"/><w lemma="strong:H07225">In the beginning</w> <w lemma="strong:H0430">God</w> <w morph="strongMorph:TH8804" lemma="strong:H0853 strong:H01254">created</w> <w lemma="strong:H08064">the heaven</w> <w lemma="strong:H0853">and</w> <w lemma="strong:H0776">the earth</w>.<verse eID="Gen.1.1"/>
|
||||
<verse osisID="Gen.1.2" sID="Gen.1.2"/><w lemma="strong:H0776">And the earth</w> <w morph="strongMorph:TH8804" lemma="strong:H01961">was</w> <w lemma="strong:H08414">without form</w>, <w lemma="strong:H0922">and void</w>; <w lemma="strong:H02822">and darkness</w> <transChange type="added">was</transChange> <w lemma="strong:H06440">upon the face</w> <w lemma="strong:H08415">of the deep</w>. <w lemma="strong:H07307">And the Spirit</w> <w lemma="strong:H0430">of God</w> <w morph="strongMorph:TH8764" lemma="strong:H07363">moved</w> <w lemma="strong:H05921">upon</w> <w lemma="strong:H06440">the face</w> <w lemma="strong:H04325">of the waters</w>.<verse eID="Gen.1.2"/>
|
||||
<verse osisID="Gen.1.3" sID="Gen.1.3"/><milestone type="x-extra-p"/><w lemma="strong:H0430">And God</w> <w morph="strongMorph:TH8799" lemma="strong:H0559">said</w>, <w morph="strongMorph:TH8799" lemma="strong:H01961">Let there be</w> <w lemma="strong:H0216">light</w>: <w lemma="strong:H0216">and there was light</w>.<verse eID="Gen.1.3"/>
|
||||
<verse osisID="Gen.1.4" sID="Gen.1.4"/><w lemma="strong:H0430">And God</w> <w morph="strongMorph:TH8799" lemma="strong:H0853 strong:H07200">saw</w> <w lemma="strong:H0216">the light</w>, <w lemma="strong:H03588">that</w> <transChange type="added">it was</transChange> <w lemma="strong:H02896">good</w>: <w lemma="strong:H0430">and God</w> <w morph="strongMorph:TH8686" lemma="strong:H0996 strong:H0914">divided</w> <w lemma="strong:H0216">the light</w> <w lemma="strong:H0996">from</w> <w lemma="strong:H02822">the darkness</w>.<note type="study">the light from…: Heb. between the light and between the darkness</note><verse eID="Gen.1.4"/>
|
||||
<verse osisID="Gen.1.5" sID="Gen.1.5"/><w lemma="strong:H0430">And God</w> <w morph="strongMorph:TH8799" lemma="strong:H07121">called</w> <w lemma="strong:H0216">the light</w> <w lemma="strong:H03117">Day</w>, <w lemma="strong:H02822">and the darkness</w> <w morph="strongMorph:TH8804" lemma="strong:H07121">he called</w> <w lemma="strong:H03915">Night</w>. <w lemma="strong:H06153">And the evening</w> <w lemma="strong:H01242">and the morning</w> <w lemma="strong:H0259">were the first</w> <w lemma="strong:H03117">day</w>.<note type="study">And the evening…: Heb. And the evening was, and the morning was etc.</note><verse eID="Gen.1.5"/>
|
||||
<verse osisID="Gen.1.6" sID="Gen.1.6"/><milestone type="x-p" marker="¶"/><w lemma="strong:H0430">And God</w> <w morph="strongMorph:TH8799" lemma="strong:H0559">said</w>, <w lemma="strong:H07549">Let there be a firmament</w> <w lemma="strong:H08432">in the midst</w> <w lemma="strong:H04325">of the waters</w>, <w morph="strongMorph:TH8688" lemma="strong:H0914">and let it divide</w> <w lemma="strong:H04325">the waters</w> <w lemma="strong:H04325">from the waters</w>.<note type="study">firmament: Heb. expansion</note><verse eID="Gen.1.6"/>
|
||||
<verse osisID="Gen.1.7" sID="Gen.1.7"/><w lemma="strong:H0430">And God</w> <w morph="strongMorph:TH8799" lemma="strong:H06213">made</w> <w lemma="strong:H07549">the firmament</w>, <w morph="strongMorph:TH8686" lemma="strong:H0914">and divided</w> <w lemma="strong:H04325">the waters</w> <w lemma="strong:H0834">which</w> <transChange type="added">were</transChange> <w lemma="strong:H08478">under</w> <w lemma="strong:H07549">the firmament</w> <w lemma="strong:H04325">from the waters</w> <w lemma="strong:H0834">which</w> <transChange type="added">were</transChange> <w lemma="strong:H05921">above</w> <w lemma="strong:H07549">the firmament</w>: <w lemma="strong:H03651">and it was so</w>.<verse eID="Gen.1.7"/>
|
||||
<verse osisID="Gen.1.8" sID="Gen.1.8"/><w lemma="strong:H0430">And God</w> <w morph="strongMorph:TH8799" lemma="strong:H07121">called</w> <w lemma="strong:H07549">the firmament</w> <w lemma="strong:H08064">Heaven</w>. <w lemma="strong:H06153">And the evening</w> <w lemma="strong:H01242">and the morning</w> <w lemma="strong:H08145">were the second</w> <w lemma="strong:H03117">day</w>.<note type="study">And the evening…: Heb. And the evening was, and the morning was etc.</note><verse eID="Gen.1.8"/>
|
||||
<verse osisID="Gen.1.9" sID="Gen.1.9"/><milestone type="x-p" marker="¶"/><w lemma="strong:H0430">And God</w> <w morph="strongMorph:TH8799" lemma="strong:H0559">said</w>, <w lemma="strong:H04325">Let the waters</w> <w lemma="strong:H08064">under the heaven</w> <w morph="strongMorph:TH8735" lemma="strong:H06960">be gathered together</w> <w lemma="strong:H0413">unto</w> <w lemma="strong:H0259">one</w> <w lemma="strong:H04725">place</w>, <w lemma="strong:H03004">and let the dry</w> <transChange type="added">land</transChange> <w morph="strongMorph:TH8735" lemma="strong:H07200">appear</w>: and it was so.<verse eID="Gen.1.9"/>
|
||||
<verse osisID="Gen.1.10" sID="Gen.1.10"/><w lemma="strong:H0430">And God</w> <w morph="strongMorph:TH8799" lemma="strong:H07121">called</w> <w lemma="strong:H03004">the dry</w> <transChange type="added">land</transChange> <w lemma="strong:H0776">Earth</w>; <w lemma="strong:H04723">and the gathering together</w> <w lemma="strong:H04325">of the waters</w> <w morph="strongMorph:TH8804" lemma="strong:H07121">called</w> <w lemma="strong:H03220">he Seas</w>: <w lemma="strong:H0430">and God</w> <w morph="strongMorph:TH8799" lemma="strong:H07200">saw</w> that <transChange type="added">it was</transChange> <w lemma="strong:H02896">good</w>.<verse eID="Gen.1.10"/>
|
||||
</chapter>
|
||||
</div>
|
||||
</osisText>
|
||||
</osis>
|
109
tests/resources/bibles/osis-web.xml
Normal file
109
tests/resources/bibles/osis-web.xml
Normal file
@ -0,0 +1,109 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<osis xmlns="http://www.bibletechnologies.net/2003/OSIS/namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.bibletechnologies.net/2003/OSIS/namespace osisCore.2.0.xsd">
|
||||
<osisText osisIDWork="WEB" osisRefWork="Bible" xml:lang="en">
|
||||
<header>
|
||||
<revisionDesc resp="Rainbow Missions, Inc.">
|
||||
<date>2007-08-26T08.23.41</date>
|
||||
<p> This draft version of the World English Bible is
|
||||
substantially complete in the New Testament, Genesis, Exodus, Job, Psalms, Proverbs, Ecclesiastes, Song of Solomon, and the “minor” prophets. Editing continues on the other books of the Old Testament. All WEB companion Apocrypha books are still in
|
||||
rough draft form. </p>
|
||||
<p>Converted web.gbf in GBF to web.osis.xml in
|
||||
an XML format that is mostly compliant with OSIS 2.0 using gbf2osis.exe.
|
||||
(Please see http://ebt.cx/translation/ for links to this software.)</p>
|
||||
<p>GBF and OSIS metadata fields do not exactly correspond to each other, so
|
||||
the conversion is not perfect in the metadata. However, the Scripture portion
|
||||
should be correct.</p>
|
||||
<p>No attempt was to convert quotation marks to structural markers using q or
|
||||
speech elements, because this would require language and style-dependent
|
||||
processing, and because the current OSIS specification is deficient in that
|
||||
quotation mark processing is not guaranteed to produce the correct results
|
||||
for all languages and translations. In English texts, the hard part of the
|
||||
conversion to markup is figuring out what ’ means.
|
||||
The other difficulty is that OSIS in no way guarantees that these punctuation
|
||||
marks would be reconstituted properly by software that reads OSIS files
|
||||
for anything other than modern English, and even then, it does not
|
||||
accommodate all styles of punctuation and all cases.
|
||||
We strongly recommend that anyone using OSIS NOT replace quotation mark
|
||||
punctuation in any existing text with q or speech elements. It is better
|
||||
for multiple language processing capabilities to leave the quotation
|
||||
punctuation as part of the text. If you need the q or speech markup, then you
|
||||
may supplement those punctuation marks with those markup elements, but specify
|
||||
the n='' parameter in those elements to indicate that no generation of any
|
||||
punctuation from those markup elements is required or desired. That way you
|
||||
can have BOTH correct punctuation already in the text AND markup so that you
|
||||
can automatically determine when you are in a quotation or not, independent
|
||||
of language. This may be useful for a search by speaker, for example.</p>
|
||||
<p>The output of gbf2osis marks Jesus' words in a non-standard way using the q
|
||||
element AND quotation marks if they were marked with FR/Fr markers in the GBF
|
||||
file. The OSIS 2.0 specification requires that quotation marks be stripped out,
|
||||
and reinserted by software that reads the OSIS files when q elements are used.
|
||||
This is not acceptable for the reasons given above, and we choose not to do
|
||||
that, but we used the q element with who='Jesus' to indicate Jesus' words.
|
||||
Do not generate any additional punctuation due to these markers. The correct
|
||||
punctuation is already in the text.</p>
|
||||
<p>OSIS does not currently support footnote start anchors. Therefore, these
|
||||
start anchors have been represented with milestone elements, in case someone
|
||||
might like to use them, for example, to start an href element in a conversion
|
||||
to HTML. (OSIS sort of supports the same idea by allowing a catchword to be
|
||||
defined within a footnote, but I did not implement the processing to convert
|
||||
to this different way of doing things, and it isn't exactly the same, anyway.)</p>
|
||||
<p>Traditional psalm book titles are rendered as text rather than titles, because
|
||||
the title element does not support containing transChange elements, as would be
|
||||
required to encode the KJV text using OSIS title elements. This may actually be
|
||||
a superior solution, anyway, in that the Masoretic text makes no such distinction
|
||||
(even though many modern typeset Bibles do make a typographic distinction in this
|
||||
case).</p>
|
||||
<p>The schema location headers were modified to use local copies rather than the
|
||||
standard locations so that these files could be validated and used without an
|
||||
Internet connection active at all times (very important for the developer's
|
||||
remote island location), but you may wish to change them back.</p>
|
||||
</revisionDesc>
|
||||
<work osisWork="WEB">
|
||||
<title>World English Bible</title>
|
||||
<creator>WEB committee</creator>
|
||||
<date event="eversion" type="Gregorian">2007-08-26</date>
|
||||
<publisher>Rainbow Missions, Inc.</publisher>
|
||||
<type type="OSIS">Bible</type>
|
||||
<identifier type="OSIS">Bible.en.WEB.draft.2007-08-26</identifier>
|
||||
<source>http://eBible.org/web/</source>
|
||||
<language type="SIL">ENG</language>
|
||||
<coverage>Wherever English is spoken in the world.</coverage>
|
||||
<rights>The World English Bible is dedicated to the Public Domain by the translators and editors. It is not copyrighted. “World English Bible” and the World English Bible logo are a trademarks of Rainbow
|
||||
Missions, Inc. They may only be used to identify this translation of the Holy Bible as published by Rainbow Missions, Inc., and faithful copies and quotations. “Faithful copies” include copies converted to other formats (i. e. HTML, PDF, etc.) or
|
||||
typeset differently, without altering the text of the Scriptures, except that changing the spellings between preferred American and British usage is allowed. Use of the markings of direct quotes of Jesus Christ for different rendition (i. e. red text)
|
||||
is optional. Comments and typo reports are welcome at http://eBible.org/cgi-bin/comment.cgi. Please see http://eBible.org/web/ for updates, revision status, free downloads, and printed edition purchase information.</rights>
|
||||
<scope>Gen-Mal</scope>
|
||||
<scope>Tob-AddEsth</scope>
|
||||
<scope>Bar-EpJer</scope>
|
||||
<scope>AddDan</scope>
|
||||
<scope>Matt-Rev</scope>
|
||||
<refSystem>Bible.WEB</refSystem>
|
||||
</work>
|
||||
</header>
|
||||
<div type="bookGroup" canonical="true">
|
||||
<div type="book" osisID="Gen" scope="Gen">
|
||||
<title type="main" short="Genesis">Genesis </title>
|
||||
<chapter sID="Gen.1" osisID="Gen.1" />
|
||||
<p>
|
||||
|
||||
<verse sID="Gen.1.1" osisID="Gen.1.1" />In the beginning <milestone type="x-noteStartAnchor" />God<note type="translation">The Hebrew word rendered “God” is “Elohim.” After “God,” the Hebrew has the two letters “Aleph Tav” (the first and last letters of the Hebrew alphabet) as a grammatical marker.</note> created the heavens and the earth.
|
||||
<verse eID="Gen.1.1" /><verse sID="Gen.1.2" osisID="Gen.1.2" />Now the earth was formless and empty. Darkness was on the surface of the deep. God’s Spirit was hovering over the surface of the waters.</p>
|
||||
<p>
|
||||
<verse eID="Gen.1.2" />
|
||||
<verse sID="Gen.1.3" osisID="Gen.1.3" />God said, “Let there be light,” and there was light.
|
||||
<verse eID="Gen.1.3" /><verse sID="Gen.1.4" osisID="Gen.1.4" />God saw the light, and saw that it was good. God divided the light from the darkness.
|
||||
<verse eID="Gen.1.4" /><verse sID="Gen.1.5" osisID="Gen.1.5" />God called the light “day,” and the darkness he called “night.” There was evening and there was morning, one day.</p>
|
||||
<p>
|
||||
<verse eID="Gen.1.5" />
|
||||
<verse sID="Gen.1.6" osisID="Gen.1.6" />God said, “Let there be an expanse in the middle of the waters, and let it divide the waters from the waters.”
|
||||
<verse eID="Gen.1.6" /><verse sID="Gen.1.7" osisID="Gen.1.7" />God made the expanse, and divided the waters which were under the expanse from the waters which were above the expanse; and it was so.
|
||||
<verse eID="Gen.1.7" /><verse sID="Gen.1.8" osisID="Gen.1.8" />God called the expanse “sky.” There was evening and there was morning, a second day.</p>
|
||||
<p>
|
||||
<verse eID="Gen.1.8" />
|
||||
<verse sID="Gen.1.9" osisID="Gen.1.9" />God said, “Let the waters under the sky be gathered together to one place, and let the dry land appear;” and it was so.
|
||||
<verse eID="Gen.1.9" /><verse sID="Gen.1.10" osisID="Gen.1.10" />God called the dry land “earth,” and the gathering together of the waters he called “seas.” God saw that it was good.
|
||||
<verse eID="Gen.1.10" /></p>
|
||||
</div>
|
||||
</div>
|
||||
</osisText>
|
||||
</osis>
|
16
tests/resources/bibles/web.json
Normal file
16
tests/resources/bibles/web.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"book": "Genesis",
|
||||
"chapter": "1",
|
||||
"verses": [
|
||||
[ "1", "In the beginning God created the heavens and the earth."],
|
||||
[ "2", "Now the earth was formless and empty. Darkness was on the surface of the deep. God’s Spirit was hovering over the surface of the waters." ],
|
||||
[ "3", "God said, “Let there be light,” and there was light." ],
|
||||
[ "4", "God saw the light, and saw that it was good. God divided the light from the darkness." ],
|
||||
[ "5", "God called the light “day,” and the darkness he called “night.” There was evening and there was morning, one day." ],
|
||||
[ "6", "God said, “Let there be an expanse in the middle of the waters, and let it divide the waters from the waters.”" ],
|
||||
[ "7", "God made the expanse, and divided the waters which were under the expanse from the waters which were above the expanse; and it was so." ],
|
||||
[ "8", "God called the expanse “sky.” There was evening and there was morning, a second day." ],
|
||||
[ "9", "God said, “Let the waters under the sky be gathered together to one place, and let the dry land appear;” and it was so." ],
|
||||
[ "10", "God called the dry land “earth,” and the gathering together of the waters he called “seas.” God saw that it was good." ]
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user