00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kded.h"
00022 #include "kdedadaptor.h"
00023 #include "kdedmodule.h"
00024
00025 #include "kresourcelist.h"
00026 #include <kcrash.h>
00027
00028 #include <unistd.h>
00029 #include <stdlib.h>
00030 #include <signal.h>
00031 #include <time.h>
00032
00033 #include <QtCore/QDir>
00034 #include <QtCore/QFile>
00035 #include <QtCore/QTimer>
00036
00037 #include <QtDBus/QtDBus>
00038
00039 #include <kuniqueapplication.h>
00040 #include <kapplication.h>
00041 #include <kcmdlineargs.h>
00042 #include <kaboutdata.h>
00043 #include <klocale.h>
00044 #include <kglobal.h>
00045 #include <kconfig.h>
00046 #include <kconfiggroup.h>
00047 #include <kdebug.h>
00048 #include <kdirwatch.h>
00049 #include <kstandarddirs.h>
00050 #include <kservicetypetrader.h>
00051 #include <ktoolinvocation.h>
00052 #include <kde_file.h>
00053 #include "klauncher_iface.h"
00054
00055 #ifdef Q_WS_X11
00056 #include <qx11info_x11.h>
00057 #include <X11/Xlib.h>
00058 #include <fixx11h.h>
00059 #endif
00060
00061 #define KDED_EXENAME "kded4"
00062
00063 #define MODULES_PATH "/modules/"
00064
00065 Kded *Kded::_self = 0;
00066
00067 static bool checkStamps = true;
00068 static bool delayedCheck = false;
00069 static int HostnamePollInterval;
00070 static bool bCheckSycoca;
00071 static bool bCheckUpdates;
00072 static bool bCheckHostname;
00073
00074 extern QDBUS_EXPORT void qDBusAddSpyHook(void (*)(const QDBusMessage&));
00075
00076 static void runBuildSycoca(QObject *callBackObj=0, const char *callBackSlot=0)
00077 {
00078 const QString exe = KStandardDirs::findExe(KBUILDSYCOCA_EXENAME);
00079 Q_ASSERT(!exe.isEmpty());
00080 QStringList args;
00081 args.append("--incremental");
00082 if(checkStamps)
00083 args.append("--checkstamps");
00084 if(delayedCheck)
00085 args.append("--nocheckfiles");
00086 else
00087 checkStamps = false;
00088 if (callBackObj)
00089 {
00090 QVariantList argList;
00091 argList << exe << args << QStringList() << QString();
00092 KToolInvocation::klauncher()->callWithCallback("kdeinit_exec_wait", argList, callBackObj,
00093 callBackSlot);
00094 }
00095 else
00096 {
00097 KToolInvocation::kdeinitExecWait( exe, args );
00098
00099 if (callBackObj && callBackSlot) {
00100 QTimer::singleShot(0, callBackObj, callBackSlot);
00101 }
00102 }
00103 }
00104
00105 static void runKonfUpdate()
00106 {
00107 KToolInvocation::kdeinitExecWait( "kconf_update", QStringList(), 0, 0, "0" );
00108 }
00109
00110 static void runDontChangeHostname(const QByteArray &oldName, const QByteArray &newName)
00111 {
00112 QStringList args;
00113 args.append(QFile::decodeName(oldName));
00114 args.append(QFile::decodeName(newName));
00115 KToolInvocation::kdeinitExecWait( "kdontchangethehostname", args );
00116 }
00117
00118 Kded::Kded(bool checkUpdates)
00119 : b_checkUpdates(checkUpdates),
00120 m_needDelayedCheck(false)
00121 {
00122 _self = this;
00123
00124 new KBuildsycocaAdaptor(this);
00125 new KdedAdaptor(this);
00126
00127 QDBusConnection session = QDBusConnection::sessionBus();
00128 session.registerObject("/kbuildsycoca", this);
00129 session.registerObject("/kded", this);
00130
00131 qDBusAddSpyHook(messageFilter);
00132
00133 m_pTimer = new QTimer(this);
00134 m_pTimer->setSingleShot( true );
00135 connect(m_pTimer, SIGNAL(timeout()), this, SLOT(recreate()));
00136
00137 m_pDirWatch = 0;
00138
00139 m_recreateCount = 0;
00140 m_recreateBusy = false;
00141 }
00142
00143 Kded::~Kded()
00144 {
00145 _self = 0;
00146 m_pTimer->stop();
00147 delete m_pTimer;
00148 delete m_pDirWatch;
00149
00150 for (QHash<QByteArray,KDEDModule*>::iterator
00151 it(m_modules.begin()), itEnd(m_modules.end());
00152 it != itEnd; ++it)
00153 {
00154 KDEDModule* module(it.value());
00155
00156
00157
00158 disconnect(module, SIGNAL(moduleDeleted(KDEDModule*)),
00159 this, SLOT(slotKDEDModuleRemoved(KDEDModule*)));
00160
00161 delete module;
00162 }
00163 }
00164
00165
00166
00167
00168 void Kded::messageFilter(const QDBusMessage &message)
00169 {
00170
00171 if (!self())
00172 return;
00173
00174 if (message.type() != QDBusMessage::MethodCallMessage)
00175 return;
00176
00177 QString obj = message.path();
00178 if (!obj.startsWith(MODULES_PATH))
00179 return;
00180
00181
00182 obj = obj.mid(strlen(MODULES_PATH));
00183 if (obj == "ksycoca")
00184 return;
00185
00186
00187 int index = obj.indexOf('/');
00188 if (index!=-1) {
00189 obj = obj.left(index);
00190 }
00191
00192 if (self()->m_dontLoad.value(obj, 0))
00193 return;
00194
00195 KDEDModule *module = self()->loadModule(obj, true);
00196 if (!module) {
00197 kDebug(7020) << "Failed to load module for " << obj;
00198 }
00199 Q_UNUSED(module);
00200 }
00201
00202 void Kded::initModules()
00203 {
00204 m_dontLoad.clear();
00205 bool kde_running = !qgetenv( "KDE_FULL_SESSION" ).isEmpty();
00206
00207 const QByteArray sessionUID = qgetenv( "KDE_SESSION_UID" );
00208 if( !sessionUID.isEmpty() && uid_t( sessionUID.toInt() ) != getuid())
00209 kde_running = false;
00210
00211 const KService::List kdedModules = KServiceTypeTrader::self()->query("KDEDModule");
00212 for(KService::List::ConstIterator it = kdedModules.begin(); it != kdedModules.end(); ++it)
00213 {
00214 KService::Ptr service = *it;
00215
00216 bool autoload = isModuleAutoloaded(service);
00217
00218
00219 QVariant phasev = service->property("X-KDE-Kded-phase", QVariant::Int );
00220 int phase = phasev.isValid() ? phasev.toInt() : 2;
00221 bool prevent_autoload = false;
00222 switch( phase )
00223 {
00224 case 0:
00225 break;
00226 case 1:
00227 if( !kde_running )
00228 prevent_autoload = true;
00229 break;
00230 case 2:
00231 default:
00232 prevent_autoload = true;
00233 break;
00234 }
00235
00236
00237 if (autoload && !prevent_autoload) {
00238 if (!loadModule(service, false)) {
00239 continue;
00240 }
00241 }
00242
00243
00244 bool loadOnDemand = isModuleLoadedOnDemand(service);
00245 if (!loadOnDemand)
00246 noDemandLoad(service->desktopEntryName());
00247
00248
00249
00250 if (!loadOnDemand && !autoload)
00251 unloadModule(service->desktopEntryName().toLatin1());
00252 }
00253 }
00254
00255 void Kded::loadSecondPhase()
00256 {
00257 kDebug(7020) << "Loading second phase autoload";
00258 KSharedConfig::Ptr config = KGlobal::config();
00259 KService::List kdedModules = KServiceTypeTrader::self()->query("KDEDModule");
00260 for(KService::List::ConstIterator it = kdedModules.constBegin(); it != kdedModules.constEnd(); ++it)
00261 {
00262 KService::Ptr service = *it;
00263 bool autoload = service->property("X-KDE-Kded-autoload", QVariant::Bool).toBool();
00264 KConfigGroup cg(config, QString("Module-%1").arg(service->desktopEntryName()));
00265 autoload = cg.readEntry("autoload", autoload);
00266 QVariant phasev = service->property("X-KDE-Kded-phase", QVariant::Int );
00267 int phase = phasev.isValid() ? phasev.toInt() : 2;
00268 if( phase == 2 && autoload )
00269 loadModule(service, false);
00270 }
00271 }
00272
00273 void Kded::noDemandLoad(const QString &obj)
00274 {
00275 m_dontLoad.insert(obj.toLatin1(), this);
00276 }
00277
00278 void Kded::setModuleAutoloading(const QString &obj, bool autoload)
00279 {
00280 KSharedConfig::Ptr config = KGlobal::config();
00281
00282 KService::Ptr service = KService::serviceByDesktopPath("kded/"+obj+".desktop");
00283 if (!service)
00284 return;
00285 KConfigGroup cg(config, QString("Module-%1").arg(service->desktopEntryName()));
00286 cg.writeEntry("autoload", autoload);
00287 cg.sync();
00288 }
00289
00290 bool Kded::isModuleAutoloaded(const QString &obj) const
00291 {
00292 KService::Ptr s = KService::serviceByDesktopPath("kded/"+obj+".desktop");
00293 if (!s)
00294 return false;
00295 return isModuleAutoloaded(s);
00296 }
00297
00298 bool Kded::isModuleAutoloaded(const KService::Ptr &module) const
00299 {
00300 KSharedConfig::Ptr config = KGlobal::config();
00301 bool autoload = module->property("X-KDE-Kded-autoload", QVariant::Bool).toBool();
00302 KConfigGroup cg(config, QString("Module-%1").arg(module->desktopEntryName()));
00303 autoload = cg.readEntry("autoload", autoload);
00304 return autoload;
00305 }
00306
00307 bool Kded::isModuleLoadedOnDemand(const QString &obj) const
00308 {
00309 KService::Ptr s = KService::serviceByDesktopPath("kded/"+obj+".desktop");
00310 if (!s)
00311 return false;
00312 return isModuleLoadedOnDemand(s);
00313 }
00314
00315 bool Kded::isModuleLoadedOnDemand(const KService::Ptr &module) const
00316 {
00317 KSharedConfig::Ptr config = KGlobal::config();
00318 bool loadOnDemand = true;
00319 QVariant p = module->property("X-KDE-Kded-load-on-demand", QVariant::Bool);
00320 if (p.isValid() && (p.toBool() == false))
00321 loadOnDemand = false;
00322 return loadOnDemand;
00323 }
00324
00325 KDEDModule *Kded::loadModule(const QString &obj, bool onDemand)
00326 {
00327
00328 Q_ASSERT(obj.indexOf('/')==-1);
00329
00330 KDEDModule *module = m_modules.value(obj, 0);
00331 if (module)
00332 return module;
00333 KService::Ptr s = KService::serviceByDesktopPath("kded/"+obj+".desktop");
00334 return loadModule(s, onDemand);
00335 }
00336
00337 KDEDModule *Kded::loadModule(const KService::Ptr& s, bool onDemand)
00338 {
00339 if (s && !s->library().isEmpty())
00340 {
00341 QString obj = s->desktopEntryName();
00342 KDEDModule *oldModule = m_modules.value(obj, 0);
00343 if (oldModule)
00344 return oldModule;
00345
00346 if (onDemand)
00347 {
00348 QVariant p = s->property("X-KDE-Kded-load-on-demand", QVariant::Bool);
00349 if (p.isValid() && (p.toBool() == false))
00350 {
00351 noDemandLoad(s->desktopEntryName());
00352 return 0;
00353 }
00354 }
00355
00356 KDEDModule *module = 0;
00357 QString libname = "kded_"+s->library();
00358 KPluginLoader loader(libname);
00359
00360 KPluginFactory *factory = loader.factory();
00361 if (!factory) {
00362
00363 QString factoryName = s->property("X-KDE-FactoryName", QVariant::String).toString();
00364 if (factoryName.isEmpty())
00365 factoryName = s->library();
00366 factoryName = "create_" + factoryName;
00367 KLibrary* lib = KLibLoader::self()->library(libname);
00368 KDEDModule* (*create)();
00369 if (lib) {
00370 create = (KDEDModule* (*)())lib->resolveFunction(QFile::encodeName(factoryName));
00371 if (create)
00372 module = create();
00373 }
00374 if (!module) {
00375 kWarning() << "Could not load library" << libname << ". ["
00376 << loader.errorString() << "]";
00377 }
00378 } else {
00379
00380 module = factory->create<KDEDModule>(this);
00381 }
00382 if (module) {
00383 module->setModuleName(obj);
00384 m_modules.insert(obj, module);
00385
00386 connect(module, SIGNAL(moduleDeleted(KDEDModule *)), SLOT(slotKDEDModuleRemoved(KDEDModule *)));
00387 kDebug(7020) << "Successfully loaded module" << obj;
00388 return module;
00389 } else {
00390 kDebug(7020) << "Could not load module" << obj;
00391
00392 }
00393 }
00394 return 0;
00395 }
00396
00397 bool Kded::unloadModule(const QString &obj)
00398 {
00399 KDEDModule *module = m_modules.value(obj, 0);
00400 if (!module)
00401 return false;
00402 kDebug(7020) << "Unloading module" << obj;
00403 m_modules.remove(obj);
00404 delete module;
00405 return true;
00406 }
00407
00408 QStringList Kded::loadedModules()
00409 {
00410 return m_modules.keys();
00411 }
00412
00413 void Kded::slotKDEDModuleRemoved(KDEDModule *module)
00414 {
00415 m_modules.remove(module->moduleName());
00416
00417
00418
00419 }
00420
00421 void Kded::slotApplicationRemoved(const QString &name, const QString &oldOwner,
00422 const QString &newOwner)
00423 {
00424 #if 0 // see kdedmodule.cpp (KDED_OBJECTS)
00425 foreach( KDEDModule* module, m_modules )
00426 {
00427 module->removeAll(appId);
00428 }
00429 #endif
00430 if (oldOwner.isEmpty() || !newOwner.isEmpty())
00431 return;
00432
00433 const QList<qlonglong> windowIds = m_windowIdList.value(name);
00434 for( QList<qlonglong>::ConstIterator it = windowIds.begin();
00435 it != windowIds.end(); ++it)
00436 {
00437 qlonglong windowId = *it;
00438 m_globalWindowIdList.remove(windowId);
00439 foreach( KDEDModule* module, m_modules )
00440 {
00441 emit module->windowUnregistered(windowId);
00442 }
00443 }
00444 m_windowIdList.remove(name);
00445 }
00446
00447 void Kded::updateDirWatch()
00448 {
00449 if (!b_checkUpdates) return;
00450
00451 delete m_pDirWatch;
00452 m_pDirWatch = new KDirWatch;
00453
00454 QObject::connect( m_pDirWatch, SIGNAL(dirty(const QString&)),
00455 this, SLOT(update(const QString&)));
00456 QObject::connect( m_pDirWatch, SIGNAL(created(const QString&)),
00457 this, SLOT(update(const QString&)));
00458 QObject::connect( m_pDirWatch, SIGNAL(deleted(const QString&)),
00459 this, SLOT(dirDeleted(const QString&)));
00460
00461
00462 for( QStringList::ConstIterator it = m_allResourceDirs.constBegin();
00463 it != m_allResourceDirs.constEnd();
00464 ++it )
00465 {
00466 readDirectory( *it );
00467 }
00468 }
00469
00470 void Kded::updateResourceList()
00471 {
00472 delete KSycoca::self();
00473
00474 if (!b_checkUpdates) return;
00475
00476 if (delayedCheck) return;
00477
00478 const QStringList dirs = KSycoca::self()->allResourceDirs();
00479
00480 for( QStringList::ConstIterator it = dirs.begin();
00481 it != dirs.end();
00482 ++it )
00483 {
00484 if (!m_allResourceDirs.contains(*it))
00485 {
00486 m_allResourceDirs.append(*it);
00487 readDirectory(*it);
00488 }
00489 }
00490 }
00491
00492 void Kded::recreate()
00493 {
00494 recreate(false);
00495 }
00496
00497 void Kded::runDelayedCheck()
00498 {
00499 if( m_needDelayedCheck )
00500 recreate(false);
00501 m_needDelayedCheck = false;
00502 }
00503
00504 void Kded::recreate(bool initial)
00505 {
00506 m_recreateBusy = true;
00507
00508
00509
00510 if (!initial)
00511 {
00512 updateDirWatch();
00513 runBuildSycoca(this, SLOT(recreateDone()));
00514 }
00515 else
00516 {
00517 if(!delayedCheck)
00518 updateDirWatch();
00519 runBuildSycoca();
00520 recreateDone();
00521 if(delayedCheck)
00522 {
00523
00524 QTimer::singleShot( 60000, this, SLOT(runDelayedCheck()));
00525 m_needDelayedCheck = true;
00526 delayedCheck = false;
00527 }
00528 else
00529 m_needDelayedCheck = false;
00530 }
00531 }
00532
00533 void Kded::recreateDone()
00534 {
00535 updateResourceList();
00536
00537 for(; m_recreateCount; m_recreateCount--)
00538 {
00539 QDBusMessage msg = m_recreateRequests.takeFirst();
00540 QDBusConnection::sessionBus().send(msg.createReply());
00541 }
00542 m_recreateBusy = false;
00543
00544
00545 if (!m_recreateRequests.isEmpty())
00546 {
00547 m_pTimer->start(2000);
00548 m_recreateCount = m_recreateRequests.count();
00549 }
00550 }
00551
00552 void Kded::dirDeleted(const QString& path)
00553 {
00554 update(path);
00555 }
00556
00557 void Kded::update(const QString& )
00558 {
00559 if (!m_recreateBusy)
00560 {
00561 m_pTimer->start( 10000 );
00562 }
00563 }
00564
00565 void Kded::recreate(const QDBusMessage &msg)
00566 {
00567 if (!m_recreateBusy)
00568 {
00569 if (m_recreateRequests.isEmpty())
00570 {
00571 m_pTimer->start(0);
00572 m_recreateCount = 0;
00573 }
00574 m_recreateCount++;
00575 }
00576 msg.setDelayedReply(true);
00577 m_recreateRequests.append(msg);
00578 return;
00579 }
00580
00581
00582 void Kded::readDirectory( const QString& _path )
00583 {
00584 QString path( _path );
00585 if ( !path.endsWith( '/' ) )
00586 path += '/';
00587
00588 if ( m_pDirWatch->contains( path ) )
00589 return;
00590
00591 m_pDirWatch->addDir(path,KDirWatch::WatchFiles|KDirWatch::WatchSubDirs);
00592 return;
00593 #if 0
00594 QDir d( _path, QString(), QDir::Unsorted, QDir::Readable | QDir::Executable | QDir::Dirs | QDir::Hidden );
00595
00596
00597
00598
00599
00600
00601
00602 if ( !d.exists() )
00603 {
00604 kDebug(7020) << "Does not exist:" << _path;
00605 return;
00606 }
00607
00608
00609
00610
00611
00612
00613 QString file;
00614 unsigned int i;
00615 unsigned int count = d.count();
00616 for( i = 0; i < count; i++ )
00617 {
00618 if (d[i] == "." || d[i] == ".." || d[i] == "magic")
00619 continue;
00620
00621 file = path;
00622 file += d[i];
00623
00624 readDirectory( file );
00625 }
00626 #endif
00627 }
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637 void Kded::registerWindowId(qlonglong windowId, const QString &sender)
00638 {
00639 m_globalWindowIdList.insert(windowId);
00640 QList<qlonglong> windowIds = m_windowIdList.value(sender);
00641 windowIds.append(windowId);
00642 m_windowIdList.insert(sender, windowIds);
00643
00644 foreach( KDEDModule* module, m_modules )
00645 {
00646 kDebug() << module->moduleName();
00647 emit module->windowRegistered(windowId);
00648 }
00649 }
00650
00651 void Kded::unregisterWindowId(qlonglong windowId, const QString &sender)
00652 {
00653 m_globalWindowIdList.remove(windowId);
00654 QList<qlonglong> windowIds = m_windowIdList.value(sender);
00655 if (!windowIds.isEmpty())
00656 {
00657 windowIds.removeAll(windowId);
00658 if (windowIds.isEmpty())
00659 m_windowIdList.remove(sender);
00660 else
00661 m_windowIdList.insert(sender, windowIds);
00662 }
00663
00664 foreach( KDEDModule* module, m_modules )
00665 {
00666 kDebug() << module->moduleName();
00667 emit module->windowUnregistered(windowId);
00668 }
00669 }
00670
00671
00672 static void sighandler(int )
00673 {
00674 if (qApp)
00675 qApp->quit();
00676 }
00677
00678 KUpdateD::KUpdateD()
00679 {
00680 m_pDirWatch = new KDirWatch;
00681 m_pTimer = new QTimer;
00682 m_pTimer->setSingleShot( true );
00683 connect(m_pTimer, SIGNAL(timeout()), this, SLOT(runKonfUpdate()));
00684 QObject::connect( m_pDirWatch, SIGNAL(dirty(const QString&)),
00685 this, SLOT(slotNewUpdateFile()));
00686
00687 const QStringList dirs = KGlobal::dirs()->findDirs("data", "kconf_update");
00688 for( QStringList::ConstIterator it = dirs.begin();
00689 it != dirs.end();
00690 ++it )
00691 {
00692 QString path = *it;
00693 if (path[path.length()-1] != '/')
00694 path += '/';
00695
00696 if (!m_pDirWatch->contains(path))
00697 m_pDirWatch->addDir(path,KDirWatch::WatchFiles|KDirWatch::WatchSubDirs);
00698 }
00699 }
00700
00701 KUpdateD::~KUpdateD()
00702 {
00703 delete m_pDirWatch;
00704 delete m_pTimer;
00705 }
00706
00707 void KUpdateD::runKonfUpdate()
00708 {
00709 ::runKonfUpdate();
00710 }
00711
00712 void KUpdateD::slotNewUpdateFile()
00713 {
00714 m_pTimer->start( 500 );
00715 }
00716
00717 KHostnameD::KHostnameD(int pollInterval)
00718 {
00719 m_Timer.start(pollInterval);
00720 connect(&m_Timer, SIGNAL(timeout()), this, SLOT(checkHostname()));
00721 checkHostname();
00722 }
00723
00724 KHostnameD::~KHostnameD()
00725 {
00726
00727 }
00728
00729 void KHostnameD::checkHostname()
00730 {
00731 char buf[1024+1];
00732 if (gethostname(buf, 1024) != 0)
00733 return;
00734 buf[sizeof(buf)-1] = '\0';
00735
00736 if (m_hostname.isEmpty())
00737 {
00738 m_hostname = buf;
00739 return;
00740 }
00741
00742 if (m_hostname == buf)
00743 return;
00744
00745 QByteArray newHostname = buf;
00746
00747 runDontChangeHostname(m_hostname, newHostname);
00748 m_hostname = newHostname;
00749 }
00750
00751
00752 #if 0
00753
00754
00755
00756
00757 class KDEDQtDCOPObject : public DCOPObject
00758 {
00759 public:
00760 KDEDQtDCOPObject() : DCOPObject("qt/kded") { }
00761
00762 virtual bool process(const DCOPCString &fun, const QByteArray &data,
00763 DCOPCString& replyType, QByteArray &replyData)
00764 {
00765 if (qApp && (fun == "quit()"))
00766 {
00767 qApp->quit();
00768 replyType = "void";
00769 return true;
00770 }
00771 return DCOPObject::process(fun, data, replyType, replyData);
00772 }
00773
00774 DCOPCStringList functions()
00775 {
00776 DCOPCStringList res = DCOPObject::functions();
00777 res += "void quit()";
00778 return res;
00779 }
00780 };
00781 #endif
00782
00783 KBuildsycocaAdaptor::KBuildsycocaAdaptor(QObject *parent)
00784 : QDBusAbstractAdaptor(parent)
00785 {
00786 }
00787
00788 void KBuildsycocaAdaptor::recreate(const QDBusMessage &msg)
00789 {
00790 Kded::self()->recreate(msg);
00791 }
00792
00793 class KDEDApplication : public KUniqueApplication
00794 {
00795 public:
00796 KDEDApplication() : KUniqueApplication( )
00797 {
00798 startup = true;
00799 }
00800
00801 int newInstance()
00802 {
00803 if (startup) {
00804 startup = false;
00805
00806
00807
00808
00809
00810
00811 Kded *kded = Kded::self();
00812
00813 if (bCheckSycoca)
00814 runBuildSycoca();
00815
00816 kded->recreate(true);
00817
00818 if (bCheckUpdates)
00819 (void) new KUpdateD;
00820
00821 #ifdef Q_WS_X11
00822 XEvent e;
00823 e.xclient.type = ClientMessage;
00824 e.xclient.message_type = XInternAtom( QX11Info::display(), "_KDE_SPLASH_PROGRESS", False );
00825 e.xclient.display = QX11Info::display();
00826 e.xclient.window = QX11Info::appRootWindow();
00827 e.xclient.format = 8;
00828 strcpy( e.xclient.data.b, "kded" );
00829 XSendEvent( QX11Info::display(), QX11Info::appRootWindow(), False, SubstructureNotifyMask, &e );
00830 #endif
00831
00832 runKonfUpdate();
00833
00834 #ifdef Q_WS_X11
00835 e.xclient.type = ClientMessage;
00836 e.xclient.message_type = XInternAtom( QX11Info::display(), "_KDE_SPLASH_PROGRESS", False );
00837 e.xclient.display = QX11Info::display();
00838 e.xclient.window = QX11Info::appRootWindow();
00839 e.xclient.format = 8;
00840 strcpy( e.xclient.data.b, "confupdate" );
00841 XSendEvent( QX11Info::display(), QX11Info::appRootWindow(), False, SubstructureNotifyMask, &e );
00842 #endif
00843
00844 if (bCheckHostname)
00845 (void) new KHostnameD(HostnamePollInterval);
00846
00847 QObject::connect(QDBusConnection::sessionBus().interface(),
00848 SIGNAL(serviceOwnerChanged(QString,QString,QString)),
00849 kded, SLOT(slotApplicationRemoved(QString,QString,QString)));
00850
00851
00852
00853
00854
00855
00856
00857
00858 QDBusMessage msg = QDBusMessage::createSignal("/kbuildsycoca", "org.kde.KSycoca", "notifyDatabaseChanged" );
00859 msg << QStringList();
00860 QDBusConnection::sessionBus().send(msg);
00861
00862 kded->initModules();
00863 } else
00864 runBuildSycoca();
00865
00866 return 0;
00867 }
00868
00869 bool startup;
00870 };
00871
00872 extern "C" KDE_EXPORT int kdemain(int argc, char *argv[])
00873 {
00874 KAboutData aboutData( "kded" ,
00875 "kdelibs4", ki18n("KDE Daemon"),
00876 "$Id: kded.cpp 910248 2009-01-12 21:31:34Z abizjak $",
00877 ki18n("KDE Daemon - triggers Sycoca database updates when needed"));
00878
00879 KCmdLineOptions options;
00880 options.add("check", ki18n("Check Sycoca database only once"));
00881
00882 KCmdLineArgs::init(argc, argv, &aboutData);
00883
00884 KUniqueApplication::addCmdLineOptions();
00885
00886 KCmdLineArgs::addCmdLineOptions( options );
00887
00888
00889 putenv(strdup("SESSION_MANAGER="));
00890
00891
00892 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
00893
00894 KComponentData componentData(&aboutData);
00895 KSharedConfig::Ptr config = componentData.config();
00896
00897 KConfigGroup cg(config, "General");
00898 if (args->isSet("check"))
00899 {
00900
00901 KApplication app;
00902 checkStamps = cg.readEntry("CheckFileStamps", true);
00903 runBuildSycoca();
00904 runKonfUpdate();
00905 return 0;
00906 }
00907
00908 if (!KUniqueApplication::start())
00909 {
00910 fprintf(stderr, "KDE Daemon (kded) already running.\n");
00911 return 0;
00912 }
00913
00914
00915
00916
00917 HostnamePollInterval = cg.readEntry("HostnamePollInterval", 5000);
00918 bCheckSycoca = cg.readEntry("CheckSycoca", true);
00919 bCheckUpdates = cg.readEntry("CheckUpdates", true);
00920 bCheckHostname = cg.readEntry("CheckHostname", true);
00921 checkStamps = cg.readEntry("CheckFileStamps", true);
00922 delayedCheck = cg.readEntry("DelayedCheck", false);
00923
00924 Kded *kded = new Kded(false);
00925
00926 KDE_signal(SIGTERM, sighandler);
00927 KDE_signal(SIGHUP, sighandler);
00928 KDEDApplication k;
00929 k.setQuitOnLastWindowClosed(false);
00930
00931 KCrash::setFlags(KCrash::AutoRestart);
00932
00933
00934
00935
00936 kded->moveToThread( k.thread() );
00937
00938 int result = k.exec();
00939
00940 delete kded;
00941
00942 return result;
00943 }
00944
00945 #include "kded.moc"