From e1400dc227da3667e2cf3099e79ff0be839c53ce Mon Sep 17 00:00:00 2001 From: Phill Ridout Date: Sat, 6 Jan 2018 09:55:19 +0000 Subject: [PATCH] Finally merge the save lite method in to the 'standard' save method' --- openlp/core/lib/serviceitem.py | 11 +- openlp/core/ui/mainwindow.py | 2 +- openlp/core/ui/servicemanager.py | 234 ++++++++++--------------------- 3 files changed, 75 insertions(+), 172 deletions(-) diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index 3a824d424..1ae450cad 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -427,13 +427,8 @@ 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: - # 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) + for file_path in header['background_audio']: + 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']: @@ -538,7 +533,7 @@ class ServiceItem(RegistryProperties): Confirms if the ServiceItem uses a file """ return self.service_item_type == ServiceItemType.Image or \ - (self.service_item_type == ServiceItemType.Command and not self.is_capable(ItemCapabilities.IsOptical)) + (self.service_item_type == ServiceItemType.Command and not self.is_capable(ItemCapabilities.IsOptical)) def is_text(self): """ diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index ee07cbd69..a2aef0e6d 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -1382,4 +1382,4 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties): 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)) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 0c2b9b473..0e27923a9 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -43,6 +43,7 @@ from openlp.core.common.path import Path, create_paths, 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 @@ -451,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): """ @@ -477,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): """ @@ -509,16 +510,19 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi write_list = [] missing_list = [] 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: + 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 - if not os.path.exists(path_from): - missing_list.append(Path(path_from)) - else: - write_list.append(Path(path_from)) + write_list.append(audio_path) return write_list, missing_list def save_file(self): @@ -531,39 +535,37 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi """ file_path = self.file_name() self.log_debug('ServiceManager.save_file - {name}'.format(name=file_path)) - service_file_name = '{name}.osj'.format(name=file_path.suffix) self.application.set_busy_cursor() service = self.create_basic_service() + write_list = [] + missing_list = [] - # Get list of missing files, and list of files to write + if not self._save_lite: + write_list, missing_list = self.get_write_file_list() - - 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 + 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) - continue + 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) - for audio_path in service_item['header']['background_audio']: - write_list.append(audio_path) + # Add the service item to the service. service.append({'serviceitem': service_item}) self.repaint_service_list(-1, -1) @@ -582,7 +584,7 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi with NamedTemporaryFile() as temp_file, \ zipfile.ZipFile(temp_file, 'w') as zip_file: # First we add service contents.. - zip_file.writestr(service_file_name, service_content) + zip_file.writestr('service_data.osj', service_content) # Finally add all the listed media files. for write_from in write_list: zip_file.write(write_from, write_from) @@ -604,61 +606,6 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi self.set_modified(False) return True - 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() - service_item = item['service_item'].get_service_repr(self._save_lite) - # TODO: check for file item on save. - 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() - 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() - 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 - def save_file_as(self, field=None): """ Get a file name and then call :func:`ServiceManager.save_file` to save the file. @@ -718,87 +665,47 @@ 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, cls=OpenLPJsonDecoder) - 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: + 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)) + 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.display_progress_bar(len(items)) + 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.')) + 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.application.set_normal_cursor() return - finally: - if file_to: - file_to.close() - if zip_file: - zip_file.close() self.main_window.finished_progress_bar() self.application.set_normal_cursor() self.repaint_service_list(-1, -1) @@ -813,7 +720,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) @@ -836,9 +744,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): """