Back up settings before upgrading them

This commit is contained in:
Philip Ridout 2017-09-03 11:18:14 +01:00
parent 1908efcdbb
commit 7a3f54e54c
4 changed files with 93 additions and 94 deletions

View File

@ -33,6 +33,7 @@ import os
import shutil import shutil
import sys import sys
import time import time
from datetime import datetime
from traceback import format_exception from traceback import format_exception
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets
@ -423,7 +424,20 @@ def main(args=None):
application.shared_memory.detach() application.shared_memory.detach()
sys.exit() sys.exit()
# Upgrade settings. # 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 # First time checks in settings
if not Settings().value('core/has run wizard'): if not Settings().value('core/has run wizard'):
if not FirstTimeLanguageForm().exec(): if not FirstTimeLanguageForm().exec():

View File

@ -26,12 +26,13 @@ import datetime
import logging import logging
import json import json
import os 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.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__) log = logging.getLogger(__name__)
@ -452,14 +453,20 @@ class Settings(QtCore.QSettings):
key = self.group() + '/' + key key = self.group() + '/' + key
return Settings.__default_settings__[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): def upgrade_settings(self):
""" """
This method is only called to clean up the config. It removes old settings and it renames settings. See This method is only called to clean up the config. It removes old settings and it renames settings. See
``__obsolete_settings__`` for more details. ``__obsolete_settings__`` for more details.
""" """
current_version = self.value('settings/version') current_version = self.value('settings/version')
if __version__ == current_version:
return
for version in range(current_version, __version__): for version in range(current_version, __version__):
version += 1 version += 1
upgrade_list = getattr(self, '__setting_upgrade_{version}__'.format(version=version)) upgrade_list = getattr(self, '__setting_upgrade_{version}__'.format(version=version))
@ -549,3 +556,59 @@ class Settings(QtCore.QSettings):
if isinstance(default_value, int): if isinstance(default_value, int):
return int(setting) return int(setting)
return 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()

View File

@ -50,6 +50,7 @@ from openlp.core.ui.media import MediaController
from openlp.core.ui.printserviceform import PrintServiceForm from openlp.core.ui.printserviceform import PrintServiceForm
from openlp.core.ui.projector.manager import ProjectorManager from openlp.core.ui.projector.manager import ProjectorManager
from openlp.core.ui.lib.dockwidget import OpenLPDockWidget from openlp.core.ui.lib.dockwidget import OpenLPDockWidget
from openlp.core.ui.lib.filedialog import FileDialog
from openlp.core.ui.lib.mediadockmanager import MediaDockManager 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) shutil.copyfile(import_file_name, temp_config)
settings = Settings() settings = Settings()
import_settings = Settings(temp_config, Settings.IniFormat) import_settings = Settings(temp_config, Settings.IniFormat)
# Convert image files
log.info('hook upgrade_plugin_settings') log.info('hook upgrade_plugin_settings')
self.plugin_manager.hook_upgrade_plugin_settings(import_settings) self.plugin_manager.hook_upgrade_plugin_settings(import_settings)
# Upgrade settings to prepare the import. # 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 # 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. # load what we can from it, and just silently ignore anything we don't recognise.
if import_settings.value('SettingsImport/type') != 'OpenLP_settings_export': 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 settings to a .conf file in INI format
""" """
export_file_name, filter_used = QtWidgets.QFileDialog.getSaveFileName( export_file_path, filter_used = FileDialog.getSaveFileName(
self, self,
translate('OpenLP.MainWindow', 'Export Settings File'), translate('OpenLP.MainWindow', 'Export Settings File'),
'', None,
translate('OpenLP.MainWindow', 'OpenLP Settings (*.conf)')) translate('OpenLP.MainWindow', 'OpenLP Settings (*.conf)'))
if not export_file_name: if not export_file_path:
return return
# Make sure it's a .conf file. # Make sure it's a .conf file.
if not export_file_name.endswith('conf'): export_file_path = export_file_path.with_suffix('.conf')
export_file_name += '.conf'
temp_file = os.path.join(gettempdir(), 'openlp', 'exportConf.tmp')
self.save_settings() self.save_settings()
setting_sections = [] Settings().export(export_file_path)
# 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))
def on_mode_default_item_clicked(self): def on_mode_default_item_clicked(self):
""" """

View File

@ -71,14 +71,6 @@ class ImagePlugin(Plugin):
'provided by the theme.') 'provided by the theme.')
return about_text 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): def set_plugin_text_strings(self):
""" """
Called to define all translatable texts of the plugin. Called to define all translatable texts of the plugin.