From 1aa98c3cfd3679de27346ff74f71ea72eddc8eca Mon Sep 17 00:00:00 2001 From: xiphon Date: Tue, 28 Jul 2020 17:29:13 +0000 Subject: [PATCH] MoneroSettings: portable mode, CWD relative 'monero-storage' dir --- src/qt/MoneroSettings.cpp | 86 ++++++++++++++++++++++++++++++++++++++- src/qt/MoneroSettings.h | 21 +++++++++- 2 files changed, 104 insertions(+), 3 deletions(-) diff --git a/src/qt/MoneroSettings.cpp b/src/qt/MoneroSettings.cpp index 409f010c..1ee5eb40 100644 --- a/src/qt/MoneroSettings.cpp +++ b/src/qt/MoneroSettings.cpp @@ -134,12 +134,13 @@ QVariant MoneroSettings::readProperty(const QMetaProperty &property) const void MoneroSettings::init() { if (!this->m_initialized) { - this->m_settings = this->m_fileName.isEmpty() ? new QSettings() : new QSettings(this->m_fileName, QSettings::IniFormat); + this->m_settings = portableConfigExists() ? portableSettings() : unportableSettings(); #ifdef QT_DEBUG qDebug() << "QQmlSettings: stored at" << this->m_settings->fileName(); #endif this->load(); this->m_initialized = true; + emit portableChanged(); } } @@ -148,11 +149,16 @@ void MoneroSettings::reset() if (this->m_initialized && this->m_settings && !this->m_changedProperties.isEmpty()) this->store(); if (this->m_settings) - delete this->m_settings; + this->m_settings.reset(); } void MoneroSettings::store() { + if (!m_writable) + { + return; + } + QHash::const_iterator it = this->m_changedProperties.constBegin(); while (it != this->m_changedProperties.constEnd()) { @@ -168,6 +174,58 @@ void MoneroSettings::store() this->m_changedProperties.clear(); } +bool MoneroSettings::portable() const +{ + return this->m_settings && this->m_settings->fileName() == portableFilePath(); +} + +bool MoneroSettings::portableConfigExists() const +{ + QFileInfo info(portableFilePath()); + return info.exists() && info.isFile(); +} + +QString MoneroSettings::portableFilePath() const +{ + static QString filename(QDir(portableFolderName()).absoluteFilePath("settings.ini")); + return filename; +} + +QString MoneroSettings::portableFolderName() const +{ + return "monero-storage"; +} + +std::unique_ptr MoneroSettings::portableSettings() const +{ + return std::unique_ptr(new QSettings(portableFilePath(), QSettings::IniFormat)); +} + +std::unique_ptr MoneroSettings::unportableSettings() const +{ + if (this->m_fileName.isEmpty()) + { + return std::unique_ptr(new QSettings()); + } + return std::unique_ptr(new QSettings(this->m_fileName, QSettings::IniFormat)); +} + +void MoneroSettings::swap(std::unique_ptr newSettings) +{ + const QMetaObject *mo = this->metaObject(); + const int count = mo->propertyCount(); + for (int offset = mo->propertyOffset(); offset < count; ++offset) + { + const QMetaProperty &property = mo->property(offset); + const QVariant value = readProperty(property); + newSettings->setValue(property.name(), value); + } + + this->m_settings.swap(newSettings); + this->m_settings->sync(); + emit portableChanged(); +} + void MoneroSettings::setFileName(const QString &fileName) { if (fileName != this->m_fileName) { @@ -183,6 +241,30 @@ QString MoneroSettings::fileName() const return this->m_fileName; } +bool MoneroSettings::setPortable(bool enabled) +{ + std::unique_ptr newSettings = enabled ? portableSettings() : unportableSettings(); + if (newSettings->status() != QSettings::NoError) + { + return false; + } + + setWritable(true); + swap(std::move(newSettings)); + + if (!enabled) + { + QFile::remove(portableFilePath()); + } + + return true; +} + +void MoneroSettings::setWritable(bool enabled) +{ + m_writable = enabled; +} + void MoneroSettings::timerEvent(QTimerEvent *event) { if (event->timerId() == this->m_timerId) { diff --git a/src/qt/MoneroSettings.h b/src/qt/MoneroSettings.h index cda22e02..3f822530 100644 --- a/src/qt/MoneroSettings.h +++ b/src/qt/MoneroSettings.h @@ -36,6 +36,8 @@ #ifndef MONEROSETTINGS_H #define MONEROSETTINGS_H +#include + #include #include #include @@ -50,15 +52,23 @@ class MoneroSettings : public QObject, public QQmlParserStatus Q_OBJECT Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QString fileName READ fileName WRITE setFileName FINAL) + Q_PROPERTY(bool portable READ portable NOTIFY portableChanged) + Q_PROPERTY(QString portableFolderName READ portableFolderName CONSTANT) + public: explicit MoneroSettings(QObject *parent = nullptr); QString fileName() const; void setFileName(const QString &fileName); + Q_INVOKABLE bool setPortable(bool enabled); + Q_INVOKABLE void setWritable(bool enabled); public slots: void _q_propertyChanged(); +signals: + void portableChanged() const; + protected: void timerEvent(QTimerEvent *event) override; void classBegin() override; @@ -71,10 +81,19 @@ private: void load(); void store(); + bool portable() const; + bool portableConfigExists() const; + QString portableFilePath() const; + QString portableFolderName() const; + std::unique_ptr portableSettings() const; + std::unique_ptr unportableSettings() const; + void swap(std::unique_ptr newSettings); + QHash m_changedProperties; - QSettings *m_settings = NULL; + std::unique_ptr m_settings; QString m_fileName = QString(""); bool m_initialized = false; + bool m_writable = true; int m_timerId = 0; };