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 kquickconfigmodule.h KQuickConfigModule |
37 | * |
38 | * The base class for QtQuick configuration modules. |
39 | * Configuration modules are realized as plugins that are dynamically loaded. |
40 | * |
41 | * All the necessary glue logic and the GUI bells and whistles |
42 | * are provided by the control center and must not concern |
43 | * the module author. |
44 | * |
45 | * To write a config module, you have to create a C++ plugin |
46 | * and an accompaning QML user interface. |
47 | * |
48 | * To allow KCMUtils to load your ConfigModule subclass, you must create a KPluginFactory implementation. |
49 | * |
50 | * \code |
51 | * #include <KPluginFactory> |
52 | * |
53 | * K_PLUGIN_CLASS_WITH_JSON(MyConfigModule, "yourmetadata.json") |
54 | * \endcode |
55 | * |
56 | * The constructor of the ConfigModule then looks like this: |
57 | * \code |
58 | * YourConfigModule::YourConfigModule(QObject *parent, const KPluginMetaData &metaData) |
59 | * : KQuickConfigModule(parent, metaData) |
60 | * { |
61 | * } |
62 | * \endcode |
63 | * |
64 | * The QML part must be in the KPackage format, installed under share/kpackage/kcms. |
65 | * @see KPackage::Package |
66 | * |
67 | * The package must have the same name as the plugin filename, to be installed |
68 | * by CMake with the command: |
69 | * \code |
70 | * kpackage_install_package(packagedir kcm_yourconfigmodule kcms) |
71 | * \endcode |
72 | * The "packagedir" is the subdirectory in the source tree where the package sources are |
73 | * located, and "kcm_yourconfigmodule" is id of the plugin. |
74 | * Finally "kcms" is the literal string "kcms", so that the package is |
75 | * installed as a configuration module (and not some other kind of package). |
76 | * |
77 | * The QML part can access all the properties of ConfigModule (together with the properties |
78 | * defined in its subclass) by accessing to the global object "kcm", or with the |
79 | * import of "org.kde.kcmutils" the ConfigModule attached property. |
80 | * |
81 | * \code |
82 | * import QtQuick |
83 | * import QtQuick.Controls as QQC2 |
84 | * import org.kde.kcmutils as KCMUtils |
85 | * import org.kde.kirigami as Kirigami |
86 | * |
87 | * Item { |
88 | * // implicit size will be used as initial size when loaded in kcmshell6 |
89 | * implicitWidth: Kirigami.Units.gridUnit * 30 |
90 | * implicitHeight: Kirigami.Units.gridUnit * 30 |
91 | * |
92 | * KCMUtils.ConfigModule.buttons: KCMUtils.ConfigModule.Help | KCMUtils.ConfigModule.Apply |
93 | * |
94 | * QQC2.Label { |
95 | * // The following two bindings are equivalent: |
96 | * text: kcm.needsSave |
97 | * enabled: KCMUtils.ConfigModule.needsSave |
98 | * } |
99 | * } |
100 | * \endcode |
101 | * |
102 | * See https://develop.kde.org/docs/extend/kcm/ for more detailed documentation. |
103 | * @since 6.0 |
104 | */ |
105 | class KCMUTILSQUICK_EXPORT KQuickConfigModule : public KAbstractConfigModule |
106 | { |
107 | Q_OBJECT |
108 | |
109 | Q_PROPERTY(QQuickItem *mainUi READ mainUi CONSTANT) |
110 | Q_PROPERTY(int columnWidth READ columnWidth WRITE setColumnWidth NOTIFY columnWidthChanged) |
111 | Q_PROPERTY(int depth READ depth NOTIFY depthChanged) |
112 | Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) |
113 | |
114 | QML_NAMED_ELEMENT(ConfigModule) |
115 | |
116 | public: |
117 | /** |
118 | * Destroys the module. |
119 | */ |
120 | ~KQuickConfigModule() override; |
121 | |
122 | /** |
123 | * @return the qml engine that built the main config UI |
124 | */ |
125 | std::shared_ptr<QQmlEngine> engine() const; |
126 | |
127 | /** |
128 | * The error string in case the mainUi failed to load. |
129 | */ |
130 | QString errorString() const; |
131 | |
132 | // QML property accessors |
133 | |
134 | /** |
135 | * @return The main UI for this configuration module. It's a QQuickItem coming from |
136 | * the QML package named the same as the KAboutData's component name for |
137 | * this config module |
138 | */ |
139 | QQuickItem *mainUi(); |
140 | |
141 | /* |
142 | * @return a subpage at a given depth |
143 | * @note This does not include the mainUi. i.e a depth of 2 is a mainUi and one subPage |
144 | * at index 0 |
145 | */ |
146 | QQuickItem *subPage(int index) const; |
147 | |
148 | /** |
149 | * returns the width the kcm wants in column mode. |
150 | * If a columnWidth is valid ( > 0 ) and less than the systemsettings' view width, |
151 | * more than one will be visible at once, and the first page will be a sidebar to the last page pushed. |
152 | * As default, this is -1 which will make the shell always show only one page at a time. |
153 | */ |
154 | int columnWidth() const; |
155 | |
156 | /** |
157 | * Sets the column width we want. |
158 | */ |
159 | void setColumnWidth(int width); |
160 | |
161 | /** |
162 | * @returns how many pages this kcm has. |
163 | * It is guaranteed to be at least 1 (the main ui) plus how many times a new page has been pushed without pop |
164 | */ |
165 | int depth() const; |
166 | |
167 | /** |
168 | * Sets the current page index this kcm should display |
169 | */ |
170 | void setCurrentIndex(int index); |
171 | |
172 | /** |
173 | * @returns the index of the page this kcm should display |
174 | */ |
175 | int currentIndex() const; |
176 | |
177 | static KQuickConfigModule *qmlAttachedProperties(QObject *object); |
178 | |
179 | public Q_SLOTS: |
180 | /** |
181 | * Push a new sub page in the KCM hierarchy: pages will be seen as a Kirigami PageRow |
182 | */ |
183 | void push(const QString &fileName, const QVariantMap &initialProperties = QVariantMap()); |
184 | |
185 | /** |
186 | * |
187 | */ |
188 | void push(QQuickItem *item); |
189 | |
190 | /** |
191 | * pop the last page of the KCM hierarchy, the page is destroyed |
192 | */ |
193 | void pop(); |
194 | |
195 | /** |
196 | * remove and return the last page of the KCM hierarchy: |
197 | * the popped page won't be deleted, it's the caller's responsibility to manage the lifetime of the returned item |
198 | * @returns the last page if any, nullptr otherwise |
199 | */ |
200 | QQuickItem *takeLast(); |
201 | |
202 | Q_SIGNALS: |
203 | |
204 | // QML NOTIFY signaling |
205 | |
206 | /** |
207 | * Emitted when a new sub page is pushed |
208 | */ |
209 | void pagePushed(QQuickItem *page); |
210 | |
211 | /** |
212 | * Emitted when a sub page is popped |
213 | */ |
214 | // RFC: page argument? |
215 | void (); |
216 | |
217 | /** |
218 | * Emitted when the wanted column width of the kcm changes |
219 | */ |
220 | void columnWidthChanged(int width); |
221 | |
222 | /** |
223 | * Emitted when the current page changed |
224 | */ |
225 | void currentIndexChanged(int index); |
226 | |
227 | /** |
228 | * Emitted when the number of pages changed |
229 | */ |
230 | void depthChanged(int index); |
231 | |
232 | /** |
233 | * Emitted when the main Ui has loaded successfully and `mainUi()` is available |
234 | */ |
235 | void mainUiReady(); |
236 | |
237 | protected: |
238 | /** |
239 | * Base class for all QtQuick config modules. |
240 | * Use KQuickConfigModuleLoader to instantiate this class |
241 | * |
242 | * @note do not emit changed signals here, since they are not yet connected to any slot. |
243 | */ |
244 | explicit KQuickConfigModule(QObject *parent, const KPluginMetaData &metaData); |
245 | |
246 | private: |
247 | void setInternalEngine(const std::shared_ptr<QQmlEngine> &engine); |
248 | friend KPluginFactory::Result<KQuickConfigModule> |
249 | KQuickConfigModuleLoader::loadModule(const KPluginMetaData &metaData, QObject *parent, const QVariantList &args, const std::shared_ptr<QQmlEngine> &engine); |
250 | const std::unique_ptr<KQuickConfigModulePrivate> d; |
251 | }; |
252 | |
253 | QML_DECLARE_TYPEINFO(KQuickConfigModule, QML_HAS_ATTACHED_PROPERTIES) |
254 | |
255 | #endif // KQUICKCONFIGMODULE_H |
256 | |