1/*
2 SPDX-FileCopyrightText: 2020 Kevin Ottens <kevin.ottens@enioka.com>
3 SPDX-FileCopyrightText: 2020 Cyril Rossi <cyril.rossi@enioka.com>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "settingstateproxy.h"
9#include "kcmutils_debug.h"
10
11#include <QDebug>
12#include <QMetaMethod>
13
14KCoreConfigSkeleton *SettingStateProxy::configObject() const
15{
16 return m_configObject;
17}
18
19void SettingStateProxy::setConfigObject(KCoreConfigSkeleton *configObject)
20{
21 if (m_configObject == configObject) {
22 return;
23 }
24
25 if (m_configObject) {
26 m_configObject->disconnect(receiver: this);
27 }
28
29 m_configObject = configObject;
30 Q_EMIT configObjectChanged();
31 updateState();
32 connectSetting();
33}
34
35QString SettingStateProxy::settingName() const
36{
37 return m_settingName;
38}
39
40void SettingStateProxy::setSettingName(const QString &settingName)
41{
42 if (m_settingName == settingName) {
43 return;
44 }
45
46 if (m_configObject) {
47 m_configObject->disconnect(receiver: this);
48 }
49
50 m_settingName = settingName;
51 Q_EMIT settingNameChanged();
52 updateState();
53 connectSetting();
54}
55
56bool SettingStateProxy::isImmutable() const
57{
58 return m_immutable;
59}
60
61bool SettingStateProxy::isDefaulted() const
62{
63 return m_defaulted;
64}
65
66void SettingStateProxy::updateState()
67{
68 const auto item = m_configObject ? m_configObject->findItem(name: m_settingName) : nullptr;
69 const auto immutable = item ? item->isImmutable() : false;
70 const auto defaulted = item ? item->isDefault() : true;
71
72 if (m_immutable != immutable) {
73 m_immutable = immutable;
74 Q_EMIT immutableChanged();
75 }
76
77 if (m_defaulted != defaulted) {
78 m_defaulted = defaulted;
79 Q_EMIT defaultedChanged();
80 }
81}
82
83void SettingStateProxy::connectSetting()
84{
85 const auto item = m_configObject ? m_configObject->findItem(name: m_settingName) : nullptr;
86 if (!item) {
87 return;
88 }
89
90 const auto updateStateSlotIndex = metaObject()->indexOfMethod(method: "updateState()");
91 Q_ASSERT(updateStateSlotIndex >= 0);
92 const auto updateStateSlot = metaObject()->method(index: updateStateSlotIndex);
93 Q_ASSERT(updateStateSlot.isValid());
94
95 const auto itemHasSignals = dynamic_cast<KConfigCompilerSignallingItem *>(item) || dynamic_cast<KPropertySkeletonItem *>(item);
96 if (!itemHasSignals) {
97 qCWarning(KCMUTILS_LOG) << "Attempting to use SettingStateProxy with a non signalling item:" << m_settingName;
98 return;
99 }
100
101 const auto propertyName = [this] {
102 auto name = m_settingName;
103 if (name.at(i: 0).isUpper()) {
104 name[0] = name[0].toLower();
105 }
106 return name.toUtf8();
107 }();
108
109 const auto metaObject = m_configObject->metaObject();
110 const auto propertyIndex = metaObject->indexOfProperty(name: propertyName.constData());
111 Q_ASSERT(propertyIndex >= 0);
112 const auto property = metaObject->property(index: propertyIndex);
113 Q_ASSERT(property.isValid());
114 if (!property.hasNotifySignal()) {
115 qCWarning(KCMUTILS_LOG) << "Attempting to use SettingStateProxy with a non notifying property:" << propertyName;
116 return;
117 }
118
119 const auto changedSignal = property.notifySignal();
120 Q_ASSERT(changedSignal.isValid());
121 connect(sender: m_configObject, signal: changedSignal, receiver: this, method: updateStateSlot);
122 connect(sender: m_configObject, signal: &KCoreConfigSkeleton::configChanged, context: this, slot: &SettingStateProxy::updateState);
123}
124
125#include "moc_settingstateproxy.cpp"
126

source code of kcmutils/src/qml/settingstateproxy.cpp