aboutsummaryrefslogtreecommitdiff
path: root/src/qt
diff options
context:
space:
mode:
authordsc <xmrdsc@protonmail.com>2019-07-03 01:27:25 +0200
committerdsc <xmrdsc@protonmail.com>2019-07-16 01:47:07 +0200
commit96c99b250ed4557c1f396941614fb755a3487cb1 (patch)
treeab10c28f94e90b00ca6a2484578640017584e4b5 /src/qt
parent4370733b2b352f3dd8af7749a19754c7dc31f702 (diff)
downloadmonzero-gui-96c99b250ed4557c1f396941614fb755a3487cb1.tar.gz
monzero-gui-96c99b250ed4557c1f396941614fb755a3487cb1.tar.xz
monzero-gui-96c99b250ed4557c1f396941614fb755a3487cb1.zip
Replace Qt.labs.settings with MoneroSettings to allow for more customization
Diffstat (limited to 'src/qt')
-rw-r--r--src/qt/MoneroSettings.cpp207
-rw-r--r--src/qt/MoneroSettings.h81
2 files changed, 288 insertions, 0 deletions
diff --git a/src/qt/MoneroSettings.cpp b/src/qt/MoneroSettings.cpp
new file mode 100644
index 00000000..ba3e6876
--- /dev/null
+++ b/src/qt/MoneroSettings.cpp
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+****************************************************************************/
+// Copyright (c) 2014-2019, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <QtCore>
+#include <QMetaObject>
+#include <QSettings>
+#include <QPointer>
+#include <QJSValue>
+#include <QHash>
+#include <QMetaProperty>
+
+#include "src/qt/MoneroSettings.h"
+
+/*!
+ \qmlmodule moneroSettings 1.0
+ \title Monero Settings QML Component
+ \ingroup qmlmodules
+ \brief Provides persistent platform-independent application settings.
+
+ This component was introduced in order to have control over where the
+ configuration file is written. This is needed for Tails OS and
+ portable installations.
+
+ For more information, see: https://doc.qt.io/qt-5/qml-qt-labs-settings-settings.html and
+ https://github.com/qt/qtdeclarative/blob/v5.12.0/src/imports/settings/qqmlsettings.cpp
+
+ To use this module, import the module with the following line:
+ \code
+ import moneroComponents.Settings 1.0
+ \endcode
+
+ Usage:
+ \code
+ MoneroSettings { id: persistentSettings, property bool foo: true }
+ \endcode
+
+ @TODO: Remove this QML component after migrating to Qt >= 5.12.0, as
+ `Qt.labs.settings` provides the fileName via a Q_PROPERTY
+*/
+
+
+void MoneroSettings::load()
+{
+ const QMetaObject *mo = this->metaObject();
+ const int offset = mo->propertyOffset();
+ const int count = mo->propertyCount();
+
+ for (int i = offset; i < count; ++i) {
+ QMetaProperty property = mo->property(i);
+ const QVariant previousValue = readProperty(property);
+ const QVariant currentValue = this->m_settings->value(property.name(), previousValue);
+
+ if (!currentValue.isNull() && (!previousValue.isValid()
+ || (currentValue.canConvert(previousValue.type()) && previousValue != currentValue))) {
+ property.write(this, currentValue);
+#ifdef QT_DEBUG
+ qDebug() << "QQmlSettings: load" << property.name() << "setting:" << currentValue << "default:" << previousValue;
+#endif
+ }
+
+ // ensure that a non-existent setting gets written
+ // even if the property wouldn't change later
+ if (!this->m_settings->contains(property.name()))
+ this->_q_propertyChanged();
+
+ // setup change notifications on first load
+ if (!this->m_initialized && property.hasNotifySignal()) {
+ static const int propertyChangedIndex = mo->indexOfSlot("_q_propertyChanged()");
+ int signalIndex = property.notifySignalIndex();
+ QMetaObject::connect(this, signalIndex, this, propertyChangedIndex);
+ }
+ }
+}
+
+void MoneroSettings::_q_propertyChanged()
+{
+ // Called on QML property change
+ const QMetaObject *mo = this->metaObject();
+ const int offset = mo->propertyOffset();
+ const int count = mo->propertyCount();
+ for (int i = offset; i < count; ++i) {
+ const QMetaProperty &property = mo->property(i);
+ const QVariant value = readProperty(property);
+ this->m_changedProperties.insert(property.name(), value);
+#ifdef QT_DEBUG
+ //qDebug() << "QQmlSettings: cache" << property.name() << ":" << value;
+#endif
+ }
+
+ if (this->m_timerId != 0)
+ this->killTimer(this->m_timerId);
+ this->m_timerId = this->startTimer(settingsWriteDelay);
+}
+
+QVariant MoneroSettings::readProperty(const QMetaProperty &property) const
+{
+ QVariant var = property.read(this);
+ if (var.userType() == qMetaTypeId<QJSValue>())
+ var = var.value<QJSValue>().toVariant();
+ return var;
+}
+
+void MoneroSettings::init()
+{
+ if (!this->m_initialized) {
+ this->m_settings = this->m_fileName.isEmpty() ? new QSettings() : new QSettings(this->m_fileName, QSettings::IniFormat);
+#ifdef QT_DEBUG
+ qDebug() << "QQmlSettings: stored at" << this->m_settings->fileName();
+#endif
+ this->load();
+ this->m_initialized = true;
+ }
+}
+
+void MoneroSettings::reset()
+{
+ if (this->m_initialized && this->m_settings && !this->m_changedProperties.isEmpty())
+ this->store();
+ delete this->m_settings;
+}
+
+void MoneroSettings::store()
+{
+ QHash<const char *, QVariant>::const_iterator it = this->m_changedProperties.constBegin();
+
+ while (it != this->m_changedProperties.constEnd()) {
+ this->m_settings->setValue(it.key(), it.value());
+
+#ifdef QT_DEBUG
+ //qDebug() << "QQmlSettings: store" << it.key() << ":" << it.value();
+#endif
+
+ ++it;
+ }
+
+ this->m_changedProperties.clear();
+}
+
+void MoneroSettings::setFileName(const QString &fileName)
+{
+ if (fileName != this->m_fileName) {
+ this->reset();
+ this->m_fileName = fileName;
+ if (this->m_initialized)
+ this->load();
+ }
+}
+
+QString MoneroSettings::fileName() const
+{
+ return this->m_fileName;
+}
+
+void MoneroSettings::timerEvent(QTimerEvent *event)
+{
+ if (event->timerId() == this->m_timerId) {
+ killTimer(this->m_timerId);
+ this->m_timerId = 0;
+ this->store();
+ }
+ QObject::timerEvent(event);
+}
+
+void MoneroSettings::componentComplete()
+{
+ this->init();
+}
+
+void MoneroSettings::classBegin()
+{
+}
+
+MoneroSettings::MoneroSettings(QObject *parent) :
+ QObject(parent)
+{
+}
diff --git a/src/qt/MoneroSettings.h b/src/qt/MoneroSettings.h
new file mode 100644
index 00000000..6de7f641
--- /dev/null
+++ b/src/qt/MoneroSettings.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+****************************************************************************/
+// Copyright (c) 2014-2019, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+#ifndef MONEROSETTINGS_H
+#define MONEROSETTINGS_H
+
+#include <QtQml/qqmlparserstatus.h>
+#include <QGuiApplication>
+#include <QClipboard>
+#include <QObject>
+#include <QDebug>
+#include <qsettings.h>
+
+static const int settingsWriteDelay = 500; // ms
+
+class MoneroSettings : public QObject, public QQmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QQmlParserStatus)
+ Q_PROPERTY(QString fileName READ fileName WRITE setFileName FINAL)
+public:
+ explicit MoneroSettings(QObject *parent = nullptr);
+
+ QString fileName() const;
+ void setFileName(const QString &fileName);
+
+public slots:
+ void _q_propertyChanged();
+
+protected:
+ void timerEvent(QTimerEvent *event) override;
+ void classBegin() override;
+ void componentComplete() override;
+
+private:
+ QVariant readProperty(const QMetaProperty &property) const;
+ void init();
+ void reset();
+ void load();
+ void store();
+
+ QHash<const char *, QVariant> m_changedProperties;
+ QSettings *m_settings;
+ QString m_fileName = QString("");
+ bool m_initialized = false;
+ int m_timerId = 0;
+};
+
+#endif // MONEROSETTINGS_H