KCMUtils

main.cpp
1/*
2 SPDX-FileCopyrightText: 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
3 SPDX-FileCopyrightText: 2000 Matthias Elter <elter@kde.org>
4 SPDX-FileCopyrightText: 2004 Frans Englich <frans.englich@telia.com>
5 SPDX-FileCopyrightText: 2023 Alexander Lohnau <alexander.lohnau@gmx.de>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8
9*/
10
11#include <QApplication>
12#include <QCommandLineOption>
13#include <QCommandLineParser>
14#include <QDebug>
15#include <QIcon>
16#include <QQmlEngine>
17#include <QRegularExpression>
18#include <QStandardPaths>
19
20#include <KAboutData>
21#include <KAuthorized>
22#include <KCModule>
23#include <KCMultiDialog>
24#include <KLocalizedString>
25#include <KPageDialog>
26#include <KPluginMetaData>
27#include <KShell>
28#include <kcmutils_debug.h>
29
30#if HAVE_QTDBUS
31#include <QDBusConnection>
32#include <QDBusConnectionInterface>
33#endif
34
35#include <algorithm>
36#include <iostream>
37
38inline QList<KPluginMetaData> findKCMsMetaData()
39{
40 QList<KPluginMetaData> metaDataList = KPluginMetaData::findPlugins(QStringLiteral("plasma/kcms"));
41 metaDataList << KPluginMetaData::findPlugins(QStringLiteral("plasma/kcms/systemsettings"));
42 metaDataList << KPluginMetaData::findPlugins(QStringLiteral("plasma/kcms/systemsettings_qwidgets"));
43 metaDataList << KPluginMetaData::findPlugins(QStringLiteral("plasma/kcms/kinfocenter"));
44 return metaDataList;
45}
46
47class KCMShellMultiDialog : public KCMultiDialog
48{
50
51public:
52 /**
53 * Constructor. Parameter @p dialogFace is passed to KCMultiDialog
54 * unchanged.
55 */
56 explicit KCMShellMultiDialog(KPageDialog::FaceType dialogFace)
58 {
59 setFaceType(dialogFace);
60 setModal(false);
61
62#if HAVE_QTDBUS
64 if (KCModule *activeModule = newPage->widget()->findChild<KCModule *>()) {
65 if (QDBusConnection::sessionBus().isConnected()
66 && QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.ActivityManager"))) {
67 QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.ActivityManager"),
68 QStringLiteral("/ActivityManager/Resources"),
69 QStringLiteral("org.kde.ActivityManager.Resources"),
70 QStringLiteral("RegisterResourceEvent"));
71
72 const QString appId = QStringLiteral("org.kde.systemsettings");
73 const uint winId = 0;
74 const QString url = QLatin1String("kcm:") + activeModule->metaData().pluginId();
75 const uint eventType = 0; // Accessed
76
77 msg.setArguments({appId, winId, url, eventType});
78
80 }
81 }
82 });
83#endif
84 }
85};
86
87int main(int argc, char *argv[])
88{
89 const bool qpaVariable = qEnvironmentVariableIsSet("QT_QPA_PLATFORM");
90 QApplication app(argc, argv);
91 if (!qpaVariable) {
92 // don't leak the env variable to processes we start
93 qunsetenv("QT_QPA_PLATFORM");
94 }
96 KAboutData aboutData(QStringLiteral("kcmshell6"),
97 QString(),
98 QLatin1String(PROJECT_VERSION),
99 i18n("A tool to start single system settings modules"),
101 i18n("(c) 1999-2023, The KDE Developers"));
102
103 aboutData.addAuthor(i18n("Frans Englich"), i18n("Maintainer"), QStringLiteral("frans.englich@kde.org"));
104 aboutData.addAuthor(i18n("Daniel Molkentin"), QString(), QStringLiteral("molkentin@kde.org"));
105 aboutData.addAuthor(i18n("Matthias Hoelzer-Kluepfel"), QString(), QStringLiteral("hoelzer@kde.org"));
106 aboutData.addAuthor(i18n("Matthias Elter"), QString(), QStringLiteral("elter@kde.org"));
107 aboutData.addAuthor(i18n("Matthias Ettrich"), QString(), QStringLiteral("ettrich@kde.org"));
108 aboutData.addAuthor(i18n("Waldo Bastian"), QString(), QStringLiteral("bastian@kde.org"));
110
111 QCommandLineParser parser;
112 aboutData.setupCommandLine(&parser);
113
114 parser.addOption(QCommandLineOption(QStringLiteral("list"), i18n("List all possible modules")));
115 parser.addPositionalArgument(QStringLiteral("module"), i18n("Configuration module to open"));
116 parser.addOption(QCommandLineOption(QStringLiteral("args"), i18n("Space separated arguments for the module"), QLatin1String("arguments")));
117 parser.addOption(QCommandLineOption(QStringLiteral("icon"), i18n("Use a specific icon for the window"), QLatin1String("icon")));
118 parser.addOption(QCommandLineOption(QStringLiteral("caption"), i18n("Use a specific caption for the window"), QLatin1String("caption")));
119 parser.addOption(QCommandLineOption(QStringLiteral("highlight"), i18n("Show an indicator when settings have changed from their default value")));
120
121 parser.parse(app.arguments());
122 aboutData.processCommandLine(&parser);
123
124 parser.process(app);
125
126 if (parser.isSet(QStringLiteral("list"))) {
127 std::cout << i18n("The following modules are available:").toLocal8Bit().constData() << '\n';
128
129 QList<KPluginMetaData> plugins = findKCMsMetaData();
130 int maxLen = 0;
131
132 for (const auto &plugin : plugins) {
133 const int len = plugin.pluginId().size();
134 maxLen = std::max(maxLen, len);
135 }
136
137 for (const auto &plugin : plugins) {
138 QString comment = plugin.description();
139 if (comment.isEmpty()) {
140 comment = i18n("No description available");
141 }
142
143 const QString entry = QStringLiteral("%1 - %2").arg(plugin.pluginId().leftJustified(maxLen, QLatin1Char(' ')), comment);
144
145 std::cout << entry.toLocal8Bit().constData() << '\n';
146 }
147
148 std::cout << std::endl;
149
150 return 0;
151 }
152
153 if (parser.positionalArguments().isEmpty()) {
154 parser.showHelp();
155 return -1;
156 }
157
158 QList<KPluginMetaData> metaDataList;
159
160 QStringList args = parser.positionalArguments();
161 args.removeDuplicates();
162 for (const QString &arg : args) {
164 metaDataList << data;
165 } else {
166 // Look in the namespaces for systemsettings/kinfocenter
167 const static auto knownKCMs = findKCMsMetaData();
168 const QStringList possibleIds{arg, QStringLiteral("kcm_") + arg, QStringLiteral("kcm") + arg};
169 bool found = std::any_of(knownKCMs.begin(), knownKCMs.end(), [&possibleIds, &metaDataList](const KPluginMetaData &data) {
170 bool idMatches = possibleIds.contains(data.pluginId());
171 if (idMatches) {
172 metaDataList << data;
173 }
174 return idMatches;
175 });
176 if (!found) {
177 metaDataList << KPluginMetaData(arg); // So that we show an error message in the dialog
178 qCWarning(KCMUTILS_LOG) << "Could not find KCM with given Id" << arg;
179 }
180 }
181 }
182 if (metaDataList.isEmpty()) {
183 return -1;
184 }
185
186 // This ensures if there are multiple QML-based kcms loaded, they use a shared engine instance
187 app.setProperty("__qmlEngine", QVariant::fromValue(new QQmlEngine));
188 const bool multipleKCMs = metaDataList.size() > 1;
190 auto dlg = new KCMShellMultiDialog(ftype);
191 dlg->setAttribute(Qt::WA_DeleteOnClose);
192
193 if (parser.isSet(QStringLiteral("caption"))) {
194 dlg->setWindowTitle(parser.value(QStringLiteral("caption")));
195 } else if (!multipleKCMs) { // We will have the "Configure" window title set by KCMultiDialog
196 dlg->setWindowTitle(metaDataList.constFirst().name());
197 }
198
199 const QStringList argSplit = KShell::splitArgs(parser.value(QStringLiteral("args")));
200 QVariantList pluginArgs(argSplit.begin(), argSplit.end());
201 if (metaDataList.size() == 1) {
202 KPageWidgetItem *item = dlg->addModule(*metaDataList.cbegin(), pluginArgs);
203 // This makes sure the content area is focused by default
205 } else {
206 for (const KPluginMetaData &m : std::as_const(metaDataList)) {
207 dlg->addModule(m, pluginArgs);
208 }
209 }
210
211 if (parser.isSet(QStringLiteral("icon"))) {
212 dlg->setWindowIcon(QIcon::fromTheme(parser.value(QStringLiteral("icon"))));
213 } else {
214 dlg->setWindowIcon(QIcon::fromTheme(metaDataList.constFirst().iconName()));
215 }
216
217 if (parser.isSet(QStringLiteral("highlight"))) {
218 dlg->setDefaultsIndicatorsVisible(true);
219 }
220
221 if (app.desktopFileName() == QLatin1String("org.kde.kcmshell6")) {
222 const QString path = metaDataList.constFirst().fileName();
223
224 if (path.endsWith(QLatin1String(".desktop"))) {
225 app.setDesktopFileName(path);
226 } else {
227 app.setDesktopFileName(metaDataList.constFirst().pluginId());
228 }
229 }
230
231 dlg->show();
232
233 app.exec();
234
235 return 0;
236}
237
238#include "main.moc"
static void setApplicationData(const KAboutData &aboutData)
The base class for QWidgets configuration modules.
Definition kcmodule.h:59
A class that offers a KPageDialog containing config modules.
static void setApplicationDomain(const QByteArray &domain)
void currentPageChanged(KPageWidgetItem *current, KPageWidgetItem *before)
void setFaceType(FaceType faceType)
QWidget * widget() const
static QList< KPluginMetaData > findPlugins(const QString &directory, std::function< bool(const KPluginMetaData &)> filter={}, KPluginMetaDataOptions options={})
bool isValid() const
QString i18n(const char *text, const TYPE &arg...)
QString path(const QString &relativePath)
KCOREADDONS_EXPORT QStringList splitArgs(const QString &cmd, Options flags=NoOptions, Errors *err=nullptr)
const char * constData() const const
bool addOption(const QCommandLineOption &option)
void addPositionalArgument(const QString &name, const QString &description, const QString &syntax)
bool isSet(const QCommandLineOption &option) const const
bool parse(const QStringList &arguments)
QStringList positionalArguments() const const
void process(const QCoreApplication &app)
void showHelp(int exitCode)
QString value(const QCommandLineOption &option) const const
QDBusPendingCall asyncCall(const QDBusMessage &message, int timeout) const const
QDBusConnection sessionBus()
QDBusMessage createMethodCall(const QString &service, const QString &path, const QString &interface, const QString &method)
void setArguments(const QList< QVariant > &arguments)
void setModal(bool modal)
QIcon fromTheme(const QString &name)
iterator begin()
const_iterator cbegin() const const
const T & constFirst() const const
iterator end()
bool isEmpty() const const
qsizetype size() const const
Q_OBJECTQ_OBJECT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
T findChild(const QString &name, Qt::FindChildOptions options) const const
QString arg(Args &&... args) const const
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QByteArray toLocal8Bit() const const
qsizetype removeDuplicates()
MouseFocusReason
WA_DeleteOnClose
QVariant fromValue(T &&value)
void setFocus()
WId winId() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 11 2024 12:13:38 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.