diff options
author | Maximilian Goldstein <max.goldstein@qt.io> | 2021-01-20 14:48:05 +0100 |
---|---|---|
committer | Maximilian Goldstein <max.goldstein@qt.io> | 2021-01-20 17:28:10 +0100 |
commit | 0fb373c9a2ebc31f76b27bfa5c2e59dadefeaf08 (patch) | |
tree | 8df5099729d1e7fd9a973b4caf8fa1db7ca31de0 /src/imports/settings | |
parent | a738c3566790c6e9abeea3c4c3dacfceaa82f66a (diff) |
Qt.labs.settings: Make plugin optional
This moves the settings types into a new library and is meant to make
them availabe to the QML compiler at some point in the future.
Task-number: QTBUG-90487
Change-Id: I986615b08ea8c1a7312b9d9c6ae0b13c03fb5497
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/imports/settings')
-rw-r--r-- | src/imports/settings/CMakeLists.txt | 5 | ||||
-rw-r--r-- | src/imports/settings/plugin.cpp | 4 | ||||
-rw-r--r-- | src/imports/settings/qqmlsettings.cpp | 534 | ||||
-rw-r--r-- | src/imports/settings/qqmlsettings_p.h | 103 |
4 files changed, 3 insertions, 643 deletions
diff --git a/src/imports/settings/CMakeLists.txt b/src/imports/settings/CMakeLists.txt index c5c76135ba..f49e741106 100644 --- a/src/imports/settings/CMakeLists.txt +++ b/src/imports/settings/CMakeLists.txt @@ -9,14 +9,13 @@ qt_internal_add_qml_module(qmlsettingsplugin VERSION "${CMAKE_PROJECT_VERSION}" CLASSNAME QmlSettingsPlugin SKIP_TYPE_REGISTRATION - GENERATE_QMLTYPES - INSTALL_QMLTYPES + PLUGIN_OPTIONAL SOURCES plugin.cpp - qqmlsettings.cpp qqmlsettings_p.h PUBLIC_LIBRARIES Qt::Core Qt::Qml + Qt::LabsSettingsPrivate ) #### Keys ignored in scope 1:.:.:settings.pro:<TRUE>: diff --git a/src/imports/settings/plugin.cpp b/src/imports/settings/plugin.cpp index e8e640412b..428bd27198 100644 --- a/src/imports/settings/plugin.cpp +++ b/src/imports/settings/plugin.cpp @@ -40,9 +40,7 @@ #include <QtQml/qqmlextensionplugin.h> #include <QtQml/qqml.h> -#include "qqmlsettings_p.h" - -extern void qml_register_types_Qt_labs_settings(); +#include <QtLabsSettings/private/qqmlsettingsglobal_p.h> QT_BEGIN_NAMESPACE diff --git a/src/imports/settings/qqmlsettings.cpp b/src/imports/settings/qqmlsettings.cpp deleted file mode 100644 index ff8ec5e065..0000000000 --- a/src/imports/settings/qqmlsettings.cpp +++ /dev/null @@ -1,534 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qqmlsettings_p.h" -#include <qcoreevent.h> -#include <qcoreapplication.h> -#include <qloggingcategory.h> -#include <qsettings.h> -#include <qpointer.h> -#include <qjsvalue.h> -#include <qqmlinfo.h> -#include <qdebug.h> -#include <qhash.h> - -QT_BEGIN_NAMESPACE - -/*! - \qmlmodule Qt.labs.settings 1.0 - \title Qt Labs Settings QML Types - \ingroup qmlmodules - \brief Provides persistent platform-independent application settings. - - To use this module, import the module with the following line: - - \code - import Qt.labs.settings - \endcode -*/ - -/*! - \qmltype Settings - \instantiates QQmlSettings - \inqmlmodule Qt.labs.settings - \ingroup settings - \brief Provides persistent platform-independent application settings. - - The Settings type provides persistent platform-independent application settings. - - \note This type is made available by importing the \b Qt.labs.settings module. - \e {Types in the Qt.labs module are not guaranteed to remain compatible - in future versions.} - - Users normally expect an application to remember its settings (window sizes - and positions, options, etc.) across sessions. The Settings type enables you - to save and restore such application settings with the minimum of effort. - - Individual setting values are specified by declaring properties within a - Settings element. All \l {QML Basic Types}{basic type} properties are - supported. The recommended approach is to use property aliases in order - to get automatic property updates both ways. The following example shows - how to use Settings to store and restore the geometry of a window. - - \qml - import QtQuick.Window - import Qt.labs.settings - - Window { - id: window - - width: 800 - height: 600 - - Settings { - property alias x: window.x - property alias y: window.y - property alias width: window.width - property alias height: window.height - } - } - \endqml - - At first application startup, the window gets default dimensions specified - as 800x600. Notice that no default position is specified - we let the window - manager handle that. Later when the window geometry changes, new values will - be automatically stored to the persistent settings. The second application - run will get initial values from the persistent settings, bringing the window - back to the previous position and size. - - A fully declarative syntax, achieved by using property aliases, comes at the - cost of storing persistent settings whenever the values of aliased properties - change. Normal properties can be used to gain more fine-grained control over - storing the persistent settings. The following example illustrates how to save - a setting on component destruction. - - \qml - import QtQuick - import Qt.labs.settings - - Item { - id: page - - state: settings.state - - states: [ - State { - name: "active" - // ... - }, - State { - name: "inactive" - // ... - } - ] - - Settings { - id: settings - property string state: "active" - } - - Component.onDestruction: { - settings.state = page.state - } - } - \endqml - - Notice how the default value is now specified in the persistent setting property, - and the actual property is bound to the setting in order to get the initial value - from the persistent settings. - - \section1 Application Identifiers - - Application specific settings are identified by providing application - \l {QCoreApplication::applicationName}{name}, - \l {QCoreApplication::organizationName}{organization} and - \l {QCoreApplication::organizationDomain}{domain}, or by specifying - \l fileName. - - \code - #include <QGuiApplication> - #include <QQmlApplicationEngine> - - int main(int argc, char *argv[]) - { - QGuiApplication app(argc, argv); - app.setOrganizationName("Some Company"); - app.setOrganizationDomain("somecompany.com"); - app.setApplicationName("Amazing Application"); - - QQmlApplicationEngine engine("main.qml"); - return app.exec(); - } - \endcode - - These are typically specified in C++ in the beginning of \c main(), - but can also be controlled in QML via the following properties: - \list - \li \l {Qt::application}{Qt.application.name}, - \li \l {Qt::application}{Qt.application.organization} and - \li \l {Qt::application}{Qt.application.domain}. - \endlist - - \section1 Categories - - Application settings may be divided into logical categories by specifying - a category name via the \l category property. Using logical categories not - only provides a cleaner settings structure, but also prevents possible - conflicts between setting keys. - - If several categories are required, use several Settings objects, each with - their own category: - - \qml - Item { - id: panel - - visible: true - - Settings { - category: "OutputPanel" - property alias visible: panel.visible - // ... - } - - Settings { - category: "General" - property alias fontSize: fontSizeSpinBox.value - // ... - } - } - \endqml - - Instead of ensuring that all settings in the application have unique names, - the settings can be divided into unique categories that may then contain - settings using the same names that are used in other categories - without - a conflict. - - \section1 Notes - - The current implementation is based on \l QSettings. This imposes certain - limitations, such as missing change notifications. Writing a setting value - using one instance of Settings does not update the value in another Settings - instance, even if they are referring to the same setting in the same category. - - The information is stored in the system registry on Windows, and in XML - preferences files on \macos. On other Unix systems, in the absence of a - standard, INI text files are used. See \l QSettings documentation for - more details. - - \sa QSettings -*/ - -Q_LOGGING_CATEGORY(lcSettings, "qt.labs.settings") - -static const int settingsWriteDelay = 500; - -class QQmlSettingsPrivate -{ - Q_DECLARE_PUBLIC(QQmlSettings) - -public: - QQmlSettingsPrivate(); - - QSettings *instance() const; - - void init(); - void reset(); - - void load(); - void store(); - - void _q_propertyChanged(); - QVariant readProperty(const QMetaProperty &property) const; - - QQmlSettings *q_ptr = nullptr; - int timerId = 0; - bool initialized = false; - QString category; - QString fileName; - mutable QPointer<QSettings> settings; - QHash<const char *, QVariant> changedProperties; -}; - -QQmlSettingsPrivate::QQmlSettingsPrivate() {} - -QSettings *QQmlSettingsPrivate::instance() const -{ - if (!settings) { - QQmlSettings *q = const_cast<QQmlSettings*>(q_func()); - settings = fileName.isEmpty() ? new QSettings(q) : new QSettings(fileName, QSettings::IniFormat, q); - if (settings->status() != QSettings::NoError) { - // TODO: can't print out the enum due to the following error: - // error: C2666: 'QQmlInfo::operator <<': 15 overloads have similar conversions - qmlWarning(q) << "Failed to initialize QSettings instance. Status code is: " << int(settings->status()); - - if (settings->status() == QSettings::AccessError) { - QVector<QString> missingIdentifiers; - if (QCoreApplication::organizationName().isEmpty()) - missingIdentifiers.append(QLatin1String("organizationName")); - if (QCoreApplication::organizationDomain().isEmpty()) - missingIdentifiers.append(QLatin1String("organizationDomain")); - if (QCoreApplication::applicationName().isEmpty()) - missingIdentifiers.append(QLatin1String("applicationName")); - - if (!missingIdentifiers.isEmpty()) - qmlWarning(q) << "The following application identifiers have not been set: " << missingIdentifiers; - } - return settings; - } - - if (!category.isEmpty()) - settings->beginGroup(category); - if (initialized) - q->d_func()->load(); - } - return settings; -} - -void QQmlSettingsPrivate::init() -{ - if (!initialized) { - qCDebug(lcSettings) << "QQmlSettings: stored at" << instance()->fileName(); - load(); - initialized = true; - } -} - -void QQmlSettingsPrivate::reset() -{ - if (initialized && settings && !changedProperties.isEmpty()) - store(); - delete settings; -} - -void QQmlSettingsPrivate::load() -{ - Q_Q(QQmlSettings); - const QMetaObject *mo = q->metaObject(); - const int offset = mo->propertyOffset(); - const int count = mo->propertyCount(); - - // don't save built-in properties if there aren't any qml properties - if (offset == 1) - return; - - for (int i = offset; i < count; ++i) { - QMetaProperty property = mo->property(i); - - const QVariant previousValue = readProperty(property); - const QVariant currentValue = instance()->value(property.name(), previousValue); - - if (!currentValue.isNull() && (!previousValue.isValid() - || (currentValue.canConvert(previousValue.metaType()) - && previousValue != currentValue))) { - property.write(q, currentValue); - qCDebug(lcSettings) << "QQmlSettings: load" << property.name() << "setting:" << currentValue << "default:" << previousValue; - } - - // ensure that a non-existent setting gets written - // even if the property wouldn't change later - if (!instance()->contains(property.name())) - _q_propertyChanged(); - - // setup change notifications on first load - if (!initialized && property.hasNotifySignal()) { - static const int propertyChangedIndex = mo->indexOfSlot("_q_propertyChanged()"); - QMetaObject::connect(q, property.notifySignalIndex(), q, propertyChangedIndex); - } - } -} - -void QQmlSettingsPrivate::store() -{ - QHash<const char *, QVariant>::const_iterator it = changedProperties.constBegin(); - while (it != changedProperties.constEnd()) { - instance()->setValue(it.key(), it.value()); - qCDebug(lcSettings) << "QQmlSettings: store" << it.key() << ":" << it.value(); - ++it; - } - changedProperties.clear(); -} - -void QQmlSettingsPrivate::_q_propertyChanged() -{ - Q_Q(QQmlSettings); - const QMetaObject *mo = q->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); - changedProperties.insert(property.name(), value); - qCDebug(lcSettings) << "QQmlSettings: cache" << property.name() << ":" << value; - } - if (timerId != 0) - q->killTimer(timerId); - timerId = q->startTimer(settingsWriteDelay); -} - -QVariant QQmlSettingsPrivate::readProperty(const QMetaProperty &property) const -{ - Q_Q(const QQmlSettings); - QVariant var = property.read(q); - if (var.userType() == qMetaTypeId<QJSValue>()) - var = var.value<QJSValue>().toVariant(); - return var; -} - -QQmlSettings::QQmlSettings(QObject *parent) - : QObject(parent), d_ptr(new QQmlSettingsPrivate) -{ - Q_D(QQmlSettings); - d->q_ptr = this; -} - -QQmlSettings::~QQmlSettings() -{ - Q_D(QQmlSettings); - d->reset(); // flush pending changes -} - -/*! - \qmlproperty string Settings::category - - This property holds the name of the settings category. - - Categories can be used to group related settings together. -*/ -QString QQmlSettings::category() const -{ - Q_D(const QQmlSettings); - return d->category; -} - -void QQmlSettings::setCategory(const QString &category) -{ - Q_D(QQmlSettings); - if (d->category != category) { - d->reset(); - d->category = category; - if (d->initialized) - d->load(); - } -} - -/*! - \qmlproperty string Settings::fileName - - This property holds the path to the settings file. If the file doesn't - already exist, it is created. - - \since Qt 5.12 - - \sa QSettings::fileName, QSettings::IniFormat -*/ -QString QQmlSettings::fileName() const -{ - Q_D(const QQmlSettings); - return d->fileName; -} - -void QQmlSettings::setFileName(const QString &fileName) -{ - Q_D(QQmlSettings); - if (d->fileName != fileName) { - d->reset(); - d->fileName = fileName; - if (d->initialized) - d->load(); - } -} - -/*! - \qmlmethod var Settings::value(string key, var defaultValue) - - Returns the value for setting \a key. If the setting doesn't exist, - returns \a defaultValue. - - \since Qt 5.12 - - \sa QSettings::value -*/ -QVariant QQmlSettings::value(const QString &key, const QVariant &defaultValue) const -{ - Q_D(const QQmlSettings); - return d->instance()->value(key, defaultValue); -} - -/*! - \qmlmethod Settings::setValue(string key, var value) - - Sets the value of setting \a key to \a value. If the key already exists, - the previous value is overwritten. - - \since Qt 5.12 - - \sa QSettings::setValue -*/ -void QQmlSettings::setValue(const QString &key, const QVariant &value) -{ - Q_D(const QQmlSettings); - d->instance()->setValue(key, value); - qCDebug(lcSettings) << "QQmlSettings: setValue" << key << ":" << value; -} - -/*! - \qmlmethod Settings::sync() - - Writes any unsaved changes to permanent storage, and reloads any - settings that have been changed in the meantime by another - application. - - This function is called automatically from QSettings's destructor and - by the event loop at regular intervals, so you normally don't need to - call it yourself. - - \sa QSettings::sync -*/ -void QQmlSettings::sync() -{ - Q_D(QQmlSettings); - d->instance()->sync(); -} - -void QQmlSettings::classBegin() -{ -} - -void QQmlSettings::componentComplete() -{ - Q_D(QQmlSettings); - d->init(); -} - -void QQmlSettings::timerEvent(QTimerEvent *event) -{ - Q_D(QQmlSettings); - if (event->timerId() == d->timerId) { - killTimer(d->timerId); - d->timerId = 0; - - d->store(); - } - QObject::timerEvent(event); -} - -QT_END_NAMESPACE - -#include "moc_qqmlsettings_p.cpp" diff --git a/src/imports/settings/qqmlsettings_p.h b/src/imports/settings/qqmlsettings_p.h deleted file mode 100644 index 100d0136ff..0000000000 --- a/src/imports/settings/qqmlsettings_p.h +++ /dev/null @@ -1,103 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQMLSETTINGS_P_H -#define QQMLSETTINGS_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtQml/qqml.h> -#include <QtCore/qobject.h> -#include <QtCore/qscopedpointer.h> -#include <QtQml/qqmlparserstatus.h> - -QT_BEGIN_NAMESPACE - -class QQmlSettingsPrivate; - -class QQmlSettings : public QObject, public QQmlParserStatus -{ - Q_OBJECT - Q_INTERFACES(QQmlParserStatus) - Q_PROPERTY(QString category READ category WRITE setCategory FINAL) - Q_PROPERTY(QString fileName READ fileName WRITE setFileName FINAL) - QML_NAMED_ELEMENT(Settings) - QML_ADDED_IN_VERSION(1, 0) - -public: - explicit QQmlSettings(QObject *parent = 0); - ~QQmlSettings(); - - QString category() const; - void setCategory(const QString &category); - - QString fileName() const; - void setFileName(const QString &fileName); - - Q_INVOKABLE QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const; - Q_INVOKABLE void setValue(const QString &key, const QVariant &value); - Q_INVOKABLE void sync(); - -protected: - void timerEvent(QTimerEvent *event) override; - - void classBegin() override; - void componentComplete() override; - -private: - Q_DISABLE_COPY(QQmlSettings) - Q_DECLARE_PRIVATE(QQmlSettings) - QScopedPointer<QQmlSettingsPrivate> d_ptr; - Q_PRIVATE_SLOT(d_func(), void _q_propertyChanged()) -}; - -QT_END_NAMESPACE - -QML_DECLARE_TYPE(QQmlSettings) - -#endif // QQMLSETTINGS_P_H |