10#include "kded_debug.h"
11#include "kded_version.h"
12#include "kdedadaptor.h"
16#include <qplatformdefs.h>
18#include <QApplication>
19#include <QCommandLineParser>
21#include <QLoggingCategory>
24#include <QDBusConnection>
25#include <QDBusConnectionInterface>
26#include <QDBusServiceWatcher>
29#include <KConfigGroup>
30#include <KDBusService>
32#include <KPluginFactory>
33#include <KPluginMetaData>
34#include <KSharedConfig>
38Kded *Kded::_self =
nullptr;
40static bool delayedCheck;
41static bool bCheckSycoca;
42static bool bCheckUpdates;
45extern Q_DBUS_EXPORT
void qDBusAddSpyHook(
void (*)(
const QDBusMessage &));
47extern QDBUS_EXPORT
void qDBusAddSpyHook(
void (*)(
const QDBusMessage &));
50static void runKonfUpdate()
54 qCWarning(KDED) << KCONF_UPDATE_EXE <<
"returned" << ret;
60 , m_pTimer(new
QTimer(this))
61 , m_needDelayedCheck(false)
70 new KdedAdaptor(
this);
76 m_pTimer->setSingleShot(
true);
85 for (
auto it = m_modules.cbegin(); it != m_modules.cend(); ++it) {
102 if (obj.
isEmpty() || obj == QLatin1String(
"ksycoca")) {
106 if (self()->m_dontLoad.value(obj,
nullptr)) {
110 self()->loadModule(obj,
true);
115 return module.value(QStringLiteral("X-KDE-Kded-phase"), 2);
121 QSet<QString> moduleIds;
122 for (
const KPluginMetaData &md : std::as_const(plugins)) {
123 moduleIds.
insert(md.pluginId());
131 if (module.isValid()) {
134 qCWarning(KDED) <<
"could not find kded module with id" << id;
138void Kded::initModules()
142 bool kde_running = !qEnvironmentVariableIsEmpty(
"KDE_FULL_SESSION");
145 const QByteArray sessionUID = qgetenv(
"KDE_SESSION_UID");
146 if (!sessionUID.
isEmpty() && uid_t(sessionUID.
toInt()) != getuid()) {
150 const QByteArray kdeSession = qgetenv(
"KDE_SESSION_VERSION");
151 if (kdeSession.
toInt() != 6) {
157 const QList<KPluginMetaData> kdedModules = availableModules();
158 for (
const KPluginMetaData &module : kdedModules) {
160 const bool autoload = isModuleAutoloaded(module);
161 if (!platformSupportsModule(module)) {
166 bool prevent_autoload =
false;
167 switch (phaseForModule(module)) {
172 prevent_autoload =
true;
178 prevent_autoload =
true;
184 if (autoload && !prevent_autoload) {
185 if (!loadModule(module,
false)) {
191 bool loadOnDemand = isModuleLoadedOnDemand(module);
193 noDemandLoad(module.pluginId());
198 if (!loadOnDemand && !autoload) {
199 unloadModule(module.pluginId());
204void Kded::noDemandLoad(
const QString &obj)
206 m_dontLoad.insert(obj,
this);
209void Kded::setModuleAutoloading(
const QString &obj,
bool autoload)
213 KPluginMetaData module = findModule(obj);
217 KConfigGroup cg(config, QStringLiteral(
"Module-").append(module.
pluginId()));
218 cg.writeEntry(
"autoload", autoload);
222bool Kded::isModuleAutoloaded(
const QString &obj)
const
224 return isModuleAutoloaded(findModule(obj));
233 bool autoload =
module.value(QStringLiteral("X-KDE-Kded-autoload"), false);
234 KConfigGroup cg(config, QStringLiteral(
"Module-").append(module.
pluginId()));
235 autoload = cg.readEntry(
"autoload", autoload);
241 const QStringList supportedPlatforms =
module.value(QStringLiteral("X-KDE-OnlyShowOnQtPlatforms"), QStringList());
243 return supportedPlatforms.
isEmpty() || supportedPlatforms.
contains(qApp->platformName());
246bool Kded::isModuleLoadedOnDemand(
const QString &obj)
const
248 return isModuleLoadedOnDemand(findModule(obj));
257 return module.value(QStringLiteral("X-KDE-Kded-load-on-demand"), true);
263 if (obj.
contains(QLatin1Char(
'/'))) {
264 qCWarning(KDED) <<
"attempting to load invalid kded module name:" << obj;
267 KDEDModule *module = m_modules.
value(obj,
nullptr);
271 return loadModule(findModule(obj), onDemand);
277 qCWarning(KDED) <<
"attempted to load an invalid module.";
280 const QString moduleId =
module.pluginId();
281 KDEDModule *oldModule = m_modules.value(moduleId,
nullptr);
283 qCDebug(KDED) <<
"kded module" << moduleId <<
"is already loaded.";
288 if (!module.
value(QStringLiteral(
"X-KDE-Kded-load-on-demand"),
true)) {
289 noDemandLoad(moduleId);
294 KDEDModule *kdedModule =
nullptr;
298 kdedModule = factoryResult.plugin->create<KDEDModule>(
this);
300 qCWarning(KDED).nospace() <<
"Could not load kded module " << moduleId <<
":" << factoryResult.errorText <<
" (library path was:" <<
module.fileName()
306 m_modules.insert(moduleId, kdedModule);
308 qCDebug(KDED) <<
"Successfully loaded module" << moduleId;
314bool Kded::unloadModule(
const QString &obj)
316 KDEDModule *module = m_modules.
value(obj,
nullptr);
320 qCDebug(KDED) <<
"Unloading module" << obj;
328 return m_modules.keys();
331void Kded::slotApplicationRemoved(
const QString &name)
334 foreach (KDEDModule *module, m_modules) {
335 module->removeAll(appId);
338 m_serviceWatcher->removeWatchedService(name);
339 const QList<qlonglong> windowIds = m_windowIdList.
value(name);
340 for (
const auto id : windowIds) {
341 m_globalWindowIdList.remove(
id);
342 for (KDEDModule *module : std::as_const(m_modules)) {
346 m_windowIdList.remove(name);
349void Kded::updateDirWatch()
351 if (!bCheckUpdates) {
356 m_pDirWatch =
new KDirWatch(
this);
363 for (
const QString &dir : std::as_const(m_allResourceDirs)) {
368 for (
auto &dir : dataDirs) {
369 dir += QLatin1String(
"/icons");
370 if (!m_pDirWatch->contains(dir)) {
376void Kded::updateResourceList()
378 KSycoca::clearCaches();
380 if (!bCheckUpdates) {
390 for (
const auto &dir : dirs) {
391 if (!m_allResourceDirs.contains(dir)) {
392 m_allResourceDirs.append(dir);
403void Kded::runDelayedCheck()
405 if (m_needDelayedCheck) {
408 m_needDelayedCheck =
false;
411void Kded::recreate(
bool initial)
431 m_needDelayedCheck =
true;
432 delayedCheck =
false;
434 m_needDelayedCheck =
false;
439void Kded::recreateDone()
441 updateResourceList();
446void Kded::dirDeleted(
const QString &path)
451void Kded::update(
const QString &path)
453 if (
path.
endsWith(QLatin1String(
"/icons")) && m_pDirWatch->contains(path)) {
455 QDBusMessage message =
QDBusMessage::createSignal(QStringLiteral(
"/KIconLoader"), QStringLiteral(
"org.kde.KIconLoader"), QStringLiteral(
"iconChanged"));
459 m_pTimer->start(1000);
463void Kded::readDirectory(
const QString &_path)
467 path += QLatin1Char(
'/');
470 if (m_pDirWatch->contains(path)) {
478void Kded::registerWindowId(qlonglong windowId,
const QString &sender)
480 if (!m_windowIdList.contains(
sender)) {
481 m_serviceWatcher->addWatchedService(
sender);
484 m_globalWindowIdList.insert(windowId);
485 QList<qlonglong> windowIds = m_windowIdList.value(
sender);
486 windowIds.
append(windowId);
487 m_windowIdList.insert(
sender, windowIds);
489 for (KDEDModule *module : std::as_const(m_modules)) {
490 qCDebug(KDED) <<
module->moduleName();
495void Kded::unregisterWindowId(qlonglong windowId,
const QString &sender)
497 m_globalWindowIdList.remove(windowId);
498 QList<qlonglong> windowIds = m_windowIdList.
value(
sender);
502 m_serviceWatcher->removeWatchedService(
sender);
503 m_windowIdList.remove(
sender);
505 m_windowIdList.insert(
sender, windowIds);
509 for (KDEDModule *module : std::as_const(m_modules)) {
510 qCDebug(KDED) <<
module->moduleName();
515static void sighandler(
int )
524 m_pDirWatch =
new KDirWatch(
this);
525 m_pTimer =
new QTimer(
this);
526 m_pTimer->setSingleShot(
true);
531 for (
auto &path : dirs) {
534 path += QLatin1Char(
'/');
537 if (!m_pDirWatch->contains(path)) {
547void KUpdateD::runKonfUpdate()
552void KUpdateD::slotNewUpdateFile(
const QString &dirty)
555 qCDebug(KDED) << dirty;
556 m_pTimer->start(500);
559static bool detectPlatform(
int argc,
char **argv)
561 if (qEnvironmentVariableIsSet(
"QT_QPA_PLATFORM")) {
564 for (
int i = 0; i < argc; i++) {
566 if (qstrcmp(argv[i],
"-platform") == 0
567 || qstrcmp(argv[i],
"--platform") == 0
573 const QByteArray sessionType = qgetenv(
"XDG_SESSION_TYPE");
577 if (qstrcmp(sessionType.
data(),
"wayland") == 0) {
578 qputenv(
"QT_QPA_PLATFORM",
"wayland");
580 }
else if (qstrcmp(sessionType.
data(),
"x11") == 0) {
581 qputenv(
"QT_QPA_PLATFORM",
"xcb");
587int main(
int argc,
char *argv[])
592 qunsetenv(
"SESSION_MANAGER");
594 const bool unsetQpa = detectPlatform(argc, argv);
603 qunsetenv(
"QT_QPA_PLATFORM");
606 app.setQuitOnLastWindowClosed(
false);
607 app.setQuitLockEnabled(
false);
609 KAboutData about(QStringLiteral(
"kded6"),
QString(), QStringLiteral(KDED_VERSION_STRING));
618 QCommandLineOption replaceOption({QStringLiteral(
"replace")}, QStringLiteral(
"Replace an existing instance"));
623 if (parser.
isSet(QStringLiteral(
"check"))) {
634 qDBusAddSpyHook(Kded::messageFilter);
641 const QString serviceName = metaData.value(QStringLiteral(
"X-KDE-DBus-ServiceName"));
647 qCWarning(KDED) <<
"Couldn't register name" << serviceName <<
"with DBUS - another process owns it already!";
655 bCheckSycoca = cg.readEntry(
"CheckSycoca",
true);
656 bCheckUpdates = cg.readEntry(
"CheckUpdates",
true);
657 delayedCheck = cg.readEntry(
"DelayedCheck",
false);
659 signal(SIGTERM, sighandler);
660 signal(SIGHUP, sighandler);
664 std::unique_ptr<Kded> kded = std::make_unique<Kded>();
666 kded->recreate(
true);
677#include "moc_kded.cpp"
static void setApplicationData(const KAboutData &aboutData)
static QString moduleForMessage(const QDBusMessage &message)
void setModuleName(const QString &name)
void windowUnregistered(qlonglong windowId)
void windowRegistered(qlonglong windowId)
void deleted(const QString &path)
void dirty(const QString &path)
void created(const QString &path)
static Result< KPluginFactory > loadFactory(const KPluginMetaData &data)
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
QStringList allResourceDirs()
KCRASH_EXPORT void setFlags(KCrash::CrashFlags flags)
KCRASH_EXPORT void initialize()
QString path(const QString &relativePath)
KIOCORE_EXPORT QString dir(const QString &fileClass)
bool isEmpty() const const
int toInt(bool *ok, int base) const const
QCommandLineOption addHelpOption()
bool addOption(const QCommandLineOption &option)
QCommandLineOption addVersionOption()
bool isSet(const QCommandLineOption &option) const const
void process(const QCoreApplication &app)
QDBusConnectionInterface * interface() const const
bool registerObject(const QString &path, QObject *object, RegisterOptions options)
bool send(const QDBusMessage &message) const const
QDBusConnection sessionBus()
QDBusReply< QDBusConnectionInterface::RegisterServiceReply > registerService(const QString &serviceName, ServiceQueueOptions qoption, ServiceReplacementOptions roption)
QDBusMessage createSignal(const QString &path, const QString &interface, const QString &name)
void serviceUnregistered(const QString &serviceName)
void append(QList< T > &&value)
bool isEmpty() const const
qsizetype removeAll(const AT &t)
T value(qsizetype i) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * sender() const const
int execute(const QString &program, const QStringList &arguments)
iterator insert(const T &value)
QStringList locateAll(StandardLocation type, const QString &fileName, LocateOptions options)
QStringList standardLocations(StandardLocation type)
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)