diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index 3a203c2c4..88b3dbfb7 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -33,6 +33,7 @@ import os import shutil import sys import time +from datetime import datetime from traceback import format_exception from PyQt5 import QtCore, QtGui, QtWidgets @@ -423,7 +424,20 @@ def main(args=None): application.shared_memory.detach() sys.exit() # Upgrade settings. - Settings().upgrade_settings() + settings = Settings() + if settings.can_upgrade(): + now = datetime.now() + # Only back up if OpenLP has previously run. + if settings.value('core/has run wizard'): + back_up_path = AppLocation.get_data_path() / (now.strftime('%Y-%m-%d %H-%M') + '.conf') + log.info('Settings about to be upgraded. Existing settings are being backed up to {back_up_path}' + .format(back_up_path=back_up_path)) + QtWidgets.QMessageBox.information( + None, translate('OpenLP', 'Settings Upgrade'), + translate('OpenLP', 'Your settings are about to upgraded. A backup will be created at {back_up_path}') + .format(back_up_path=back_up_path)) + settings.export(back_up_path) + settings.upgrade_settings() # First time checks in settings if not Settings().value('core/has run wizard'): if not FirstTimeLanguageForm().exec(): diff --git a/openlp/core/common/settings.py b/openlp/core/common/settings.py index 4b15c5ddd..5bfcd31a9 100644 --- a/openlp/core/common/settings.py +++ b/openlp/core/common/settings.py @@ -26,12 +26,13 @@ import datetime import logging import json import os +from tempfile import gettempdir -from PyQt5 import QtCore, QtGui +from PyQt5 import QtCore, QtGui, QtWidgets -from openlp.core.common import SlideLimits, ThemeLevel, UiStrings, is_linux, is_win +from openlp.core.common import SlideLimits, ThemeLevel, UiStrings, is_linux, is_win, translate from openlp.core.common.json import OpenLPJsonDecoder, OpenLPJsonEncoder -from openlp.core.common.path import Path, path_to_str, str_to_path +from openlp.core.common.path import Path, str_to_path log = logging.getLogger(__name__) @@ -452,14 +453,20 @@ class Settings(QtCore.QSettings): key = self.group() + '/' + key return Settings.__default_settings__[key] + def can_upgrade(self): + """ + Can / should the settings be upgraded + + :rtype: bool + """ + return __version__ != self.value('settings/version') + def upgrade_settings(self): """ This method is only called to clean up the config. It removes old settings and it renames settings. See ``__obsolete_settings__`` for more details. """ current_version = self.value('settings/version') - if __version__ == current_version: - return for version in range(current_version, __version__): version += 1 upgrade_list = getattr(self, '__setting_upgrade_{version}__'.format(version=version)) @@ -549,3 +556,59 @@ class Settings(QtCore.QSettings): if isinstance(default_value, int): return int(setting) return setting + + def export(self, dest_path): + """ + Export the settings to file. + + :param openlp.core.common.path.Path dest_path: The file path to create the export file. + :return: Success + :rtype: bool + """ + temp_path = Path(gettempdir(), 'openlp', 'exportConf.tmp') + # Delete old files if found. + if temp_path.exists(): + temp_path.unlink() + if dest_path.exists(): + dest_path.unlink() + self.remove('SettingsImport') + # Get the settings. + keys = self.allKeys() + export_settings = QtCore.QSettings(str(temp_path), Settings.IniFormat) + # Add a header section. + # This is to insure it's our conf file for import. + now = datetime.datetime.now() + # Write INI format using QSettings. + # Write our header. + export_settings.beginGroup('SettingsImport') + export_settings.setValue('Make_Changes', 'At_Own_RISK') + export_settings.setValue('type', 'OpenLP_settings_export') + export_settings.setValue('file_date_created', now.strftime("%Y-%m-%d %H:%M")) + export_settings.endGroup() + # Write all the sections and keys. + for section_key in keys: + # FIXME: We are conflicting with the standard "General" section. + if 'eneral' in section_key: + section_key = section_key.lower() + key_value = super().value(section_key) + if key_value is not None: + export_settings.setValue(section_key, key_value) + export_settings.sync() + # Temp CONF file has been written. Blanks in keys are now '%20'. + # Read the temp file and output the user's CONF file with blanks to + # make it more readable. + try: + with dest_path.open('w') as export_conf_file, temp_path.open('r') as temp_conf: + for file_record in temp_conf: + # Get rid of any invalid entries. + if file_record.find('@Invalid()') == -1: + file_record = file_record.replace('%20', ' ') + export_conf_file.write(file_record) + except OSError as ose: + QtWidgets.QMessageBox.critical(self, translate('OpenLP.MainWindow', 'Export setting error'), + translate('OpenLP.MainWindow', + 'An error occurred while exporting the settings: {err}' + ).format(err=ose.strerror), + QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok)) + finally: + temp_path.unlink() diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 023d1799d..413e97a17 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -50,6 +50,7 @@ from openlp.core.ui.media import MediaController from openlp.core.ui.printserviceform import PrintServiceForm from openlp.core.ui.projector.manager import ProjectorManager from openlp.core.ui.lib.dockwidget import OpenLPDockWidget +from openlp.core.ui.lib.filedialog import FileDialog from openlp.core.ui.lib.mediadockmanager import MediaDockManager @@ -876,11 +877,12 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties): shutil.copyfile(import_file_name, temp_config) settings = Settings() import_settings = Settings(temp_config, Settings.IniFormat) - # Convert image files + log.info('hook upgrade_plugin_settings') self.plugin_manager.hook_upgrade_plugin_settings(import_settings) # Upgrade settings to prepare the import. - import_settings.upgrade_settings() + if import_settings.can_upgrade(): + import_settings.upgrade_settings() # Lets do a basic sanity check. If it contains this string we can assume it was created by OpenLP and so we'll # load what we can from it, and just silently ignore anything we don't recognise. if import_settings.value('SettingsImport/type') != 'OpenLP_settings_export': @@ -936,89 +938,17 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties): """ Export settings to a .conf file in INI format """ - export_file_name, filter_used = QtWidgets.QFileDialog.getSaveFileName( + export_file_path, filter_used = FileDialog.getSaveFileName( self, translate('OpenLP.MainWindow', 'Export Settings File'), - '', + None, translate('OpenLP.MainWindow', 'OpenLP Settings (*.conf)')) - if not export_file_name: + if not export_file_path: return - # Make sure it's a .conf file. - if not export_file_name.endswith('conf'): - export_file_name += '.conf' - temp_file = os.path.join(gettempdir(), 'openlp', 'exportConf.tmp') + # Make sure it's a .conf file. + export_file_path = export_file_path.with_suffix('.conf') self.save_settings() - setting_sections = [] - # Add main sections. - setting_sections.extend([self.general_settings_section]) - setting_sections.extend([self.advanced_settings_section]) - setting_sections.extend([self.ui_settings_section]) - setting_sections.extend([self.shortcuts_settings_section]) - setting_sections.extend([self.service_manager_settings_section]) - setting_sections.extend([self.themes_settings_section]) - setting_sections.extend([self.display_tags_section]) - # Add plugin sections. - for plugin in self.plugin_manager.plugins: - setting_sections.extend([plugin.name]) - # Delete old files if found. - if os.path.exists(temp_file): - os.remove(temp_file) - if os.path.exists(export_file_name): - os.remove(export_file_name) - settings = Settings() - settings.remove(self.header_section) - # Get the settings. - keys = settings.allKeys() - export_settings = Settings(temp_file, Settings.IniFormat) - # Add a header section. - # This is to insure it's our conf file for import. - now = datetime.now() - application_version = get_application_version() - # Write INI format using Qsettings. - # Write our header. - export_settings.beginGroup(self.header_section) - export_settings.setValue('Make_Changes', 'At_Own_RISK') - export_settings.setValue('type', 'OpenLP_settings_export') - export_settings.setValue('file_date_created', now.strftime("%Y-%m-%d %H:%M")) - export_settings.setValue('version', application_version['full']) - export_settings.endGroup() - # Write all the sections and keys. - for section_key in keys: - # FIXME: We are conflicting with the standard "General" section. - if 'eneral' in section_key: - section_key = section_key.lower() - try: - key_value = settings.value(section_key) - except KeyError: - QtWidgets.QMessageBox.critical(self, translate('OpenLP.MainWindow', 'Export setting error'), - translate('OpenLP.MainWindow', 'The key "{key}" does not have a default ' - 'value so it will be skipped in this ' - 'export.').format(key=section_key), - QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok)) - key_value = None - if key_value is not None: - export_settings.setValue(section_key, key_value) - export_settings.sync() - # Temp CONF file has been written. Blanks in keys are now '%20'. - # Read the temp file and output the user's CONF file with blanks to - # make it more readable. - temp_conf = open(temp_file, 'r') - try: - export_conf = open(export_file_name, 'w') - for file_record in temp_conf: - # Get rid of any invalid entries. - if file_record.find('@Invalid()') == -1: - file_record = file_record.replace('%20', ' ') - export_conf.write(file_record) - temp_conf.close() - export_conf.close() - os.remove(temp_file) - except OSError as ose: - QtWidgets.QMessageBox.critical(self, translate('OpenLP.MainWindow', 'Export setting error'), - translate('OpenLP.MainWindow', - 'An error occurred while exporting the ' - 'settings: {err}').format(err=ose.strerror), - QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok)) + Settings().export(export_file_path) def on_mode_default_item_clicked(self): """ diff --git a/openlp/plugins/images/imageplugin.py b/openlp/plugins/images/imageplugin.py index 75d6ceab3..c4da26dfe 100644 --- a/openlp/plugins/images/imageplugin.py +++ b/openlp/plugins/images/imageplugin.py @@ -71,14 +71,6 @@ class ImagePlugin(Plugin): 'provided by the theme.') return about_text - def upgrade_settings(self, settings): - """ - Upgrade the settings of this plugin. - - :param settings: The Settings object containing the old settings. - """ - pass - def set_plugin_text_strings(self): """ Called to define all translatable texts of the plugin.