From e1dfaa5cb107232d594739a9549b642864e537dd Mon Sep 17 00:00:00 2001 From: JiDe Zhang Date: Thu, 6 Mar 2025 17:43:51 +0800 Subject: [PATCH] feat: Improve the design of SettingsDialog to support code generated by dconfig2cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the implementation related to SettingsDialog, it no longer forcibly depends on DConfigWrapper, but instead uses QObject as the base type, and obtains properties, signals, and other information through its property metatype system, allowing support for both classes generated by dconfig2cpp and the DConfigWrapper class. feat: 改进 SettingsDialog 的设计以支持dconfig2cpp生成的代码 在SettingsDialog相关的实现中不再强制依赖DConfigWrapper,而是使用QObject 这个基础类型,通过它的property这种元对象系统获取属性、信号等信息,这样 就可以同时支持dconfig2cpp生成的类,以及DConfigWrapper这个类。 --- qt6/src/qml/settings/SettingsDialog.qml | 2 +- src/private/dconfigwrapper.cpp | 10 ++-- src/private/dconfigwrapper_p.h | 2 +- src/private/dsettingscontainer.cpp | 66 +++++++++++++++++++------ src/private/dsettingscontainer_p.h | 16 +++--- src/qml/settings/SettingsDialog.qml | 2 +- 6 files changed, 67 insertions(+), 31 deletions(-) diff --git a/qt6/src/qml/settings/SettingsDialog.qml b/qt6/src/qml/settings/SettingsDialog.qml index e5c3f6bd3..edbbc8e89 100644 --- a/qt6/src/qml/settings/SettingsDialog.qml +++ b/qt6/src/qml/settings/SettingsDialog.qml @@ -12,7 +12,7 @@ DialogWindow { id: control property list groups - property D.Config config + property QtObject config property Settings.SettingsContainer container : Settings.SettingsContainer { id: settingsContainer config: control.config diff --git a/src/private/dconfigwrapper.cpp b/src/private/dconfigwrapper.cpp index 4c3cd4c70..a3ebf8a10 100644 --- a/src/private/dconfigwrapper.cpp +++ b/src/private/dconfigwrapper.cpp @@ -363,9 +363,11 @@ void DConfigWrapper::initializeProperties() const // Must fallback to the initial value, in the sync mode, the DConfigWrapperMetaObject's // properties is not initialize. const auto value = impl->value(key, initialValue); - callInGuiThread(wrapper, [wrapper, key, value] { - if (value.isValid()) + callInGuiThread(wrapper, [wrapper, key, value, currentValue] { + if (value.isValid() && value != currentValue) { wrapper->mo->setValue(key.toLocal8Bit(), value); + Q_EMIT wrapper->valueChanged(key, value); + } }); } } @@ -387,8 +389,8 @@ void DConfigWrapper::initializeProperties() const wrapper->mo->setValue(propName, value); }); - QMetaObject::invokeMethod(wrapper, [wrapper, key] { - Q_EMIT wrapper->valueChanged(key); + QMetaObject::invokeMethod(wrapper, [wrapper, key, value] { + Q_EMIT wrapper->valueChanged(key, value); }); }, Qt::DirectConnection); diff --git a/src/private/dconfigwrapper_p.h b/src/private/dconfigwrapper_p.h index 0c1b3ac23..78f555ae7 100644 --- a/src/private/dconfigwrapper_p.h +++ b/src/private/dconfigwrapper_p.h @@ -47,7 +47,7 @@ public Q_SLOTS: bool isDefaultValue(const QString &key) const; Q_SIGNALS: - void valueChanged(const QString &key); + void valueChanged(const QString &key, const QVariant &value); void initialized(); private: diff --git a/src/private/dsettingscontainer.cpp b/src/private/dsettingscontainer.cpp index 86a64a2e7..50600b829 100644 --- a/src/private/dsettingscontainer.cpp +++ b/src/private/dsettingscontainer.cpp @@ -14,6 +14,13 @@ DCORE_USE_NAMESPACE; DQUICK_BEGIN_NAMESPACE + +#ifndef QT_DEBUG + Q_LOGGING_CATEGORY(settingLog, "dtk.dsg.settings" , QtInfoMsg); +#else + Q_LOGGING_CATEGORY(settingLog, "dtk.dsg.settings"); +#endif + static constexpr char const *settingsOptionObjectName = "_d_settings_option"; static constexpr char const *settingsGroupObjectName = "_d_settings_group"; @@ -210,12 +217,12 @@ void SettingsContainer::onGroupVisibleChanged(bool visible) } } -DConfigWrapper *SettingsContainer::config() const +QObject *SettingsContainer::config() const { return m_config; } -void SettingsContainer::setConfig(DConfigWrapper *config) +void SettingsContainer::setConfig(QObject *config) { if (m_config == config) return; @@ -245,9 +252,10 @@ QString SettingsOption::name() const QVariant SettingsOption::value() { - if (!m_valueInitialized) { - if (m_config->isValid()) { - m_value = m_config->value(m_key); + if (!m_valueInitialized && m_config) { + auto value = m_config->property(m_key.toLocal8Bit()); + if (value.isValid()) { + m_value = value; m_valueInitialized = true; } } @@ -270,17 +278,16 @@ static int indexOfProperty(const QObject * obj, const QString &name) return -1; } -void SettingsOption::setConfig(DConfigWrapper *config) +void SettingsOption::setConfig(QObject *config) { m_config = config; int propertyIndex = indexOfProperty(m_config, m_key); if (propertyIndex < 0) { - connect(m_config, &DConfigWrapper::valueChanged, this, [this](const QString &key){ - if (key == m_key) { - setValue(m_config->value(key), false); - m_valueInitialized = true; - } - }); + const auto ok = connect(m_config, SIGNAL(valueChanged(QString, QVariant)), + this, SLOT(onValueChanged(QString, QVariant))); + if (!ok) { + qCWarning(settingLog) << "Failed to connect valueChanged signal from Config object:" << m_config; + } } else { // valueChanged is not emitted when the key of Config defined in qml const auto mo = m_config->metaObject(); @@ -305,10 +312,21 @@ SettingsOption *SettingsOption::qmlAttachedProperties(QObject *object) void SettingsOption::onConfigValueChanged() { - setValue(m_config->value(m_key), false); + const auto value = m_config->property(m_key.toLocal8Bit()); + if (!value.isValid()) + return; + setValue(value, false); m_valueInitialized = true; } +void SettingsOption::onValueChanged(const QString &key, const QVariant &value) +{ + if (key == m_key && value.isValid()) { + setValue(value, false); + m_valueInitialized = true; + } +} + void SettingsOption::setValue(QVariant value) { setValue(value, true); @@ -321,14 +339,30 @@ void SettingsOption::setValue(const QVariant &value, bool updateConfig) m_value = value; if (updateConfig && m_config) - m_config->setValue(m_key, value); + m_config->setProperty(m_key.toLocal8Bit(), value); Q_EMIT valueChanged(value); } void SettingsOption::resetValue() { - m_config->resetValue(m_key); + const auto index = indexOfProperty(m_config, m_key); + if (index < 0) { + qCWarning(settingLog) << "The key" << m_key << "not found in the Config object:" << m_config; + return; + } + + const auto mo = m_config->metaObject(); + const auto p = mo->property(index); + + if (!p.isResettable()) { + qCDebug(settingLog) << "The key" << m_key << "can't reset in the Config object:" << m_config; + return; + } + + if (!p.reset(m_config)) { + qCWarning(settingLog) << "The key" << m_key << "reset failed in the Config object:" << m_config; + } } void SettingsOption::setKey(QString key) @@ -404,7 +438,7 @@ void SettingsGroup::setBackground(QQmlComponent *background) Q_EMIT backgroundChanged(); } -void SettingsGroup::setConfig(DConfigWrapper *config) +void SettingsGroup::setConfig(QObject *config) { for (auto childGroup : qAsConst(m_children)) { childGroup->setConfig(config); diff --git a/src/private/dsettingscontainer_p.h b/src/private/dsettingscontainer_p.h index 36405c77e..4d8d4e17c 100644 --- a/src/private/dsettingscontainer_p.h +++ b/src/private/dsettingscontainer_p.h @@ -10,7 +10,6 @@ #include #include #include -#include "dconfigwrapper_p.h" DQUICK_BEGIN_NAMESPACE @@ -40,7 +39,7 @@ class SettingsOption : public QObject QQmlComponent *delegate() const; void setDelegate(QQmlComponent *delegate); - void setConfig(DConfigWrapper *config); + void setConfig(QObject *config); static SettingsOption *qmlAttachedProperties(QObject *object); @@ -52,6 +51,7 @@ class SettingsOption : public QObject private Q_SLOTS: void onConfigValueChanged(); + void onValueChanged(const QString &key, const QVariant &value); private: void setValue(const QVariant &value, bool updateConfig); @@ -61,7 +61,7 @@ private Q_SLOTS: QVariant m_value; bool m_valueInitialized = false; QQmlComponent *m_delegate = nullptr; - DConfigWrapper *m_config = nullptr; + QObject *m_config = nullptr; }; class SettingsGroup : public QObject @@ -97,7 +97,7 @@ class SettingsGroup : public QObject QQmlListProperty children(); QQmlComponent *background() const; void setBackground(QQmlComponent *background); - void setConfig(DConfigWrapper *config); + void setConfig(QObject *config); SettingsGroup *parentGroup() const; void setParentGroup(SettingsGroup *parentGroup); int index() const; @@ -190,7 +190,7 @@ class SettingsContainer : public QObject, public QQmlParserStatus { Q_OBJECT Q_INTERFACES(QQmlParserStatus) - Q_PROPERTY(DConfigWrapper *config READ config WRITE setConfig NOTIFY configChanged) + Q_PROPERTY(QObject *config READ config WRITE setConfig NOTIFY configChanged) Q_PROPERTY(QQmlListProperty groups READ groups NOTIFY groupsChanged) Q_PROPERTY(SettingsContentModel *contentModel READ contentModel NOTIFY contentModelChanged) Q_PROPERTY(QQmlComponent *contentTitle READ contentTitle WRITE setContentTitle NOTIFY contentTitleChanged) @@ -206,8 +206,8 @@ class SettingsContainer : public QObject, public QQmlParserStatus explicit SettingsContainer(QObject *parent = nullptr); virtual ~SettingsContainer() override; - DConfigWrapper *config() const; - void setConfig(DConfigWrapper *config); + QObject *config() const; + void setConfig(QObject *config); QQmlListProperty groups(); SettingsContentModel *contentModel() const; SettingsNavigationModel *navigationModel() const; @@ -248,7 +248,7 @@ private Q_SLOTS: QQmlComponent *m_contentTitle = nullptr; QQmlComponent *m_navigationTitle = nullptr; QQmlComponent * m_contentBackground = nullptr; - DConfigWrapper *m_config = nullptr; + QObject *m_config = nullptr; }; DQUICK_END_NAMESPACE diff --git a/src/qml/settings/SettingsDialog.qml b/src/qml/settings/SettingsDialog.qml index 2f36c05e0..9d6eabcf8 100644 --- a/src/qml/settings/SettingsDialog.qml +++ b/src/qml/settings/SettingsDialog.qml @@ -12,7 +12,7 @@ DialogWindow { id: control property list groups - property D.Config config + property QtObject config property Settings.SettingsContainer container : Settings.SettingsContainer { id: settingsContainer config: control.config