Skip to content

Commit

Permalink
Drop settings backup handling and migrating commands (hluk#2237)
Browse files Browse the repository at this point in the history
  • Loading branch information
hluk authored Feb 23, 2023
1 parent ffb4187 commit 968cb64
Show file tree
Hide file tree
Showing 7 changed files with 17 additions and 293 deletions.
51 changes: 1 addition & 50 deletions src/app/clipboardserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,53 +81,6 @@ void setTabWidth(QTextEdit *editor, int spaces)
#endif
}

/// Move commands to separate config file.
void migrateCommands(const QString &commandConfigPath)
{
Settings oldSettings;
const auto oldCommands = loadCommands(&oldSettings.constSettingsData());

const QString commandConfigPathNew = commandConfigPath + QStringLiteral(".new");
{
Settings newSettings(commandConfigPathNew);
saveCommands(oldCommands, newSettings.settingsData());
}

{
QSettings newSettings(commandConfigPathNew, QSettings::IniFormat);
const auto newCommands = loadCommands(&newSettings);
if ( newCommands != oldCommands ) {
log( QString("Failed to save commands in new file %1")
.arg(commandConfigPathNew), LogError );
return;
}
}

if ( !QFile::rename(commandConfigPathNew, commandConfigPath) ) {
log( QString("Failed to save commands in new file %1")
.arg(commandConfigPath), LogError );
return;
}

oldSettings.remove("Commands");
oldSettings.remove("Command");
}

void restoreConfiguration()
{
Settings().restore();

const QString commandConfigPath = getConfigurationFilePath("-commands.ini");
if ( QFile::exists(commandConfigPath) ) {
const QString staleCommandConfigPathBakup =
commandConfigPath + QStringLiteral(".new.bak");
QFile::remove(staleCommandConfigPathBakup);
Settings(commandConfigPath).restore();
} else {
migrateCommands(commandConfigPath);
}
}

} // namespace

ClipboardServer::ClipboardServer(QApplication *app, const QString &sessionName)
Expand All @@ -143,8 +96,6 @@ ClipboardServer::ClipboardServer(QApplication *app, const QString &sessionName)
m_server = new Server(serverName, this);

if ( m_server->isListening() ) {
Settings::canModifySettings = true;
restoreConfiguration();
App::installTranslator();
qApp->setLayoutDirection(QLocale().textDirection());
COPYQ_LOG("Server \"" + serverName + "\" started.");
Expand Down Expand Up @@ -696,7 +647,7 @@ void ClipboardServer::loadSettings(AppConfig *appConfig)

COPYQ_LOG("Loading configuration");

QSettings &settings = appConfig->settings().constSettingsData();
QSettings &settings = appConfig->settings();

m_sharedData->itemFactory->loadItemFactorySettings(&settings);

Expand Down
2 changes: 1 addition & 1 deletion src/common/commandstore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ Commands loadAllCommands()
void saveCommands(const Commands &commands)
{
Settings settings(getConfigurationFilePath("-commands.ini"));
saveCommands(commands, settings.settingsData());
saveCommands(commands, &settings);
}

Commands loadCommands(QSettings *settings)
Expand Down
126 changes: 3 additions & 123 deletions src/common/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,138 +2,18 @@

#include "settings.h"

#include "common/common.h"
#include "common/config.h"
#include "common/log.h"

#include <QCoreApplication>
#include <QDateTime>
#include <QFileInfo>
#include <QStringList>

namespace {

bool needsUpdate(const Settings &newSettings, const QSettings &oldSettings)
{
if ( Settings::isEmpty(oldSettings) )
return false;

const QFileInfo newFile(newSettings.fileName());
const QFileInfo oldFile(oldSettings.fileName());

return newFile.size() != oldFile.size()
|| newFile.lastModified() < oldFile.lastModified();
}

void copySettings(const QSettings &from, QSettings *to)
{
Q_ASSERT(from.group().isEmpty());
Q_ASSERT(to->group().isEmpty());

to->clear();

for ( const auto &key : from.allKeys() )
to->setValue(key, from.value(key));

to->sync();
}

QString lockFileName(const QString &path)
{
if ( path.isEmpty() )
return getConfigurationFilePath(".bad");
return path + ".bad";
}

bool isLastSaveUnfinished(const QString &path)
{
return QFile::exists(lockFileName(path));
}

void beginSave(const QString &path)
{
QFile lockFile(lockFileName(path));
lockFile.open(QIODevice::WriteOnly);
}

void endSave(const QString &path)
{
QFile::remove(lockFileName(path));
}

} // namespace

bool Settings::canModifySettings = false;

bool Settings::isEmpty(const QSettings &settings)
{
return settings.childGroups().isEmpty();
}

Settings::Settings()
: m_settings(
: QSettings(
QSettings::defaultFormat(),
QSettings::UserScope,
QCoreApplication::organizationName(),
QCoreApplication::applicationName() + "-bak" )
, m_changed(false)
QCoreApplication::applicationName() )
{
}

Settings::Settings(const QString &path)
: m_settings(path + ".bak", QSettings::IniFormat)
, m_path(path)
{
}

Settings::~Settings()
{
// Only main application is allowed to change settings.
if (canModifySettings && m_changed) {
m_settings.sync();

beginSave(m_path);

while ( !m_settings.group().isEmpty() )
m_settings.endGroup();

save();

endSave(m_path);
}
}

void Settings::restore()
{
if ( isLastSaveUnfinished(m_path) ) {
log("Restoring application settings", LogWarning);

if ( isEmpty() )
log("Cannot restore application settings", LogError);
else
save();

endSave(m_path);
} else if ( m_path.isEmpty() ) {
restore( QSettings() );
} else {
restore( QSettings(m_path, QSettings::IniFormat) );
}
}

void Settings::restore(const QSettings &settings)
{
if ( needsUpdate(*this, settings) )
copySettings(settings, &m_settings);
}

void Settings::save()
: QSettings(path, QSettings::IniFormat)
{
if ( m_path.isEmpty() ) {
QSettings settings;
copySettings(m_settings, &settings);
} else {
QSettings settings(m_path, QSettings::IniFormat);
copySettings(m_settings, &settings);
}
}
112 changes: 3 additions & 109 deletions src/common/settings.h
Original file line number Diff line number Diff line change
@@ -1,126 +1,20 @@
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef SETTINGS_H
#define SETTINGS_H
#pragma once

#include <QSettings>
#include <QString>

/**
* Wrapper for safer QSettings() handling.
*
* For more safety, this should be instantiated only from main application thread.
*
* Stores and reads values from application settings copy. Updates the application
* settings when destroyed.
*
* Special file is used to designate whether application settings or its copy is valid.
*
* While special file doesn't exist, the application settings is valid.
*
* While special file exists, copy is valid and application settings is not.
*
* When created:
* - if last save was unsuccessful, restores copy of application settings,
* - if last save was successful, copies application settings and uses this copy.
*
* When destroyed:
* - synchronizes the underlying copy of application settings,
* - creates special file,
* - copies settings from copy to real application settings and flushes it,
* - deletes special file.
* Simple wrapper class for QSettings.
*/
class Settings final
class Settings final : public QSettings
{
public:
static bool canModifySettings;

static bool isEmpty(const QSettings &settings);

Settings();

explicit Settings(const QString &path);

~Settings();

bool isEmpty() const { return isEmpty(m_settings); }

bool contains(const QString &name) const { return m_settings.contains(name); }

QVariant value(const QString &name) const { return m_settings.value(name); }

void setValue(const QString &name, const QVariant &value) {
m_changed = true;
m_settings.setValue(name, value);
}

void remove(const QString &name) {
m_changed = true;
m_settings.remove(name);
}

void clear() {
m_changed = true;
m_settings.clear();
}

void beginGroup(const QString &prefix) {
m_settings.beginGroup(prefix);
}

void endGroup() {
m_settings.endGroup();
}

QStringList allKeys() {
return m_settings.allKeys();
}

int beginReadArray(const QString &prefix) {
return m_settings.beginReadArray(prefix);
}

void beginWriteArray(const QString &prefix, int size = -1) {
m_changed = true;
m_settings.beginWriteArray(prefix, size);
}

void endArray() {
m_settings.endArray();
}

void setArrayIndex(int i) {
m_settings.setArrayIndex(i);
}

QString fileName() const {
return m_settings.fileName();
}

QSettings *settingsData() {
m_changed = true;
return &m_settings;
}

QSettings &constSettingsData() { return m_settings; }

Settings(const Settings &) = delete;
Settings &operator=(const Settings &) = delete;

void restore();

private:
void restore(const QSettings &settings);

void save();

QSettings m_settings;

/// True only if QSetting data changed and need to be synced.
bool m_changed;

QString m_path;
};


#endif // SETTINGS_H
12 changes: 6 additions & 6 deletions src/gui/configurationmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,11 +442,11 @@ void ConfigurationManager::loadSettings(AppConfig *appConfig)
settings.endGroup();

settings.beginGroup("Shortcuts");
m_tabShortcuts->loadShortcuts(settings.constSettingsData());
m_tabShortcuts->loadShortcuts(settings);
settings.endGroup();

settings.beginGroup("Theme");
m_tabAppearance->loadTheme(settings.constSettingsData());
m_tabAppearance->loadTheme(settings);
settings.endGroup();

m_tabAppearance->setEditor( appConfig->option<Config::editor>() );
Expand Down Expand Up @@ -522,16 +522,16 @@ void ConfigurationManager::apply(AppConfig *appConfig)
settings.setValue( it.key(), it.value().value() );
settings.endGroup();

m_tabTabs->saveTabs(settings.settingsData());
m_tabTabs->saveTabs(&settings);

// Save configuration without command line alternatives only if option widgets are initialized
// (i.e. clicked OK or Apply in configuration dialog).
settings.beginGroup("Shortcuts");
m_tabShortcuts->saveShortcuts(settings.settingsData());
m_tabShortcuts->saveShortcuts(&settings);
settings.endGroup();

settings.beginGroup("Theme");
m_tabAppearance->saveTheme(settings.settingsData());
m_tabAppearance->saveTheme(&settings);
settings.endGroup();

// Save settings for each plugin.
Expand All @@ -552,7 +552,7 @@ void ConfigurationManager::apply(AppConfig *appConfig)
if (w) {
PluginWidget *pluginWidget = qobject_cast<PluginWidget *>(w);
const auto &loader = pluginWidget->loader();
loader->applySettings(*settings.settingsData());
loader->applySettings(settings);
}

const bool isPluginEnabled = m_tabItems->isItemChecked(i);
Expand Down
Loading

0 comments on commit 968cb64

Please sign in to comment.