1 | /* |
2 | SPDX-FileCopyrightText: 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org> |
3 | SPDX-FileCopyrightText: 2001 Michael Goffioul <kdeprint@swing.be> |
4 | SPDX-FileCopyrightText: 2004 Frans Englich <frans.englich@telia.com> |
5 | SPDX-FileCopyrightText: 2009 Dario Freddi <drf@kde.org> |
6 | SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org> |
7 | SPDX-FileCopyrightText: 2023 Alexander Lohnau <alexander.lohnau@gmx.de> |
8 | |
9 | SPDX-License-Identifier: LGPL-2.0-or-later |
10 | */ |
11 | |
12 | #ifndef KQUICKCONFIGMODULE_H |
13 | #define KQUICKCONFIGMODULE_H |
14 | |
15 | #include "kcmutilsquick_export.h" |
16 | |
17 | #include <QObject> |
18 | #include <QQmlComponent> |
19 | #include <QStringList> |
20 | #include <QVariant> |
21 | |
22 | #include <KPluginFactory> |
23 | #include <KPluginMetaData> |
24 | |
25 | #include <memory> |
26 | #include <qqmlintegration.h> |
27 | |
28 | #include "kabstractconfigmodule.h" |
29 | #include "kquickconfigmoduleloader.h" |
30 | |
31 | class QQuickItem; |
32 | class QQmlEngine; |
33 | class KQuickConfigModulePrivate; |
34 | |
35 | /*! |
36 | * \class KQuickConfigModule |
37 | * \inmodule KCMUtilsQuick |
38 | * \brief The base class for QtQuick configuration modules. |
39 | * |
40 | * Configuration modules are realized as plugins that are dynamically loaded. |
41 | * |
42 | * All the necessary glue logic and the GUI bells and whistles |
43 | * are provided by the control center and must not concern |
44 | * the module author. |
45 | * |
46 | * To write a config module, you have to create a C++ plugin |
47 | * and an accompanying QML user interface. |
48 | * |
49 | * To allow KCMUtils to load your ConfigModule subclass, you must create a KPluginFactory implementation. |
50 | * |
51 | * \code |
52 | * #include <KPluginFactory> |
53 | * |
54 | * K_PLUGIN_CLASS_WITH_JSON(MyConfigModule, "yourmetadata.json") |
55 | * \endcode |
56 | * |
57 | * The constructor of the ConfigModule then looks like this: |
58 | * \code |
59 | * YourConfigModule::YourConfigModule(QObject *parent, const KPluginMetaData &metaData) |
60 | * : KQuickConfigModule(parent, metaData) |
61 | * { |
62 | * } |
63 | * \endcode |
64 | * |
65 | * The QML part must be in the KPackage format, installed under share/kpackage/kcms. |
66 | * \sa KPackage::Package |
67 | * |
68 | * The package must have the same name as the plugin filename, to be installed |
69 | * by CMake with the command: |
70 | * \badcode |
71 | * kpackage_install_package(packagedir kcm_yourconfigmodule kcms) |
72 | * \endcode |
73 | * The "packagedir" is the subdirectory in the source tree where the package sources are |
74 | * located, and "kcm_yourconfigmodule" is id of the plugin. |
75 | * Finally "kcms" is the literal string "kcms", so that the package is |
76 | * installed as a configuration module (and not some other kind of package). |
77 | * |
78 | * The QML part can access all the properties of ConfigModule (together with the properties |
79 | * defined in its subclass) by accessing to the global object "kcm", or with the |
80 | * import of "org.kde.kcmutils" the ConfigModule attached property. |
81 | * |
82 | * \qml |
83 | * import QtQuick |
84 | * import QtQuick.Controls as QQC2 |
85 | * import org.kde.kcmutils as KCMUtils |
86 | * import org.kde.kirigami as Kirigami |
87 | * |
88 | * Item { |
89 | * // implicit size will be used as initial size when loaded in kcmshell6 |
90 | * implicitWidth: Kirigami.Units.gridUnit * 30 |
91 | * implicitHeight: Kirigami.Units.gridUnit * 30 |
92 | * |
93 | * KCMUtils.ConfigModule.buttons: KCMUtils.ConfigModule.Help | KCMUtils.ConfigModule.Apply |
94 | * |
95 | * QQC2.Label { |
96 | * // The following two bindings are equivalent: |
97 | * text: kcm.needsSave |
98 | * enabled: KCMUtils.ConfigModule.needsSave |
99 | * } |
100 | * } |
101 | * \endqml |
102 | * |
103 | * See https://develop.kde.org/docs/features/configuration/kcm/ for more detailed documentation. |
104 | * \since 6.0 |
105 | */ |
106 | class KCMUTILSQUICK_EXPORT KQuickConfigModule : public KAbstractConfigModule |
107 | { |
108 | Q_OBJECT |
109 | |
110 | /*! \property KQuickConfigModule::mainUi */ |
111 | Q_PROPERTY(QQuickItem *mainUi READ mainUi CONSTANT) |
112 | /*! \property KQuickConfigModule::columnWidth */ |
113 | Q_PROPERTY(int columnWidth READ columnWidth WRITE setColumnWidth NOTIFY columnWidthChanged) |
114 | /*! \property KQuickConfigModule::depth */ |
115 | Q_PROPERTY(int depth READ depth NOTIFY depthChanged) |
116 | /*! \property KQuickConfigModule::currentIndex */ |
117 | Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) |
118 | |
119 | QML_NAMED_ELEMENT(ConfigModule) |
120 | QML_ATTACHED(KQuickConfigModule) |
121 | |
122 | public: |
123 | ~KQuickConfigModule() override; |
124 | |
125 | /*! |
126 | * \brief Returns the qml engine that built the main config UI. |
127 | */ |
128 | std::shared_ptr<QQmlEngine> engine() const; |
129 | |
130 | /*! |
131 | * \brief The error string in case the mainUi failed to load. |
132 | */ |
133 | QString errorString() const; |
134 | |
135 | // QML property accessors |
136 | |
137 | /*! |
138 | * \brief Returns the main UI for this configuration module. |
139 | * |
140 | * It's a QQuickItem coming from the QML package named |
141 | * the same as the KAboutData's component name for this config module. |
142 | * |
143 | * Normally, ui/main.qml will be loaded from the qrc baked into the plugin. However, |
144 | * if the PLASMA_PLATFORM environmental variable is set, the module will try to load |
145 | * a platform-specific QML file as its mainUi starting point. |
146 | * |
147 | * For example: |
148 | * |
149 | * environment has set |
150 | * \c {export PLASMA_PLATFORM=phone:handset} |
151 | * |
152 | * The module will try to find main_phone.qml, then main_handset.qml, then main.qml. |
153 | * The first file that is found will be used as mainUi. If none is found and main.qml |
154 | * doesn't exist, the module is broken and an error will be displayed. |
155 | */ |
156 | QQuickItem *mainUi(); |
157 | |
158 | /*! |
159 | * \brief Returns a subpage at a given depth \a index. |
160 | * \note This does not include the mainUi. That is, a depth of 2 |
161 | * is a mainUi and one subPage at index 0. |
162 | */ |
163 | QQuickItem *subPage(int index) const; |
164 | |
165 | /*! |
166 | * \brief Returns the width the kcm wants in column mode. |
167 | * |
168 | * If a columnWidth is valid ( > 0 ) and less than the systemsettings' view width, |
169 | * more than one will be visible at once, and the first page will be a sidebar to the last page pushed. |
170 | * As default, this is -1 which will make the shell always show only one page at a time. |
171 | */ |
172 | int columnWidth() const; |
173 | |
174 | /*! |
175 | * \brief Sets the column \a width we want. |
176 | */ |
177 | void setColumnWidth(int width); |
178 | |
179 | /*! |
180 | * \brief Returns how many pages this kcm has. |
181 | * |
182 | * It is guaranteed to be at least 1 (the main ui) plus how many times a new page has been pushed without pop. |
183 | */ |
184 | int depth() const; |
185 | |
186 | /*! |
187 | * \brief Sets the current page \a index this KCM should display. |
188 | */ |
189 | void setCurrentIndex(int index); |
190 | |
191 | /*! |
192 | * \brief Returns the index of the page this KCM should display. |
193 | */ |
194 | int currentIndex() const; |
195 | |
196 | static KQuickConfigModule *qmlAttachedProperties(QObject *object); |
197 | |
198 | public Q_SLOTS: |
199 | /*! |
200 | * \brief Push a new sub page with the given \a fileName |
201 | * with optional \a initialProperties in the KCM hierarchy: |
202 | * pages will be seen as a Kirigami PageRow. |
203 | */ |
204 | void push(const QString &fileName, const QVariantMap &initialProperties = QVariantMap()); |
205 | |
206 | /*! |
207 | * \brief Push a given QQuick \a item as a new sub page in the KCM hierarchy. |
208 | * \overload KQuickConfigModule::push() |
209 | */ |
210 | void push(QQuickItem *item); |
211 | |
212 | /*! |
213 | * \brief Pop the last page of the KCM hierarchy, the page is destroyed. |
214 | */ |
215 | void pop(); |
216 | |
217 | /*! |
218 | * \brief Remove and return the last page of the KCM hierarchy. |
219 | * |
220 | * The popped page won't be deleted, it's the caller's responsibility |
221 | * to manage the lifetime of the returned item. |
222 | * |
223 | * Returns the last page if any, \c nullptr otherwise. |
224 | */ |
225 | QQuickItem *takeLast(); |
226 | |
227 | Q_SIGNALS: |
228 | |
229 | // QML NOTIFY signaling |
230 | |
231 | /*! |
232 | * \brief Emitted when a new sub \a page is pushed. |
233 | */ |
234 | void pagePushed(QQuickItem *page); |
235 | |
236 | // RFC: page argument? |
237 | /*! |
238 | * \brief Emitted when a sub page is popped. |
239 | */ |
240 | void (); |
241 | |
242 | /*! |
243 | * \brief Emitted when the wanted column \a width of the KCM changes. |
244 | */ |
245 | void columnWidthChanged(int width); |
246 | |
247 | /*! |
248 | * \brief Emitted when the \a index of the current page changed. |
249 | */ |
250 | void currentIndexChanged(int index); |
251 | |
252 | /*! |
253 | * \brief Emitted when the number of pages changed, and so their \a index. |
254 | */ |
255 | void depthChanged(int index); |
256 | |
257 | /*! |
258 | * \brief Emitted when the main Ui has loaded successfully and mainUi() is available. |
259 | */ |
260 | void mainUiReady(); |
261 | |
262 | protected: |
263 | /*! |
264 | * \brief Base class for all QtQuick config modules. |
265 | * |
266 | * Creates a new KQuickConfigModule with the given \a metaData as a child of \a parent. |
267 | * Use KQuickConfigModuleLoader to instantiate this class. |
268 | * |
269 | * \note Do not emit changed signals here, since they are not yet connected to any slot. |
270 | */ |
271 | explicit KQuickConfigModule(QObject *parent, const KPluginMetaData &metaData); |
272 | |
273 | private: |
274 | void setInternalEngine(const std::shared_ptr<QQmlEngine> &engine); |
275 | friend KPluginFactory::Result<KQuickConfigModule> |
276 | KQuickConfigModuleLoader::loadModule(const KPluginMetaData &metaData, QObject *parent, const QVariantList &args, const std::shared_ptr<QQmlEngine> &engine); |
277 | const std::unique_ptr<KQuickConfigModulePrivate> d; |
278 | }; |
279 | |
280 | #endif // KQUICKCONFIGMODULE_H |
281 | |