forked from openlp/openlp
head
This commit is contained in:
commit
7f39fe90d1
@ -36,6 +36,7 @@ from openlp.core.common import md5_hash
|
||||
from openlp.core.common.applocation import AppLocation
|
||||
from openlp.core.common.i18n import translate
|
||||
from openlp.core.common.mixins import RegistryProperties
|
||||
from openlp.core.common.path import Path
|
||||
from openlp.core.common.settings import Settings
|
||||
from openlp.core.lib import ImageSource, build_icon, clean_tags, expand_tags, expand_chords
|
||||
|
||||
@ -427,13 +428,13 @@ class ServiceItem(RegistryProperties):
|
||||
self.has_original_files = True
|
||||
if 'background_audio' in header:
|
||||
self.background_audio = []
|
||||
for filename in header['background_audio']:
|
||||
# Give them real file paths.
|
||||
filepath = str(filename)
|
||||
if path:
|
||||
for file_path in header['background_audio']:
|
||||
# In OpenLP 3.0 we switched to storing Path objects in JSON files
|
||||
if isinstance(file_path, str):
|
||||
# Handle service files prior to OpenLP 3.0
|
||||
# Windows can handle both forward and backward slashes, so we use ntpath to get the basename
|
||||
filepath = os.path.join(path, ntpath.basename(str(filename)))
|
||||
self.background_audio.append(filepath)
|
||||
file_path = Path(path, ntpath.basename(file_path))
|
||||
self.background_audio.append(file_path)
|
||||
self.theme_overwritten = header.get('theme_overwritten', False)
|
||||
if self.service_item_type == ServiceItemType.Text:
|
||||
for slide in service_item['serviceitem']['data']:
|
||||
@ -444,8 +445,8 @@ class ServiceItem(RegistryProperties):
|
||||
if path:
|
||||
self.has_original_files = False
|
||||
for text_image in service_item['serviceitem']['data']:
|
||||
filename = os.path.join(path, text_image)
|
||||
self.add_from_image(filename, text_image, background)
|
||||
file_path = os.path.join(path, text_image)
|
||||
self.add_from_image(file_path, text_image, background)
|
||||
else:
|
||||
for text_image in service_item['serviceitem']['data']:
|
||||
self.add_from_image(text_image['path'], text_image['title'], background)
|
||||
|
@ -400,9 +400,9 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties):
|
||||
if item:
|
||||
item.setIcon(build_icon(Path(gettempdir(), 'openlp', screenshot)))
|
||||
|
||||
def _download_progress(self, count, block_size):
|
||||
def update_progress(self, count, block_size):
|
||||
"""
|
||||
Calculate and display the download progress.
|
||||
Calculate and display the download progress. This method is called by download_file().
|
||||
"""
|
||||
increment = (count * block_size) - self.previous_size
|
||||
self._increment_progress_bar(None, increment)
|
||||
|
@ -63,7 +63,7 @@ class UiFirstTimeWizard(object):
|
||||
first_time_wizard.setOptions(QtWidgets.QWizard.IndependentPages | QtWidgets.QWizard.NoBackButtonOnStartPage |
|
||||
QtWidgets.QWizard.NoBackButtonOnLastPage | QtWidgets.QWizard.HaveCustomButton1 |
|
||||
QtWidgets.QWizard.HaveCustomButton2)
|
||||
if is_macosx():
|
||||
if is_macosx(): # pragma: nocover
|
||||
first_time_wizard.setPixmap(QtWidgets.QWizard.BackgroundPixmap,
|
||||
QtGui.QPixmap(':/wizards/openlp-osx-wizard.png'))
|
||||
first_time_wizard.resize(634, 386)
|
||||
|
@ -1308,11 +1308,13 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert
|
||||
self.load_progress_bar.setValue(0)
|
||||
self.application.process_events()
|
||||
|
||||
def increment_progress_bar(self):
|
||||
def increment_progress_bar(self, increment=1):
|
||||
"""
|
||||
Increase the Progress Bar value by 1
|
||||
Increase the Progress Bar by the value in increment.
|
||||
|
||||
:param int increment: The value you to increase the progress bar by.
|
||||
"""
|
||||
self.load_progress_bar.setValue(self.load_progress_bar.value() + 1)
|
||||
self.load_progress_bar.setValue(self.load_progress_bar.value() + increment)
|
||||
self.application.process_events()
|
||||
|
||||
def finished_progress_bar(self):
|
||||
@ -1380,4 +1382,4 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert
|
||||
if not isinstance(filename, str):
|
||||
filename = str(filename, sys.getfilesystemencoding())
|
||||
if filename.endswith(('.osz', '.oszl')):
|
||||
self.service_manager_contents.load_file(filename)
|
||||
self.service_manager_contents.load_file(Path(filename))
|
||||
|
@ -27,8 +27,9 @@ import json
|
||||
import os
|
||||
import shutil
|
||||
import zipfile
|
||||
from contextlib import suppress
|
||||
from datetime import datetime, timedelta
|
||||
from tempfile import mkstemp
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
@ -36,11 +37,13 @@ from openlp.core.common import ThemeLevel, delete_file
|
||||
from openlp.core.common.actions import ActionList, CategoryOrder
|
||||
from openlp.core.common.applocation import AppLocation
|
||||
from openlp.core.common.i18n import UiStrings, format_time, translate
|
||||
from openlp.core.common.json import OpenLPJsonDecoder, OpenLPJsonEncoder
|
||||
from openlp.core.common.mixins import LogMixin, RegistryProperties
|
||||
from openlp.core.common.path import Path, create_paths, str_to_path
|
||||
from openlp.core.common.path import Path, str_to_path
|
||||
from openlp.core.common.registry import Registry, RegistryBase
|
||||
from openlp.core.common.settings import Settings
|
||||
from openlp.core.lib import ServiceItem, ItemCapabilities, PluginStatus, build_icon
|
||||
from openlp.core.lib.exceptions import ValidationError
|
||||
from openlp.core.lib.ui import critical_error_message_box, create_widget_action, find_and_set_in_combo_box
|
||||
from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm
|
||||
from openlp.core.widgets.dialogs import FileDialog
|
||||
@ -449,7 +452,7 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi
|
||||
else:
|
||||
file_path = str_to_path(load_file)
|
||||
Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', file_path.parent)
|
||||
self.load_file(str(file_path))
|
||||
self.load_file(file_path)
|
||||
|
||||
def save_modified_service(self):
|
||||
"""
|
||||
@ -475,7 +478,7 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi
|
||||
elif result == QtWidgets.QMessageBox.Save:
|
||||
self.decide_save_method()
|
||||
sender = self.sender()
|
||||
self.load_file(sender.data())
|
||||
self.load_file(Path(sender.data()))
|
||||
|
||||
def new_file(self):
|
||||
"""
|
||||
@ -503,6 +506,31 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi
|
||||
service.append({'openlp_core': core})
|
||||
return service
|
||||
|
||||
def get_write_file_list(self):
|
||||
"""
|
||||
Get a list of files used in the service and files that are missing.
|
||||
|
||||
:return: A list of files used in the service that exist, and a list of files that don't.
|
||||
:rtype: (list[openlp.core.common.path.Path], list[openlp.core.common.path.Path])
|
||||
"""
|
||||
write_list = []
|
||||
missing_list = []
|
||||
for item in self.service_items:
|
||||
if item['service_item'].uses_file():
|
||||
for frame in item['service_item'].get_frames():
|
||||
path_from = item['service_item'].get_frame_path(frame=frame)
|
||||
if path_from in write_list or path_from in missing_list:
|
||||
continue
|
||||
if not os.path.exists(path_from):
|
||||
missing_list.append(Path(path_from))
|
||||
else:
|
||||
write_list.append(Path(path_from))
|
||||
for audio_path in item['service_item'].background_audio:
|
||||
if audio_path in write_list:
|
||||
continue
|
||||
write_list.append(audio_path)
|
||||
return write_list, missing_list
|
||||
|
||||
def save_file(self):
|
||||
"""
|
||||
Save the current service file.
|
||||
@ -511,178 +539,74 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi
|
||||
there be an error when saving. Audio files are also copied into the service manager directory, and then packaged
|
||||
into the zip file.
|
||||
"""
|
||||
if not self.file_name():
|
||||
return self.save_file_as()
|
||||
temp_file, temp_file_name = mkstemp('.osz', 'openlp_')
|
||||
# We don't need the file handle.
|
||||
os.close(temp_file)
|
||||
self.log_debug(temp_file_name)
|
||||
path_file_name = str(self.file_name())
|
||||
path, file_name = os.path.split(path_file_name)
|
||||
base_name = os.path.splitext(file_name)[0]
|
||||
service_file_name = '{name}.osj'.format(name=base_name)
|
||||
self.log_debug('ServiceManager.save_file - {name}'.format(name=path_file_name))
|
||||
Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', Path(path))
|
||||
file_path = self.file_name()
|
||||
self.log_debug('ServiceManager.save_file - {name}'.format(name=file_path))
|
||||
self.application.set_busy_cursor()
|
||||
|
||||
service = self.create_basic_service()
|
||||
|
||||
write_list = []
|
||||
missing_list = []
|
||||
audio_files = []
|
||||
total_size = 0
|
||||
self.application.set_busy_cursor()
|
||||
# Number of items + 1 to zip it
|
||||
self.main_window.display_progress_bar(len(self.service_items) + 1)
|
||||
# Get list of missing files, and list of files to write
|
||||
for item in self.service_items:
|
||||
if not item['service_item'].uses_file():
|
||||
continue
|
||||
for frame in item['service_item'].get_frames():
|
||||
path_from = item['service_item'].get_frame_path(frame=frame)
|
||||
if path_from in write_list or path_from in missing_list:
|
||||
continue
|
||||
if not os.path.exists(path_from):
|
||||
missing_list.append(path_from)
|
||||
else:
|
||||
write_list.append(path_from)
|
||||
if missing_list:
|
||||
self.application.set_normal_cursor()
|
||||
title = translate('OpenLP.ServiceManager', 'Service File(s) Missing')
|
||||
message = translate('OpenLP.ServiceManager',
|
||||
'The following file(s) in the service are missing: {name}\n\n'
|
||||
'These files will be removed if you continue to save.'
|
||||
).format(name="\n\t".join(missing_list))
|
||||
answer = QtWidgets.QMessageBox.critical(self, title, message,
|
||||
QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok |
|
||||
QtWidgets.QMessageBox.Cancel))
|
||||
if answer == QtWidgets.QMessageBox.Cancel:
|
||||
self.main_window.finished_progress_bar()
|
||||
return False
|
||||
|
||||
if not self._save_lite:
|
||||
write_list, missing_list = self.get_write_file_list()
|
||||
|
||||
if missing_list:
|
||||
self.application.set_normal_cursor()
|
||||
title = translate('OpenLP.ServiceManager', 'Service File(s) Missing')
|
||||
message = translate('OpenLP.ServiceManager',
|
||||
'The following file(s) in the service are missing: {name}\n\n'
|
||||
'These files will be removed if you continue to save.'
|
||||
).format(name='\n\t'.join(missing_list))
|
||||
answer = QtWidgets.QMessageBox.critical(self, title, message,
|
||||
QtWidgets.QMessageBox.StandardButtons(
|
||||
QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel))
|
||||
if answer == QtWidgets.QMessageBox.Cancel:
|
||||
return False
|
||||
# Check if item contains a missing file.
|
||||
for item in list(self.service_items):
|
||||
self.main_window.increment_progress_bar()
|
||||
item['service_item'].remove_invalid_frames(missing_list)
|
||||
if item['service_item'].missing_frames():
|
||||
self.service_items.remove(item)
|
||||
else:
|
||||
service_item = item['service_item'].get_service_repr(self._save_lite)
|
||||
if service_item['header']['background_audio']:
|
||||
for i, file_name in enumerate(service_item['header']['background_audio']):
|
||||
new_file = os.path.join('audio', item['service_item'].unique_identifier, str(file_name))
|
||||
audio_files.append((file_name, new_file))
|
||||
service_item['header']['background_audio'][i] = new_file
|
||||
# Add the service item to the service.
|
||||
service.append({'serviceitem': service_item})
|
||||
self.repaint_service_list(-1, -1)
|
||||
for file_item in write_list:
|
||||
file_size = os.path.getsize(file_item)
|
||||
total_size += file_size
|
||||
self.log_debug('ServiceManager.save_file - ZIP contents size is %i bytes' % total_size)
|
||||
service_content = json.dumps(service)
|
||||
# Usual Zip file cannot exceed 2GiB, file with Zip64 cannot be extracted using unzip in UNIX.
|
||||
allow_zip_64 = (total_size > 2147483648 + len(service_content))
|
||||
self.log_debug('ServiceManager.save_file - allowZip64 is {text}'.format(text=allow_zip_64))
|
||||
zip_file = None
|
||||
success = True
|
||||
self.main_window.increment_progress_bar()
|
||||
try:
|
||||
zip_file = zipfile.ZipFile(temp_file_name, 'w', zipfile.ZIP_STORED, allow_zip_64)
|
||||
# First we add service contents..
|
||||
zip_file.writestr(service_file_name, service_content)
|
||||
# Finally add all the listed media files.
|
||||
for write_from in write_list:
|
||||
zip_file.write(write_from, write_from)
|
||||
for audio_from, audio_to in audio_files:
|
||||
audio_from = str(audio_from)
|
||||
audio_to = str(audio_to)
|
||||
if audio_from.startswith('audio'):
|
||||
# When items are saved, they get new unique_identifier. Let's copy the file to the new location.
|
||||
# Unused files can be ignored, OpenLP automatically cleans up the service manager dir on exit.
|
||||
audio_from = os.path.join(self.service_path, audio_from)
|
||||
save_file = os.path.join(self.service_path, audio_to)
|
||||
save_path = os.path.split(save_file)[0]
|
||||
create_paths(Path(save_path))
|
||||
if not os.path.exists(save_file):
|
||||
shutil.copy(audio_from, save_file)
|
||||
zip_file.write(audio_from, audio_to)
|
||||
except OSError:
|
||||
self.log_exception('Failed to save service to disk: {name}'.format(name=temp_file_name))
|
||||
self.main_window.error_message(translate('OpenLP.ServiceManager', 'Error Saving File'),
|
||||
translate('OpenLP.ServiceManager', 'There was an error saving your file.'))
|
||||
success = False
|
||||
finally:
|
||||
if zip_file:
|
||||
zip_file.close()
|
||||
self.main_window.finished_progress_bar()
|
||||
self.application.set_normal_cursor()
|
||||
if success:
|
||||
try:
|
||||
shutil.copy(temp_file_name, path_file_name)
|
||||
except (shutil.Error, PermissionError):
|
||||
return self.save_file_as()
|
||||
except OSError as ose:
|
||||
QtWidgets.QMessageBox.critical(self, translate('OpenLP.ServiceManager', 'Error Saving File'),
|
||||
translate('OpenLP.ServiceManager', 'An error occurred while writing the '
|
||||
'service file: {error}').format(error=ose.strerror),
|
||||
QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok))
|
||||
success = False
|
||||
self.main_window.add_recent_file(path_file_name)
|
||||
self.set_modified(False)
|
||||
delete_file(Path(temp_file_name))
|
||||
return success
|
||||
|
||||
def save_local_file(self):
|
||||
"""
|
||||
Save the current service file but leave all the file references alone to point to the current machine.
|
||||
This format is not transportable as it will not contain any files.
|
||||
"""
|
||||
if not self.file_name():
|
||||
return self.save_file_as()
|
||||
temp_file, temp_file_name = mkstemp('.oszl', 'openlp_')
|
||||
# We don't need the file handle.
|
||||
os.close(temp_file)
|
||||
self.log_debug(temp_file_name)
|
||||
path_file_name = str(self.file_name())
|
||||
path, file_name = os.path.split(path_file_name)
|
||||
base_name = os.path.splitext(file_name)[0]
|
||||
service_file_name = '{name}.osj'.format(name=base_name)
|
||||
self.log_debug('ServiceManager.save_file - {name}'.format(name=path_file_name))
|
||||
Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', Path(path))
|
||||
service = self.create_basic_service()
|
||||
self.application.set_busy_cursor()
|
||||
# Number of items + 1 to zip it
|
||||
self.main_window.display_progress_bar(len(self.service_items) + 1)
|
||||
for item in self.service_items:
|
||||
self.main_window.increment_progress_bar()
|
||||
if not self._save_lite:
|
||||
item['service_item'].remove_invalid_frames(missing_list)
|
||||
if item['service_item'].missing_frames():
|
||||
self.service_items.remove(item)
|
||||
continue
|
||||
service_item = item['service_item'].get_service_repr(self._save_lite)
|
||||
# TODO: check for file item on save.
|
||||
# Add the service item to the service.
|
||||
service.append({'serviceitem': service_item})
|
||||
self.main_window.increment_progress_bar()
|
||||
service_content = json.dumps(service)
|
||||
zip_file = None
|
||||
success = True
|
||||
self.main_window.increment_progress_bar()
|
||||
self.repaint_service_list(-1, -1)
|
||||
service_content = json.dumps(service, cls=OpenLPJsonEncoder)
|
||||
service_content_size = len(bytes(service_content, encoding='utf-8'))
|
||||
total_size = service_content_size
|
||||
for file_item in write_list:
|
||||
total_size += file_item.stat().st_size
|
||||
self.log_debug('ServiceManager.save_file - ZIP contents size is %i bytes' % total_size)
|
||||
self.main_window.display_progress_bar(total_size)
|
||||
try:
|
||||
zip_file = zipfile.ZipFile(temp_file_name, 'w', zipfile.ZIP_STORED, True)
|
||||
# First we add service contents.
|
||||
zip_file.writestr(service_file_name, service_content)
|
||||
except OSError:
|
||||
self.log_exception('Failed to save service to disk: {name}'.format(name=temp_file_name))
|
||||
self.main_window.error_message(translate('OpenLP.ServiceManager', 'Error Saving File'),
|
||||
translate('OpenLP.ServiceManager', 'There was an error saving your file.'))
|
||||
success = False
|
||||
finally:
|
||||
if zip_file:
|
||||
zip_file.close()
|
||||
with NamedTemporaryFile(dir=str(file_path.parent), prefix='.') as temp_file, \
|
||||
zipfile.ZipFile(temp_file, 'w') as zip_file:
|
||||
# First we add service contents..
|
||||
zip_file.writestr('service_data.osj', service_content)
|
||||
self.main_window.increment_progress_bar(service_content_size)
|
||||
# Finally add all the listed media files.
|
||||
for write_path in write_list:
|
||||
zip_file.write(str(write_path), str(write_path))
|
||||
self.main_window.increment_progress_bar(write_path.stat().st_size)
|
||||
with suppress(FileNotFoundError):
|
||||
file_path.unlink()
|
||||
os.link(temp_file.name, str(file_path))
|
||||
Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', file_path.parent)
|
||||
except (PermissionError, OSError) as error:
|
||||
self.log_exception('Failed to save service to disk: {name}'.format(name=file_path))
|
||||
self.main_window.error_message(
|
||||
translate('OpenLP.ServiceManager', 'Error Saving File'),
|
||||
translate('OpenLP.ServiceManager',
|
||||
'There was an error saving your file.\n\n{error}').format(error=error))
|
||||
return self.save_file_as()
|
||||
self.main_window.finished_progress_bar()
|
||||
self.application.set_normal_cursor()
|
||||
if success:
|
||||
try:
|
||||
shutil.copy(temp_file_name, path_file_name)
|
||||
except (shutil.Error, PermissionError):
|
||||
return self.save_file_as()
|
||||
self.main_window.add_recent_file(path_file_name)
|
||||
self.set_modified(False)
|
||||
delete_file(Path(temp_file_name))
|
||||
return success
|
||||
self.main_window.add_recent_file(file_path)
|
||||
self.set_modified(False)
|
||||
return True
|
||||
|
||||
def save_file_as(self):
|
||||
"""
|
||||
@ -743,87 +667,49 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi
|
||||
"""
|
||||
if not self.file_name():
|
||||
return self.save_file_as()
|
||||
if self._save_lite:
|
||||
return self.save_local_file()
|
||||
else:
|
||||
return self.save_file()
|
||||
return self.save_file()
|
||||
|
||||
def load_file(self, file_name):
|
||||
def load_file(self, file_path):
|
||||
"""
|
||||
Load an existing service file
|
||||
:param file_name:
|
||||
:param file_path:
|
||||
"""
|
||||
if not file_name:
|
||||
if not file_path.exists():
|
||||
return False
|
||||
file_name = str(file_name)
|
||||
if not os.path.exists(file_name):
|
||||
return False
|
||||
zip_file = None
|
||||
file_to = None
|
||||
service_data = None
|
||||
self.application.set_busy_cursor()
|
||||
try:
|
||||
zip_file = zipfile.ZipFile(file_name)
|
||||
for zip_info in zip_file.infolist():
|
||||
try:
|
||||
ucs_file = zip_info.filename
|
||||
except UnicodeDecodeError:
|
||||
self.log_exception('file_name "{name}" is not valid UTF-8'.format(name=zip_info.file_name))
|
||||
critical_error_message_box(message=translate('OpenLP.ServiceManager',
|
||||
'File is not a valid service.\n The content encoding is not UTF-8.'))
|
||||
continue
|
||||
os_file = ucs_file.replace('/', os.path.sep)
|
||||
os_file = os.path.basename(os_file)
|
||||
self.log_debug('Extract file: {name}'.format(name=os_file))
|
||||
zip_info.filename = os_file
|
||||
zip_file.extract(zip_info, self.service_path)
|
||||
if os_file.endswith('osj') or os_file.endswith('osd'):
|
||||
p_file = os.path.join(self.service_path, os_file)
|
||||
if 'p_file' in locals():
|
||||
file_to = open(p_file, 'r')
|
||||
if p_file.endswith('osj'):
|
||||
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.'))
|
||||
return
|
||||
file_to.close()
|
||||
with zipfile.ZipFile(str(file_path)) as zip_file:
|
||||
compressed_size = 0
|
||||
for zip_info in zip_file.infolist():
|
||||
compressed_size += zip_info.compress_size
|
||||
self.main_window.display_progress_bar(compressed_size)
|
||||
for zip_info in zip_file.infolist():
|
||||
self.log_debug('Extract file: {name}'.format(name=zip_info.filename))
|
||||
# The json file has been called 'service_data.osj' since OpenLP 3.0
|
||||
if zip_info.filename == 'service_data.osj' or zip_info.filename.endswith('osj'):
|
||||
with zip_file.open(zip_info, 'r') as json_file:
|
||||
service_data = json_file.read()
|
||||
else:
|
||||
zip_info.filename = os.path.basename(zip_info.filename)
|
||||
zip_file.extract(zip_info, str(self.service_path))
|
||||
self.main_window.increment_progress_bar(zip_info.compress_size)
|
||||
if service_data:
|
||||
items = json.loads(service_data, cls=OpenLPJsonDecoder)
|
||||
self.new_file()
|
||||
self.set_file_name(str_to_path(file_name))
|
||||
self.main_window.display_progress_bar(len(items))
|
||||
self.process_service_items(items)
|
||||
delete_file(Path(p_file))
|
||||
self.main_window.add_recent_file(file_name)
|
||||
self.set_file_name(file_path)
|
||||
self.main_window.add_recent_file(file_path)
|
||||
self.set_modified(False)
|
||||
Settings().setValue('servicemanager/last file', Path(file_name))
|
||||
Settings().setValue('servicemanager/last file', file_path)
|
||||
else:
|
||||
critical_error_message_box(message=translate('OpenLP.ServiceManager', 'File is not a valid service.'))
|
||||
self.log_error('File contains no service data')
|
||||
except (OSError, NameError):
|
||||
self.log_exception('Problem loading service file {name}'.format(name=file_name))
|
||||
critical_error_message_box(message=translate('OpenLP.ServiceManager',
|
||||
'File could not be opened because it is corrupt.'))
|
||||
except zipfile.BadZipFile:
|
||||
if os.path.getsize(file_name) == 0:
|
||||
self.log_exception('Service file is zero sized: {name}'.format(name=file_name))
|
||||
QtWidgets.QMessageBox.information(self, translate('OpenLP.ServiceManager', 'Empty File'),
|
||||
translate('OpenLP.ServiceManager',
|
||||
'This service file does not contain '
|
||||
'any data.'))
|
||||
else:
|
||||
self.log_exception('Service file is cannot be extracted as zip: {name}'.format(name=file_name))
|
||||
QtWidgets.QMessageBox.information(self, translate('OpenLP.ServiceManager', 'Corrupt File'),
|
||||
translate('OpenLP.ServiceManager',
|
||||
'This file is either corrupt or it is not an OpenLP 2 '
|
||||
'service file.'))
|
||||
self.application.set_normal_cursor()
|
||||
return
|
||||
finally:
|
||||
if file_to:
|
||||
file_to.close()
|
||||
if zip_file:
|
||||
zip_file.close()
|
||||
raise ValidationError(msg='No service data found')
|
||||
except (NameError, OSError, ValidationError, zipfile.BadZipFile) as e:
|
||||
self.log_exception('Problem loading service file {name}'.format(name=file_path))
|
||||
critical_error_message_box(
|
||||
message=translate('OpenLP.ServiceManager',
|
||||
'The service file {file_path} could not be loaded because it is either corrupt, or '
|
||||
'not a valid OpenLP 2 or OpenLP 3 service file.'.format(file_path=file_path)))
|
||||
self.main_window.finished_progress_bar()
|
||||
self.application.set_normal_cursor()
|
||||
self.repaint_service_list(-1, -1)
|
||||
@ -838,7 +724,8 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi
|
||||
self.main_window.increment_progress_bar()
|
||||
service_item = ServiceItem()
|
||||
if 'openlp_core' in item:
|
||||
item = item.get('openlp_core')
|
||||
item = item['openlp_core']
|
||||
self._save_lite = item.get('lite-service', False)
|
||||
theme = item.get('service-theme', None)
|
||||
if theme:
|
||||
find_and_set_in_combo_box(self.theme_combo_box, theme, set_missing=False)
|
||||
@ -861,9 +748,9 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi
|
||||
Load the last service item from the service manager when the service was last closed. Can be blank if there was
|
||||
no service present.
|
||||
"""
|
||||
file_name = str_to_path(Settings().value('servicemanager/last file'))
|
||||
if file_name:
|
||||
self.load_file(file_name)
|
||||
file_path = Settings().value('servicemanager/last file')
|
||||
if file_path:
|
||||
self.load_file(file_path)
|
||||
|
||||
def context_menu(self, point):
|
||||
"""
|
||||
|
@ -19,3 +19,26 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
Functional tests to test the remote index
|
||||
"""
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from openlp.core.api.endpoint.remote import index
|
||||
from openlp.core.api.endpoint.core import TRANSLATED_STRINGS
|
||||
|
||||
|
||||
@patch('openlp.core.api.endpoint.remote.remote_endpoint')
|
||||
def test_index(mocked_endpoint):
|
||||
"""
|
||||
Test the index method of the remote
|
||||
"""
|
||||
# GIVEN: A mocked Endpoint
|
||||
mocked_endpoint.render_template.return_value = 'test template'
|
||||
|
||||
# WHEN: index is called
|
||||
result = index(MagicMock(), 'index')
|
||||
|
||||
# THEN: The result should be "test template" and the right methods should have been called
|
||||
mocked_endpoint.render_template.assert_called_once_with('index.mako', **TRANSLATED_STRINGS)
|
||||
assert result == 'test template'
|
@ -23,7 +23,7 @@
|
||||
Package to test the openlp.core.lib.pluginmanager package.
|
||||
"""
|
||||
from unittest import TestCase
|
||||
from unittest.mock import MagicMock
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from openlp.core.common.registry import Registry
|
||||
from openlp.core.common.settings import Settings
|
||||
@ -50,6 +50,32 @@ class TestPluginManager(TestCase):
|
||||
Registry().register('main_window', self.mocked_main_window)
|
||||
Registry().register('settings_form', self.mocked_settings_form)
|
||||
|
||||
def test_bootstrap_initialise(self):
|
||||
"""
|
||||
Test the PluginManager.bootstrap_initialise() method
|
||||
"""
|
||||
# GIVEN: A plugin manager with some mocked out methods
|
||||
manager = PluginManager()
|
||||
|
||||
with patch.object(manager, 'find_plugins') as mocked_find_plugins, \
|
||||
patch.object(manager, 'hook_settings_tabs') as mocked_hook_settings_tabs, \
|
||||
patch.object(manager, 'hook_media_manager') as mocked_hook_media_manager, \
|
||||
patch.object(manager, 'hook_import_menu') as mocked_hook_import_menu, \
|
||||
patch.object(manager, 'hook_export_menu') as mocked_hook_export_menu, \
|
||||
patch.object(manager, 'hook_tools_menu') as mocked_hook_tools_menu, \
|
||||
patch.object(manager, 'initialise_plugins') as mocked_initialise_plugins:
|
||||
# WHEN: bootstrap_initialise() is called
|
||||
manager.bootstrap_initialise()
|
||||
|
||||
# THEN: The hook methods should have been called
|
||||
mocked_find_plugins.assert_called_with()
|
||||
mocked_hook_settings_tabs.assert_called_with()
|
||||
mocked_hook_media_manager.assert_called_with()
|
||||
mocked_hook_import_menu.assert_called_with()
|
||||
mocked_hook_export_menu.assert_called_with()
|
||||
mocked_hook_tools_menu.assert_called_with()
|
||||
mocked_initialise_plugins.assert_called_with()
|
||||
|
||||
def test_hook_media_manager_with_disabled_plugin(self):
|
||||
"""
|
||||
Test running the hook_media_manager() method with a disabled plugin
|
||||
|
@ -27,6 +27,7 @@ from unittest import TestCase
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from openlp.core.common import md5_hash
|
||||
from openlp.core.common.path import Path
|
||||
from openlp.core.common.registry import Registry
|
||||
from openlp.core.common.settings import Settings
|
||||
from openlp.core.lib import ItemCapabilities, ServiceItem, ServiceItemType, FormattingTags
|
||||
@ -351,5 +352,5 @@ class TestServiceItem(TestCase, TestMixin):
|
||||
'"Amazing Grace! how sweet the s" has been returned as the title'
|
||||
assert '’Twas grace that taught my hea' == service_item.get_frame_title(1), \
|
||||
'"’Twas grace that taught my hea" has been returned as the title'
|
||||
assert '/test/amazing_grace.mp3' == service_item.background_audio[0], \
|
||||
assert Path('/test/amazing_grace.mp3') == service_item.background_audio[0], \
|
||||
'"/test/amazing_grace.mp3" should be in the background_audio list'
|
||||
|
@ -23,6 +23,7 @@
|
||||
Package to test openlp.core.ui.mainwindow package.
|
||||
"""
|
||||
import os
|
||||
from pathlib import Path
|
||||
from unittest import TestCase
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
@ -84,14 +85,13 @@ class TestMainWindow(TestCase, TestMixin):
|
||||
"""
|
||||
# GIVEN a service as an argument to openlp
|
||||
service = os.path.join(TEST_RESOURCES_PATH, 'service', 'test.osz')
|
||||
self.main_window.arguments = [service]
|
||||
|
||||
# WHEN the argument is processed
|
||||
with patch.object(self.main_window.service_manager, 'load_file') as mocked_load_file:
|
||||
self.main_window.open_cmd_line_files(service)
|
||||
|
||||
# THEN the service from the arguments is loaded
|
||||
mocked_load_file.assert_called_with(service)
|
||||
mocked_load_file.assert_called_with(Path(service))
|
||||
|
||||
@patch('openlp.core.ui.servicemanager.ServiceManager.load_file')
|
||||
def test_cmd_line_arg(self, mocked_load_file):
|
||||
@ -242,3 +242,30 @@ class TestMainWindow(TestCase, TestMixin):
|
||||
|
||||
# THEN: projector_manager_dock.setVisible should had been called once
|
||||
mocked_dock.setVisible.assert_called_once_with(False)
|
||||
|
||||
def test_increment_progress_bar_default_increment(self):
|
||||
"""
|
||||
Test that increment_progress_bar increments the progress bar by 1 when called without the `increment` arg.
|
||||
"""
|
||||
# GIVEN: A mocked progress bar
|
||||
with patch.object(self.main_window, 'load_progress_bar', **{'value.return_value': 0}) as mocked_progress_bar:
|
||||
|
||||
# WHEN: Calling increment_progress_bar without the `increment` arg
|
||||
self.main_window.increment_progress_bar()
|
||||
|
||||
# THEN: The progress bar value should have been incremented by 1
|
||||
mocked_progress_bar.setValue.assert_called_once_with(1)
|
||||
|
||||
def test_increment_progress_bar_custom_increment(self):
|
||||
"""
|
||||
Test that increment_progress_bar increments the progress bar by the `increment` arg when called with the
|
||||
`increment` arg with a set value.
|
||||
"""
|
||||
# GIVEN: A mocked progress bar
|
||||
with patch.object(self.main_window, 'load_progress_bar', **{'value.return_value': 0}) as mocked_progress_bar:
|
||||
|
||||
# WHEN: Calling increment_progress_bar with `increment` set to 10
|
||||
self.main_window.increment_progress_bar(increment=10)
|
||||
|
||||
# THEN: The progress bar value should have been incremented by 10
|
||||
mocked_progress_bar.setValue.assert_called_once_with(10)
|
||||
|
@ -623,10 +623,10 @@ class TestServiceManager(TestCase):
|
||||
# THEN: make_preview() should not have been called
|
||||
assert mocked_make_preview.call_count == 0, 'ServiceManager.make_preview() should not be called'
|
||||
|
||||
@patch('openlp.core.ui.servicemanager.shutil.copy')
|
||||
@patch('openlp.core.ui.servicemanager.zipfile')
|
||||
@patch('openlp.core.ui.servicemanager.ServiceManager.save_file_as')
|
||||
def test_save_file_raises_permission_error(self, mocked_save_file_as, mocked_zipfile, mocked_shutil_copy):
|
||||
@patch('openlp.core.ui.servicemanager.os')
|
||||
def test_save_file_raises_permission_error(self, mocked_os, mocked_save_file_as, mocked_zipfile):
|
||||
"""
|
||||
Test that when a PermissionError is raised when trying to save a file, it is handled correctly
|
||||
"""
|
||||
@ -636,50 +636,22 @@ class TestServiceManager(TestCase):
|
||||
Registry().register('main_window', mocked_main_window)
|
||||
Registry().register('application', MagicMock())
|
||||
service_manager = ServiceManager(None)
|
||||
service_manager._service_path = os.path.join('temp', 'filename.osz')
|
||||
service_manager._service_path = MagicMock()
|
||||
service_manager._save_lite = False
|
||||
service_manager.service_items = []
|
||||
service_manager.service_theme = 'Default'
|
||||
service_manager.service_manager_list = MagicMock()
|
||||
mocked_save_file_as.return_value = True
|
||||
mocked_zipfile.ZipFile.return_value = MagicMock()
|
||||
mocked_shutil_copy.side_effect = PermissionError
|
||||
mocked_os.link.side_effect = PermissionError
|
||||
|
||||
# WHEN: The service is saved and a PermissionError is thrown
|
||||
# WHEN: The service is saved and a PermissionError is raised
|
||||
result = service_manager.save_file()
|
||||
|
||||
# THEN: The "save_as" method is called to save the service
|
||||
assert result is True
|
||||
mocked_save_file_as.assert_called_with()
|
||||
|
||||
@patch('openlp.core.ui.servicemanager.shutil.copy')
|
||||
@patch('openlp.core.ui.servicemanager.zipfile')
|
||||
@patch('openlp.core.ui.servicemanager.ServiceManager.save_file_as')
|
||||
def test_save_local_file_raises_permission_error(self, mocked_save_file_as, mocked_zipfile, mocked_shutil_copy):
|
||||
"""
|
||||
Test that when a PermissionError is raised when trying to save a local file, it is handled correctly
|
||||
"""
|
||||
# GIVEN: A service manager, a service to save
|
||||
mocked_main_window = MagicMock()
|
||||
mocked_main_window.service_manager_settings_section = 'servicemanager'
|
||||
Registry().register('main_window', mocked_main_window)
|
||||
Registry().register('application', MagicMock())
|
||||
service_manager = ServiceManager(None)
|
||||
service_manager._service_path = os.path.join('temp', 'filename.osz')
|
||||
service_manager._save_lite = False
|
||||
service_manager.service_items = []
|
||||
service_manager.service_theme = 'Default'
|
||||
mocked_save_file_as.return_value = True
|
||||
mocked_zipfile.ZipFile.return_value = MagicMock()
|
||||
mocked_shutil_copy.side_effect = PermissionError
|
||||
|
||||
# WHEN: The service is saved and a PermissionError is thrown
|
||||
result = service_manager.save_local_file()
|
||||
|
||||
# THEN: The "save_as" method is called to save the service
|
||||
assert result is True
|
||||
mocked_save_file_as.assert_called_with()
|
||||
|
||||
@patch('openlp.core.ui.servicemanager.ServiceManager.regenerate_service_items')
|
||||
def test_theme_change_global(self, mocked_regenerate_service_items):
|
||||
"""
|
||||
|
@ -19,36 +19,46 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
from unittest import TestCase
|
||||
"""
|
||||
Test the openlp.core.ui package.
|
||||
"""
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from openlp.core.common.registry import Registry
|
||||
from openlp.core.api.endpoint.controller import controller_text
|
||||
from openlp.core.ui import SingleColumnTableWidget
|
||||
|
||||
|
||||
class TestController(TestCase):
|
||||
def test_single_col_widget_create():
|
||||
"""
|
||||
Test the Remote plugin deploy functions
|
||||
Test creating the SingleColumnTableWidget object
|
||||
"""
|
||||
# GIVEN: the SingleColumnTableWidget class
|
||||
# WHEN: An object is created
|
||||
widget = SingleColumnTableWidget(None)
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Setup for tests
|
||||
"""
|
||||
Registry.create()
|
||||
self.registry = Registry()
|
||||
self.mocked_live_controller = MagicMock()
|
||||
Registry().register('live_controller', self.mocked_live_controller)
|
||||
# THEN: The object should have 1 column and no visible header
|
||||
assert widget.columnCount() == 1, 'There should be only 1 column'
|
||||
assert widget.horizontalHeader().isVisible() is False, 'The horizontal header should not be visible'
|
||||
|
||||
def test_controller_text(self):
|
||||
"""
|
||||
Remote Deploy tests - test the dummy zip file is processed correctly
|
||||
"""
|
||||
# GIVEN: A mocked service with a dummy service item
|
||||
self.mocked_live_controller.service_item = MagicMock()
|
||||
# WHEN: I trigger the method
|
||||
ret = controller_text("SomeText")
|
||||
# THEN: I get a basic set of results
|
||||
results = ret['results']
|
||||
assert isinstance(results['item'], MagicMock)
|
||||
assert len(results['slides']) == 0
|
||||
|
||||
@patch('openlp.core.ui.QtWidgets.QTableWidget')
|
||||
def test_single_col_widget_resize_event(MockQTableWidget):
|
||||
"""
|
||||
Test that the resizeEvent method does the right thing
|
||||
"""
|
||||
# GIVEN: An instance of a SingleColumnTableWidget and a mocked event
|
||||
widget = SingleColumnTableWidget(None)
|
||||
mocked_event = MagicMock()
|
||||
mocked_event.size.return_value.width.return_value = 10
|
||||
|
||||
# WHEN: resizeEvent() is called
|
||||
with patch.object(widget, 'columnCount') as mocked_column_count, \
|
||||
patch.object(widget, 'setColumnWidth') as mocked_set_column_width, \
|
||||
patch.object(widget, 'resizeRowsToContents') as mocked_resize_rows_to_contents:
|
||||
mocked_column_count.return_value = 1
|
||||
widget.resizeEvent(mocked_event)
|
||||
|
||||
# THEN: The correct calls should have been made
|
||||
MockQTableWidget.resizeEvent.assert_called_once_with(widget, mocked_event)
|
||||
mocked_column_count.assert_called_once_with()
|
||||
mocked_set_column_width.assert_called_once_with(0, 10)
|
||||
mocked_resize_rows_to_contents.assert_called_once_with()
|
Loading…
Reference in New Issue
Block a user