26#include <kdeversion.h>
34#include <QtCore/QFile>
35#include <QtCore/QTimer>
37#include <QtDBus/QtDBus>
43#ifndef KDE_NO_DEPRECATED
61#include <qx11info_x11.h>
66#define KDED_EXENAME "kded4"
68#define MODULES_PATH "/modules/"
80extern Q_DBUS_EXPORT
void qDBusAddSpyHook(
void (*)(
const QDBusMessage&));
88 Q_ASSERT(!exe.isEmpty());
90 args.append(
"--incremental");
92 args.append(
"--checkstamps");
94 args.append(
"--nocheckfiles");
100 argList << exe << args << QStringList() << QString();
117 args.append(QFile::decodeName(oldName));
118 args.append(QFile::decodeName(newName));
123 : m_needDelayedCheck(false)
127 m_serviceWatcher =
new QDBusServiceWatcher(
this);
128 m_serviceWatcher->setConnection(QDBusConnection::sessionBus());
129 m_serviceWatcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
130 QObject::connect(m_serviceWatcher, SIGNAL(serviceUnregistered(QString)),
136 QDBusConnection session = QDBusConnection::sessionBus();
137 session.registerObject(
"/kbuildsycoca",
this);
138 session.registerObject(
"/kded",
this);
142 m_pTimer =
new QTimer(
this);
143 m_pTimer->setSingleShot(
true );
149 m_recreateBusy =
false;
160 it(m_modules.begin()), itEnd(m_modules.end());
167 disconnect(module, SIGNAL(moduleDeleted(
KDEDModule*)),
183 if (message.type() != QDBusMessage::MethodCallMessage)
186 QString obj = message.path();
192 if (obj ==
"ksycoca")
196 int index = obj.indexOf(
'/');
198 obj = obj.left(index);
201 if (
self()->m_dontLoad.value(obj, 0))
204 KDEDModule *
module = self()->loadModule(obj, true);
206 kDebug(7020) <<
"Failed to load module for " << obj;
213 const QVariant phasev = service->property(
"X-KDE-Kded-phase", QVariant::Int );
214 return phasev.isValid() ? phasev.toInt() : 2;
220 bool kde_running = !qgetenv(
"KDE_FULL_SESSION" ).isEmpty();
223 const QByteArray sessionUID = qgetenv(
"KDE_SESSION_UID" );
224 if( !sessionUID.isEmpty() && uid_t( sessionUID.toInt() ) != getuid())
228 const QByteArray kdeSession = qgetenv(
"KDE_SESSION_VERSION");
229 if (kdeSession.toInt() != KDE_VERSION_MAJOR)
237 const bool loadPhase2Now = (kde_running && qgetenv(
"KDED_STARTED_BY_KDEINIT").toInt() == 0);
241 for(KService::List::ConstIterator it = kdedModules.begin(); it != kdedModules.end(); ++it)
248 bool prevent_autoload =
false;
255 prevent_autoload =
true;
260 if (!loadPhase2Now) {
261 prevent_autoload =
true;
267 if (autoload && !prevent_autoload) {
280 if (!loadOnDemand && !autoload)
287 kDebug(7020) <<
"Loading second phase autoload";
290 for(KService::List::ConstIterator it = kdedModules.constBegin(); it != kdedModules.constEnd(); ++it) {
302 m_dontLoad.insert(obj.toLatin1(),
this);
312 KConfigGroup cg(config, QString(
"Module-%1").arg(service->desktopEntryName()));
328 bool autoload =
module->property("X-KDE-Kded-autoload", QVariant::Bool).toBool();
329 KConfigGroup cg(config, QString(
"Module-%1").arg(module->desktopEntryName()));
330 autoload = cg.
readEntry(
"autoload", autoload);
345 bool loadOnDemand =
true;
346 QVariant p =
module->property("X-KDE-Kded-load-on-demand", QVariant::Bool);
347 if (p.isValid() && (p.toBool() ==
false))
348 loadOnDemand =
false;
355 Q_ASSERT(obj.indexOf(
'/')==-1);
366 if (s && !s->library().isEmpty())
368 QString obj = s->desktopEntryName();
369 KDEDModule *oldModule = m_modules.value(obj, 0);
375 QVariant p = s->property(
"X-KDE-Kded-load-on-demand", QVariant::Bool);
376 if (p.isValid() && (p.toBool() ==
false))
384 QString libname =
"kded_"+s->library();
390 QString factoryName = s->property(
"X-KDE-FactoryName", QVariant::String).toString();
391 if (factoryName.isEmpty())
392 factoryName = s->library();
393 factoryName =
"create_" + factoryName;
394#ifndef KDE_NO_DEPRECATED
404 kWarning() <<
"Could not load library" << libname <<
". ["
409 module = factory->create<KDEDModule>(this);
412 module->setModuleName(obj);
413 m_modules.insert(obj, module);
416 kDebug(7020) <<
"Successfully loaded module" << obj;
419 kDebug(7020) <<
"Could not load module" << obj;
431 kDebug(7020) <<
"Unloading module" << obj;
432 m_modules.remove(obj);
439 return m_modules.keys();
455 module->removeAll(appId);
458 m_serviceWatcher->removeWatchedService(name);
461 it != windowIds.end(); ++it)
463 qlonglong windowId = *it;
464 m_globalWindowIdList.remove(windowId);
467 emit
module->windowUnregistered(windowId);
470 m_windowIdList.remove(name);
480 QObject::connect( m_pDirWatch, SIGNAL(dirty(QString)),
481 this, SLOT(
update(QString)));
482 QObject::connect( m_pDirWatch, SIGNAL(created(QString)),
483 this, SLOT(
update(QString)));
484 QObject::connect( m_pDirWatch, SIGNAL(deleted(QString)),
488 for( QStringList::ConstIterator it = m_allResourceDirs.constBegin();
489 it != m_allResourceDirs.constEnd();
492 readDirectory( *it );
498 KSycoca::clearCaches();
506 for( QStringList::ConstIterator it = dirs.begin();
510 if (!m_allResourceDirs.contains(*it))
512 m_allResourceDirs.append(*it);
525 if( m_needDelayedCheck )
527 m_needDelayedCheck =
false;
532 m_recreateBusy =
true;
552 m_needDelayedCheck =
true;
556 m_needDelayedCheck =
false;
563 for(; m_recreateCount; m_recreateCount--)
565 QDBusMessage msg = m_recreateRequests.takeFirst();
566 QDBusConnection::sessionBus().send(msg.createErrorReply(error));
568 afterRecreateFinished();
575 for(; m_recreateCount; m_recreateCount--)
577 QDBusMessage msg = m_recreateRequests.takeFirst();
578 QDBusConnection::sessionBus().send(msg.createReply());
580 afterRecreateFinished();
583void Kded::afterRecreateFinished()
585 m_recreateBusy =
false;
588 if (!m_recreateRequests.isEmpty())
590 m_pTimer->start(2000);
591 m_recreateCount = m_recreateRequests.count();
606 m_pTimer->start( 10000 );
614 if (m_recreateRequests.isEmpty())
621 msg.setDelayedReply(
true);
622 m_recreateRequests.append(msg);
627void Kded::readDirectory(
const QString& _path )
629 QString path( _path );
630 if ( !path.endsWith(
'/' ) )
633 if ( m_pDirWatch->
contains( path ) )
639 QDir d( _path, QString(), QDir::Unsorted, QDir::Readable | QDir::Executable | QDir::Dirs | QDir::Hidden );
649 kDebug(7020) <<
"Does not exist:" << _path;
660 unsigned int count = d.count();
661 for( i = 0; i < count; i++ )
663 if (d[i] ==
"." || d[i] ==
".." || d[i] ==
"magic")
669 readDirectory( file );
684 if (!m_windowIdList.contains(sender)) {
685 m_serviceWatcher->addWatchedService(sender);
688 m_globalWindowIdList.insert(windowId);
690 windowIds.append(windowId);
691 m_windowIdList.insert(sender, windowIds);
696 emit
module->windowRegistered(windowId);
702 m_globalWindowIdList.remove(windowId);
704 if (!windowIds.isEmpty())
706 windowIds.removeAll(windowId);
707 if (windowIds.isEmpty()) {
708 m_serviceWatcher->removeWatchedService(sender);
709 m_windowIdList.remove(sender);
711 m_windowIdList.insert(sender, windowIds);
718 emit
module->windowUnregistered(windowId);
732 m_pTimer =
new QTimer;
733 m_pTimer->setSingleShot(
true );
735 QObject::connect( m_pDirWatch, SIGNAL(dirty(QString)),
739 for( QStringList::ConstIterator it = dirs.begin();
744 if (path[path.length()-1] !=
'/')
765 m_pTimer->start( 500 );
770 m_Timer.start(pollInterval);
783 if (gethostname(buf, 1024) != 0)
785 buf[
sizeof(buf)-1] =
'\0';
787 if (m_hostname.isEmpty())
793 if (m_hostname == buf)
796 QByteArray newHostname = buf;
799 m_hostname = newHostname;
840 e.xclient.type = ClientMessage;
841 e.xclient.message_type = XInternAtom( QX11Info::display(),
"_KDE_SPLASH_PROGRESS", False );
842 e.xclient.display = QX11Info::display();
843 e.xclient.window = QX11Info::appRootWindow();
844 e.xclient.format = 8;
845 strcpy( e.xclient.data.b,
"kded" );
846 XSendEvent( QX11Info::display(), QX11Info::appRootWindow(), False, SubstructureNotifyMask, &e );
852 e.xclient.type = ClientMessage;
853 e.xclient.message_type = XInternAtom( QX11Info::display(),
"_KDE_SPLASH_PROGRESS", False );
854 e.xclient.display = QX11Info::display();
855 e.xclient.window = QX11Info::appRootWindow();
856 e.xclient.format = 8;
857 strcpy( e.xclient.data.b,
"confupdate" );
858 XSendEvent( QX11Info::display(), QX11Info::appRootWindow(), False, SubstructureNotifyMask, &e );
872extern "C" KDE_EXPORT
int kdemain(
int argc,
char *argv[])
875 "kdelibs4",
ki18n(
"KDE Daemon"),
877 ki18n(
"KDE Daemon - triggers Sycoca database updates when needed"));
880 options.
add(
"check",
ki18n(
"Check Sycoca database only once"));
889 putenv(qstrdup(
"SESSION_MANAGER="));
898 if (args->
isSet(
"check"))
910 fprintf(stderr,
"KDE Daemon (kded) already running.\n");
931 k.setQuitOnLastWindowClosed(
false);
938 kded->moveToThread( k.thread() );
940 int result = k.exec();
KBuildsycocaAdaptor(QObject *parent)
Q_NOREPLY void recreate(const QDBusMessage &)
bool isSet(const QByteArray &option) const
static void init(const KAboutData *about)
static KCmdLineArgs * parsedArgs(const QByteArray &id=QByteArray())
static void addCmdLineOptions(const KCmdLineOptions &options, const KLocalizedString &name=KLocalizedString(), const QByteArray &id=QByteArray(), const QByteArray &afterId=QByteArray())
KCmdLineOptions & add(const KCmdLineOptions &options)
const KSharedConfig::Ptr & config() const
void writeEntry(const char *key, const char *value, WriteConfigFlags pFlags=Normal)
QString readEntry(const char *key, const char *aDefault=0) const
QString moduleName() const
bool contains(const QString &path) const
void addDir(const QString &path, WatchModes watchModes=WatchDirOnly)
KHostnameD(int pollInterval)
static KLibLoader * self()
KLibrary * library(const QString &libname, QLibrary::LoadHints loadHint=0)
void_function_ptr resolveFunction(const char *name)
QString errorString() const
KPluginFactory * factory()
static KServiceTypeTrader * self()
KService::List query(const QString &servicetype, const QString &constraint=QString()) const
static Ptr serviceByDesktopPath(const QString &_path)
static QString findExe(const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
QStringList findDirs(const char *type, const QString &reldir) const
QStringList allResourceDirs()
static void addCmdLineOptions()
void initModules()
Loads / unloads modules according to config.
void registerWindowId(qlonglong windowId, const QString &sender)
Applications can register/unregister their windows with kded modules.
void recreateDone()
Recreating finished.
static void messageFilter(const QDBusMessage &)
void noDemandLoad(const QString &obj)
void update(const QString &dir)
void setModuleAutoloading(const QString &module, bool autoload)
Configure whether a module should be loaded on startup.
bool isModuleAutoloaded(const QString &module) const
Check if a module should be loaded on startup.
void recreate()
Recreate the database file.
void slotApplicationRemoved(const QString &)
An application unregistered itself from DBus.
bool unloadModule(const QString &obj)
void dirDeleted(const QString &path)
void unregisterWindowId(qlonglong windowId, const QString &sender)
Unregister a window previously registered with KDED.
KDEDModule * loadModule(const QString &obj, bool onDemand)
void updateResourceList()
Update directories to watch.
void updateDirWatch()
Collect all directories to watch.
void recreate(const QDBusMessage &)
void recreateFailed(const QDBusError &error)
QStringList loadedModules()
void slotKDEDModuleRemoved(KDEDModule *)
A KDEDModule is about to get destroyed.
bool isModuleLoadedOnDemand(const QString &module) const
Check if a module should be loaded on demand.
static bool bCheckHostname
QDBUS_EXPORT void qDBusAddSpyHook(void(*)(const QDBusMessage &))
static void sighandler(int)
int kdemain(int argc, char *argv[])
static void runKonfUpdate()
static int HostnamePollInterval
static void runDontChangeHostname(const QByteArray &oldName, const QByteArray &newName)
static bool bCheckUpdates
static int phaseForModule(const KService::Ptr &service)
static void runBuildSycoca(QObject *callBackObj=0, const char *callBackSlot=0, const char *callBackErrorSlot=0)
KLocalizedString ki18n(const char *msg)
#define KBUILDSYCOCA_EXENAME
void setFlags(CrashFlags flags)
KSharedConfigPtr config()