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 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():

View File

@ -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()

View File

@ -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):
"""

View File

@ -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.