Libplasma

configmodel.cpp
1/*
2 SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
3 SPDX-FileCopyrightText: 2015 Eike Hein <hein@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "configmodel.h"
9#include "Plasma/Applet"
10#include "Plasma/Containment"
11#include "configcategory_p.h"
12#include "configview.h"
13#include "debug_p.h"
14#include "sharedqmlengine.h"
15
16#include <QDebug>
17#include <QDir>
18#include <QQmlComponent>
19#include <QQmlContext>
20#include <QQmlEngine>
21#include <QQuickItem>
22
23#include <KLocalizedString>
24#include <KQuickConfigModule>
25#include <KQuickConfigModuleLoader>
26
27#include <Plasma/Corona>
28#include <Plasma/PluginLoader>
29#include <kquickconfigmoduleloader.h>
30
31namespace PlasmaQuick
32{
33//////////////////////////////ConfigModel
34
35class ConfigModelPrivate
36{
37public:
38 ConfigModelPrivate(ConfigModel *model);
39 ~ConfigModelPrivate();
40
41 ConfigModel *q;
42 QList<ConfigCategory *> categories;
43 QPointer<Plasma::Applet> appletInterface;
44 QHash<QString, KQuickConfigModule *> kcms;
45
46 void appendCategory(ConfigCategory *c);
47 void removeCategory(ConfigCategory *c);
48 void removeCategoryAt(int index);
49 void clear();
50 QVariant get(int row) const;
51
52 static ConfigCategory *categories_at(QQmlListProperty<ConfigCategory> *prop, qsizetype index);
53 static qsizetype categories_count(QQmlListProperty<ConfigCategory> *prop);
54 static void categories_append(QQmlListProperty<ConfigCategory> *prop, ConfigCategory *o);
55 static void categories_clear(QQmlListProperty<ConfigCategory> *prop);
56};
57
58ConfigModelPrivate::ConfigModelPrivate(ConfigModel *model)
59 : q(model)
60{
61}
62
63ConfigModelPrivate::~ConfigModelPrivate()
64{
65}
66
67ConfigCategory *ConfigModelPrivate::categories_at(QQmlListProperty<ConfigCategory> *prop, qsizetype index)
68{
69 ConfigModel *model = qobject_cast<ConfigModel *>(prop->object);
70 if (!model || index >= model->d->categories.count() || index < 0) {
71 return nullptr;
72 } else {
73 return model->d->categories.at(index);
74 }
75}
76
77void ConfigModelPrivate::categories_append(QQmlListProperty<ConfigCategory> *prop, ConfigCategory *o)
78{
79 ConfigModel *model = qobject_cast<ConfigModel *>(prop->object);
80 if (!o || !model) {
81 return;
82 }
83
84 if (o->parent() == prop->object) {
85 o->setParent(nullptr);
86 }
87
88 o->setParent(prop->object);
89 model->d->appendCategory(o);
90}
91
92qsizetype ConfigModelPrivate::categories_count(QQmlListProperty<ConfigCategory> *prop)
93{
94 ConfigModel *model = qobject_cast<ConfigModel *>(prop->object);
95 if (model) {
96 return model->d->categories.count();
97 } else {
98 return 0;
99 }
100}
101
102void ConfigModelPrivate::categories_clear(QQmlListProperty<ConfigCategory> *prop)
103{
104 ConfigModel *model = qobject_cast<ConfigModel *>(prop->object);
105 if (!model) {
106 return;
107 }
108
109 model->clear();
110}
111
112void ConfigModelPrivate::clear()
113{
114 q->beginResetModel();
115 while (!categories.isEmpty()) {
116 categories.first()->setParent(nullptr);
117 categories.pop_front();
118 }
119 q->endResetModel();
120 Q_EMIT q->countChanged();
121}
122
123void ConfigModelPrivate::appendCategory(ConfigCategory *c)
124{
125 if (!c) {
126 return;
127 }
128
129 q->beginInsertRows(QModelIndex(), categories.size(), categories.size());
130 categories.append(c);
131
132 auto emitChange = [this, c] {
133 const int row = categories.indexOf(c);
134 if (row > -1) {
135 QModelIndex modelIndex = q->index(row);
136 Q_EMIT q->dataChanged(modelIndex, modelIndex);
137 }
138 };
139
140 QObject::connect(c, &ConfigCategory::nameChanged, q, emitChange);
141 QObject::connect(c, &ConfigCategory::iconChanged, q, emitChange);
142 QObject::connect(c, &ConfigCategory::sourceChanged, q, emitChange);
143 QObject::connect(c, &ConfigCategory::pluginNameChanged, q, emitChange);
144 QObject::connect(c, &ConfigCategory::visibleChanged, q, emitChange);
145
146 q->endInsertRows();
147 Q_EMIT q->countChanged();
148}
149
150void ConfigModelPrivate::removeCategory(ConfigCategory *c)
151{
152 const int index = categories.indexOf(c);
153 if (index > -1) {
154 removeCategoryAt(index);
155 }
156}
157
158void ConfigModelPrivate::removeCategoryAt(int index)
159{
160 if (index < 0 || index >= categories.count()) {
161 return;
162 }
163
164 q->beginRemoveRows(QModelIndex(), index, index);
165
166 ConfigCategory *c = categories.takeAt(index);
167 if (c->parent() == q) {
168 c->deleteLater();
169 }
170
171 q->endRemoveRows();
172 Q_EMIT q->countChanged();
173}
174
175QVariant ConfigModelPrivate::get(int row) const
176{
177 QVariantMap value;
178 if (row < 0 || row >= categories.count()) {
179 return value;
180 }
181
182 value[QStringLiteral("name")] = categories.at(row)->name();
183 value[QStringLiteral("icon")] = categories.at(row)->icon();
184 value[QStringLiteral("pluginName")] = categories.at(row)->pluginName();
185 value[QStringLiteral("source")] = q->data(q->index(row, 0), ConfigModel::SourceRole);
186 value[QStringLiteral("visible")] = categories.at(row)->visible();
187
188 return value;
189}
190
191ConfigModel::ConfigModel(QObject *parent)
192 : QAbstractListModel(parent)
193 , d(new ConfigModelPrivate(this))
194{
195}
196
197ConfigModel::~ConfigModel()
198{
199 delete d;
200}
201
202int ConfigModel::rowCount(const QModelIndex &index) const
203{
204 if (index.column() > 0) {
205 return 0;
206 }
207 return d->categories.count();
208}
209
210QVariant ConfigModel::data(const QModelIndex &index, int role) const
211{
212 if (index.row() < 0 || index.row() >= d->categories.count()) {
213 return QVariant();
214 }
215 switch (role) {
216 case NameRole:
217 return d->categories.at(index.row())->name();
218 case IconRole:
219 return d->categories.at(index.row())->icon();
220 case SourceRole: {
221 const QString source = d->categories.at(index.row())->source();
222 // Quick check if source is an absolute path or not
223 if (d->appletInterface && !source.isEmpty() && !(source.startsWith(QLatin1Char('/')) && source.endsWith(QLatin1String("qml")))) {
224 return d->appletInterface.data()->fileUrl("ui", source);
225 } else {
226 return source;
227 }
228 }
229 case PluginNameRole:
230 return d->categories.at(index.row())->pluginName();
231 case VisibleRole:
232 return d->categories.at(index.row())->visible();
233 default:
234 return QVariant();
235 }
236}
237
238QHash<int, QByteArray> ConfigModel::roleNames() const
239{
240 return {
241 {NameRole, "name"},
242 {IconRole, "icon"},
243 {SourceRole, "source"},
244 {PluginNameRole, "pluginName"},
245 {VisibleRole, "visible"},
246 };
247}
248
250{
251 return d->get(row);
252}
253
254void ConfigModel::appendCategory(const QString &iconName, const QString &name, const QString &path, const QString &pluginName)
255{
256 ConfigCategory *cat = new ConfigCategory(this);
257 cat->setIcon(iconName);
258 cat->setName(name);
259 cat->setSource(path);
260 cat->setPluginName(pluginName);
261 d->appendCategory(cat);
262}
263
264void ConfigModel::appendCategory(const QString &iconName, const QString &name, const QString &path, const QString &pluginName, bool visible)
265{
266 ConfigCategory *cat = new ConfigCategory(this);
267 cat->setIcon(iconName);
268 cat->setName(name);
269 cat->setSource(path);
270 cat->setPluginName(pluginName);
271 cat->setVisible(visible);
272 d->appendCategory(cat);
273}
274
275void ConfigModel::appendCategory(ConfigCategory *category)
276{
277 d->appendCategory(category);
278}
279
280void ConfigModel::removeCategory(ConfigCategory *category)
281{
282 d->removeCategory(category);
283}
284
285void ConfigModel::removeCategoryAt(int index)
286{
287 d->removeCategoryAt(index);
288}
289
291{
292 d->clear();
293}
294
295void ConfigModel::setApplet(Plasma::Applet *interface)
296{
297 d->appletInterface = interface;
298}
299
300Plasma::Applet *ConfigModel::applet() const
301{
302 return d->appletInterface.data();
303}
304
305QQmlListProperty<ConfigCategory> ConfigModel::categories()
306{
308 nullptr,
309 ConfigModelPrivate::categories_append,
310 ConfigModelPrivate::categories_count,
311 ConfigModelPrivate::categories_at,
312 ConfigModelPrivate::categories_clear);
313}
314
315}
316
317#include "moc_configmodel.cpp"
This model contains all the possible config categories for a dialog, such as categories of the config...
Definition configmodel.h:51
void clear()
clears the model
void appendCategory(const QString &iconName, const QString &name, const QString &path, const QString &pluginName)
add a new category in the model
Q_INVOKABLE QVariant get(int row) const
The base Applet class.
Definition applet.h:64
The EdgeEventForwarder class This class forwards edge events to be replayed within the given margin T...
Definition action.h:20
int column() const const
int row() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
const QChar at(qsizetype position) const const
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
void * data()
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri May 2 2025 11:55:47 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.