forked from openlp/openlp
head
This commit is contained in:
commit
8cc3f3b968
@ -30,7 +30,6 @@
|
||||
The :mod:`openlp` module contains all the project produced OpenLP functionality
|
||||
"""
|
||||
|
||||
import openlp.core
|
||||
import openlp.plugins
|
||||
from openlp import core, plugins
|
||||
|
||||
__all__ = ['core', 'plugins']
|
||||
|
@ -38,7 +38,7 @@ import traceback
|
||||
|
||||
from PyQt4 import QtCore
|
||||
|
||||
log = logging.getLogger(__name__+'.__init__')
|
||||
log = logging.getLogger(__name__ + '.__init__')
|
||||
|
||||
|
||||
FIRST_CAMEL_REGEX = re.compile('(.)([A-Z][a-z]+)')
|
||||
@ -51,8 +51,10 @@ def trace_error_handler(logger):
|
||||
|
||||
:param logger: logger to use so traceback is logged to correct class
|
||||
"""
|
||||
log_string = "OpenLP Error trace"
|
||||
for tb in traceback.extract_stack():
|
||||
logger.error('Called by ' + tb[3] + ' at line ' + str(tb[1]) + ' in ' + tb[0])
|
||||
log_string = '%s\n File %s at line %d \n\t called %s' % (log_string, tb[0], tb[1], tb[3])
|
||||
logger.error(log_string)
|
||||
|
||||
|
||||
def check_directory_exists(directory, do_not_log=False):
|
||||
@ -74,6 +76,9 @@ def check_directory_exists(directory, do_not_log=False):
|
||||
def get_frozen_path(frozen_option, non_frozen_option):
|
||||
"""
|
||||
Return a path based on the system status.
|
||||
|
||||
:param frozen_option:
|
||||
:param non_frozen_option:
|
||||
"""
|
||||
if hasattr(sys, 'frozen') and sys.frozen == 1:
|
||||
return frozen_option
|
||||
|
@ -39,7 +39,7 @@ from PyQt4 import QtCore, QtGui, Qt
|
||||
|
||||
from openlp.core.common import translate
|
||||
|
||||
log = logging.getLogger(__name__+'.__init__')
|
||||
log = logging.getLogger(__name__ + '.__init__')
|
||||
|
||||
|
||||
class ServiceItemContext(object):
|
||||
|
@ -168,29 +168,29 @@ class MediaManagerItem(QtGui.QWidget, RegistryProperties):
|
||||
Create buttons for the media item toolbar
|
||||
"""
|
||||
toolbar_actions = []
|
||||
## Import Button ##
|
||||
# Import Button
|
||||
if self.has_import_icon:
|
||||
toolbar_actions.append(['Import', StringContent.Import,
|
||||
':/general/general_import.png', self.on_import_click])
|
||||
## Load Button ##
|
||||
# Load Button
|
||||
if self.has_file_icon:
|
||||
toolbar_actions.append(['Load', StringContent.Load, ':/general/general_open.png', self.on_file_click])
|
||||
## New Button ##
|
||||
# New Button
|
||||
if self.has_new_icon:
|
||||
toolbar_actions.append(['New', StringContent.New, ':/general/general_new.png', self.on_new_click])
|
||||
## Edit Button ##
|
||||
# Edit Button
|
||||
if self.has_edit_icon:
|
||||
toolbar_actions.append(['Edit', StringContent.Edit, ':/general/general_edit.png', self.on_edit_click])
|
||||
## Delete Button ##
|
||||
# Delete Button
|
||||
if self.has_delete_icon:
|
||||
toolbar_actions.append(['Delete', StringContent.Delete,
|
||||
':/general/general_delete.png', self.on_delete_click])
|
||||
## Preview ##
|
||||
# Preview
|
||||
toolbar_actions.append(['Preview', StringContent.Preview,
|
||||
':/general/general_preview.png', self.on_preview_click])
|
||||
## Live Button ##
|
||||
# Live Button
|
||||
toolbar_actions.append(['Live', StringContent.Live, ':/general/general_live.png', self.on_live_click])
|
||||
## Add to service Button ##
|
||||
# Add to service Button
|
||||
toolbar_actions.append(['Service', StringContent.Service, ':/general/general_add.png', self.on_add_click])
|
||||
for action in toolbar_actions:
|
||||
if action[0] == StringContent.Preview:
|
||||
|
@ -101,7 +101,7 @@ class Plugin(QtCore.QObject, RegistryProperties):
|
||||
``add_import_menu_item(import_menu)``
|
||||
Add an item to the Import menu.
|
||||
|
||||
``add_export_menu_Item(export_menu)``
|
||||
``add_export_menu_item(export_menu)``
|
||||
Add an item to the Export menu.
|
||||
|
||||
``create_settings_tab()``
|
||||
@ -226,7 +226,7 @@ class Plugin(QtCore.QObject, RegistryProperties):
|
||||
"""
|
||||
pass
|
||||
|
||||
def add_export_menu_Item(self, export_menu):
|
||||
def add_export_menu_item(self, export_menu):
|
||||
"""
|
||||
Create a menu item and add it to the "Export" menu.
|
||||
|
||||
@ -329,22 +329,24 @@ class Plugin(QtCore.QObject, RegistryProperties):
|
||||
def set_plugin_ui_text_strings(self, tooltips):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
|
||||
:param tooltips:
|
||||
"""
|
||||
## Load Action ##
|
||||
# Load Action
|
||||
self.__set_name_text_string(StringContent.Load, UiStrings().Load, tooltips['load'])
|
||||
## Import Action ##
|
||||
# Import Action
|
||||
self.__set_name_text_string(StringContent.Import, UiStrings().Import, tooltips['import'])
|
||||
## New Action ##
|
||||
# New Action
|
||||
self.__set_name_text_string(StringContent.New, UiStrings().Add, tooltips['new'])
|
||||
## Edit Action ##
|
||||
# Edit Action
|
||||
self.__set_name_text_string(StringContent.Edit, UiStrings().Edit, tooltips['edit'])
|
||||
## Delete Action ##
|
||||
# Delete Action
|
||||
self.__set_name_text_string(StringContent.Delete, UiStrings().Delete, tooltips['delete'])
|
||||
## Preview Action ##
|
||||
# Preview Action
|
||||
self.__set_name_text_string(StringContent.Preview, UiStrings().Preview, tooltips['preview'])
|
||||
## Send Live Action ##
|
||||
# Send Live Action
|
||||
self.__set_name_text_string(StringContent.Live, UiStrings().Live, tooltips['live'])
|
||||
## Add to Service Action ##
|
||||
# Add to Service Action
|
||||
self.__set_name_text_string(StringContent.Service, UiStrings().Service, tooltips['service'])
|
||||
|
||||
def __set_name_text_string(self, name, title, tooltip):
|
||||
|
@ -161,7 +161,7 @@ class PluginManager(RegistryMixin, OpenLPMixin, RegistryProperties):
|
||||
"""
|
||||
for plugin in self.plugins:
|
||||
if plugin.status is not PluginStatus.Disabled:
|
||||
plugin.add_export_menu_Item(self.main_window.file_export_menu)
|
||||
plugin.add_export_menu_item(self.main_window.file_export_menu)
|
||||
|
||||
def hook_tools_menu(self):
|
||||
"""
|
||||
|
@ -178,15 +178,7 @@ class SearchEdit(QtGui.QLineEdit):
|
||||
correct action on the button, and set the current search type (using the list of identifiers provided by the
|
||||
developer), the ``searchTypeChanged(int)`` signal is emitted with the identifier.
|
||||
"""
|
||||
sender = self.sender()
|
||||
for action in self.menu_button.menu().actions():
|
||||
# Why is this needed?
|
||||
action.setChecked(False)
|
||||
self.menu_button.setDefaultAction(sender)
|
||||
self._current_search_type = sender.data()
|
||||
# setplaceholder_text has been implemented in Qt 4.7 and in at least
|
||||
# PyQt 4.9 (I am not sure, if it was implemented in PyQt 4.8).
|
||||
try:
|
||||
self.setPlaceholderText(self.menu_button.defaultAction().placeholder_text)
|
||||
except AttributeError:
|
||||
pass
|
||||
self.emit(QtCore.SIGNAL('searchTypeChanged(int)'), self._current_search_type)
|
||||
self.set_current_search_type(self.sender().data())
|
||||
|
@ -108,6 +108,9 @@ class ItemCapabilities(object):
|
||||
``CanAutoStartForLive``
|
||||
The capability to ignore the do not play if display blank flag.
|
||||
|
||||
``CanEditTitle``
|
||||
The capability to edit the title of the item
|
||||
|
||||
"""
|
||||
CanPreview = 1
|
||||
CanEdit = 2
|
||||
@ -125,6 +128,7 @@ class ItemCapabilities(object):
|
||||
CanWordSplit = 14
|
||||
HasBackgroundAudio = 15
|
||||
CanAutoStartForLive = 16
|
||||
CanEditTitle = 17
|
||||
|
||||
|
||||
class ServiceItem(RegistryProperties):
|
||||
@ -383,7 +387,7 @@ class ServiceItem(RegistryProperties):
|
||||
self.will_auto_start = header.get('will_auto_start', False)
|
||||
self.processor = header.get('processor', None)
|
||||
self.has_original_files = True
|
||||
#TODO Remove me in 2,3 build phase
|
||||
# TODO: Remove me in 2,3 build phase
|
||||
if self.is_capable(ItemCapabilities.HasDetailedTitleDisplay):
|
||||
self.capabilities.remove(ItemCapabilities.HasDetailedTitleDisplay)
|
||||
self.processor = self.title
|
||||
@ -423,7 +427,7 @@ class ServiceItem(RegistryProperties):
|
||||
"""
|
||||
Returns the title of the service item.
|
||||
"""
|
||||
if self.is_text():
|
||||
if self.is_text() or ItemCapabilities.CanEditTitle in self.capabilities:
|
||||
return self.title
|
||||
else:
|
||||
if len(self._raw_frames) > 1:
|
||||
|
@ -95,15 +95,15 @@ class Ui_ExceptionDialog(object):
|
||||
Translate the widgets on the fly.
|
||||
"""
|
||||
exception_dialog.setWindowTitle(translate('OpenLP.ExceptionDialog', 'Error Occurred'))
|
||||
self.description_explanation.setText(translate('OpenLP.ExceptionDialog',
|
||||
'Please enter a description of what you were doing to cause this error '
|
||||
'\n(Minimum 20 characters)'))
|
||||
self.message_label.setText(translate('OpenLP.ExceptionDialog', 'Oops! '
|
||||
'OpenLP hit a problem, and couldn\'t recover. The text in the box '
|
||||
'below contains information that might be helpful to the OpenLP '
|
||||
'developers, so please e-mail it to bugs@openlp.org, along with a '
|
||||
'detailed description of what you were doing when the problem '
|
||||
'occurred.'))
|
||||
self.description_explanation.setText(
|
||||
translate('OpenLP.ExceptionDialog', 'Please enter a description of what you were doing to cause this error '
|
||||
'\n(Minimum 20 characters)'))
|
||||
self.message_label.setText(
|
||||
translate('OpenLP.ExceptionDialog', 'Oops! OpenLP hit a problem, and couldn\'t recover. The text in the '
|
||||
'box below contains information that might be helpful to the OpenLP '
|
||||
'developers, so please e-mail it to bugs@openlp.org, along with a '
|
||||
'detailed description of what you were doing when the problem '
|
||||
'occurred.'))
|
||||
self.send_report_button.setText(translate('OpenLP.ExceptionDialog', 'Send E-Mail'))
|
||||
self.save_report_button.setText(translate('OpenLP.ExceptionDialog', 'Save to File'))
|
||||
self.attach_tile_button.setText(translate('OpenLP.ExceptionDialog', 'Attach File'))
|
||||
|
@ -211,9 +211,9 @@ class Ui_FirstTimeWizard(object):
|
||||
first_time_wizard.setWindowTitle(translate('OpenLP.FirstTimeWizard', 'First Time Wizard'))
|
||||
self.title_label.setText('<span style="font-size:14pt; font-weight:600;">%s</span>' %
|
||||
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.'))
|
||||
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.'))
|
||||
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'))
|
||||
|
@ -63,7 +63,6 @@ class FormattingTagForm(QtGui.QDialog, Ui_FormattingTagDialog, FormattingTagCont
|
||||
self.services = FormattingTagController()
|
||||
self.tag_table_widget.itemSelectionChanged.connect(self.on_row_selected)
|
||||
self.new_button.clicked.connect(self.on_new_clicked)
|
||||
#self.save_button.clicked.connect(self.on_saved_clicked)
|
||||
self.delete_button.clicked.connect(self.on_delete_clicked)
|
||||
self.tag_table_widget.currentCellChanged.connect(self.on_current_cell_changed)
|
||||
self.button_box.rejected.connect(self.close)
|
||||
@ -202,5 +201,4 @@ class FormattingTagForm(QtGui.QDialog, Ui_FormattingTagDialog, FormattingTagCont
|
||||
if errors:
|
||||
QtGui.QMessageBox.warning(self, translate('OpenLP.FormattingTagForm', 'Validation Error'), errors,
|
||||
QtGui.QMessageBox.Ok)
|
||||
#self.tag_table_widget.selectRow(pre_row - 1)
|
||||
self.tag_table_widget.resizeRowsToContents()
|
||||
|
@ -56,29 +56,27 @@ from openlp.core.ui.firsttimeform import FirstTimeForm
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
MEDIA_MANAGER_STYLE = """
|
||||
QToolBox {
|
||||
QToolBox {
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
QToolBox::tab {
|
||||
}
|
||||
QToolBox::tab {
|
||||
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
|
||||
stop: 0 palette(button), stop: 0.5 palette(button),
|
||||
stop: 1.0 palette(mid));
|
||||
border: 1px groove palette(mid);
|
||||
border-radius: 5px;
|
||||
}
|
||||
QToolBox::tab:selected {
|
||||
stop: 0 palette(button), stop: 1.0 palette(mid));
|
||||
border: 1px solid palette(mid);
|
||||
border-radius: 3px;
|
||||
}
|
||||
QToolBox::tab:selected {
|
||||
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
|
||||
stop: 0 palette(light), stop: 0.5 palette(midlight),
|
||||
stop: 1.0 palette(dark));
|
||||
border: 1px groove palette(dark);
|
||||
stop: 0 palette(light), stop: 1.0 palette(button));
|
||||
border: 1px solid palette(mid);
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
PROGRESSBAR_STYLE = """
|
||||
QProgressBar{
|
||||
height: 10px;
|
||||
}
|
||||
QProgressBar{
|
||||
height: 10px;
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
@ -369,7 +367,7 @@ class Ui_MainWindow(object):
|
||||
self.settings_menu.setTitle(translate('OpenLP.MainWindow', '&Settings'))
|
||||
self.settings_language_menu.setTitle(translate('OpenLP.MainWindow', '&Language'))
|
||||
self.help_menu.setTitle(translate('OpenLP.MainWindow', '&Help'))
|
||||
self.media_manager_dock.setWindowTitle(translate('OpenLP.MainWindow', 'Media Manager'))
|
||||
self.media_manager_dock.setWindowTitle(translate('OpenLP.MainWindow', 'Library'))
|
||||
self.service_manager_dock.setWindowTitle(translate('OpenLP.MainWindow', 'Service Manager'))
|
||||
self.theme_manager_dock.setWindowTitle(translate('OpenLP.MainWindow', 'Theme Manager'))
|
||||
self.file_new_item.setText(translate('OpenLP.MainWindow', '&New'))
|
||||
@ -396,12 +394,12 @@ class Ui_MainWindow(object):
|
||||
self.settings_shortcuts_item.setText(translate('OpenLP.MainWindow', 'Configure &Shortcuts...'))
|
||||
self.formatting_tag_item.setText(translate('OpenLP.MainWindow', 'Configure &Formatting Tags...'))
|
||||
self.settings_configure_item.setText(translate('OpenLP.MainWindow', '&Configure OpenLP...'))
|
||||
self.settings_export_item.setStatusTip(translate('OpenLP.MainWindow',
|
||||
'Export OpenLP settings to a specified *.config file'))
|
||||
self.settings_export_item.setStatusTip(
|
||||
translate('OpenLP.MainWindow', 'Export OpenLP settings to a specified *.config file'))
|
||||
self.settings_export_item.setText(translate('OpenLP.MainWindow', 'Settings'))
|
||||
self.settings_import_item.setStatusTip(translate('OpenLP.MainWindow',
|
||||
'Import OpenLP settings from a specified *.config file previously '
|
||||
'exported on this or another machine'))
|
||||
self.settings_import_item.setStatusTip(
|
||||
translate('OpenLP.MainWindow', 'Import OpenLP settings from a specified *.config file previously '
|
||||
'exported on this or another machine'))
|
||||
self.settings_import_item.setText(translate('OpenLP.MainWindow', 'Settings'))
|
||||
self.view_media_manager_item.setText(translate('OpenLP.MainWindow', '&Media Manager'))
|
||||
self.view_media_manager_item.setToolTip(translate('OpenLP.MainWindow', 'Toggle Media Manager'))
|
||||
@ -598,13 +596,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow, RegistryProperties):
|
||||
self.live_controller.display.setFocus()
|
||||
self.activateWindow()
|
||||
if self.arguments:
|
||||
args = []
|
||||
for a in self.arguments:
|
||||
args.extend([a])
|
||||
filename = args[0]
|
||||
if not isinstance(filename, str):
|
||||
filename = str(filename, sys.getfilesystemencoding())
|
||||
self.service_manager_contents.load_file(filename)
|
||||
self.open_cmd_line_files()
|
||||
elif Settings().value(self.general_settings_section + '/auto open'):
|
||||
self.service_manager_contents.load_Last_file()
|
||||
self.timer_version_id = self.startTimer(1000)
|
||||
@ -652,7 +644,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow, RegistryProperties):
|
||||
translate('OpenLP.MainWindow', 'Are you sure you want to re-run the First '
|
||||
'Time Wizard?\n\nRe-running this wizard may make changes to your '
|
||||
'current OpenLP configuration and possibly add songs to your '
|
||||
'#existing songs list and change your default theme.'),
|
||||
'existing songs list and change your default theme.'),
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes |
|
||||
QtGui.QMessageBox.No),
|
||||
QtGui.QMessageBox.No)
|
||||
@ -868,7 +860,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow, RegistryProperties):
|
||||
section = 'general'
|
||||
section_key = section + "/" + key
|
||||
# Make sure it's a valid section for us.
|
||||
if not section in setting_sections:
|
||||
if section not in setting_sections:
|
||||
continue
|
||||
# We have a good file, import it.
|
||||
for section_key in import_keys:
|
||||
@ -1364,3 +1356,17 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow, RegistryProperties):
|
||||
if self.new_data_path == AppLocation.get_directory(AppLocation.DataDir):
|
||||
settings.remove('advanced/data path')
|
||||
self.application.set_normal_cursor()
|
||||
|
||||
def open_cmd_line_files(self):
|
||||
"""
|
||||
Open files passed in through command line arguments
|
||||
"""
|
||||
args = []
|
||||
for a in self.arguments:
|
||||
args.extend([a])
|
||||
for arg in args:
|
||||
filename = arg
|
||||
if not isinstance(filename, str):
|
||||
filename = str(filename, sys.getfilesystemencoding())
|
||||
if filename.endswith(('.osz', '.oszl')):
|
||||
self.service_manager_contents.load_file(filename)
|
||||
|
@ -35,7 +35,7 @@ from openlp.core.common import Settings
|
||||
|
||||
from PyQt4 import QtCore
|
||||
|
||||
log = logging.getLogger(__name__+'.__init__')
|
||||
log = logging.getLogger(__name__ + '.__init__')
|
||||
|
||||
|
||||
class MediaState(object):
|
||||
|
@ -137,7 +137,7 @@ class MediaController(RegistryMixin, OpenLPMixin, RegistryProperties):
|
||||
for player in list(self.media_players.values()):
|
||||
if player.is_active:
|
||||
for item in player.audio_extensions_list:
|
||||
if not item in self.audio_extensions_list:
|
||||
if item not in self.audio_extensions_list:
|
||||
self.audio_extensions_list.append(item)
|
||||
suffix_list.append(item[2:])
|
||||
self.video_extensions_list = []
|
||||
@ -184,8 +184,8 @@ class MediaController(RegistryMixin, OpenLPMixin, RegistryProperties):
|
||||
return False
|
||||
saved_players, overridden_player = get_media_players()
|
||||
invalid_media_players = \
|
||||
[mediaPlayer for mediaPlayer in saved_players if not mediaPlayer in self.media_players or
|
||||
not self.media_players[mediaPlayer].check_available()]
|
||||
[media_player for media_player in saved_players if media_player not in self.media_players or
|
||||
not self.media_players[media_player].check_available()]
|
||||
if invalid_media_players:
|
||||
for invalidPlayer in invalid_media_players:
|
||||
saved_players.remove(invalidPlayer)
|
||||
|
66
openlp/core/ui/media/vendor/vlc.py
vendored
66
openlp/core/ui/media/vendor/vlc.py
vendored
@ -48,13 +48,13 @@ import sys
|
||||
from inspect import getargspec
|
||||
|
||||
__version__ = "N/A"
|
||||
build_date = "Mon Apr 1 23:47:38 2013"
|
||||
build_date = "Tue Jul 2 10:35:53 2013"
|
||||
|
||||
if sys.version_info[0] > 2:
|
||||
str = str
|
||||
str = str
|
||||
unicode = str
|
||||
bytes = bytes
|
||||
str = (str, bytes)
|
||||
basestring = (str, bytes)
|
||||
PYTHON3 = True
|
||||
def str_to_bytes(s):
|
||||
"""Translate string or bytes to bytes.
|
||||
@ -73,14 +73,14 @@ if sys.version_info[0] > 2:
|
||||
return b
|
||||
else:
|
||||
str = str
|
||||
str = str
|
||||
unicode = unicode
|
||||
bytes = str
|
||||
str = str
|
||||
basestring = basestring
|
||||
PYTHON3 = False
|
||||
def str_to_bytes(s):
|
||||
"""Translate string or bytes to bytes.
|
||||
"""
|
||||
if isinstance(s, str):
|
||||
if isinstance(s, unicode):
|
||||
return s.encode(sys.getfilesystemencoding())
|
||||
else:
|
||||
return s
|
||||
@ -89,7 +89,7 @@ else:
|
||||
"""Translate bytes to unicode string.
|
||||
"""
|
||||
if isinstance(b, str):
|
||||
return str(b, sys.getfilesystemencoding())
|
||||
return unicode(b, sys.getfilesystemencoding())
|
||||
else:
|
||||
return b
|
||||
|
||||
@ -110,7 +110,7 @@ def find_lib():
|
||||
p = find_library('libvlc.dll')
|
||||
if p is None:
|
||||
try: # some registry settings
|
||||
import winreg as w # leaner than win32api, win32con
|
||||
import _winreg as w # leaner than win32api, win32con
|
||||
for r in w.HKEY_LOCAL_MACHINE, w.HKEY_CURRENT_USER:
|
||||
try:
|
||||
r = w.OpenKey(r, 'Software\\VideoLAN\\VLC')
|
||||
@ -168,7 +168,7 @@ class VLCException(Exception):
|
||||
pass
|
||||
|
||||
try:
|
||||
_Ints = (int, int)
|
||||
_Ints = (int, long)
|
||||
except NameError: # no long in Python 3+
|
||||
_Ints = int
|
||||
_Seqs = (list, tuple)
|
||||
@ -327,6 +327,9 @@ class _Enum(ctypes.c_uint):
|
||||
n = self._enum_names_.get(self.value, '') or ('FIXME_(%r)' % (self.value,))
|
||||
return '.'.join((self.__class__.__name__, n))
|
||||
|
||||
def __hash__(self):
|
||||
return self.value
|
||||
|
||||
def __repr__(self):
|
||||
return '.'.join((self.__class__.__module__, self.__str__()))
|
||||
|
||||
@ -1294,7 +1297,7 @@ class Instance(_Ctype):
|
||||
i = args[0]
|
||||
if isinstance(i, _Ints):
|
||||
return _Constructor(cls, i)
|
||||
elif isinstance(i, str):
|
||||
elif isinstance(i, basestring):
|
||||
args = i.strip().split()
|
||||
elif isinstance(i, _Seqs):
|
||||
args = i
|
||||
@ -2078,7 +2081,7 @@ class MediaList(_Ctype):
|
||||
@param mrl: a media instance or a MRL.
|
||||
@return: 0 on success, -1 if the media list is read-only.
|
||||
"""
|
||||
if isinstance(mrl, str):
|
||||
if isinstance(mrl, basestring):
|
||||
mrl = (self.get_instance() or get_default_instance()).media_new(mrl)
|
||||
return libvlc_media_list_add_media(self, mrl)
|
||||
|
||||
@ -3351,6 +3354,39 @@ def libvlc_event_type_name(event_type):
|
||||
ctypes.c_char_p, ctypes.c_uint)
|
||||
return f(event_type)
|
||||
|
||||
def libvlc_log_get_context(ctx):
|
||||
'''Gets debugging informations about a log message: the name of the VLC module
|
||||
emitting the message and the message location within the source code.
|
||||
The returned module name and file name will be NULL if unknown.
|
||||
The returned line number will similarly be zero if unknown.
|
||||
@param ctx: message context (as passed to the @ref libvlc_log_cb callback).
|
||||
@return: module module name storage (or NULL), file source code file name storage (or NULL), line source code file line number storage (or NULL).
|
||||
@version: LibVLC 2.1.0 or later.
|
||||
'''
|
||||
f = _Cfunctions.get('libvlc_log_get_context', None) or \
|
||||
_Cfunction('libvlc_log_get_context', ((1,), (2,), (2,), (2,),), None,
|
||||
None, Log_ptr, ListPOINTER(ctypes.c_char_p), ListPOINTER(ctypes.c_char_p), ctypes.POINTER(ctypes.c_uint))
|
||||
return f(ctx)
|
||||
|
||||
def libvlc_log_get_object(ctx, id):
|
||||
'''Gets VLC object informations about a log message: the type name of the VLC
|
||||
object emitting the message, the object header if any and a temporaly-unique
|
||||
object identifier. These informations are mainly meant for B{manual}
|
||||
troubleshooting.
|
||||
The returned type name may be "generic" if unknown, but it cannot be NULL.
|
||||
The returned header will be NULL if unset; in current versions, the header
|
||||
is used to distinguish for VLM inputs.
|
||||
The returned object ID will be zero if the message is not associated with
|
||||
any VLC object.
|
||||
@param ctx: message context (as passed to the @ref libvlc_log_cb callback).
|
||||
@return: name object name storage (or NULL), header object header (or NULL), line source code file line number storage (or NULL).
|
||||
@version: LibVLC 2.1.0 or later.
|
||||
'''
|
||||
f = _Cfunctions.get('libvlc_log_get_object', None) or \
|
||||
_Cfunction('libvlc_log_get_object', ((1,), (2,), (2,), (1,),), None,
|
||||
None, Log_ptr, ListPOINTER(ctypes.c_char_p), ListPOINTER(ctypes.c_char_p), ctypes.POINTER(ctypes.c_uint))
|
||||
return f(ctx, id)
|
||||
|
||||
def libvlc_log_unset(p_instance):
|
||||
'''Unsets the logging callback for a LibVLC instance. This is rarely needed:
|
||||
the callback is implicitly unset when the instance is destroyed.
|
||||
@ -5827,7 +5863,7 @@ def libvlc_vlm_get_event_manager(p_instance):
|
||||
# libvlc_printerr
|
||||
# libvlc_set_exit_handler
|
||||
|
||||
# 15 function(s) not wrapped as methods:
|
||||
# 17 function(s) not wrapped as methods:
|
||||
# libvlc_audio_output_device_list_release
|
||||
# libvlc_audio_output_list_release
|
||||
# libvlc_clearerr
|
||||
@ -5838,6 +5874,8 @@ def libvlc_vlm_get_event_manager(p_instance):
|
||||
# libvlc_get_changeset
|
||||
# libvlc_get_compiler
|
||||
# libvlc_get_version
|
||||
# libvlc_log_get_context
|
||||
# libvlc_log_get_object
|
||||
# libvlc_media_tracks_release
|
||||
# libvlc_module_description_list_release
|
||||
# libvlc_new
|
||||
@ -5910,9 +5948,9 @@ def debug_callback(event, *args, **kwds):
|
||||
'''
|
||||
l = ['event %s' % (event.type,)]
|
||||
if args:
|
||||
l.extend(list(map(str, args)))
|
||||
l.extend(map(str, args))
|
||||
if kwds:
|
||||
l.extend(sorted('%s=%s' % t for t in list(kwds.items())))
|
||||
l.extend(sorted('%s=%s' % t for t in kwds.items()))
|
||||
print('Debug callback (%s)' % ', '.join(l))
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -174,34 +174,11 @@ FLASH_HTML = """
|
||||
<div id="flash" class="size" style="visibility:hidden"></div>
|
||||
"""
|
||||
|
||||
VIDEO_EXT = [
|
||||
'*.3gp',
|
||||
'*.3gpp',
|
||||
'*.3g2',
|
||||
'*.3gpp2',
|
||||
'*.aac',
|
||||
'*.flv',
|
||||
'*.f4a',
|
||||
'*.f4b',
|
||||
'*.f4p',
|
||||
'*.f4v',
|
||||
'*.mov',
|
||||
'*.m4a',
|
||||
'*.m4b',
|
||||
'*.m4p',
|
||||
'*.m4v',
|
||||
'*.mkv',
|
||||
'*.mp4',
|
||||
'*.ogv',
|
||||
'*.webm',
|
||||
'*.mpg', '*.wmv', '*.mpeg', '*.avi',
|
||||
'*.swf'
|
||||
]
|
||||
VIDEO_EXT = ['*.3gp', '*.3gpp', '*.3g2', '*.3gpp2', '*.aac', '*.flv', '*.f4a', '*.f4b', '*.f4p', '*.f4v', '*.mov',
|
||||
'*.m4a', '*.m4b', '*.m4p', '*.m4v', '*.mkv', '*.mp4', '*.ogv', '*.webm', '*.mpg', '*.wmv', '*.mpeg',
|
||||
'*.avi', '*.swf']
|
||||
|
||||
AUDIO_EXT = [
|
||||
'*.mp3',
|
||||
'*.ogg'
|
||||
]
|
||||
AUDIO_EXT = ['*.mp3', '*.ogg']
|
||||
|
||||
|
||||
class WebkitPlayer(MediaPlayer):
|
||||
@ -411,10 +388,9 @@ class WebkitPlayer(MediaPlayer):
|
||||
"""
|
||||
Return some information about this player
|
||||
"""
|
||||
return(translate('Media.player', 'Webkit is a media player which runs '
|
||||
'inside a web browser. This player allows text over video to be '
|
||||
'rendered.') +
|
||||
'<br/> <strong>' + translate('Media.player', 'Audio') +
|
||||
'</strong><br/>' + str(AUDIO_EXT) + '<br/><strong>' +
|
||||
translate('Media.player', 'Video') + '</strong><br/>' +
|
||||
str(VIDEO_EXT) + '<br/>')
|
||||
part1 = translate('Media.player', 'Webkit is a media player which runs inside a web browser. This player '
|
||||
'allows text over video to be rendered.')
|
||||
part2 = translate('Media.player', 'Audio')
|
||||
part3 = translate('Media.player', 'Video')
|
||||
return part1 + '<br/> <strong>' + part2 + '</strong><br/>' + str(AUDIO_EXT) + '<br/><strong>' + part3 + \
|
||||
'</strong><br/>' + str(VIDEO_EXT) + '<br/>'
|
||||
|
@ -234,6 +234,8 @@ class Ui_ServiceManager(object):
|
||||
self.menu = QtGui.QMenu()
|
||||
self.edit_action = create_widget_action(self.menu, text=translate('OpenLP.ServiceManager', '&Edit Item'),
|
||||
icon=':/general/general_edit.png', triggers=self.remote_edit)
|
||||
self.rename_action = create_widget_action(self.menu, text=translate('OpenLP.ServiceManager', '&Rename...'),
|
||||
icon=':/general/general_edit.png', triggers=self.on_service_item_rename)
|
||||
self.maintain_action = create_widget_action(self.menu, text=translate('OpenLP.ServiceManager', '&Reorder Item'),
|
||||
icon=':/general/general_edit.png',
|
||||
triggers=self.on_service_item_edit_form)
|
||||
@ -399,7 +401,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
|
||||
:param suffix_list: New Suffix's to be supported
|
||||
"""
|
||||
for suffix in suffix_list:
|
||||
if not suffix in self.suffixes:
|
||||
if suffix not in self.suffixes:
|
||||
self.suffixes.append(suffix)
|
||||
|
||||
def on_new_service_clicked(self, field=None):
|
||||
@ -629,7 +631,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
|
||||
for item in self.service_items:
|
||||
self.main_window.increment_progress_bar()
|
||||
service_item = item['service_item'].get_service_repr(self._save_lite)
|
||||
#TODO: check for file item on save.
|
||||
# TODO: check for file item on save.
|
||||
service.append({'serviceitem': service_item})
|
||||
self.main_window.increment_progress_bar()
|
||||
service_content = json.dumps(service)
|
||||
@ -754,8 +756,9 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
|
||||
items = json.load(file_to)
|
||||
else:
|
||||
critical_error_message_box(message=translate('OpenLP.ServiceManager',
|
||||
'The service file you are trying to open is in an old format.\n '
|
||||
'Please save it using OpenLP 2.0.2 or greater.'))
|
||||
'The service file you are trying to open is in an old '
|
||||
'format.\n Please save it using OpenLP 2.0.2 or '
|
||||
'greater.'))
|
||||
return
|
||||
file_to.close()
|
||||
self.new_file()
|
||||
@ -848,6 +851,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
|
||||
pos = item.data(0, QtCore.Qt.UserRole)
|
||||
service_item = self.service_items[pos - 1]
|
||||
self.edit_action.setVisible(False)
|
||||
self.rename_action.setVisible(False)
|
||||
self.create_custom_action.setVisible(False)
|
||||
self.maintain_action.setVisible(False)
|
||||
self.notes_action.setVisible(False)
|
||||
@ -855,6 +859,8 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
|
||||
self.auto_start_action.setVisible(False)
|
||||
if service_item['service_item'].is_capable(ItemCapabilities.CanEdit) and service_item['service_item'].edit_id:
|
||||
self.edit_action.setVisible(True)
|
||||
if service_item['service_item'].is_capable(ItemCapabilities.CanEditTitle):
|
||||
self.rename_action.setVisible(True)
|
||||
if service_item['service_item'].is_capable(ItemCapabilities.CanMaintain):
|
||||
self.maintain_action.setVisible(True)
|
||||
if item.parent() is None:
|
||||
@ -1482,6 +1488,22 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
|
||||
if new_item:
|
||||
self.add_service_item(new_item, replace=True)
|
||||
|
||||
def on_service_item_rename(self):
|
||||
"""
|
||||
Opens a dialog to rename the service item.
|
||||
"""
|
||||
item = self.find_service_item()[0]
|
||||
if not self.service_items[item]['service_item'].is_capable(ItemCapabilities.CanEditTitle):
|
||||
return
|
||||
title = self.service_items[item]['service_item'].title
|
||||
title, ok = QtGui.QInputDialog.getText(self, translate('OpenLP.ServiceManager', 'Rename item title'),
|
||||
translate('OpenLP.ServiceManager', 'Title:'),
|
||||
QtGui.QLineEdit.Normal, self.trUtf8(title))
|
||||
if ok:
|
||||
self.service_items[item]['service_item'].title = title
|
||||
self.repaint_service_list(item, -1)
|
||||
self.set_modified()
|
||||
|
||||
def create_custom(self, field=None):
|
||||
"""
|
||||
Saves the current text item as a custom slide
|
||||
|
@ -150,5 +150,5 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog, RegistryProperties):
|
||||
|
||||
:param function: The function to be called
|
||||
"""
|
||||
if not function in self.processes:
|
||||
if function not in self.processes:
|
||||
self.processes.append(function)
|
||||
|
@ -1039,7 +1039,6 @@ class SlideController(DisplayController, RegistryProperties):
|
||||
"""
|
||||
self.preview_widget.change_slide(row)
|
||||
self.update_preview()
|
||||
Registry().execute('slidecontroller_%s_changed' % self.type_prefix, row)
|
||||
|
||||
def update_preview(self):
|
||||
"""
|
||||
|
@ -44,7 +44,6 @@ class Ui_ThemeLayoutDialog(object):
|
||||
Set up the UI
|
||||
"""
|
||||
themeLayoutDialog.setObjectName('themeLayoutDialogDialog')
|
||||
#themeLayoutDialog.resize(300, 200)
|
||||
self.preview_layout = QtGui.QVBoxLayout(themeLayoutDialog)
|
||||
self.preview_layout.setObjectName('preview_layout')
|
||||
self.preview_area = QtGui.QWidget(themeLayoutDialog)
|
||||
|
@ -114,17 +114,19 @@ class ThemesTab(SettingsTab):
|
||||
self.global_group_box.setTitle(translate('OpenLP.ThemesTab', 'Global Theme'))
|
||||
self.level_group_box.setTitle(translate('OpenLP.ThemesTab', 'Theme Level'))
|
||||
self.song_level_radio_button.setText(translate('OpenLP.ThemesTab', 'S&ong Level'))
|
||||
self.song_level_label.setText(translate('OpenLP.ThemesTab', 'Use the theme from each song '
|
||||
'in the database. If a song doesn\'t have a theme associated with '
|
||||
'it, then use the service\'s theme. If the service doesn\'t have '
|
||||
'a theme, then use the global theme.'))
|
||||
self.song_level_label.setText(
|
||||
translate('OpenLP.ThemesTab', 'Use the theme from each song in the database. If a song doesn\'t have a '
|
||||
'theme associated with it, then use the service\'s theme. If the service '
|
||||
'doesn\'t have a theme, then use the global theme.'))
|
||||
self.service_level_radio_button.setText(translate('OpenLP.ThemesTab', '&Service Level'))
|
||||
self.service_level_label.setText(translate('OpenLP.ThemesTab', 'Use the theme from the service, '
|
||||
'overriding any of the individual songs\' themes. If the '
|
||||
'service doesn\'t have a theme, then use the global theme.'))
|
||||
self.service_level_label.setText(
|
||||
translate('OpenLP.ThemesTab', 'Use the theme from the service, overriding any of the individual '
|
||||
'songs\' themes. If the service doesn\'t have a theme, then use the global '
|
||||
'theme.'))
|
||||
self.global_level_radio_button.setText(translate('OpenLP.ThemesTab', '&Global Level'))
|
||||
self.global_level_label.setText(translate('OpenLP.ThemesTab', 'Use the global theme, overriding '
|
||||
'any themes associated with either the service or the songs.'))
|
||||
self.global_level_label.setText(translate('OpenLP.ThemesTab', 'Use the global theme, overriding any themes '
|
||||
'associated with either the service or the '
|
||||
'songs.'))
|
||||
|
||||
def load(self):
|
||||
"""
|
||||
|
@ -56,7 +56,7 @@ if sys.platform != 'win32' and sys.platform != 'darwin':
|
||||
|
||||
from openlp.core.common import translate
|
||||
|
||||
log = logging.getLogger(__name__+'.__init__')
|
||||
log = logging.getLogger(__name__ + '.__init__')
|
||||
|
||||
APPLICATION_VERSION = {}
|
||||
IMAGES_FILTER = None
|
||||
|
@ -74,7 +74,7 @@ class LanguageManager(object):
|
||||
log.debug('Translation files: %s', AppLocation.get_directory(
|
||||
AppLocation.LanguageDir))
|
||||
trans_dir = QtCore.QDir(AppLocation.get_directory(AppLocation.LanguageDir))
|
||||
file_names = trans_dir.entryList('*.qm', QtCore.QDir.Files, QtCore.QDir.Name)
|
||||
file_names = trans_dir.entryList(['*.qm'], QtCore.QDir.Files, QtCore.QDir.Name)
|
||||
# Remove qm files from the list which start with "qt_".
|
||||
file_names = [file_ for file_ in file_names if not file_.startswith('qt_')]
|
||||
return list(map(trans_dir.filePath, file_names))
|
||||
|
@ -207,12 +207,12 @@ class AlertsPlugin(Plugin):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
"""
|
||||
## Name PluginList ##
|
||||
# Name PluginList
|
||||
self.text_strings[StringContent.Name] = {
|
||||
'singular': translate('AlertsPlugin', 'Alert', 'name singular'),
|
||||
'plural': translate('AlertsPlugin', 'Alerts', 'name plural')
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
# Name for MediaDockManager, SettingsManager
|
||||
self.text_strings[StringContent.VisibleName] = {
|
||||
'title': translate('AlertsPlugin', 'Alerts', 'container title')
|
||||
}
|
||||
|
@ -88,8 +88,6 @@ class BiblePlugin(Plugin):
|
||||
self.import_bible_item.setVisible(True)
|
||||
action_list = ActionList.get_instance()
|
||||
action_list.add_action(self.import_bible_item, UiStrings().Import)
|
||||
# Do not add the action to the list yet.
|
||||
#action_list.add_action(self.export_bible_item, UiStrings().Export)
|
||||
# Set to invisible until we can export bibles
|
||||
self.export_bible_item.setVisible(False)
|
||||
self.tools_upgrade_item.setVisible(bool(self.manager.old_bible_databases))
|
||||
@ -104,7 +102,6 @@ class BiblePlugin(Plugin):
|
||||
action_list = ActionList.get_instance()
|
||||
action_list.remove_action(self.import_bible_item, UiStrings().Import)
|
||||
self.import_bible_item.setVisible(False)
|
||||
#action_list.remove_action(self.export_bible_item, UiStrings().Export)
|
||||
self.export_bible_item.setVisible(False)
|
||||
|
||||
def app_startup(self):
|
||||
@ -115,19 +112,27 @@ class BiblePlugin(Plugin):
|
||||
if self.manager.old_bible_databases:
|
||||
if QtGui.QMessageBox.information(
|
||||
self.main_window, translate('OpenLP', 'Information'),
|
||||
translate('OpenLP', 'Bible format has changed.\nYou have to upgrade your existing Bibles.\n'
|
||||
'Should OpenLP upgrade now?'),
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)) == \
|
||||
translate('OpenLP', 'Bible format has changed.\nYou have to upgrade your '
|
||||
'existing Bibles.\nShould OpenLP upgrade now?'),
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)) == \
|
||||
QtGui.QMessageBox.Yes:
|
||||
self.on_tools_upgrade_Item_triggered()
|
||||
|
||||
def add_import_menu_item(self, import_menu):
|
||||
"""
|
||||
|
||||
:param import_menu:
|
||||
"""
|
||||
self.import_bible_item = create_action(import_menu, 'importBibleItem',
|
||||
text=translate('BiblesPlugin', '&Bible'), visible=False,
|
||||
triggers=self.on_bible_import_click)
|
||||
import_menu.addAction(self.import_bible_item)
|
||||
|
||||
def add_export_menu_Item(self, export_menu):
|
||||
def add_export_menu_item(self, export_menu):
|
||||
"""
|
||||
|
||||
:param export_menu:
|
||||
"""
|
||||
self.export_bible_item = create_action(export_menu, 'exportBibleItem',
|
||||
text=translate('BiblesPlugin', '&Bible'), visible=False)
|
||||
export_menu.addAction(self.export_bible_item)
|
||||
@ -190,12 +195,12 @@ class BiblePlugin(Plugin):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
"""
|
||||
## Name PluginList ##
|
||||
# Name PluginList
|
||||
self.text_strings[StringContent.Name] = {
|
||||
'singular': translate('BiblesPlugin', 'Bible', 'name singular'),
|
||||
'plural': translate('BiblesPlugin', 'Bibles', 'name plural')
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
# Name for MediaDockManager, SettingsManager
|
||||
self.text_strings[StringContent.VisibleName] = {
|
||||
'title': translate('BiblesPlugin', 'Bibles', 'container title')
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ class BibleUpgradeForm(OpenLPWizard):
|
||||
Set up the UI for the bible wizard.
|
||||
"""
|
||||
super(BibleUpgradeForm, self).setupUi(image)
|
||||
Registry().execute('openlp_stop_wizard', self.stop_import)
|
||||
Registry().register_function('openlp_stop_wizard', self.stop_import)
|
||||
|
||||
def stop_import(self):
|
||||
"""
|
||||
|
@ -154,7 +154,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
|
||||
if 'path' in kwargs:
|
||||
self.path = kwargs['path']
|
||||
self.wizard = None
|
||||
Registry().execute('openlp_stop_wizard', self.stop_import)
|
||||
Registry().register_function('openlp_stop_wizard', self.stop_import)
|
||||
|
||||
def stop_import(self):
|
||||
"""
|
||||
@ -191,7 +191,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
|
||||
:param testament: *Defaults to 1.* The testament_reference_id from
|
||||
bibles_resources.sqlite of the testament this book belongs to.
|
||||
"""
|
||||
log.debug('BibleDB.create_book("%s", "%s")', name, bk_ref_id)
|
||||
log.debug('BibleDB.create_book("%s", "%s")' % (name, bk_ref_id))
|
||||
book = Book.populate(name=name, book_reference_id=bk_ref_id, testament_reference_id=testament)
|
||||
self.save_object(book)
|
||||
return book
|
||||
@ -202,7 +202,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
|
||||
|
||||
:param book: The book object
|
||||
"""
|
||||
log.debug('BibleDB.update_book("%s")', book.name)
|
||||
log.debug('BibleDB.update_book("%s")' % book.name)
|
||||
return self.save_object(book)
|
||||
|
||||
def delete_book(self, db_book):
|
||||
@ -211,7 +211,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
|
||||
|
||||
:param db_book: The book object.
|
||||
"""
|
||||
log.debug('BibleDB.delete_book("%s")', db_book.name)
|
||||
log.debug('BibleDB.delete_book("%s")' % db_book.name)
|
||||
if self.delete_object(Book, db_book.id):
|
||||
return True
|
||||
return False
|
||||
@ -225,7 +225,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
|
||||
:param text_list: A dict of the verses to be inserted. The key is the verse number, and the value is the
|
||||
verse text.
|
||||
"""
|
||||
log.debug('BibleDBcreate_chapter("%s", "%s")', book_id, chapter)
|
||||
log.debug('BibleDBcreate_chapter("%s", "%s")' % (book_id, chapter))
|
||||
# Text list has book and chapter as first two elements of the array.
|
||||
for verse_number, verse_text in text_list.items():
|
||||
verse = Verse.populate(
|
||||
@ -267,7 +267,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
|
||||
"""
|
||||
if not isinstance(value, str):
|
||||
value = str(value)
|
||||
log.debug('BibleDB.save_meta("%s/%s")', key, value)
|
||||
log.debug('BibleDB.save_meta("%s/%s")' % (key, value))
|
||||
meta = self.get_object(BibleMeta, key)
|
||||
if meta:
|
||||
meta.value = value
|
||||
@ -281,7 +281,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
|
||||
|
||||
:param book: The name of the book to return.
|
||||
"""
|
||||
log.debug('BibleDB.get_book("%s")', book)
|
||||
log.debug('BibleDB.get_book("%s")' % book)
|
||||
return self.get_object_filtered(Book, Book.name.like(book + '%'))
|
||||
|
||||
def get_books(self):
|
||||
@ -292,17 +292,17 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
|
||||
log.debug('BibleDB.get_books()')
|
||||
return self.get_all_objects(Book, order_by_ref=Book.id)
|
||||
|
||||
def get_book_by_book_ref_id(self, id):
|
||||
def get_book_by_book_ref_id(self, ref_id):
|
||||
"""
|
||||
Return a book object from the database.
|
||||
|
||||
:param id: The reference id of the book to return.
|
||||
:param ref_id: The reference id of the book to return.
|
||||
"""
|
||||
log.debug('BibleDB.get_book_by_book_ref_id("%s")', id)
|
||||
return self.get_object_filtered(Book, Book.book_reference_id.like(id))
|
||||
log.debug('BibleDB.get_book_by_book_ref_id("%s")' % ref_id)
|
||||
return self.get_object_filtered(Book, Book.book_reference_id.like(ref_id))
|
||||
|
||||
def get_book_ref_id_by_name(self, book, maxbooks, language_id=None):
|
||||
log.debug('BibleDB.get_book_ref_id_by_name:("%s", "%s")', book, language_id)
|
||||
log.debug('BibleDB.get_book_ref_id_by_name:("%s", "%s")' % (book, language_id))
|
||||
book_id = None
|
||||
if BiblesResourcesDB.get_book(book, True):
|
||||
book_temp = BiblesResourcesDB.get_book(book, True)
|
||||
@ -328,7 +328,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
|
||||
:param book: The name of the book, according to the selected language.
|
||||
:param language_selection: The language selection the user has chosen in the settings section of the Bible.
|
||||
"""
|
||||
log.debug('get_book_ref_id_by_localised_name("%s", "%s")', book, language_selection)
|
||||
log.debug('get_book_ref_id_by_localised_name("%s", "%s")' % (book, language_selection))
|
||||
from openlp.plugins.bibles.lib import LanguageSelection, BibleStrings
|
||||
book_names = BibleStrings().BookNames
|
||||
# escape reserved characters
|
||||
@ -376,14 +376,14 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
|
||||
[(u'35', 1, 1, 1), (u'35', 2, 2, 3)]
|
||||
:param show_error:
|
||||
"""
|
||||
log.debug('BibleDB.get_verses("%s")', reference_list)
|
||||
log.debug('BibleDB.get_verses("%s")' % reference_list)
|
||||
verse_list = []
|
||||
book_error = False
|
||||
for book_id, chapter, start_verse, end_verse in reference_list:
|
||||
db_book = self.get_book_by_book_ref_id(book_id)
|
||||
if db_book:
|
||||
book_id = db_book.book_reference_id
|
||||
log.debug('Book name corrected to "%s"', db_book.name)
|
||||
log.debug('Book name corrected to "%s"' % db_book.name)
|
||||
if end_verse == -1:
|
||||
end_verse = self.get_verse_count(book_id, chapter)
|
||||
verses = self.session.query(Verse) \
|
||||
@ -395,7 +395,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
|
||||
.all()
|
||||
verse_list.extend(verses)
|
||||
else:
|
||||
log.debug('OpenLP failed to find book with id "%s"', book_id)
|
||||
log.debug('OpenLP failed to find book with id "%s"' % book_id)
|
||||
book_error = True
|
||||
if book_error and show_error:
|
||||
critical_error_message_box(
|
||||
@ -414,7 +414,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
|
||||
contains spaces, it will split apart and AND'd on the list of
|
||||
values.
|
||||
"""
|
||||
log.debug('BibleDB.verse_search("%s")', text)
|
||||
log.debug('BibleDB.verse_search("%s")' % text)
|
||||
verses = self.session.query(Verse)
|
||||
if text.find(',') > -1:
|
||||
keywords = ['%%%s%%' % keyword.strip() for keyword in text.split(',')]
|
||||
@ -433,7 +433,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
|
||||
|
||||
:param book: The book object to get the chapter count for.
|
||||
"""
|
||||
log.debug('BibleDB.get_chapter_count("%s")', book.name)
|
||||
log.debug('BibleDB.get_chapter_count("%s")' % book.name)
|
||||
count = self.session.query(func.max(Verse.chapter)).join(Book).filter(
|
||||
Book.book_reference_id == book.book_reference_id).scalar()
|
||||
if not count:
|
||||
@ -447,7 +447,7 @@ class BibleDB(QtCore.QObject, Manager, RegistryProperties):
|
||||
:param book_ref_id: The book reference id.
|
||||
:param chapter: The chapter to get the verse count for.
|
||||
"""
|
||||
log.debug('BibleDB.get_verse_count("%s", "%s")', book_ref_id, chapter)
|
||||
log.debug('BibleDB.get_verse_count("%s", "%s")' % (book_ref_id, chapter))
|
||||
count = self.session.query(func.max(Verse.verse)).join(Book) \
|
||||
.filter(Book.book_reference_id == book_ref_id) \
|
||||
.filter(Verse.chapter == chapter) \
|
||||
@ -561,9 +561,9 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
||||
Return a book by name or abbreviation.
|
||||
|
||||
:param name: The name or abbreviation of the book.
|
||||
:param lower: True if the comparsion should be only lowercase
|
||||
:param lower: True if the comparison should be only lowercase
|
||||
"""
|
||||
log.debug('BiblesResourcesDB.get_book("%s")', name)
|
||||
log.debug('BiblesResourcesDB.get_book("%s")' % name)
|
||||
if not isinstance(name, str):
|
||||
name = str(name)
|
||||
if lower:
|
||||
@ -592,7 +592,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
||||
|
||||
:param string: The string to search for in the book names or abbreviations.
|
||||
"""
|
||||
log.debug('BiblesResourcesDB.get_book_like("%s")', string)
|
||||
log.debug('BiblesResourcesDB.get_book_like("%s")' % string)
|
||||
if not isinstance(string, str):
|
||||
name = str(string)
|
||||
books = BiblesResourcesDB.run_sql(
|
||||
@ -611,17 +611,17 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def get_book_by_id(id):
|
||||
def get_book_by_id(book_id):
|
||||
"""
|
||||
Return a book by id.
|
||||
|
||||
:param id: The id of the book.
|
||||
:param book_id: The id of the book.
|
||||
"""
|
||||
log.debug('BiblesResourcesDB.get_book_by_id("%s")', id)
|
||||
if not isinstance(id, int):
|
||||
id = int(id)
|
||||
log.debug('BiblesResourcesDB.get_book_by_id("%s")' % book_id)
|
||||
if not isinstance(book_id, int):
|
||||
book_id = int(book_id)
|
||||
books = BiblesResourcesDB.run_sql(
|
||||
'SELECT id, testament_id, name, abbreviation, chapters FROM book_reference WHERE id = ?', (id, ))
|
||||
'SELECT id, testament_id, name, abbreviation, chapters FROM book_reference WHERE id = ?', (book_id, ))
|
||||
if books:
|
||||
return {
|
||||
'id': books[0][0],
|
||||
@ -641,7 +641,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
||||
:param book_ref_id: The id of a book.
|
||||
:param chapter: The chapter number.
|
||||
"""
|
||||
log.debug('BiblesResourcesDB.get_chapter("%s", "%s")', book_ref_id, chapter)
|
||||
log.debug('BiblesResourcesDB.get_chapter("%s", "%s")' % (book_ref_id, chapter))
|
||||
if not isinstance(chapter, int):
|
||||
chapter = int(chapter)
|
||||
chapters = BiblesResourcesDB.run_sql(
|
||||
@ -649,10 +649,10 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
||||
'chapter, verse_count FROM chapters WHERE book_reference_id = ?', (book_ref_id,))
|
||||
try:
|
||||
return {
|
||||
'id': chapters[chapter-1][0],
|
||||
'book_reference_id': chapters[chapter-1][1],
|
||||
'chapter': chapters[chapter-1][2],
|
||||
'verse_count': chapters[chapter-1][3]
|
||||
'id': chapters[chapter - 1][0],
|
||||
'book_reference_id': chapters[chapter - 1][1],
|
||||
'chapter': chapters[chapter - 1][2],
|
||||
'verse_count': chapters[chapter - 1][3]
|
||||
}
|
||||
except (IndexError, TypeError):
|
||||
return None
|
||||
@ -664,7 +664,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
||||
|
||||
:param book_ref_id: The id of the book.
|
||||
"""
|
||||
log.debug('BiblesResourcesDB.get_chapter_count("%s")', book_ref_id)
|
||||
log.debug('BiblesResourcesDB.get_chapter_count("%s")' % book_ref_id)
|
||||
details = BiblesResourcesDB.get_book_by_id(book_ref_id)
|
||||
if details:
|
||||
return details['chapters']
|
||||
@ -678,7 +678,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
||||
:param book_ref_id: The id of the book.
|
||||
:param chapter: The number of the chapter.
|
||||
"""
|
||||
log.debug('BiblesResourcesDB.get_verse_count("%s", "%s")', book_ref_id, chapter)
|
||||
log.debug('BiblesResourcesDB.get_verse_count("%s", "%s")' % (book_ref_id, chapter))
|
||||
details = BiblesResourcesDB.get_chapter(book_ref_id, chapter)
|
||||
if details:
|
||||
return details['verse_count']
|
||||
@ -691,7 +691,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
||||
|
||||
:param source: The name or abbreviation of the book.
|
||||
"""
|
||||
log.debug('BiblesResourcesDB.get_download_source("%s")', source)
|
||||
log.debug('BiblesResourcesDB.get_download_source("%s")' % source)
|
||||
if not isinstance(source, str):
|
||||
source = str(source)
|
||||
source = source.title()
|
||||
@ -712,7 +712,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
||||
|
||||
:param source: The source of the web_bible.
|
||||
"""
|
||||
log.debug('BiblesResourcesDB.get_webbibles("%s")', source)
|
||||
log.debug('BiblesResourcesDB.get_webbibles("%s")' % source)
|
||||
if not isinstance(source, str):
|
||||
source = str(source)
|
||||
source = BiblesResourcesDB.get_download_source(source)
|
||||
@ -737,7 +737,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
||||
:param abbreviation: The abbreviation of the web_bible.
|
||||
:param source: The source of the web_bible.
|
||||
"""
|
||||
log.debug('BiblesResourcesDB.get_webbibles("%s", "%s")', abbreviation, source)
|
||||
log.debug('BiblesResourcesDB.get_webbibles("%s", "%s")' % (abbreviation, source))
|
||||
if not isinstance(abbreviation, str):
|
||||
abbreviation = str(abbreviation)
|
||||
if not isinstance(source, str):
|
||||
@ -765,7 +765,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
||||
:param name: The name to search the id.
|
||||
:param language_id: The language_id for which language should be searched
|
||||
"""
|
||||
log.debug('BiblesResourcesDB.get_alternative_book_name("%s", "%s")', name, language_id)
|
||||
log.debug('BiblesResourcesDB.get_alternative_book_name("%s", "%s")' % (name, language_id))
|
||||
if language_id:
|
||||
books = BiblesResourcesDB.run_sql(
|
||||
'SELECT book_reference_id, name FROM alternative_book_names WHERE language_id = ? ORDER BY id',
|
||||
@ -784,7 +784,7 @@ class BiblesResourcesDB(QtCore.QObject, Manager):
|
||||
|
||||
:param name: The name or abbreviation of the language.
|
||||
"""
|
||||
log.debug('BiblesResourcesDB.get_language("%s")', name)
|
||||
log.debug('BiblesResourcesDB.get_language("%s")' % name)
|
||||
if not isinstance(name, str):
|
||||
name = str(name)
|
||||
language = BiblesResourcesDB.run_sql(
|
||||
@ -846,13 +846,13 @@ class AlternativeBookNamesDB(QtCore.QObject, Manager):
|
||||
file_path = os.path.join(
|
||||
AppLocation.get_directory(AppLocation.DataDir), 'bibles', 'alternative_book_names.sqlite')
|
||||
if not os.path.exists(file_path):
|
||||
#create new DB, create table alternative_book_names
|
||||
# create new DB, create table alternative_book_names
|
||||
AlternativeBookNamesDB.conn = sqlite3.connect(file_path)
|
||||
AlternativeBookNamesDB.conn.execute(
|
||||
'CREATE TABLE alternative_book_names(id INTEGER NOT NULL, '
|
||||
'book_reference_id INTEGER, language_id INTEGER, name VARCHAR(50), PRIMARY KEY (id))')
|
||||
else:
|
||||
#use existing DB
|
||||
# use existing DB
|
||||
AlternativeBookNamesDB.conn = sqlite3.connect(file_path)
|
||||
AlternativeBookNamesDB.cursor = AlternativeBookNamesDB.conn.cursor()
|
||||
return AlternativeBookNamesDB.cursor
|
||||
@ -880,7 +880,7 @@ class AlternativeBookNamesDB(QtCore.QObject, Manager):
|
||||
:param name: The name to search the id.
|
||||
:param language_id: The language_id for which language should be searched
|
||||
"""
|
||||
log.debug('AlternativeBookNamesDB.get_book_reference_id("%s", "%s")', name, language_id)
|
||||
log.debug('AlternativeBookNamesDB.get_book_reference_id("%s", "%s")' % (name, language_id))
|
||||
if language_id:
|
||||
books = AlternativeBookNamesDB.run_sql(
|
||||
'SELECT book_reference_id, name FROM alternative_book_names WHERE language_id = ?', (language_id, ))
|
||||
@ -901,8 +901,8 @@ class AlternativeBookNamesDB(QtCore.QObject, Manager):
|
||||
:param book_reference_id: The book_reference_id of the book.
|
||||
:param language_id: The language to which the alternative book name belong.
|
||||
"""
|
||||
log.debug('AlternativeBookNamesDB.create_alternative_book_name("%s", "%s", "%s")',
|
||||
name, book_reference_id, language_id)
|
||||
log.debug('AlternativeBookNamesDB.create_alternative_book_name("%s", "%s", "%s")' %
|
||||
(name, book_reference_id, language_id))
|
||||
return AlternativeBookNamesDB.run_sql(
|
||||
'INSERT INTO alternative_book_names(book_reference_id, language_id, name) '
|
||||
'VALUES (?, ?, ?)', (book_reference_id, language_id, name), True)
|
||||
|
@ -552,10 +552,10 @@ class HTTPBible(BibleDB, RegistryProperties):
|
||||
self.application.set_busy_cursor()
|
||||
search_results = self.get_chapter(book, reference[1])
|
||||
if search_results and search_results.has_verse_list():
|
||||
## We have found a book of the bible lets check to see
|
||||
## if it was there. By reusing the returned book name
|
||||
## we get a correct book. For example it is possible
|
||||
## to request ac and get Acts back.
|
||||
# We have found a book of the bible lets check to see
|
||||
# if it was there. By reusing the returned book name
|
||||
# we get a correct book. For example it is possible
|
||||
# to request ac and get Acts back.
|
||||
book_name = search_results.book
|
||||
self.application.process_events()
|
||||
# Check to see if book/chapter exists.
|
||||
|
@ -480,6 +480,10 @@ class BibleMediaItem(MediaManagerItem):
|
||||
self.reload_bibles()
|
||||
|
||||
def on_delete_click(self):
|
||||
"""
|
||||
When the delete button is pressed
|
||||
"""
|
||||
bible = None
|
||||
if self.quickTab.isVisible():
|
||||
bible = self.quickVersionComboBox.currentText()
|
||||
elif self.advancedTab.isVisible():
|
||||
@ -488,8 +492,9 @@ class BibleMediaItem(MediaManagerItem):
|
||||
if QtGui.QMessageBox.question(
|
||||
self, UiStrings().ConfirmDelete,
|
||||
translate('BiblesPlugin.MediaItem', 'Are you sure you want to completely delete "%s" Bible from '
|
||||
'OpenLP?\n\nYou will need to re-import this Bible to use it again.') % bible,
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No),
|
||||
'OpenLP?\n\nYou will need to re-import this Bible to use it '
|
||||
'again.') % bible,
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No),
|
||||
QtGui.QMessageBox.Yes) == QtGui.QMessageBox.No:
|
||||
return
|
||||
self.plugin.manager.delete_bible(bible)
|
||||
@ -752,7 +757,7 @@ class BibleMediaItem(MediaManagerItem):
|
||||
log.exception('The second_search_results does not have as many verses as the search_results.')
|
||||
break
|
||||
bible_text = '%s %d%s%d (%s, %s)' % (book, verse.chapter, verse_separator, verse.verse, version,
|
||||
second_version)
|
||||
second_version)
|
||||
else:
|
||||
bible_text = '%s %d%s%d (%s)' % (book, verse.chapter, verse_separator, verse.verse, version)
|
||||
bible_verse = QtGui.QListWidgetItem(bible_text)
|
||||
@ -840,6 +845,7 @@ class BibleMediaItem(MediaManagerItem):
|
||||
service_item.add_capability(ItemCapabilities.CanPreview)
|
||||
service_item.add_capability(ItemCapabilities.CanLoop)
|
||||
service_item.add_capability(ItemCapabilities.CanWordSplit)
|
||||
service_item.add_capability(ItemCapabilities.CanEditTitle)
|
||||
# Service Item: Title
|
||||
service_item.title = create_separated_list(raw_title)
|
||||
# Service Item: Theme
|
||||
|
@ -94,5 +94,5 @@ class VerseReferenceList(object):
|
||||
result = result + ', ' + version['permission']
|
||||
result = result.rstrip()
|
||||
if result.endswith(','):
|
||||
return result[:len(result)-1]
|
||||
return result[:len(result) - 1]
|
||||
return result
|
||||
|
@ -43,7 +43,7 @@ log = logging.getLogger(__name__)
|
||||
|
||||
__default_settings__ = {
|
||||
'custom/db type': 'sqlite',
|
||||
'custom/last search type': CustomSearch.Titles,
|
||||
'custom/last search type': CustomSearch.Titles,
|
||||
'custom/display footer': True,
|
||||
'custom/add custom from service': True
|
||||
}
|
||||
@ -97,12 +97,12 @@ class CustomPlugin(Plugin):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
"""
|
||||
## Name PluginList ##
|
||||
# Name PluginList
|
||||
self.text_strings[StringContent.Name] = {
|
||||
'singular': translate('CustomPlugin', 'Custom Slide', 'name singular'),
|
||||
'plural': translate('CustomPlugin', 'Custom Slides', 'name plural')
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
# Name for MediaDockManager, SettingsManager
|
||||
self.text_strings[StringContent.VisibleName] = {
|
||||
'title': translate('CustomPlugin', 'Custom Slides', 'container title')
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
#lint:disable
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
|
@ -51,7 +51,7 @@ from lxml import etree, objectify
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
#TODO: These classes need to be refactored into a single class.
|
||||
# TODO: These classes need to be refactored into a single class.
|
||||
class CustomXMLBuilder(object):
|
||||
"""
|
||||
This class builds the XML used to describe songs.
|
||||
|
@ -95,12 +95,12 @@ class ImagePlugin(Plugin):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin.
|
||||
"""
|
||||
## Name PluginList ##
|
||||
# Name PluginList
|
||||
self.text_strings[StringContent.Name] = {
|
||||
'singular': translate('ImagePlugin', 'Image', 'name singular'),
|
||||
'plural': translate('ImagePlugin', 'Images', 'name plural')
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
# Name for MediaDockManager, SettingsManager
|
||||
self.text_strings[StringContent.VisibleName] = {'title': translate('ImagePlugin', 'Images', 'container title')}
|
||||
# Middle Header Bar
|
||||
tooltips = {
|
||||
|
@ -550,6 +550,7 @@ class ImageMediaItem(MediaManagerItem):
|
||||
service_item.add_capability(ItemCapabilities.CanPreview)
|
||||
service_item.add_capability(ItemCapabilities.CanLoop)
|
||||
service_item.add_capability(ItemCapabilities.CanAppend)
|
||||
service_item.add_capability(ItemCapabilities.CanEditTitle)
|
||||
# force a nonexistent theme
|
||||
service_item.theme = -1
|
||||
missing_items_file_names = []
|
||||
|
@ -95,7 +95,6 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
|
||||
self.reset_action.setToolTip(UiStrings().ResetLiveBG)
|
||||
self.automatic = UiStrings().Automatic
|
||||
self.display_type_label.setText(translate('MediaPlugin.MediaItem', 'Use Player:'))
|
||||
#self.rebuild_players()
|
||||
|
||||
def required_icons(self):
|
||||
"""
|
||||
@ -141,7 +140,7 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
|
||||
if index == 0:
|
||||
set_media_players(player)
|
||||
else:
|
||||
set_media_players(player, player[index-1])
|
||||
set_media_players(player, player[index - 1])
|
||||
|
||||
def on_reset_click(self):
|
||||
"""
|
||||
@ -216,6 +215,7 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
|
||||
if not self.media_controller.media_length(service_item):
|
||||
return False
|
||||
service_item.add_capability(ItemCapabilities.CanAutoStartForLive)
|
||||
service_item.add_capability(ItemCapabilities.CanEditTitle)
|
||||
service_item.add_capability(ItemCapabilities.RequiresMedia)
|
||||
if Settings().value(self.settings_section + '/media auto start') == QtCore.Qt.Checked:
|
||||
service_item.will_auto_start = True
|
||||
|
@ -73,12 +73,12 @@ class MediaPlugin(Plugin):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
"""
|
||||
## Name PluginList ##
|
||||
# Name PluginList
|
||||
self.text_strings[StringContent.Name] = {
|
||||
'singular': translate('MediaPlugin', 'Media', 'name singular'),
|
||||
'plural': translate('MediaPlugin', 'Media', 'name plural')
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
# Name for MediaDockManager, SettingsManager
|
||||
self.text_strings[StringContent.VisibleName] = {
|
||||
'title': translate('MediaPlugin', 'Media', 'container title')
|
||||
}
|
||||
|
@ -377,8 +377,6 @@ class ImpressDocument(PresentationDocument):
|
||||
Stop the presentation, remove from screen.
|
||||
"""
|
||||
log.debug('stop presentation OpenOffice')
|
||||
# deactivate should hide the screen according to docs, but doesn't
|
||||
#self.control.deactivate()
|
||||
self.presentation.end()
|
||||
self.control = None
|
||||
|
||||
|
@ -263,6 +263,7 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
file_type = os.path.splitext(filename)[1][1:]
|
||||
if not self.display_type_combo_box.currentText():
|
||||
return False
|
||||
service_item.add_capability(ItemCapabilities.CanEditTitle)
|
||||
if (file_type == 'pdf' or file_type == 'xps') and context != ServiceItemContext.Service:
|
||||
service_item.add_capability(ItemCapabilities.CanMaintain)
|
||||
service_item.add_capability(ItemCapabilities.CanPreview)
|
||||
|
@ -74,7 +74,7 @@ class PdfController(PresentationController):
|
||||
runlog = ''
|
||||
log.debug('testing program_path: %s', program_path)
|
||||
try:
|
||||
runlog = check_output([program_path, '--help'], stderr=STDOUT)
|
||||
runlog = check_output([program_path, '--help'], stderr=STDOUT)
|
||||
except CalledProcessError as e:
|
||||
runlog = e.output
|
||||
except Exception:
|
||||
@ -183,7 +183,7 @@ class PdfDocument(PresentationDocument):
|
||||
self.image_files = []
|
||||
self.num_pages = -1
|
||||
|
||||
def gs_get_resolution(self, size):
|
||||
def gs_get_resolution(self, size):
|
||||
"""
|
||||
Only used when using ghostscript
|
||||
Ghostscript can't scale automatically while keeping aspect like mupdf, so we need
|
||||
@ -236,7 +236,7 @@ class PdfDocument(PresentationDocument):
|
||||
if os.path.isfile(os.path.join(self.get_temp_folder(), 'mainslide001.png')):
|
||||
created_files = sorted(os.listdir(self.get_temp_folder()))
|
||||
for fn in created_files:
|
||||
if os.path.isfile(os.path.join(self.get_temp_folder(), fn)):
|
||||
if os.path.isfile(os.path.join(self.get_temp_folder(), fn)):
|
||||
self.image_files.append(os.path.join(self.get_temp_folder(), fn))
|
||||
self.num_pages = len(self.image_files)
|
||||
return True
|
||||
|
@ -247,7 +247,7 @@ class PowerpointDocument(PresentationDocument):
|
||||
Starts a presentation from the beginning.
|
||||
"""
|
||||
log.debug('start_presentation')
|
||||
#SlideShowWindow measures its size/position by points, not pixels
|
||||
# SlideShowWindow measures its size/position by points, not pixels
|
||||
try:
|
||||
dpi = win32ui.GetActiveWindow().GetDC().GetDeviceCaps(88)
|
||||
except win32ui.error:
|
||||
|
@ -87,7 +87,7 @@ class PptviewController(PresentationController):
|
||||
return
|
||||
log.debug('start PPTView')
|
||||
dll_path = os.path.join(AppLocation.get_directory(AppLocation.AppDir),
|
||||
'presentations', 'lib', 'pptviewlib', 'pptviewlib.dll')
|
||||
'plugins', 'presentations', 'lib', 'pptviewlib', 'pptviewlib.dll')
|
||||
self.process = cdll.LoadLibrary(dll_path)
|
||||
if log.isEnabledFor(logging.DEBUG):
|
||||
self.process.SetDebug(1)
|
||||
|
@ -175,10 +175,10 @@ class PresentationTab(SettingsTab):
|
||||
if pdf_program == '':
|
||||
enable_pdf_program = 0
|
||||
if pdf_program != Settings().value(self.settings_section + '/pdf_program'):
|
||||
Settings().setValue(self.settings_section + '/pdf_program', pdf_program)
|
||||
Settings().setValue(self.settings_section + '/pdf_program', pdf_program)
|
||||
changed = True
|
||||
if enable_pdf_program != Settings().value(self.settings_section + '/enable_pdf_program'):
|
||||
Settings().setValue(self.settings_section + '/enable_pdf_program', enable_pdf_program)
|
||||
Settings().setValue(self.settings_section + '/enable_pdf_program', enable_pdf_program)
|
||||
changed = True
|
||||
if changed:
|
||||
self.settings_form.register_post_process('mediaitem_suffix_reset')
|
||||
|
@ -156,12 +156,12 @@ class PresentationPlugin(Plugin):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin.
|
||||
"""
|
||||
## Name PluginList ##
|
||||
# Name PluginList
|
||||
self.text_strings[StringContent.Name] = {
|
||||
'singular': translate('PresentationPlugin', 'Presentation', 'name singular'),
|
||||
'plural': translate('PresentationPlugin', 'Presentations', 'name plural')
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
# Name for MediaDockManager, SettingsManager
|
||||
self.text_strings[StringContent.VisibleName] = {
|
||||
'title': translate('PresentationPlugin', 'Presentations', 'container title')
|
||||
}
|
||||
|
@ -28,15 +28,15 @@
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The :mod:`http` module contains the API web server. This is a lightweight web
|
||||
server used by remotes to interact with OpenLP. It uses JSON to communicate with
|
||||
the remotes.
|
||||
The :mod:`http` module contains the API web server. This is a lightweight web server used by remotes to interact
|
||||
with OpenLP. It uses JSON to communicate with the remotes.
|
||||
"""
|
||||
|
||||
import ssl
|
||||
import socket
|
||||
import os
|
||||
import logging
|
||||
import time
|
||||
|
||||
from PyQt4 import QtCore
|
||||
|
||||
@ -53,8 +53,8 @@ log = logging.getLogger(__name__)
|
||||
class CustomHandler(BaseHTTPRequestHandler, HttpRouter):
|
||||
"""
|
||||
Stateless session handler to handle the HTTP request and process it.
|
||||
This class handles just the overrides to the base methods and the logic to invoke the
|
||||
methods within the HttpRouter class.
|
||||
This class handles just the overrides to the base methods and the logic to invoke the methods within the HttpRouter
|
||||
class.
|
||||
DO not try change the structure as this is as per the documentation.
|
||||
"""
|
||||
|
||||
@ -116,9 +116,20 @@ class OpenLPServer():
|
||||
log.debug('Started ssl httpd...')
|
||||
else:
|
||||
port = Settings().value(self.settings_section + '/port')
|
||||
self.httpd = ThreadingHTTPServer((address, port), CustomHandler)
|
||||
loop = 1
|
||||
while loop < 3:
|
||||
try:
|
||||
self.httpd = ThreadingHTTPServer((address, port), CustomHandler)
|
||||
except OSError:
|
||||
loop += 1
|
||||
time.sleep(0.1)
|
||||
except:
|
||||
log.error('Failed to start server ')
|
||||
log.debug('Started non ssl httpd...')
|
||||
self.httpd.serve_forever()
|
||||
if hasattr(self, 'httpd') and self.httpd:
|
||||
self.httpd.serve_forever()
|
||||
else:
|
||||
log.debug('Failed to start server')
|
||||
|
||||
def stop_server(self):
|
||||
"""
|
||||
|
@ -92,12 +92,12 @@ class RemotesPlugin(Plugin):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
"""
|
||||
## Name PluginList ##
|
||||
# Name PluginList
|
||||
self.text_strings[StringContent.Name] = {
|
||||
'singular': translate('RemotePlugin', 'Remote', 'name singular'),
|
||||
'plural': translate('RemotePlugin', 'Remotes', 'name plural')
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
# Name for MediaDockManager, SettingsManager
|
||||
self.text_strings[StringContent.VisibleName] = {
|
||||
'title': translate('RemotePlugin', 'Remote', 'container title')
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ class DuplicateSongRemovalForm(OpenLPWizard, RegistryProperties):
|
||||
self.review_layout.addWidget(self.review_scroll_area)
|
||||
self.review_page_id = self.addPage(self.review_page)
|
||||
# Add a dummy page to the end, to prevent the finish button to appear and the next button do disappear on the
|
||||
#review page.
|
||||
# review page.
|
||||
self.dummy_page = QtGui.QWizardPage()
|
||||
self.dummy_page_id = self.addPage(self.dummy_page)
|
||||
|
||||
@ -217,12 +217,12 @@ class DuplicateSongRemovalForm(OpenLPWizard, RegistryProperties):
|
||||
duplicate_added = False
|
||||
for duplicate_group in self.duplicate_song_list:
|
||||
# Skip the first song in the duplicate lists, since the first one has to be an earlier song.
|
||||
if search_song in duplicate_group and not duplicate_song in duplicate_group:
|
||||
if search_song in duplicate_group and duplicate_song not in duplicate_group:
|
||||
duplicate_group.append(duplicate_song)
|
||||
duplicate_group_found = True
|
||||
duplicate_added = True
|
||||
break
|
||||
elif not search_song in duplicate_group and duplicate_song in duplicate_group:
|
||||
elif search_song not in duplicate_group and duplicate_song in duplicate_group:
|
||||
duplicate_group.append(search_song)
|
||||
duplicate_group_found = True
|
||||
duplicate_added = True
|
||||
|
@ -675,14 +675,13 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog, RegistryProperties):
|
||||
separator = parts.find(':')
|
||||
if separator >= 0:
|
||||
verse_name = parts[0:separator].strip()
|
||||
verse_num = parts[separator+1:].strip()
|
||||
verse_num = parts[separator + 1:].strip()
|
||||
else:
|
||||
verse_name = parts
|
||||
verse_num = '1'
|
||||
verse_index = VerseType.from_loose_input(verse_name)
|
||||
verse_tag = VerseType.tags[verse_index]
|
||||
# Later we need to handle v1a as well.
|
||||
#regex = re.compile(r'(\d+\w.)')
|
||||
regex = re.compile(r'\D*(\d+)\D*')
|
||||
match = regex.match(verse_num)
|
||||
if match:
|
||||
|
@ -75,7 +75,7 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
|
||||
text = self.verse_text_edit.toPlainText()
|
||||
position = self.verse_text_edit.textCursor().position()
|
||||
insert_string = '[---]'
|
||||
if position and text[position-1] != '\n':
|
||||
if position and text[position - 1] != '\n':
|
||||
insert_string = '\n' + insert_string
|
||||
if position == len(text) or text[position] != '\n':
|
||||
insert_string += '\n'
|
||||
|
@ -66,8 +66,10 @@ class Ui_MediaFilesDialog(object):
|
||||
def retranslateUi(self, media_files_dialog):
|
||||
"""
|
||||
Translate the UI on the fly.
|
||||
|
||||
:param media_files_dialog:
|
||||
"""
|
||||
media_files_dialog.setWindowTitle(translate('SongsPlugin.MediaFilesForm', 'Select Media File(s)'))
|
||||
self.select_label.setText(translate('SongsPlugin.MediaFilesForm',
|
||||
'Select one or more audio files from the list below, and click OK to import them '
|
||||
'into this song.'))
|
||||
self.select_label.setText(translate('SongsPlugin.MediaFilesForm', 'Select one or more audio files from the '
|
||||
'list below, and click OK to import them '
|
||||
'into this song.'))
|
||||
|
@ -152,9 +152,9 @@ class SongExportForm(OpenLPWizard):
|
||||
self.setWindowTitle(translate('SongsPlugin.ExportWizardForm', 'Song Export Wizard'))
|
||||
self.title_label.setText(WizardStrings.HeaderStyle %
|
||||
translate('OpenLP.Ui', 'Welcome to the Song Export Wizard'))
|
||||
self.information_label.setText(translate('SongsPlugin.ExportWizardForm', 'This wizard will help to'
|
||||
' export your songs to the open and free <strong>OpenLyrics </strong> worship '
|
||||
'song format.'))
|
||||
self.information_label.setText(
|
||||
translate('SongsPlugin.ExportWizardForm', 'This wizard will help to export your songs to the open and free '
|
||||
'<strong>OpenLyrics </strong> worship song format.'))
|
||||
self.available_songs_page.setTitle(translate('SongsPlugin.ExportWizardForm', 'Select Songs'))
|
||||
self.available_songs_page.setSubTitle(translate('SongsPlugin.ExportWizardForm',
|
||||
'Check the songs you want to export.'))
|
||||
|
@ -270,13 +270,13 @@ class CCLIFileImport(SongImport):
|
||||
verse_text = ''
|
||||
verse_start = False
|
||||
else:
|
||||
#line_number=0, song title
|
||||
# line_number=0, song title
|
||||
if line_number == 0:
|
||||
self.title = clean_line
|
||||
line_number += 1
|
||||
#line_number=1, verses
|
||||
# line_number=1, verses
|
||||
elif line_number == 1:
|
||||
#line_number=1, ccli number, first line after verses
|
||||
# line_number=1, ccli number, first line after verses
|
||||
if clean_line.startswith('CCLI'):
|
||||
line_number += 1
|
||||
ccli_parts = clean_line.split(' ')
|
||||
@ -319,21 +319,21 @@ class CCLIFileImport(SongImport):
|
||||
# last part. Add l so as to keep the CRLF
|
||||
verse_text = verse_text + line
|
||||
else:
|
||||
#line_number=2, copyright
|
||||
# line_number=2, copyright
|
||||
if line_number == 2:
|
||||
line_number += 1
|
||||
if clean_line.startswith('©'):
|
||||
self.copyright = clean_line
|
||||
else:
|
||||
song_author = clean_line
|
||||
#n=3, authors
|
||||
# n=3, authors
|
||||
elif line_number == 3:
|
||||
line_number += 1
|
||||
if song_author:
|
||||
self.copyright = clean_line
|
||||
else:
|
||||
song_author = clean_line
|
||||
#line_number=4, comments lines before last line
|
||||
# line_number=4, comments lines before last line
|
||||
elif line_number == 4 and not clean_line.startswith('CCL'):
|
||||
self.comments += clean_line
|
||||
# split on known separators
|
||||
|
@ -305,7 +305,7 @@ class EasyWorshipSongImport(SongImport):
|
||||
elif field_desc.field_type == FieldType.Logical:
|
||||
return field ^ 0x80 == 1
|
||||
elif field_desc.field_type == FieldType.Memo or field_desc.field_type == FieldType.Blob:
|
||||
block_start, blob_size = struct.unpack_from('<II', field, len(field)-10)
|
||||
block_start, blob_size = struct.unpack_from('<II', field, len(field) - 10)
|
||||
sub_block = block_start & 0xff
|
||||
block_start &= ~0xff
|
||||
self.memo_file.seek(block_start)
|
||||
|
@ -96,7 +96,7 @@ class SongMediaItem(MediaManagerItem):
|
||||
|
||||
def add_end_header_bar(self):
|
||||
self.toolbar.addSeparator()
|
||||
## Song Maintenance Button ##
|
||||
# Song Maintenance Button
|
||||
self.maintenance_action = self.toolbar.add_toolbar_action('maintenance_action',
|
||||
icon=':/songs/song_maintenance.png',
|
||||
triggers=self.on_song_maintenance_click)
|
||||
@ -266,7 +266,7 @@ class SongMediaItem(MediaManagerItem):
|
||||
# Do not display temporary songs
|
||||
if song.temporary:
|
||||
continue
|
||||
if song_number and not song_number in song.song_number:
|
||||
if song_number and song_number not in song.song_number:
|
||||
continue
|
||||
song_detail = '%s - %s (%s)' % (book.name, song.song_number, song.title)
|
||||
song_name = QtGui.QListWidgetItem(song_detail)
|
||||
|
@ -132,7 +132,7 @@ class SongsPlugin(Plugin):
|
||||
)
|
||||
import_menu.addAction(self.import_songselect_item)
|
||||
|
||||
def add_export_menu_Item(self, export_menu):
|
||||
def add_export_menu_item(self, export_menu):
|
||||
"""
|
||||
Give the Songs plugin the opportunity to add items to the **Export** menu.
|
||||
|
||||
@ -261,12 +261,12 @@ class SongsPlugin(Plugin):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
"""
|
||||
## Name PluginList ##
|
||||
# Name PluginList
|
||||
self.text_strings[StringContent.Name] = {
|
||||
'singular': translate('SongsPlugin', 'Song', 'name singular'),
|
||||
'plural': translate('SongsPlugin', 'Songs', 'name plural')
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
# Name for MediaDockManager, SettingsManager
|
||||
self.text_strings[StringContent.VisibleName] = {
|
||||
'title': translate('SongsPlugin', 'Songs', 'container title')
|
||||
}
|
||||
|
@ -246,12 +246,12 @@ class SongUsagePlugin(Plugin):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
"""
|
||||
## Name PluginList ##
|
||||
# Name PluginList
|
||||
self.text_strings[StringContent.Name] = {
|
||||
'singular': translate('SongUsagePlugin', 'SongUsage', 'name singular'),
|
||||
'plural': translate('SongUsagePlugin', 'SongUsage', 'name plural')
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
# Name for MediaDockManager, SettingsManager
|
||||
self.text_strings[StringContent.VisibleName] = {
|
||||
'title': translate('SongUsagePlugin', 'SongUsage', 'container title')
|
||||
}
|
||||
|
@ -32,4 +32,3 @@ The :mod:`resources` module contains a bunch of resources for OpenLP.
|
||||
DO NOT REMOVE THIS FILE, IT IS REQUIRED FOR INCLUDING THE RESOURCES ON SOME
|
||||
PLATFORMS!
|
||||
"""
|
||||
|
||||
|
@ -52,7 +52,9 @@ This is done easily via the ``-d``, ``-p`` and ``-u`` options::
|
||||
|
||||
"""
|
||||
import os
|
||||
import urllib.request, urllib.error, urllib.parse
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
import urllib.parse
|
||||
from getpass import getpass
|
||||
import base64
|
||||
import json
|
||||
@ -70,6 +72,7 @@ quiet_mode = False
|
||||
username = ''
|
||||
password = ''
|
||||
|
||||
|
||||
class Command(object):
|
||||
"""
|
||||
Provide an enumeration of commands.
|
||||
@ -80,6 +83,7 @@ class Command(object):
|
||||
Update = 4
|
||||
Generate = 5
|
||||
|
||||
|
||||
class CommandStack(object):
|
||||
"""
|
||||
This class provides an iterable stack.
|
||||
@ -134,13 +138,13 @@ class CommandStack(object):
|
||||
results.append(str((item['command'], )))
|
||||
return '[%s]' % ', '.join(results)
|
||||
|
||||
|
||||
def print_quiet(text, linefeed=True):
|
||||
"""
|
||||
This method checks to see if we are in quiet mode, and if not prints
|
||||
``text`` out.
|
||||
This method checks to see if we are in quiet mode, and if not prints ``text`` out.
|
||||
|
||||
``text``
|
||||
The text to print.
|
||||
:param text: The text to print.
|
||||
:param linefeed: Linefeed required
|
||||
"""
|
||||
global quiet_mode
|
||||
if not quiet_mode:
|
||||
@ -149,33 +153,33 @@ def print_quiet(text, linefeed=True):
|
||||
else:
|
||||
print(text, end=' ')
|
||||
|
||||
|
||||
def print_verbose(text):
|
||||
"""
|
||||
This method checks to see if we are in verbose mode, and if so prints
|
||||
``text`` out.
|
||||
This method checks to see if we are in verbose mode, and if so prints ``text`` out.
|
||||
|
||||
``text``
|
||||
The text to print.
|
||||
:param text: The text to print.
|
||||
"""
|
||||
global verbose_mode, quiet_mode
|
||||
if not quiet_mode and verbose_mode:
|
||||
print(' %s' % text)
|
||||
|
||||
|
||||
def run(command):
|
||||
"""
|
||||
This method runs an external application.
|
||||
|
||||
``command``
|
||||
The command to run.
|
||||
:param command: The command to run.
|
||||
"""
|
||||
print_verbose(command)
|
||||
process = QtCore.QProcess()
|
||||
process.start(command)
|
||||
while (process.waitForReadyRead()):
|
||||
while process.waitForReadyRead():
|
||||
print_verbose('ReadyRead: %s' % QtCore.QString(process.readAll()))
|
||||
print_verbose('Error(s):\n%s' % process.readAllStandardError())
|
||||
print_verbose('Output:\n%s' % process.readAllStandardOutput())
|
||||
|
||||
|
||||
def download_translations():
|
||||
"""
|
||||
This method downloads the translation files from the Pootle server.
|
||||
@ -190,9 +194,8 @@ def download_translations():
|
||||
password = getpass(' Transifex password: ')
|
||||
# First get the list of languages
|
||||
url = SERVER_URL + 'resource/ents/'
|
||||
base64string = base64.encodestring(
|
||||
'%s:%s' % (username, password))[:-1]
|
||||
auth_header = 'Basic %s' % base64string
|
||||
base64string = base64.encodbytes('%s:%s' % (username, password))[:-1]
|
||||
auth_header = 'Basic %s' % base64string
|
||||
request = urllib.request.Request(url + '?details')
|
||||
request.add_header('Authorization', auth_header)
|
||||
print_verbose('Downloading list of languages from: %s' % url)
|
||||
@ -207,8 +210,7 @@ def download_translations():
|
||||
lang_url = url + 'translation/%s/?file' % language
|
||||
request = urllib.request.Request(lang_url)
|
||||
request.add_header('Authorization', auth_header)
|
||||
filename = os.path.join(os.path.abspath('..'), 'resources', 'i18n',
|
||||
language + '.ts')
|
||||
filename = os.path.join(os.path.abspath('..'), 'resources', 'i18n', language + '.ts')
|
||||
print_verbose('Get Translation File: %s' % filename)
|
||||
response = urllib.request.urlopen(request)
|
||||
fd = open(filename, 'w')
|
||||
@ -217,10 +219,10 @@ def download_translations():
|
||||
print_quiet(' Done.')
|
||||
return True
|
||||
|
||||
|
||||
def prepare_project():
|
||||
"""
|
||||
This method creates the project file needed to update the translation files
|
||||
and compile them into .qm files.
|
||||
This method creates the project file needed to update the translation files and compile them into .qm files.
|
||||
"""
|
||||
print_quiet('Generating the openlp.pro file')
|
||||
lines = []
|
||||
@ -229,9 +231,9 @@ def prepare_project():
|
||||
print_verbose('Starting directory: %s' % start_dir)
|
||||
for root, dirs, files in os.walk(start_dir):
|
||||
for file in files:
|
||||
path = root.replace(start_dir, '').replace('\\', '/') #.replace(u'..', u'.')
|
||||
path = root.replace(start_dir, '').replace('\\', '/')
|
||||
if file.startswith('hook-') or file.startswith('test_'):
|
||||
continue
|
||||
continue
|
||||
ignore = False
|
||||
for ignored_path in IGNORED_PATHS:
|
||||
if path.startswith(ignored_path):
|
||||
@ -263,6 +265,7 @@ def prepare_project():
|
||||
file.close()
|
||||
print_quiet(' Done.')
|
||||
|
||||
|
||||
def update_translations():
|
||||
print_quiet('Update the translation files')
|
||||
if not os.path.exists(os.path.join(os.path.abspath('..'), 'openlp.pro')):
|
||||
@ -273,11 +276,12 @@ def update_translations():
|
||||
run('pylupdate4 -verbose -noobsolete openlp.pro')
|
||||
os.chdir(os.path.abspath('scripts'))
|
||||
|
||||
|
||||
def generate_binaries():
|
||||
print_quiet('Generate the related *.qm files')
|
||||
if not os.path.exists(os.path.join(os.path.abspath('..'), 'openlp.pro')):
|
||||
print('You have not generated a project file yet, please run this script with the -p option. It is also ' +
|
||||
'recommended that you this script with the -u option to update the translation files as well.')
|
||||
'recommended that you this script with the -u option to update the translation files as well.')
|
||||
return
|
||||
else:
|
||||
os.chdir(os.path.abspath('..'))
|
||||
@ -290,12 +294,11 @@ def create_translation():
|
||||
This method opens a browser to the OpenLP project page at Transifex so
|
||||
that the user can request a new language.
|
||||
"""
|
||||
print_quiet('Please request a new language at the OpenLP project on '
|
||||
'Transifex.')
|
||||
webbrowser.open('https://www.transifex.net/projects/p/openlp/'
|
||||
'resource/ents/')
|
||||
print_quiet('Please request a new language at the OpenLP project on Transifex.')
|
||||
webbrowser.open('https://www.transifex.net/projects/p/openlp/resource/ents/')
|
||||
print_quiet('Opening browser to OpenLP project...')
|
||||
|
||||
|
||||
def process_stack(command_stack):
|
||||
"""
|
||||
This method looks at the commands in the command stack, and processes them
|
||||
@ -323,6 +326,7 @@ def process_stack(command_stack):
|
||||
else:
|
||||
print_quiet('No commands to process.')
|
||||
|
||||
|
||||
def main():
|
||||
global verbose_mode, quiet_mode, username, password
|
||||
# Set up command line options.
|
||||
@ -331,23 +335,23 @@ def main():
|
||||
'This script is used to manage OpenLP\'s translation files.'
|
||||
parser = OptionParser(usage=usage)
|
||||
parser.add_option('-U', '--username', dest='username', metavar='USERNAME',
|
||||
help='Transifex username, used for authentication')
|
||||
help='Transifex username, used for authentication')
|
||||
parser.add_option('-P', '--password', dest='password', metavar='PASSWORD',
|
||||
help='Transifex password, used for authentication')
|
||||
help='Transifex password, used for authentication')
|
||||
parser.add_option('-d', '--download-ts', dest='download',
|
||||
action='store_true', help='download language files from Transifex')
|
||||
action='store_true', help='download language files from Transifex')
|
||||
parser.add_option('-c', '--create', dest='create', action='store_true',
|
||||
help='go to Transifex to request a new translation file')
|
||||
help='go to Transifex to request a new translation file')
|
||||
parser.add_option('-p', '--prepare', dest='prepare', action='store_true',
|
||||
help='generate a project file, used to update the translations')
|
||||
help='generate a project file, used to update the translations')
|
||||
parser.add_option('-u', '--update', action='store_true', dest='update',
|
||||
help='update translation files (needs a project file)')
|
||||
help='update translation files (needs a project file)')
|
||||
parser.add_option('-g', '--generate', dest='generate', action='store_true',
|
||||
help='compile .ts files into .qm files')
|
||||
help='compile .ts files into .qm files')
|
||||
parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
|
||||
help='show extra information while processing translations')
|
||||
help='show extra information while processing translations')
|
||||
parser.add_option('-q', '--quiet', dest='quiet', action='store_true',
|
||||
help='suppress all output other than errors')
|
||||
help='suppress all output other than errors')
|
||||
(options, args) = parser.parse_args()
|
||||
# Create and populate the command stack
|
||||
command_stack = CommandStack()
|
||||
|
10
setup.py
10
setup.py
@ -106,9 +106,9 @@ try:
|
||||
# If they are equal, then this tree is tarball with the source for the release. We do not want the revision number
|
||||
# in the version string.
|
||||
if tree_revision == tag_revision:
|
||||
version_string = tag_version
|
||||
version_string = tag_version
|
||||
else:
|
||||
version_string = '%s-bzr%s' % (tag_version, tree_revision)
|
||||
version_string = '%s-bzr%s' % (tag_version, tree_revision)
|
||||
ver_file = open(VERSION_FILE, 'w')
|
||||
ver_file.write(version_string)
|
||||
except:
|
||||
@ -123,7 +123,9 @@ setup(
|
||||
version=version_string,
|
||||
description="Open source Church presentation and lyrics projection application.",
|
||||
long_description="""\
|
||||
OpenLP (previously openlp.org) is free church presentation software, or lyrics projection software, used to display slides of songs, Bible verses, videos, images, and even presentations (if PowerPoint is installed) for church worship using a computer and a data projector.""",
|
||||
OpenLP (previously openlp.org) is free church presentation software, or lyrics projection software, used to display
|
||||
slides of songs, Bible verses, videos, images, and even presentations (if PowerPoint is installed) for church worship
|
||||
using a computer and a data projector.""",
|
||||
classifiers=[
|
||||
'Development Status :: 4 - Beta',
|
||||
'Environment :: MacOS X',
|
||||
@ -158,7 +160,7 @@ OpenLP (previously openlp.org) is free church presentation software, or lyrics p
|
||||
'Topic :: Multimedia :: Sound/Audio',
|
||||
'Topic :: Multimedia :: Video',
|
||||
'Topic :: Religion'
|
||||
], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
|
||||
], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
|
||||
keywords='open source church presentation lyrics projection song bible display project',
|
||||
author='Raoul Snyman',
|
||||
author_email='raoulsnyman@openlp.org',
|
||||
|
@ -54,9 +54,9 @@ class TestAppLocation(TestCase):
|
||||
# GIVEN: A mocked out Settings class and a mocked out AppLocation.get_directory()
|
||||
mocked_settings = mocked_class.return_value
|
||||
mocked_settings.contains.return_value = False
|
||||
mocked_get_directory.return_value = os.path.join('test','dir')
|
||||
mocked_get_directory.return_value = os.path.join('test', 'dir')
|
||||
mocked_check_directory_exists.return_value = True
|
||||
mocked_os.path.normpath.return_value = os.path.join('test','dir')
|
||||
mocked_os.path.normpath.return_value = os.path.join('test', 'dir')
|
||||
|
||||
# WHEN: we call AppLocation.get_data_path()
|
||||
data_path = AppLocation.get_data_path()
|
||||
@ -64,8 +64,8 @@ class TestAppLocation(TestCase):
|
||||
# THEN: check that all the correct methods were called, and the result is correct
|
||||
mocked_settings.contains.assert_called_with('advanced/data path')
|
||||
mocked_get_directory.assert_called_with(AppLocation.DataDir)
|
||||
mocked_check_directory_exists.assert_called_with(os.path.join('test','dir'))
|
||||
self.assertEqual(os.path.join('test','dir'), data_path, 'Result should be "test/dir"')
|
||||
mocked_check_directory_exists.assert_called_with(os.path.join('test', 'dir'))
|
||||
self.assertEqual(os.path.join('test', 'dir'), data_path, 'Result should be "test/dir"')
|
||||
|
||||
def get_data_path_with_custom_location_test(self):
|
||||
"""
|
||||
@ -110,14 +110,14 @@ class TestAppLocation(TestCase):
|
||||
with patch('openlp.core.common.AppLocation.get_data_path') as mocked_get_data_path, \
|
||||
patch('openlp.core.common.applocation.os.listdir') as mocked_listdir:
|
||||
# GIVEN: Our mocked modules/methods.
|
||||
mocked_get_data_path.return_value = os.path.join('test','dir')
|
||||
mocked_get_data_path.return_value = os.path.join('test', 'dir')
|
||||
mocked_listdir.return_value = copy.deepcopy(FILE_LIST)
|
||||
|
||||
# When: Get the list of files.
|
||||
result = AppLocation.get_files('section', '.mp3')
|
||||
|
||||
# Then: Check if the section parameter was used correctly.
|
||||
mocked_listdir.assert_called_with(os.path.join('test','dir','section'))
|
||||
mocked_listdir.assert_called_with(os.path.join('test', 'dir', 'section'))
|
||||
|
||||
# Then: check if the file lists are identical.
|
||||
self.assertListEqual(['file5.mp3', 'file6.mp3'], result, 'The file lists should be identical.')
|
||||
@ -129,15 +129,15 @@ class TestAppLocation(TestCase):
|
||||
with patch('openlp.core.common.AppLocation.get_data_path') as mocked_get_data_path, \
|
||||
patch('openlp.core.common.applocation.check_directory_exists') as mocked_check_directory_exists:
|
||||
# GIVEN: A mocked out AppLocation.get_data_path()
|
||||
mocked_get_data_path.return_value = os.path.join('test','dir')
|
||||
mocked_get_data_path.return_value = os.path.join('test', 'dir')
|
||||
mocked_check_directory_exists.return_value = True
|
||||
|
||||
# WHEN: we call AppLocation.get_data_path()
|
||||
data_path = AppLocation.get_section_data_path('section')
|
||||
|
||||
# THEN: check that all the correct methods were called, and the result is correct
|
||||
mocked_check_directory_exists.assert_called_with(os.path.join('test','dir','section'))
|
||||
self.assertEqual(os.path.join('test','dir','section'), data_path, 'Result should be "test/dir/section"')
|
||||
mocked_check_directory_exists.assert_called_with(os.path.join('test', 'dir', 'section'))
|
||||
self.assertEqual(os.path.join('test', 'dir', 'section'), data_path, 'Result should be "test/dir/section"')
|
||||
|
||||
def get_directory_for_app_dir_test(self):
|
||||
"""
|
||||
@ -145,13 +145,13 @@ class TestAppLocation(TestCase):
|
||||
"""
|
||||
# GIVEN: A mocked out _get_frozen_path function
|
||||
with patch('openlp.core.common.applocation.get_frozen_path') as mocked_get_frozen_path:
|
||||
mocked_get_frozen_path.return_value = os.path.join('app','dir')
|
||||
mocked_get_frozen_path.return_value = os.path.join('app', 'dir')
|
||||
|
||||
# WHEN: We call AppLocation.get_directory
|
||||
directory = AppLocation.get_directory(AppLocation.AppDir)
|
||||
|
||||
# THEN: check that the correct directory is returned
|
||||
self.assertEqual(os.path.join('app','dir'), directory, 'Directory should be "app/dir"')
|
||||
self.assertEqual(os.path.join('app', 'dir'), directory, 'Directory should be "app/dir"')
|
||||
|
||||
def get_directory_for_plugins_dir_test(self):
|
||||
"""
|
||||
|
@ -32,12 +32,13 @@ Functional tests to test the AppLocation class and related methods.
|
||||
|
||||
from unittest import TestCase
|
||||
|
||||
from openlp.core.common import de_hump
|
||||
from openlp.core.common import de_hump, trace_error_handler
|
||||
from tests.functional import MagicMock, patch
|
||||
|
||||
|
||||
class TestInitFunctions(TestCase):
|
||||
class TestCommonFunctions(TestCase):
|
||||
"""
|
||||
A test suite to test out various functions in the __init__ class.
|
||||
A test suite to test out various functions in the openlp.core.common module.
|
||||
"""
|
||||
def de_hump_conversion_test(self):
|
||||
"""
|
||||
@ -64,3 +65,19 @@ class TestInitFunctions(TestCase):
|
||||
|
||||
# THEN: the new string should be converted to python format
|
||||
self.assertTrue(new_string == "my_class", 'The class name should have been preserved')
|
||||
|
||||
def trace_error_handler_test(self):
|
||||
"""
|
||||
Test the trace_error_handler() method
|
||||
"""
|
||||
# GIVEN: Mocked out objects
|
||||
with patch('openlp.core.common.traceback') as mocked_traceback:
|
||||
mocked_traceback.extract_stack.return_value = [('openlp.fake', 56, None, 'trace_error_handler_test')]
|
||||
mocked_logger = MagicMock()
|
||||
|
||||
# WHEN: trace_error_handler() is called
|
||||
trace_error_handler(mocked_logger)
|
||||
|
||||
# THEN: The mocked_logger.error() method should have been called with the correct parameters
|
||||
mocked_logger.error.assert_called_with('OpenLP Error trace\n File openlp.fake at line 56 \n\t called trace_error_handler_test')
|
||||
|
@ -119,4 +119,3 @@ class TestRegistry(TestCase):
|
||||
|
||||
def dummy_function_2(self):
|
||||
return "function_2"
|
||||
|
||||
|
@ -63,4 +63,4 @@ class TestRegistryProperties(TestCase, RegistryProperties):
|
||||
# WHEN the application is registered
|
||||
Registry().register('application', application)
|
||||
# THEN the application should be none
|
||||
self.assertEquals(self.application, application, 'The application value should match')
|
||||
self.assertEquals(self.application, application, 'The application value should match')
|
||||
|
@ -46,5 +46,3 @@ class TestUiStrings(TestCase):
|
||||
|
||||
# THEN: Check if the instances are the same.
|
||||
self.assertIs(first_instance, second_instance, 'Two UiStrings objects should be the same instance')
|
||||
|
||||
|
||||
|
@ -28,4 +28,4 @@
|
||||
###############################################################################
|
||||
"""
|
||||
Package to test the openlp.core.lib package.
|
||||
"""
|
||||
"""
|
||||
|
@ -50,9 +50,9 @@ class TestDB(TestCase):
|
||||
"""
|
||||
# GIVEN: Mocked out SQLAlchemy calls and return objects, and an in-memory SQLite database URL
|
||||
with patch('openlp.core.lib.db.create_engine') as mocked_create_engine, \
|
||||
patch('openlp.core.lib.db.MetaData') as MockedMetaData, \
|
||||
patch('openlp.core.lib.db.sessionmaker') as mocked_sessionmaker, \
|
||||
patch('openlp.core.lib.db.scoped_session') as mocked_scoped_session:
|
||||
patch('openlp.core.lib.db.MetaData') as MockedMetaData, \
|
||||
patch('openlp.core.lib.db.sessionmaker') as mocked_sessionmaker, \
|
||||
patch('openlp.core.lib.db.scoped_session') as mocked_scoped_session:
|
||||
mocked_engine = MagicMock()
|
||||
mocked_metadata = MagicMock()
|
||||
mocked_sessionmaker_object = MagicMock()
|
||||
|
@ -42,7 +42,8 @@ class TestFileDialog(TestCase):
|
||||
# THEN: The returned value should be an empty QStringList and os.path.exists should not have been called
|
||||
assert not self.mocked_os.path.exists.called
|
||||
self.assertEqual(result, [],
|
||||
'FileDialog.getOpenFileNames should return and empty list when QFileDialog.getOpenFileNames is canceled')
|
||||
'FileDialog.getOpenFileNames should return and empty list when QFileDialog.getOpenFileNames '
|
||||
'is canceled')
|
||||
|
||||
def returned_file_list_test(self):
|
||||
"""
|
||||
@ -70,5 +71,5 @@ class TestFileDialog(TestCase):
|
||||
self.mocked_os.path.exists.assert_callde_with('/non-existing')
|
||||
self.mocked_os.path.exists.assert_callde_with('/non-existing')
|
||||
self.mocked_qt_gui.QmessageBox.information.called_with(self.mocked_parent, UiStrings().FileNotFound,
|
||||
UiStrings().FileNotFoundMessage % '/non-existing')
|
||||
self.assertEqual(result, ['/Valid File', '/url encoded file #1'], 'The returned file list is incorrect')
|
||||
UiStrings().FileNotFoundMessage % '/non-existing')
|
||||
self.assertEqual(result, ['/Valid File', '/url encoded file #1'], 'The returned file list is incorrect')
|
||||
|
@ -108,4 +108,3 @@ class TestFormattingTags(TestCase):
|
||||
|
||||
# THEN: The lists should now be identical.
|
||||
assert old_tags_list == FormattingTags.get_html_tags(), 'The lists should be identical.'
|
||||
|
||||
|
@ -321,4 +321,3 @@ class Htmbuilder(TestCase):
|
||||
|
||||
# THEN: THE css should be the same.
|
||||
assert FOOTER_CSS == css, 'The footer strings should be equal.'
|
||||
|
||||
|
@ -311,8 +311,8 @@ class TestLib(TestCase):
|
||||
mocked_buffer.open.assert_called_with('writeonly')
|
||||
mocked_image.save.assert_called_with(mocked_buffer, "PNG")
|
||||
mocked_byte_array.toBase64.assert_called_with()
|
||||
self.assertEqual('base64mock', result,
|
||||
'The result should be the return value of the mocked out base64 method')
|
||||
self.assertEqual('base64mock', result, 'The result should be the return value of the mocked out '
|
||||
'base64 method')
|
||||
|
||||
def create_thumb_with_size_test(self):
|
||||
"""
|
||||
|
@ -212,9 +212,9 @@ class TestPluginManager(TestCase):
|
||||
# WHEN: We run hook_export_menu()
|
||||
plugin_manager.hook_export_menu()
|
||||
|
||||
# THEN: The add_export_menu_Item() method should not have been called
|
||||
self.assertEqual(0, mocked_plugin.add_export_menu_Item.call_count,
|
||||
'The add_export_menu_Item() method should not have been called.')
|
||||
# THEN: The add_export_menu_item() method should not have been called
|
||||
self.assertEqual(0, mocked_plugin.add_export_menu_item.call_count,
|
||||
'The add_export_menu_item() method should not have been called.')
|
||||
|
||||
def hook_export_menu_with_active_plugin_test(self):
|
||||
"""
|
||||
@ -229,8 +229,8 @@ class TestPluginManager(TestCase):
|
||||
# WHEN: We run hook_export_menu()
|
||||
plugin_manager.hook_export_menu()
|
||||
|
||||
# THEN: The add_export_menu_Item() method should have been called
|
||||
mocked_plugin.add_export_menu_Item.assert_called_with(self.mocked_main_window.file_export_menu)
|
||||
# THEN: The add_export_menu_item() method should have been called
|
||||
mocked_plugin.add_export_menu_item.assert_called_with(self.mocked_main_window.file_export_menu)
|
||||
|
||||
def hook_upgrade_plugin_settings_with_disabled_plugin_test(self):
|
||||
"""
|
||||
@ -264,7 +264,7 @@ class TestPluginManager(TestCase):
|
||||
# WHEN: We run hook_upgrade_plugin_settings()
|
||||
plugin_manager.hook_upgrade_plugin_settings(settings)
|
||||
|
||||
# THEN: The add_export_menu_Item() method should have been called
|
||||
# THEN: The add_export_menu_item() method should have been called
|
||||
mocked_plugin.upgrade_settings.assert_called_with(settings)
|
||||
|
||||
def hook_tools_menu_with_disabled_plugin_test(self):
|
||||
|
@ -86,4 +86,4 @@ class TestRenderer(TestCase):
|
||||
self.assertEqual(renderer.width, 1024, 'The base renderer should be a live controller')
|
||||
self.assertEqual(renderer.height, 768, 'The base renderer should be a live controller')
|
||||
self.assertEqual(renderer.screen_ratio, 0.75, 'The base renderer should be a live controller')
|
||||
self.assertEqual(renderer.footer_start, 691, 'The base renderer should be a live controller')
|
||||
self.assertEqual(renderer.footer_start, 691, 'The base renderer should be a live controller')
|
||||
|
@ -69,4 +69,3 @@ class TestTheme(TestCase):
|
||||
'The theme should have a font_footer_name of Arial')
|
||||
self.assertTrue(default_theme.font_main_bold is False, 'The theme should have a font_main_bold of false')
|
||||
self.assertTrue(len(default_theme.__dict__) == 47, 'The theme should have 47 variables')
|
||||
|
||||
|
@ -81,3 +81,20 @@ class TestUi(TestCase):
|
||||
self.assertIsInstance(btnbox, QtGui.QDialogButtonBox)
|
||||
self.assertEqual(1, len(btnbox.buttons()))
|
||||
self.assertEqual(QtGui.QDialogButtonBox.HelpRole, btnbox.buttonRole(btnbox.buttons()[0]))
|
||||
|
||||
def test_create_valign_selection_widgets(self):
|
||||
"""
|
||||
Test creating a combo box for valign selection
|
||||
"""
|
||||
# GIVEN: A dialog
|
||||
dialog = QtGui.QDialog()
|
||||
|
||||
# WHEN: We create the widgets
|
||||
label, combo = create_valign_selection_widgets(dialog)
|
||||
|
||||
# THEN: We should get a label and a combobox.
|
||||
self.assertEqual(translate('OpenLP.Ui', '&Vertical Align:'), label.text())
|
||||
self.assertIsInstance(combo, QtGui.QComboBox)
|
||||
self.assertEqual(combo, label.buddy())
|
||||
for text in [UiStrings().Top, UiStrings().Middle, UiStrings().Bottom]:
|
||||
self.assertTrue(combo.findText(text) >= 0)
|
||||
|
@ -72,9 +72,10 @@ class TestFormattingTagController(TestCase):
|
||||
|
||||
# THEN: The result should match the predetermined value.
|
||||
self.assertTrue(result == test['gen'],
|
||||
'Function should handle end tag correctly : %s and %s for %s ' % (test['gen'], result, test['start']))
|
||||
self.assertTrue(error == test['valid'],
|
||||
'Function should not generate unexpected error messages : %s ' % error)
|
||||
'Function should handle end tag correctly : %s and %s for %s ' %
|
||||
(test['gen'], result, test['start']))
|
||||
self.assertTrue(error == test['valid'], 'Function should not generate unexpected error messages : %s ' %
|
||||
error)
|
||||
|
||||
def test_start_tag_changed_processes_correctly(self):
|
||||
"""
|
||||
@ -94,10 +95,10 @@ class TestFormattingTagController(TestCase):
|
||||
error, result = self.services.start_tag_changed(test['start'], test['end'])
|
||||
|
||||
# THEN: The result should match the predetermined value.
|
||||
self.assertTrue(result == test['gen'],
|
||||
'Function should handle end tag correctly : %s and %s ' % (test['gen'], result))
|
||||
self.assertTrue(error == test['valid'],
|
||||
'Function should not generate unexpected error messages : %s ' % error)
|
||||
self.assertTrue(result == test['gen'], 'Function should handle end tag correctly : %s and %s ' %
|
||||
(test['gen'], result))
|
||||
self.assertTrue(error == test['valid'], 'Function should not generate unexpected error messages : %s ' %
|
||||
error)
|
||||
|
||||
def test_start_html_to_end_html(self):
|
||||
"""
|
||||
@ -112,5 +113,5 @@ class TestFormattingTagController(TestCase):
|
||||
result = self.services.start_html_to_end_html(test1)
|
||||
|
||||
# THEN: The result should match the predetermined value.
|
||||
self.assertTrue(result == test2, 'Calculated end tag should be valid: %s and %s = %s'
|
||||
% (test1, test2, result))
|
||||
self.assertTrue(result == test2, 'Calculated end tag should be valid: %s and %s = %s' %
|
||||
(test1, test2, result))
|
||||
|
@ -74,4 +74,3 @@ class TestFormattingTagForm(TestCase):
|
||||
|
||||
# THEN: setEnabled and setDefault should have been called on save_push_button
|
||||
#form.save_button.setEnabled.assert_called_with(True)
|
||||
|
||||
|
97
tests/functional/openlp_core_ui/test_mainwindow.py
Normal file
97
tests/functional/openlp_core_ui/test_mainwindow.py
Normal file
@ -0,0 +1,97 @@
|
||||
# -*- 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 #
|
||||
###############################################################################
|
||||
"""
|
||||
Package to test openlp.core.ui.mainwindow package.
|
||||
"""
|
||||
import os
|
||||
|
||||
from unittest import TestCase
|
||||
|
||||
from openlp.core.ui.mainwindow import MainWindow
|
||||
from openlp.core.common.registry import Registry
|
||||
from tests.utils.constants import TEST_RESOURCES_PATH
|
||||
from tests.helpers.testmixin import TestMixin
|
||||
from tests.functional import MagicMock, patch
|
||||
|
||||
|
||||
class TestMainWindow(TestCase, TestMixin):
|
||||
|
||||
def setUp(self):
|
||||
Registry.create()
|
||||
self.registry = Registry()
|
||||
self.get_application()
|
||||
# Mock cursor busy/normal methods.
|
||||
self.app.set_busy_cursor = MagicMock()
|
||||
self.app.set_normal_cursor = MagicMock()
|
||||
self.app.args = []
|
||||
Registry().register('application', self.app)
|
||||
# Mock classes and methods used by mainwindow.
|
||||
with patch('openlp.core.ui.mainwindow.SettingsForm') as mocked_settings_form, \
|
||||
patch('openlp.core.ui.mainwindow.ImageManager') as mocked_image_manager, \
|
||||
patch('openlp.core.ui.mainwindow.LiveController') as mocked_live_controller, \
|
||||
patch('openlp.core.ui.mainwindow.PreviewController') as mocked_preview_controller, \
|
||||
patch('openlp.core.ui.mainwindow.OpenLPDockWidget') as mocked_dock_widget, \
|
||||
patch('openlp.core.ui.mainwindow.QtGui.QToolBox') as mocked_q_tool_box_class, \
|
||||
patch('openlp.core.ui.mainwindow.QtGui.QMainWindow.addDockWidget') as mocked_add_dock_method, \
|
||||
patch('openlp.core.ui.mainwindow.ThemeManager') as mocked_theme_manager, \
|
||||
patch('openlp.core.ui.mainwindow.Renderer') as mocked_renderer:
|
||||
self.main_window = MainWindow()
|
||||
|
||||
def tearDown(self):
|
||||
del self.main_window
|
||||
|
||||
def cmd_line_file_test(self):
|
||||
"""
|
||||
Test that passing a service file from the command line loads the service.
|
||||
"""
|
||||
# GIVEN a service as an argument to openlp
|
||||
service = os.path.join(TEST_RESOURCES_PATH, 'service', 'test.osz')
|
||||
self.main_window.arguments = [service]
|
||||
with patch('openlp.core.ui.servicemanager.ServiceManager.load_file') as mocked_load_path:
|
||||
|
||||
# WHEN the argument is processed
|
||||
self.main_window.open_cmd_line_files()
|
||||
|
||||
# THEN the service from the arguments is loaded
|
||||
mocked_load_path.assert_called_with(service), 'load_path should have been called with the service\'s path'
|
||||
|
||||
def cmd_line_arg_test(self):
|
||||
"""
|
||||
Test that passing a non service file does nothing.
|
||||
"""
|
||||
# GIVEN a non service file as an argument to openlp
|
||||
service = os.path.join('openlp.py')
|
||||
self.main_window.arguments = [service]
|
||||
with patch('openlp.core.ui.servicemanager.ServiceManager.load_file') as mocked_load_path:
|
||||
|
||||
# WHEN the argument is processed
|
||||
self.main_window.open_cmd_line_files()
|
||||
|
||||
# THEN the file should not be opened
|
||||
assert not mocked_load_path.called, 'load_path should not have been called'
|
@ -74,4 +74,4 @@ class TestServiceManager(TestCase):
|
||||
# THEN: The the controller should be registered in the registry.
|
||||
self.assertNotEqual(service, None, 'The base service should be created')
|
||||
self.assertEqual(service['openlp_core']['service-theme'], 'test_theme', 'The test theme should be saved')
|
||||
self.assertEqual(service['openlp_core']['lite-service'], False, 'The lite service should be saved')
|
||||
self.assertEqual(service['openlp_core']['lite-service'], False, 'The lite service should be saved')
|
||||
|
@ -25,4 +25,4 @@
|
||||
# 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 #
|
||||
###############################################################################
|
||||
###############################################################################
|
||||
|
@ -149,5 +149,3 @@ class TestActionList(TestCase, TestMixin):
|
||||
# THEN: Both action should keep their shortcuts.
|
||||
assert len(action3.shortcuts()) == 2, 'The action should have two shortcut assigned.'
|
||||
assert len(action_with_same_shortcuts3.shortcuts()) == 2, 'The action should have two shortcuts assigned.'
|
||||
|
||||
|
||||
|
@ -107,7 +107,7 @@ class TestUtils(TestCase):
|
||||
"""
|
||||
# GIVEN: sys.getfilesystemencoding returns "cp1252"
|
||||
with patch('openlp.core.utils.sys.getfilesystemencoding') as mocked_getfilesystemencoding, \
|
||||
patch('openlp.core.utils.sys.getdefaultencoding') as mocked_getdefaultencoding:
|
||||
patch('openlp.core.utils.sys.getdefaultencoding') as mocked_getdefaultencoding:
|
||||
mocked_getfilesystemencoding.return_value = 'cp1252'
|
||||
|
||||
# WHEN: get_filesystem_encoding() is called
|
||||
@ -124,7 +124,7 @@ class TestUtils(TestCase):
|
||||
"""
|
||||
# GIVEN: sys.getfilesystemencoding returns None and sys.getdefaultencoding returns "utf-8"
|
||||
with patch('openlp.core.utils.sys.getfilesystemencoding') as mocked_getfilesystemencoding, \
|
||||
patch('openlp.core.utils.sys.getdefaultencoding') as mocked_getdefaultencoding:
|
||||
patch('openlp.core.utils.sys.getdefaultencoding') as mocked_getdefaultencoding:
|
||||
mocked_getfilesystemencoding.return_value = None
|
||||
mocked_getdefaultencoding.return_value = 'utf-8'
|
||||
|
||||
@ -175,7 +175,7 @@ class TestUtils(TestCase):
|
||||
|
||||
# THEN: A tuple should be returned.
|
||||
self.assertEqual(wanted_result, result,
|
||||
'A two-entry tuple with the directory and file name (empty) should have been returned.')
|
||||
'A two-entry tuple with the directory and file name (empty) should have been returned.')
|
||||
|
||||
def clean_filename_test(self):
|
||||
"""
|
||||
@ -206,7 +206,7 @@ class TestUtils(TestCase):
|
||||
|
||||
# THEN: We get a properly sorted list
|
||||
self.assertEqual(['Aushang', '\u00C4u\u00DFerung', 'Auszug'], sorted_list,
|
||||
'Strings should be sorted properly')
|
||||
'Strings should be sorted properly')
|
||||
|
||||
def get_natural_key_test(self):
|
||||
"""
|
||||
|
@ -26,4 +26,3 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
|
@ -116,7 +116,8 @@ class TestBSExtract(TestCase):
|
||||
self.mock_get_soup_for_bible_ref.assert_called_once_with(
|
||||
'http://m.bibleserver.com/overlay/selectBook?translation=NIV')
|
||||
self.assertIsNone(result,
|
||||
'BSExtract.get_books_from_http should return None when get_soup_for_bible_ref returns a false value')
|
||||
'BSExtract.get_books_from_http should return None when get_soup_for_bible_ref returns a '
|
||||
'false value')
|
||||
|
||||
def get_books_from_http_no_content_test(self):
|
||||
"""
|
||||
@ -146,7 +147,8 @@ class TestBSExtract(TestCase):
|
||||
self.mock_log.error.assert_called_once_with('No books found in the Bibleserver response.')
|
||||
self.mock_send_error_message.assert_called_once_with('parse')
|
||||
self.assertIsNone(result,
|
||||
'BSExtract.get_books_from_http should return None when get_soup_for_bible_ref returns a false value')
|
||||
'BSExtract.get_books_from_http should return None when get_soup_for_bible_ref returns a '
|
||||
'false value')
|
||||
|
||||
def get_books_from_http_content_test(self):
|
||||
"""
|
||||
|
@ -85,5 +85,3 @@ class TestLib(TestCase):
|
||||
|
||||
# THEN: It should be False
|
||||
self.assertFalse(has_verse_list, 'The SearchResults object should have a verse list')
|
||||
|
||||
|
||||
|
@ -25,4 +25,4 @@
|
||||
# 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 #
|
||||
###############################################################################
|
||||
###############################################################################
|
||||
|
@ -108,7 +108,7 @@ class TestImageMediaItem(TestCase):
|
||||
Test that the save_new_images_list() saves all images in the list
|
||||
"""
|
||||
# GIVEN: A list with 3 images
|
||||
image_list = [ 'test_image_1.jpg', 'test_image_2.jpg', 'test_image_3.jpg' ]
|
||||
image_list = ['test_image_1.jpg', 'test_image_2.jpg', 'test_image_3.jpg']
|
||||
with patch('openlp.plugins.images.lib.mediaitem.ImageMediaItem.load_full_list') as mocked_load_full_list:
|
||||
self.media_item.manager = MagicMock()
|
||||
|
||||
@ -124,7 +124,7 @@ class TestImageMediaItem(TestCase):
|
||||
Test that the save_new_images_list() ignores everything in the provided list except strings
|
||||
"""
|
||||
# GIVEN: A list with images and objects
|
||||
image_list = [ 'test_image_1.jpg', None, True, ImageFilenames(), 'test_image_2.jpg' ]
|
||||
image_list = ['test_image_1.jpg', None, True, ImageFilenames(), 'test_image_2.jpg']
|
||||
with patch('openlp.plugins.images.lib.mediaitem.ImageMediaItem.load_full_list') as mocked_load_full_list:
|
||||
self.media_item.manager = MagicMock()
|
||||
|
||||
@ -171,7 +171,7 @@ class TestImageMediaItem(TestCase):
|
||||
assert self.media_item.manager.delete_object.call_count == 7, \
|
||||
'manager.delete_object() should be called exactly 7 times'
|
||||
|
||||
# CLEANUP: Remove added attribute from ImageFilenames and ImageGroups
|
||||
# CLEANUP: Remove added attribute from Image Filenames and ImageGroups
|
||||
delattr(ImageFilenames, 'group_id')
|
||||
delattr(ImageGroups, 'parent_id')
|
||||
|
||||
|
@ -25,4 +25,4 @@
|
||||
# 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 #
|
||||
###############################################################################
|
||||
###############################################################################
|
||||
|
@ -33,6 +33,7 @@ import os
|
||||
import shutil
|
||||
from unittest import TestCase, SkipTest
|
||||
from tempfile import mkdtemp
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.plugins.presentations.lib.pdfcontroller import PdfController, PdfDocument
|
||||
from tests.functional import MagicMock
|
||||
@ -45,6 +46,12 @@ __default_settings__ = {
|
||||
'presentations/enable_pdf_program': False
|
||||
}
|
||||
|
||||
SCREEN = {
|
||||
'primary': False,
|
||||
'number': 1,
|
||||
'size': QtCore.QRect(0, 0, 1024, 768)
|
||||
}
|
||||
|
||||
|
||||
class TestPdfController(TestCase, TestMixin):
|
||||
"""
|
||||
@ -56,7 +63,12 @@ class TestPdfController(TestCase, TestMixin):
|
||||
"""
|
||||
self.get_application()
|
||||
self.build_settings()
|
||||
ScreenList.create(self.app.desktop())
|
||||
# Mocked out desktop object
|
||||
self.desktop = MagicMock()
|
||||
self.desktop.primaryScreen.return_value = SCREEN['primary']
|
||||
self.desktop.screenCount.return_value = SCREEN['number']
|
||||
self.desktop.screenGeometry.return_value = SCREEN['size']
|
||||
self.screens = ScreenList.create(self.desktop)
|
||||
Settings().extend_default_settings(__default_settings__)
|
||||
self.temp_folder = mkdtemp()
|
||||
self.thumbnail_folder = mkdtemp()
|
||||
@ -67,12 +79,10 @@ class TestPdfController(TestCase, TestMixin):
|
||||
"""
|
||||
Delete all the C++ objects at the end so that we don't have a segfault
|
||||
"""
|
||||
try:
|
||||
self.destroy_settings()
|
||||
shutil.rmtree(self.thumbnail_folder)
|
||||
shutil.rmtree(self.temp_folder)
|
||||
except OSError:
|
||||
pass
|
||||
del self.screens
|
||||
self.destroy_settings()
|
||||
shutil.rmtree(self.thumbnail_folder)
|
||||
shutil.rmtree(self.temp_folder)
|
||||
|
||||
def constructor_test(self):
|
||||
"""
|
||||
@ -106,3 +116,30 @@ class TestPdfController(TestCase, TestMixin):
|
||||
# THEN: The load should succeed and we should be able to get a pagecount
|
||||
self.assertTrue(loaded, 'The loading of the PDF should succeed.')
|
||||
self.assertEqual(3, document.get_slide_count(), 'The pagecount of the PDF should be 3.')
|
||||
|
||||
def load_pdf_pictures_test(self):
|
||||
"""
|
||||
Test loading of a Pdf and check size of generate pictures
|
||||
"""
|
||||
# GIVEN: A Pdf-file
|
||||
test_file = os.path.join(TEST_RESOURCES_PATH, 'presentations', 'pdf_test1.pdf')
|
||||
|
||||
# WHEN: The Pdf is loaded
|
||||
controller = PdfController(plugin=self.mock_plugin)
|
||||
if not controller.check_available():
|
||||
raise SkipTest('Could not detect mudraw or ghostscript, so skipping PDF test')
|
||||
controller.temp_folder = self.temp_folder
|
||||
controller.thumbnail_folder = self.thumbnail_folder
|
||||
document = PdfDocument(controller, test_file)
|
||||
loaded = document.load_presentation()
|
||||
|
||||
# THEN: The load should succeed and pictures should be created and have been scales to fit the screen
|
||||
self.assertTrue(loaded, 'The loading of the PDF should succeed.')
|
||||
image = QtGui.QImage(os.path.join(self.temp_folder, 'pdf_test1.pdf', 'mainslide001.png'))
|
||||
# Based on the converter used the resolution will differ a bit
|
||||
if controller.gsbin:
|
||||
self.assertEqual(760, image.height(), 'The height should be 760')
|
||||
self.assertEqual(537, image.width(), 'The width should be 537')
|
||||
else:
|
||||
self.assertEqual(767, image.height(), 'The height should be 767')
|
||||
self.assertEqual(543, image.width(), 'The width should be 543')
|
||||
|
@ -80,7 +80,8 @@ class TestPptviewController(TestCase, TestMixin):
|
||||
controller = PptviewController(plugin=self.mock_plugin)
|
||||
|
||||
# THEN: The name of the presentation controller should be correct
|
||||
self.assertEqual('Powerpoint Viewer', controller.name, 'The name of the presentation controller should be correct')
|
||||
self.assertEqual('Powerpoint Viewer', controller.name,
|
||||
'The name of the presentation controller should be correct')
|
||||
|
||||
def check_available_test(self):
|
||||
"""
|
||||
@ -98,9 +99,9 @@ class TestPptviewController(TestCase, TestMixin):
|
||||
|
||||
# THEN: On windows it should return True, on other platforms False
|
||||
if os.name == 'nt':
|
||||
self.assertTrue(available, 'check_available should return True on windows.')
|
||||
self.assertTrue(available, 'check_available should return True on windows.')
|
||||
else:
|
||||
self.assertFalse(available, 'check_available should return False when not on windows.')
|
||||
self.assertFalse(available, 'check_available should return False when not on windows.')
|
||||
|
||||
|
||||
class TestPptviewDocument(TestCase):
|
||||
|
@ -25,4 +25,4 @@
|
||||
# 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 #
|
||||
###############################################################################
|
||||
###############################################################################
|
||||
|
@ -111,7 +111,8 @@ class TestRouter(TestCase, TestMixin):
|
||||
Test the get_content_type logic
|
||||
"""
|
||||
# GIVEN: a set of files and their corresponding types
|
||||
headers = [ ['test.html', 'text/html'], ['test.css', 'text/css'],
|
||||
headers = [
|
||||
['test.html', 'text/html'], ['test.css', 'text/css'],
|
||||
['test.js', 'application/javascript'], ['test.jpg', 'image/jpeg'],
|
||||
['test.gif', 'image/gif'], ['test.ico', 'image/x-icon'],
|
||||
['test.png', 'image/png'], ['test.whatever', 'text/plain'],
|
||||
@ -142,7 +143,7 @@ class TestRouter(TestCase, TestMixin):
|
||||
|
||||
# THEN: it should return a 404
|
||||
self.router.send_response.assert_called_once_with(404)
|
||||
self.router.send_header.assert_called_once_with('Content-type','text/html')
|
||||
self.router.send_header.assert_called_once_with('Content-type', 'text/html')
|
||||
self.assertEqual(self.router.end_headers.call_count, 1, 'end_headers called once')
|
||||
|
||||
def serve_file_with_valid_params_test(self):
|
||||
|
@ -41,33 +41,33 @@ TEST_PATH = os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'easyworshipsongs'))
|
||||
SONG_TEST_DATA = [
|
||||
{'title': 'Amazing Grace',
|
||||
'authors': ['John Newton'],
|
||||
'copyright': 'Public Domain',
|
||||
'ccli_number': 0,
|
||||
'verses':
|
||||
[('Amazing grace how sweet the sound,\nThat saved a wretch like me;\n'
|
||||
'I once was lost, but now am found\nWas blind, but now I see.', 'v1'),
|
||||
('T\'was grace that taught my heart to fear,\nAnd grace my fears relieved;\n'
|
||||
'How precious did that grace appear\nThe hour I first believed.', 'v2'),
|
||||
('Through many dangers, toil and snares,\nI have already come;\n'
|
||||
'\'Tis grace has brought me safe thus far,\nAnd grace will lead me home.', 'v3'),
|
||||
('When we\'ve been there ten thousand years\nBright shining as the sun,\n'
|
||||
'We\'ve no less days to sing God\'s praise\nThan when we\'ve first begun.', 'v4')],
|
||||
'verse_order_list': []},
|
||||
'authors': ['John Newton'],
|
||||
'copyright': 'Public Domain',
|
||||
'ccli_number': 0,
|
||||
'verses':
|
||||
[('Amazing grace how sweet the sound,\nThat saved a wretch like me;\n'
|
||||
'I once was lost, but now am found\nWas blind, but now I see.', 'v1'),
|
||||
('T\'was grace that taught my heart to fear,\nAnd grace my fears relieved;\n'
|
||||
'How precious did that grace appear\nThe hour I first believed.', 'v2'),
|
||||
('Through many dangers, toil and snares,\nI have already come;\n'
|
||||
'\'Tis grace has brought me safe thus far,\nAnd grace will lead me home.', 'v3'),
|
||||
('When we\'ve been there ten thousand years\nBright shining as the sun,\n'
|
||||
'We\'ve no less days to sing God\'s praise\nThan when we\'ve first begun.', 'v4')],
|
||||
'verse_order_list': []},
|
||||
{'title': 'Beautiful Garden Of Prayer',
|
||||
'authors': ['Eleanor Allen Schroll James H. Fillmore'],
|
||||
'copyright': 'Public Domain',
|
||||
'ccli_number': 0,
|
||||
'verses':
|
||||
[('O the beautiful garden, the garden of prayer,\nO the beautiful garden of prayer.\n'
|
||||
'There my Savior awaits, and He opens the gates\nTo the beautiful garden of prayer.', 'c1'),
|
||||
('There\'s a garden where Jesus is waiting,\nThere\'s a place that is wondrously fair.\n'
|
||||
'For it glows with the light of His presence,\n\'Tis the beautiful garden of prayer.', 'v1'),
|
||||
('There\'s a garden where Jesus is waiting,\nAnd I go with my burden and care.\n'
|
||||
'Just to learn from His lips, words of comfort,\nIn the beautiful garden of prayer.', 'v2'),
|
||||
('There\'s a garden where Jesus is waiting,\nAnd He bids you to come meet Him there,\n'
|
||||
'Just to bow and receive a new blessing,\nIn the beautiful garden of prayer.', 'v3')],
|
||||
'verse_order_list': []}]
|
||||
'authors': ['Eleanor Allen Schroll James H. Fillmore'],
|
||||
'copyright': 'Public Domain',
|
||||
'ccli_number': 0,
|
||||
'verses':
|
||||
[('O the beautiful garden, the garden of prayer,\nO the beautiful garden of prayer.\n'
|
||||
'There my Savior awaits, and He opens the gates\nTo the beautiful garden of prayer.', 'c1'),
|
||||
('There\'s a garden where Jesus is waiting,\nThere\'s a place that is wondrously fair.\n'
|
||||
'For it glows with the light of His presence,\n\'Tis the beautiful garden of prayer.', 'v1'),
|
||||
('There\'s a garden where Jesus is waiting,\nAnd I go with my burden and care.\n'
|
||||
'Just to learn from His lips, words of comfort,\nIn the beautiful garden of prayer.', 'v2'),
|
||||
('There\'s a garden where Jesus is waiting,\nAnd He bids you to come meet Him there,\n'
|
||||
'Just to bow and receive a new blessing,\nIn the beautiful garden of prayer.', 'v3')],
|
||||
'verse_order_list': []}]
|
||||
|
||||
|
||||
class EasyWorshipSongImportLogger(EasyWorshipSongImport):
|
||||
@ -95,26 +95,32 @@ class TestFieldDesc:
|
||||
self.size = size
|
||||
|
||||
TEST_DATA_ENCODING = 'cp1252'
|
||||
CODE_PAGE_MAPPINGS = [(852, 'cp1250'), (737, 'cp1253'), (775, 'cp1257'), (855, 'cp1251'), (857, 'cp1254'),
|
||||
CODE_PAGE_MAPPINGS = [
|
||||
(852, 'cp1250'), (737, 'cp1253'), (775, 'cp1257'), (855, 'cp1251'), (857, 'cp1254'),
|
||||
(866, 'cp1251'), (869, 'cp1253'), (862, 'cp1255'), (874, 'cp874')]
|
||||
TEST_FIELD_DESCS = [TestFieldDesc('Title', FieldType.String, 50),
|
||||
TEST_FIELD_DESCS = [
|
||||
TestFieldDesc('Title', FieldType.String, 50),
|
||||
TestFieldDesc('Text Percentage Bottom', FieldType.Int16, 2), TestFieldDesc('RecID', FieldType.Int32, 4),
|
||||
TestFieldDesc('Default Background', FieldType.Logical, 1), TestFieldDesc('Words', FieldType.Memo, 250),
|
||||
TestFieldDesc('Words', FieldType.Memo, 250), TestFieldDesc('BK Bitmap', FieldType.Blob, 10),
|
||||
TestFieldDesc('Last Modified', FieldType.Timestamp, 10)]
|
||||
TEST_FIELDS = [b'A Heart Like Thine\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', 32868, 2147483750,
|
||||
TEST_FIELDS = [
|
||||
b'A Heart Like Thine\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', 32868, 2147483750,
|
||||
129, b'{\\rtf1\\ansi\\deff0\\deftab254{\\fonttbl{\\f0\\fnil\\fcharset0 Arial;}{\\f1\\fnil\\fcharset0 Verdana;}}'
|
||||
b'{\\colortbl\\red0\\green0\\blue0;\\red255\\green0\\blue0;\\red0\\green128\\blue0;\\red0\\green0\\blue255;'
|
||||
b'\\red255\\green255\\blue0;\\red255\\green0\\blue255;\\red128\\g\xBF\xBD\7\0f\r\0\0\1\0',
|
||||
b'{\\rtf1\\ansi\\deff0\\deftab254{\\fonttbl{\\f0\\fnil\\fcharset0 Arial;}{\\f1\\fnil\\fcharset0 Verdana;}}'
|
||||
b'{\\colortbl\\red0\\green0\\blue0;\\red255\\green0\\blue0;\\red0\\green128\\blue0;\\red0\\green0\\blue255;\\red255'
|
||||
b'\\green255\\blue0;\\red255\\green0\\blue255;\\red128\\g\6\0\xEF\xBF\xBD\6\0\0\1\0', b'\0\0\0\0\0\0\0\0\0\0', 0]
|
||||
b'{\\colortbl\\red0\\green0\\blue0;\\red255\\green0\\blue0;\\red0\\green128\\blue0;\\red0\\green0\\blue255;'
|
||||
b'\\red255\\green255\\blue0;\\red255\\green0\\blue255;\\red128\\g\xBF\xBD\7\0f\r\0\0\1\0',
|
||||
b'{\\rtf1\\ansi\\deff0\\deftab254{\\fonttbl{\\f0\\fnil\\fcharset0 Arial;}{\\f1\\fnil\\fcharset0 Verdana;}}'
|
||||
b'{\\colortbl\\red0\\green0\\blue0;\\red255\\green0\\blue0;\\red0\\green128\\blue0;\\red0\\green0'
|
||||
b'\\blue255;\\red255'
|
||||
b'\\green255\\blue0;\\red255\\green0\\blue255;\\red128\\g\6\0\xEF\xBF\xBD\6\0\0\1\0',
|
||||
b'\0\0\0\0\0\0\0\0\0\0', 0]
|
||||
GET_MEMO_FIELD_TEST_RESULTS = [
|
||||
(4, b'\2', {'return': b'\2','read': (1, 3430), 'seek': (507136, (8, os.SEEK_CUR))}),
|
||||
(4, b'\2', {'return': b'\2', 'read': (1, 3430), 'seek': (507136, (8, os.SEEK_CUR))}),
|
||||
(4, b'\3', {'return': b'', 'read': (1, ), 'seek': (507136, )}),
|
||||
(5, b'\3', {'return': b'\3', 'read': (1, 1725), 'seek': (3220111360, (41, os.SEEK_CUR), 3220111408)}),
|
||||
(5, b'\4', {'return': b'', 'read': (), 'seek': ()})]
|
||||
|
||||
|
||||
class TestEasyWorshipSongImport(TestCase):
|
||||
"""
|
||||
Test the functions in the :mod:`ewimport` module.
|
||||
@ -135,7 +141,7 @@ class TestEasyWorshipSongImport(TestCase):
|
||||
self.assertIsNotNone(field_desc_entry, 'Import should not be none')
|
||||
self.assertEquals(field_desc_entry.name, name, 'FieldDescEntry.name should be the same as the name argument')
|
||||
self.assertEquals(field_desc_entry.field_type, field_type,
|
||||
'FieldDescEntry.type should be the same as the typeargument')
|
||||
'FieldDescEntry.type should be the same as the type argument')
|
||||
self.assertEquals(field_desc_entry.size, size, 'FieldDescEntry.size should be the same as the size argument')
|
||||
|
||||
def create_importer_test(self):
|
||||
@ -164,7 +170,7 @@ class TestEasyWorshipSongImport(TestCase):
|
||||
|
||||
# WHEN: Called with a field name that exists
|
||||
existing_fields = ['Title', 'Text Percentage Bottom', 'RecID', 'Default Background', 'Words',
|
||||
'BK Bitmap', 'Last Modified']
|
||||
'BK Bitmap', 'Last Modified']
|
||||
for field_name in existing_fields:
|
||||
|
||||
# THEN: The item corresponding the index returned should have the same name attribute
|
||||
@ -194,7 +200,7 @@ class TestEasyWorshipSongImport(TestCase):
|
||||
# GIVEN: A mocked out SongImport class, a mocked out struct class, and a mocked out "manager" and a list of
|
||||
# field descriptions
|
||||
with patch('openlp.plugins.songs.lib.ewimport.SongImport'), \
|
||||
patch('openlp.plugins.songs.lib.ewimport.struct') as mocked_struct:
|
||||
patch('openlp.plugins.songs.lib.ewimport.struct') as mocked_struct:
|
||||
mocked_manager = MagicMock()
|
||||
importer = EasyWorshipSongImport(mocked_manager, filenames=[])
|
||||
|
||||
@ -225,7 +231,8 @@ class TestEasyWorshipSongImport(TestCase):
|
||||
|
||||
# THEN: get_field should return the known results
|
||||
self.assertEquals(return_value, result,
|
||||
'get_field should return "%s" when called with "%s"' % (result, TEST_FIELDS[field_index]))
|
||||
'get_field should return "%s" when called with "%s"' %
|
||||
(result, TEST_FIELDS[field_index]))
|
||||
|
||||
def get_memo_field_test(self):
|
||||
"""
|
||||
@ -265,7 +272,7 @@ class TestEasyWorshipSongImport(TestCase):
|
||||
"""
|
||||
# GIVEN: A mocked out SongImport class, a mocked out "manager"
|
||||
with patch('openlp.plugins.songs.lib.ewimport.SongImport'), \
|
||||
patch('openlp.plugins.songs.lib.ewimport.os.path') as mocked_os_path:
|
||||
patch('openlp.plugins.songs.lib.ewimport.os.path') as mocked_os_path:
|
||||
mocked_manager = MagicMock()
|
||||
importer = EasyWorshipSongImport(mocked_manager, filenames=[])
|
||||
mocked_os_path.isfile.side_effect = [True, False]
|
||||
@ -284,7 +291,7 @@ class TestEasyWorshipSongImport(TestCase):
|
||||
"""
|
||||
# GIVEN: A mocked out SongImport class, os.path and a mocked out "manager"
|
||||
with patch('openlp.plugins.songs.lib.ewimport.SongImport'), \
|
||||
patch('openlp.plugins.songs.lib.ewimport.os.path') as mocked_os_path:
|
||||
patch('openlp.plugins.songs.lib.ewimport.os.path') as mocked_os_path:
|
||||
mocked_manager = MagicMock()
|
||||
importer = EasyWorshipSongImport(mocked_manager, filenames=[])
|
||||
mocked_os_path.isfile.return_value = True
|
||||
@ -305,7 +312,7 @@ class TestEasyWorshipSongImport(TestCase):
|
||||
with patch('openlp.plugins.songs.lib.ewimport.SongImport'), \
|
||||
patch('openlp.plugins.songs.lib.ewimport.os.path') as mocked_os_path, \
|
||||
patch('builtins.open') as mocked_open, \
|
||||
patch('openlp.plugins.songs.lib.ewimport.struct') as mocked_struct:
|
||||
patch('openlp.plugins.songs.lib.ewimport.struct') as mocked_struct:
|
||||
mocked_manager = MagicMock()
|
||||
importer = EasyWorshipSongImport(mocked_manager, filenames=[])
|
||||
mocked_os_path.isfile.return_value = True
|
||||
@ -320,7 +327,7 @@ class TestEasyWorshipSongImport(TestCase):
|
||||
for effect in struct_unpack_return_values:
|
||||
self.assertIsNone(importer.do_import(), 'do_import should return None when db_size is less than 0x800')
|
||||
self.assertEqual(mocked_open().close.call_count, 2,
|
||||
'The open db and memo files should have been closed')
|
||||
'The open db and memo files should have been closed')
|
||||
mocked_open().close.reset_mock()
|
||||
self.assertIs(mocked_open().seek.called, False, 'db_file.seek should not have been called.')
|
||||
|
||||
@ -332,7 +339,8 @@ class TestEasyWorshipSongImport(TestCase):
|
||||
with patch('openlp.plugins.songs.lib.ewimport.SongImport'), \
|
||||
patch('openlp.plugins.songs.lib.ewimport.os.path') as mocked_os_path, \
|
||||
patch('builtins.open'), patch('openlp.plugins.songs.lib.ewimport.struct') as mocked_struct, \
|
||||
patch('openlp.plugins.songs.lib.ewimport.retrieve_windows_encoding') as mocked_retrieve_windows_encoding:
|
||||
patch('openlp.plugins.songs.lib.ewimport.retrieve_windows_encoding') as \
|
||||
mocked_retrieve_windows_encoding:
|
||||
mocked_manager = MagicMock()
|
||||
importer = EasyWorshipSongImport(mocked_manager, filenames=[])
|
||||
mocked_os_path.isfile.return_value = True
|
||||
@ -357,7 +365,8 @@ class TestEasyWorshipSongImport(TestCase):
|
||||
# GIVEN: Test files with a mocked out SongImport class, a mocked out "manager", a mocked out "import_wizard",
|
||||
# and mocked out "author", "add_copyright", "add_verse", "finish" methods.
|
||||
with patch('openlp.plugins.songs.lib.ewimport.SongImport'), \
|
||||
patch('openlp.plugins.songs.lib.ewimport.retrieve_windows_encoding') as mocked_retrieve_windows_encoding:
|
||||
patch('openlp.plugins.songs.lib.ewimport.retrieve_windows_encoding') as \
|
||||
mocked_retrieve_windows_encoding:
|
||||
mocked_retrieve_windows_encoding.return_value = 'cp1252'
|
||||
mocked_manager = MagicMock()
|
||||
mocked_import_wizard = MagicMock()
|
||||
@ -395,10 +404,10 @@ class TestEasyWorshipSongImport(TestCase):
|
||||
self.assertEqual(importer.copyright, song_copyright)
|
||||
if ccli_number:
|
||||
self.assertEquals(importer.ccli_number, ccli_number, 'ccli_number for %s should be %s'
|
||||
% (title, ccli_number))
|
||||
% (title, ccli_number))
|
||||
for verse_text, verse_tag in add_verse_calls:
|
||||
mocked_add_verse.assert_any_call(verse_text, verse_tag)
|
||||
if verse_order_list:
|
||||
self.assertEquals(importer.verse_order_list, verse_order_list, 'verse_order_list for %s should be %s'
|
||||
% (title, verse_order_list))
|
||||
self.assertEquals(importer.verse_order_list, verse_order_list,
|
||||
'verse_order_list for %s should be %s' % (title, verse_order_list))
|
||||
mocked_finish.assert_called_with()
|
||||
|
@ -44,20 +44,20 @@ class TestLib(TestCase):
|
||||
"""
|
||||
Mock up two songs and provide a set of lyrics for the songs_probably_equal tests.
|
||||
"""
|
||||
self.full_lyrics ='''amazing grace how sweet the sound that saved a wretch like me i once was lost but now am
|
||||
self.full_lyrics = '''amazing grace how sweet the sound that saved a wretch like me i once was lost but now am
|
||||
found was blind but now i see twas grace that taught my heart to fear and grace my fears relieved how
|
||||
precious did that grace appear the hour i first believed through many dangers toils and snares i have already
|
||||
come tis grace that brought me safe thus far and grace will lead me home'''
|
||||
self.short_lyrics ='''twas grace that taught my heart to fear and grace my fears relieved how precious did that
|
||||
grace appear the hour i first believed'''
|
||||
self.error_lyrics ='''amazing how sweet the trumpet that saved a wrench like me i once was losst but now am
|
||||
precious did that grace appear the hour i first believed through many dangers toils and snares i have
|
||||
already come tis grace that brought me safe thus far and grace will lead me home'''
|
||||
self.short_lyrics = '''twas grace that taught my heart to fear and grace my fears relieved how precious did
|
||||
that grace appear the hour i first believed'''
|
||||
self.error_lyrics = '''amazing how sweet the trumpet that saved a wrench like me i once was losst but now am
|
||||
found waf blind but now i see it was grace that taught my heart to fear and grace my fears relieved how
|
||||
precious did that grace appppppppear the hour i first believedxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx snares i have
|
||||
already come to this grace that brought me safe so far and grace will lead me home'''
|
||||
self.different_lyrics='''on a hill far away stood an old rugged cross the emblem of suffering and shame and i love
|
||||
that old cross where the dearest and best for a world of lost sinners was slain so ill cherish the old rugged
|
||||
cross till my trophies at last i lay down i will cling to the old rugged cross and exchange it some day for a
|
||||
crown'''
|
||||
self.different_lyrics = '''on a hill far away stood an old rugged cross the emblem of suffering and shame and
|
||||
i love that old cross where the dearest and best for a world of lost sinners was slain so ill cherish the
|
||||
old rugged cross till my trophies at last i lay down i will cling to the old rugged cross and exchange it
|
||||
some day for a crown'''
|
||||
self.song1 = MagicMock()
|
||||
self.song2 = MagicMock()
|
||||
|
||||
@ -99,7 +99,7 @@ class TestLib(TestCase):
|
||||
result = songs_probably_equal(self.song1, self.song2)
|
||||
|
||||
# THEN: The result should be True.
|
||||
assert result == True, 'The result should be True'
|
||||
assert result is True, 'The result should be True'
|
||||
|
||||
def songs_probably_equal_short_song_test(self):
|
||||
"""
|
||||
@ -113,7 +113,7 @@ class TestLib(TestCase):
|
||||
result = songs_probably_equal(self.song1, self.song2)
|
||||
|
||||
# THEN: The result should be True.
|
||||
assert result == True, 'The result should be True'
|
||||
assert result is True, 'The result should be True'
|
||||
|
||||
def songs_probably_equal_error_song_test(self):
|
||||
"""
|
||||
@ -127,7 +127,7 @@ class TestLib(TestCase):
|
||||
result = songs_probably_equal(self.song1, self.song2)
|
||||
|
||||
# THEN: The result should be True.
|
||||
assert result == True, 'The result should be True'
|
||||
assert result is True, 'The result should be True'
|
||||
|
||||
def songs_probably_equal_different_song_test(self):
|
||||
"""
|
||||
@ -141,7 +141,7 @@ class TestLib(TestCase):
|
||||
result = songs_probably_equal(self.song1, self.song2)
|
||||
|
||||
# THEN: The result should be False.
|
||||
assert result == False, 'The result should be False'
|
||||
assert result is False, 'The result should be False'
|
||||
|
||||
def remove_typos_beginning_test(self):
|
||||
"""
|
||||
@ -267,8 +267,8 @@ class TestLib(TestCase):
|
||||
|
||||
# WHEN: We call strip_rtf on the input RTF
|
||||
result, result_enc = strip_rtf(
|
||||
'{\\rtf1 \\ansi \\ansicpg1252 {\\fonttbl \\f0 \\fswiss \\fcharset%s Helvetica;}' \
|
||||
'{\\colortbl ;\\red0 \\green0 \\blue0 ;}\\pard \\f0 %s}' % (charset, input))
|
||||
'{\\rtf1 \\ansi \\ansicpg1252 {\\fonttbl \\f0 \\fswiss \\fcharset%s Helvetica;}'
|
||||
'{\\colortbl ;\\red0 \\green0 \\blue0 ;}\\pard \\f0 %s}' % (charset, input))
|
||||
|
||||
# THEN: The stripped text matches thed expected result
|
||||
assert result == exp_result, 'The result should be %s' % exp_result
|
||||
|
@ -110,7 +110,7 @@ class TestSongBeamerImport(TestCase):
|
||||
# THEN: do_import should return none and the progress bar setMaximum should be called with the length of
|
||||
# import_source.
|
||||
self.assertIsNone(importer.do_import(),
|
||||
'do_import should return None when import_source is a list and stop_import_flag is True')
|
||||
'do_import should return None when import_source is a list and stop_import_flag is True')
|
||||
mocked_import_wizard.progress_bar.setMaximum.assert_called_with(len(importer.import_source))
|
||||
|
||||
def file_import_test(self):
|
||||
@ -147,9 +147,9 @@ class TestSongBeamerImport(TestCase):
|
||||
for verse_text, verse_tag in add_verse_calls:
|
||||
mocked_add_verse.assert_any_call(verse_text, verse_tag)
|
||||
if song_book_name:
|
||||
self.assertEquals(importer.song_book_name, song_book_name, 'song_book_name for %s should be "%s"'
|
||||
% (song_file, song_book_name))
|
||||
self.assertEquals(importer.song_book_name, song_book_name, 'song_book_name for %s should be "%s"' %
|
||||
(song_file, song_book_name))
|
||||
if song_number:
|
||||
self.assertEquals(importer.song_number, song_number, 'song_number for %s should be %s'
|
||||
% (song_file, song_number))
|
||||
self.assertEquals(importer.song_number, song_number, 'song_number for %s should be %s' %
|
||||
(song_file, song_number))
|
||||
mocked_finish.assert_called_with()
|
||||
|
@ -352,7 +352,7 @@ class TestSongSelect(TestCase):
|
||||
"""
|
||||
# GIVEN: A song to save, and some mocked out objects
|
||||
with patch('openlp.plugins.songs.lib.songselect.clean_song') as mocked_clean_song, \
|
||||
patch('openlp.plugins.songs.lib.songselect.Author') as MockedAuthor:
|
||||
patch('openlp.plugins.songs.lib.songselect.Author') as MockedAuthor:
|
||||
song_dict = {
|
||||
'title': 'Arky Arky',
|
||||
'authors': ['Public Domain'],
|
||||
|
@ -115,8 +115,8 @@ class TestSongShowPlusImport(TestCase):
|
||||
|
||||
# THEN: do_import should return none and the progress bar setMaximum should be called with the length of
|
||||
# import_source.
|
||||
self.assertIsNone(importer.do_import(),
|
||||
'do_import should return None when import_source is a list and stop_import_flag is True')
|
||||
self.assertIsNone(importer.do_import(), 'do_import should return None when import_source is a list '
|
||||
'and stop_import_flag is True')
|
||||
mocked_import_wizard.progress_bar.setMaximum.assert_called_with(len(importer.import_source))
|
||||
|
||||
def to_openlp_verse_tag_test(self):
|
||||
@ -129,7 +129,8 @@ class TestSongShowPlusImport(TestCase):
|
||||
importer = SongShowPlusImport(mocked_manager, filenames=[])
|
||||
|
||||
# WHEN: Supplied with the following arguments replicating verses being added
|
||||
test_values = [('Verse 1', VerseType.tags[VerseType.Verse] + '1'),
|
||||
test_values = [
|
||||
('Verse 1', VerseType.tags[VerseType.Verse] + '1'),
|
||||
('Verse 2', VerseType.tags[VerseType.Verse] + '2'),
|
||||
('verse1', VerseType.tags[VerseType.Verse] + '1'),
|
||||
('Verse', VerseType.tags[VerseType.Verse] + '1'),
|
||||
@ -143,8 +144,8 @@ class TestSongShowPlusImport(TestCase):
|
||||
# THEN: The returned value should should correlate with the input arguments
|
||||
for original_tag, openlp_tag in test_values:
|
||||
self.assertEquals(importer.to_openlp_verse_tag(original_tag), openlp_tag,
|
||||
'SongShowPlusImport.to_openlp_verse_tag should return "%s" when called with "%s"'
|
||||
% (openlp_tag, original_tag))
|
||||
'SongShowPlusImport.to_openlp_verse_tag should return "%s" when called with "%s"' %
|
||||
(openlp_tag, original_tag))
|
||||
|
||||
def to_openlp_verse_tag_verse_order_test(self):
|
||||
"""
|
||||
@ -156,7 +157,8 @@ class TestSongShowPlusImport(TestCase):
|
||||
importer = SongShowPlusImport(mocked_manager, filenames=[])
|
||||
|
||||
# WHEN: Supplied with the following arguments replicating a verse order being added
|
||||
test_values = [('Verse 1', VerseType.tags[VerseType.Verse] + '1'),
|
||||
test_values = [
|
||||
('Verse 1', VerseType.tags[VerseType.Verse] + '1'),
|
||||
('Verse 2', VerseType.tags[VerseType.Verse] + '2'),
|
||||
('verse1', VerseType.tags[VerseType.Verse] + '1'),
|
||||
('Verse', VerseType.tags[VerseType.Verse] + '1'),
|
||||
@ -171,5 +173,5 @@ class TestSongShowPlusImport(TestCase):
|
||||
# THEN: The returned value should should correlate with the input arguments
|
||||
for original_tag, openlp_tag in test_values:
|
||||
self.assertEquals(importer.to_openlp_verse_tag(original_tag, ignore_unique=True), openlp_tag,
|
||||
'SongShowPlusImport.to_openlp_verse_tag should return "%s" when called with "%s"'
|
||||
% (openlp_tag, original_tag))
|
||||
'SongShowPlusImport.to_openlp_verse_tag should return "%s" when called with "%s"' %
|
||||
(openlp_tag, original_tag))
|
||||
|
@ -73,35 +73,37 @@ class WorshipCenterProImportLogger(WorshipCenterProImport):
|
||||
|
||||
|
||||
RECORDSET_TEST_DATA = [TestRecord(1, 'TITLE', 'Amazing Grace'),
|
||||
TestRecord(1, 'LYRICS',
|
||||
'Amazing grace! How&crlf;sweet the sound&crlf;That saved a wretch like me!&crlf;'
|
||||
'I once was lost,&crlf;but now am found;&crlf;Was blind, but now I see.&crlf;&crlf;'
|
||||
'\'Twas grace that&crlf;taught my heart to fear,&crlf;And grace my fears relieved;&crlf;'
|
||||
'How precious did&crlf;that grace appear&crlf;The hour I first believed.&crlf;&crlf;'
|
||||
'Through many dangers,&crlf;toils and snares,&crlf;I have already come;&crlf;'
|
||||
'\'Tis grace hath brought&crlf;me safe thus far,&crlf;'
|
||||
'And grace will lead me home.&crlf;&crlf;The Lord has&crlf;promised good to me,&crlf;'
|
||||
'His Word my hope secures;&crlf;He will my Shield&crlf;and Portion be,&crlf;'
|
||||
'As long as life endures.&crlf;&crlf;Yea, when this flesh&crlf;and heart shall fail,&crlf;'
|
||||
'And mortal life shall cease,&crlf;I shall possess,&crlf;within the veil,&crlf;'
|
||||
'A life of joy and peace.&crlf;&crlf;The earth shall soon&crlf;dissolve like snow,&crlf;'
|
||||
'The sun forbear to shine;&crlf;But God, Who called&crlf;me here below,&crlf;'
|
||||
'Shall be forever mine.&crlf;&crlf;When we\'ve been there&crlf;ten thousand years,&crlf;'
|
||||
'Bright shining as the sun,&crlf;We\'ve no less days to&crlf;sing God\'s praise&crlf;'
|
||||
'Than when we\'d first begun.&crlf;&crlf;'),
|
||||
TestRecord(
|
||||
1, 'LYRICS',
|
||||
'Amazing grace! How&crlf;sweet the sound&crlf;That saved a wretch like me!&crlf;'
|
||||
'I once was lost,&crlf;but now am found;&crlf;Was blind, but now I see.&crlf;&crlf;'
|
||||
'\'Twas grace that&crlf;taught my heart to fear,&crlf;And grace my fears relieved;&crlf;'
|
||||
'How precious did&crlf;that grace appear&crlf;The hour I first believed.&crlf;&crlf;'
|
||||
'Through many dangers,&crlf;toils and snares,&crlf;I have already come;&crlf;'
|
||||
'\'Tis grace hath brought&crlf;me safe thus far,&crlf;'
|
||||
'And grace will lead me home.&crlf;&crlf;The Lord has&crlf;promised good to me,&crlf;'
|
||||
'His Word my hope secures;&crlf;He will my Shield&crlf;and Portion be,&crlf;'
|
||||
'As long as life endures.&crlf;&crlf;Yea, when this flesh&crlf;and heart shall fail,&crlf;'
|
||||
'And mortal life shall cease,&crlf;I shall possess,&crlf;within the veil,&crlf;'
|
||||
'A life of joy and peace.&crlf;&crlf;The earth shall soon&crlf;dissolve like snow,&crlf;'
|
||||
'The sun forbear to shine;&crlf;But God, Who called&crlf;me here below,&crlf;'
|
||||
'Shall be forever mine.&crlf;&crlf;When we\'ve been there&crlf;ten thousand years,&crlf;'
|
||||
'Bright shining as the sun,&crlf;We\'ve no less days to&crlf;sing God\'s praise&crlf;'
|
||||
'Than when we\'d first begun.&crlf;&crlf;'),
|
||||
TestRecord(2, 'TITLE', 'Beautiful Garden Of Prayer, The'),
|
||||
TestRecord(2, 'LYRICS',
|
||||
'There\'s a garden where&crlf;Jesus is waiting,&crlf;'
|
||||
'There\'s a place that&crlf;is wondrously fair,&crlf;For it glows with the&crlf;'
|
||||
'light of His presence.&crlf;\'Tis the beautiful&crlf;garden of prayer.&crlf;&crlf;'
|
||||
'Oh, the beautiful garden,&crlf;the garden of prayer!&crlf;Oh, the beautiful&crlf;'
|
||||
'garden of prayer!&crlf;There my Savior awaits,&crlf;and He opens the gates&crlf;'
|
||||
'To the beautiful&crlf;garden of prayer.&crlf;&crlf;There\'s a garden where&crlf;'
|
||||
'Jesus is waiting,&crlf;And I go with my&crlf;burden and care,&crlf;'
|
||||
'Just to learn from His&crlf;lips words of comfort&crlf;In the beautiful&crlf;'
|
||||
'garden of prayer.&crlf;&crlf;There\'s a garden where&crlf;Jesus is waiting,&crlf;'
|
||||
'And He bids you to come,&crlf;meet Him there;&crlf;Just to bow and&crlf;'
|
||||
'receive a new blessing&crlf;In the beautiful&crlf;garden of prayer.&crlf;&crlf;')]
|
||||
TestRecord(
|
||||
2, 'LYRICS',
|
||||
'There\'s a garden where&crlf;Jesus is waiting,&crlf;'
|
||||
'There\'s a place that&crlf;is wondrously fair,&crlf;For it glows with the&crlf;'
|
||||
'light of His presence.&crlf;\'Tis the beautiful&crlf;garden of prayer.&crlf;&crlf;'
|
||||
'Oh, the beautiful garden,&crlf;the garden of prayer!&crlf;Oh, the beautiful&crlf;'
|
||||
'garden of prayer!&crlf;There my Savior awaits,&crlf;and He opens the gates&crlf;'
|
||||
'To the beautiful&crlf;garden of prayer.&crlf;&crlf;There\'s a garden where&crlf;'
|
||||
'Jesus is waiting,&crlf;And I go with my&crlf;burden and care,&crlf;'
|
||||
'Just to learn from His&crlf;lips words of comfort&crlf;In the beautiful&crlf;'
|
||||
'garden of prayer.&crlf;&crlf;There\'s a garden where&crlf;Jesus is waiting,&crlf;'
|
||||
'And He bids you to come,&crlf;meet Him there;&crlf;Just to bow and&crlf;'
|
||||
'receive a new blessing&crlf;In the beautiful&crlf;garden of prayer.&crlf;&crlf;')]
|
||||
SONG_TEST_DATA = [{'title': 'Amazing Grace',
|
||||
'verses': [
|
||||
('Amazing grace! How\nsweet the sound\nThat saved a wretch like me!\nI once was lost,\n'
|
||||
@ -118,7 +120,7 @@ SONG_TEST_DATA = [{'title': 'Amazing Grace',
|
||||
'me here below,\nShall be forever mine.'),
|
||||
('When we\'ve been there\nten thousand years,\nBright shining as the sun,\n'
|
||||
'We\'ve no less days to\nsing God\'s praise\nThan when we\'d first begun.')]},
|
||||
{'title': 'Beautiful Garden Of Prayer, The',
|
||||
{'title': 'Beautiful Garden Of Prayer, The',
|
||||
'verses': [
|
||||
('There\'s a garden where\nJesus is waiting,\nThere\'s a place that\nis wondrously fair,\n'
|
||||
'For it glows with the\nlight of His presence.\n\'Tis the beautiful\ngarden of prayer.'),
|
||||
@ -129,6 +131,7 @@ SONG_TEST_DATA = [{'title': 'Amazing Grace',
|
||||
('There\'s a garden where\nJesus is waiting,\nAnd He bids you to come,\nmeet Him there;\n'
|
||||
'Just to bow and\nreceive a new blessing\nIn the beautiful\ngarden of prayer.')]}]
|
||||
|
||||
|
||||
class TestWorshipCenterProSongImport(TestCase):
|
||||
"""
|
||||
Test the functions in the :mod:`worshipcenterproimport` module.
|
||||
@ -155,7 +158,7 @@ class TestWorshipCenterProSongImport(TestCase):
|
||||
# a mocked "manager" and a mocked out log_error method.
|
||||
with patch('openlp.plugins.songs.lib.worshipcenterproimport.SongImport'), \
|
||||
patch('openlp.plugins.songs.lib.worshipcenterproimport.pyodbc.connect') as mocked_pyodbc_connect, \
|
||||
patch('openlp.plugins.songs.lib.worshipcenterproimport.translate') as mocked_translate:
|
||||
patch('openlp.plugins.songs.lib.worshipcenterproimport.translate') as mocked_translate:
|
||||
mocked_manager = MagicMock()
|
||||
mocked_log_error = MagicMock()
|
||||
mocked_translate.return_value = 'Translated Text'
|
||||
@ -171,9 +174,9 @@ class TestWorshipCenterProSongImport(TestCase):
|
||||
|
||||
# THEN: do_import should return None, and pyodbc, translate & log_error are called with known calls
|
||||
self.assertIsNone(return_value, 'do_import should return None when pyodbc raises an exception.')
|
||||
mocked_pyodbc_connect.assert_called_with( 'DRIVER={Microsoft Access Driver (*.mdb)};DBQ=import_source')
|
||||
mocked_pyodbc_connect.assert_called_with('DRIVER={Microsoft Access Driver (*.mdb)};DBQ=import_source')
|
||||
mocked_translate.assert_called_with('SongsPlugin.WorshipCenterProImport',
|
||||
'Unable to connect the WorshipCenter Pro database.')
|
||||
'Unable to connect the WorshipCenter Pro database.')
|
||||
mocked_log_error.assert_called_with('import_source', 'Translated Text')
|
||||
|
||||
def song_import_test(self):
|
||||
@ -184,7 +187,7 @@ class TestWorshipCenterProSongImport(TestCase):
|
||||
# translate method, a mocked "manager", add_verse method & mocked_finish method.
|
||||
with patch('openlp.plugins.songs.lib.worshipcenterproimport.SongImport'), \
|
||||
patch('openlp.plugins.songs.lib.worshipcenterproimport.pyodbc') as mocked_pyodbc, \
|
||||
patch('openlp.plugins.songs.lib.worshipcenterproimport.translate') as mocked_translate:
|
||||
patch('openlp.plugins.songs.lib.worshipcenterproimport.translate') as mocked_translate:
|
||||
mocked_manager = MagicMock()
|
||||
mocked_import_wizard = MagicMock()
|
||||
mocked_add_verse = MagicMock()
|
||||
@ -201,9 +204,8 @@ class TestWorshipCenterProSongImport(TestCase):
|
||||
# WHEN: Calling the do_import method
|
||||
return_value = importer.do_import()
|
||||
|
||||
|
||||
# THEN: do_import should return None, and pyodbc, import_wizard, importer.title and add_verse are called with
|
||||
# known calls
|
||||
# THEN: do_import should return None, and pyodbc, import_wizard, importer.title and add_verse are called
|
||||
# with known calls
|
||||
self.assertIsNone(return_value, 'do_import should return None when pyodbc raises an exception.')
|
||||
mocked_pyodbc.connect.assert_called_with('DRIVER={Microsoft Access Driver (*.mdb)};DBQ=import_source')
|
||||
mocked_pyodbc.connect().cursor.assert_any_call()
|
||||
@ -214,10 +216,10 @@ class TestWorshipCenterProSongImport(TestCase):
|
||||
for song_data in SONG_TEST_DATA:
|
||||
title_value = song_data['title']
|
||||
self.assertIn(title_value, importer._title_assignment_list,
|
||||
'title should have been set to %s' % title_value)
|
||||
'title should have been set to %s' % title_value)
|
||||
verse_calls = song_data['verses']
|
||||
add_verse_call_count += len(verse_calls)
|
||||
for call in verse_calls:
|
||||
mocked_add_verse.assert_any_call(call)
|
||||
self.assertEqual(mocked_add_verse.call_count, add_verse_call_count,
|
||||
'Incorrect number of calls made to add_verse')
|
||||
'Incorrect number of calls made to add_verse')
|
||||
|
@ -116,28 +116,27 @@ class SongImportTestHelper(TestCase):
|
||||
if song_copyright:
|
||||
self.mocked_add_copyright.assert_called_with(song_copyright)
|
||||
if ccli_number:
|
||||
self.assertEquals(importer.ccli_number, ccli_number, 'ccli_number for %s should be %s'
|
||||
% (source_file_name, ccli_number))
|
||||
self.assertEquals(importer.ccli_number, ccli_number, 'ccli_number for %s should be %s' %
|
||||
(source_file_name, ccli_number))
|
||||
for verse_text, verse_tag in add_verse_calls:
|
||||
self.mocked_add_verse.assert_any_call(verse_text, verse_tag)
|
||||
if topics:
|
||||
self.assertEquals(importer.topics, topics, 'topics for %s should be %s' % (source_file_name, topics))
|
||||
if comments:
|
||||
self.assertEquals(importer.comments, comments, 'comments for %s should be "%s"'
|
||||
% (source_file_name, comments))
|
||||
self.assertEquals(importer.comments, comments, 'comments for %s should be "%s"' %
|
||||
(source_file_name, comments))
|
||||
if song_book_name:
|
||||
self.assertEquals(importer.song_book_name, song_book_name, 'song_book_name for %s should be "%s"'
|
||||
% (source_file_name, song_book_name))
|
||||
self.assertEquals(importer.song_book_name, song_book_name, 'song_book_name for %s should be "%s"' %
|
||||
(source_file_name, song_book_name))
|
||||
if song_number:
|
||||
self.assertEquals(importer.song_number, song_number, 'song_number for %s should be %s'
|
||||
% (source_file_name, song_number))
|
||||
self.assertEquals(importer.song_number, song_number, 'song_number for %s should be %s' %
|
||||
(source_file_name, song_number))
|
||||
if verse_order_list:
|
||||
self.assertEquals(importer.verse_order_list, [], 'verse_order_list for %s should be %s'
|
||||
% (source_file_name, verse_order_list))
|
||||
self.assertEquals(importer.verse_order_list, [], 'verse_order_list for %s should be %s' %
|
||||
(source_file_name, verse_order_list))
|
||||
self.mocked_finish.assert_called_with()
|
||||
|
||||
def _get_data(self, data, key):
|
||||
if key in data:
|
||||
return data[key]
|
||||
return ''
|
||||
|
||||
|
@ -25,4 +25,4 @@
|
||||
# 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 #
|
||||
###############################################################################
|
||||
###############################################################################
|
||||
|
@ -95,4 +95,3 @@ class TestPluginManager(TestCase, TestMixin):
|
||||
assert 'songusage' in plugin_names, 'There should be a "songusage" plugin.'
|
||||
assert 'alerts' in plugin_names, 'There should be a "alerts" plugin.'
|
||||
assert 'remotes' in plugin_names, 'There should be a "remotes" plugin.'
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user