• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDED

kded.cpp

Go to the documentation of this file.
00001 // vim: expandtab sw=4 ts=4
00002 /*  This file is part of the KDE libraries
00003  *  Copyright (C) 1999 David Faure <faure@kde.org>
00004  *  Copyright (C) 2000 Waldo Bastian <bastian@kde.org>
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Library General Public
00008  *  License version 2 as published by the Free Software Foundation;
00009  *
00010  *  This library is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  *  Library General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU Library General Public License
00016  *  along with this library; see the file COPYING.LIB.  If not, write to
00017  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  *  Boston, MA 02110-1301, USA.
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; // useful only during kded startup
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" /*no startup notification*/ );
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       // first disconnect otherwise slotKDEDModuleRemoved() is called
00157       // and changes m_modules while we're iterating over it
00158       disconnect(module, SIGNAL(moduleDeleted(KDEDModule*)),
00159                  this, SLOT(slotKDEDModuleRemoved(KDEDModule*)));
00160 
00161       delete module;
00162   }
00163 }
00164 
00165 // on-demand module loading
00166 // this function is called by the D-Bus message processing function before
00167 // calls are delivered to objects
00168 void Kded::messageFilter(const QDBusMessage &message)
00169 {
00170   // This happens when kded goes down and some modules try to clean up.
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   // Remove the <MODULES_PATH> part
00182   obj = obj.mid(strlen(MODULES_PATH));
00183   if (obj == "ksycoca")
00184      return; // Ignore this one.
00185 
00186   // Remove the part after the modules name
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     // not the same user like the one running the session (most likely we're run via sudo or something)
00207     const QByteArray sessionUID = qgetenv( "KDE_SESSION_UID" );
00208     if( !sessionUID.isEmpty() && uid_t( sessionUID.toInt() ) != getuid())
00209         kde_running = false;
00210      // Preload kded modules.
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          // Should the service load on startup?
00216          bool autoload = isModuleAutoloaded(service);
00217 
00218          // see ksmserver's README for description of the phases
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: // always autoload
00225                  break;
00226              case 1: // autoload only in KDE
00227                  if( !kde_running )
00228                      prevent_autoload = true;
00229                  break;
00230              case 2: // autoload delayed, only in KDE
00231              default:
00232                  prevent_autoload = true;
00233                  break;
00234          }
00235 
00236         // Load the module if necessary and allowed
00237          if (autoload && !prevent_autoload) {
00238             if (!loadModule(service, false)) {
00239                 continue;
00240             }
00241          }
00242 
00243          // Remember if the module is allowed to load on demand
00244          bool loadOnDemand = isModuleLoadedOnDemand(service);
00245          if (!loadOnDemand)
00246             noDemandLoad(service->desktopEntryName());
00247 
00248          // In case of reloading the configuration it is possible for a module
00249          // to run even if it is now allowed to. Stop it then.
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     // Ensure the service exists.
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   // Make sure this method is only called with valid module names.
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             // kde3 compat
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             // create the module
00380             module = factory->create<KDEDModule>(this);
00381         }
00382         if (module) {
00383             module->setModuleName(obj);
00384             m_modules.insert(obj, module);
00385             //m_libs.insert(obj, lib);
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             //loader.unload();
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   //KLibrary *lib = m_libs.take(module->moduleName());
00417   //if (lib)
00418   //   lib->unload();
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   // For each resource
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   // For each resource
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    // Using KLauncher here is difficult since we might not have a
00508    // database
00509 
00510    if (!initial)
00511    {
00512       updateDirWatch(); // Update tree first, to be sure to miss nothing.
00513       runBuildSycoca(this, SLOT(recreateDone()));
00514    }
00515    else
00516    {
00517       if(!delayedCheck)
00518          updateDirWatch(); // this would search all the directories
00519       runBuildSycoca();
00520       recreateDone();
00521       if(delayedCheck)
00522       {
00523          // do a proper ksycoca check after a delay
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    // Did a new request come in while building?
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 ) ) // Already seen this one?
00589      return;
00590 
00591   m_pDirWatch->addDir(path,KDirWatch::WatchFiles|KDirWatch::WatchSubDirs);          // add watch on this dir
00592   return; // KDirWatch now claims to also support recursive watching
00593 #if 0
00594   QDir d( _path, QString(), QDir::Unsorted, QDir::Readable | QDir::Executable | QDir::Dirs | QDir::Hidden );
00595   // set QDir ...
00596 
00597 
00598   //************************************************************************
00599   //                           Setting dirs
00600   //************************************************************************
00601 
00602   if ( !d.exists() )                            // exists&isdir?
00603   {
00604     kDebug(7020) << "Does not exist:" << _path;
00605     return;                             // return false
00606   }
00607 
00608   // Note: If some directory is gone, dirwatch will delete it from the list.
00609 
00610   //************************************************************************
00611   //                               Reading
00612   //************************************************************************
00613   QString file;
00614   unsigned int i;                           // counter and string length.
00615   unsigned int count = d.count();
00616   for( i = 0; i < count; i++ )                        // check all entries
00617   {
00618      if (d[i] == "." || d[i] == ".." || d[i] == "magic")
00619        continue;                          // discard those ".", "..", "magic"...
00620 
00621      file = path;                           // set full path
00622      file += d[i];                          // and add the file name.
00623 
00624      readDirectory( file );      // yes, dive into it.
00625   }
00626 #endif
00627 }
00628 
00629 /*
00630 bool Kded::isWindowRegistered(long windowId) const
00631 {
00632   return m_globalWindowIdList.contains(windowId);
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 /*sig*/)
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); // repetitive timer (not single-shot)
00720     connect(&m_Timer, SIGNAL(timeout()), this, SLOT(checkHostname()));
00721     checkHostname();
00722 }
00723 
00724 KHostnameD::~KHostnameD()
00725 {
00726     // Empty
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 // Thiago: I have no idea what the following class is here for
00754 // David: the commit log was:
00755 //       Disable DCOP-Qt bridge but make sure that "dcopquit kded" continues to work.
00756 //       (see the setQtBridgeEnabled below)
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           // This long initialization has to be here, not in kdemain.
00807           // If it was in main, it would cause a dbus timeout when
00808           // our parent from KUniqueApplication tries to call our
00809           // newInstance method.
00810 
00811           Kded *kded = Kded::self();
00812 
00813           if (bCheckSycoca)
00814               runBuildSycoca();
00815 
00816           kded->recreate(true); // initial
00817 
00818           if (bCheckUpdates)
00819             (void) new KUpdateD; // Watch for updates
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(); // Run it once.
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); // Watch for hostname changes
00846 
00847           QObject::connect(QDBusConnection::sessionBus().interface(),
00848                           SIGNAL(serviceOwnerChanged(QString,QString,QString)),
00849                           kded, SLOT(slotApplicationRemoved(QString,QString,QString)));
00850 
00851           // During startup kdesktop waits for KDED to finish.
00852           // Send a notifyDatabaseChanged signal even if the database hasn't
00853           // changed.
00854           // If the database changed, kbuildsycoca's signal didn't go anywhere
00855           // anyway, because it was too early, so let's send this signal
00856           // unconditionnally (David)
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" /*don't change this one to kded4! dbus registration should be org.kde.kded etc.*/,
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      // WABA: Make sure not to enable session management.
00889      putenv(strdup("SESSION_MANAGER="));
00890 
00891      // Parse command line before checking DCOP
00892      KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
00893 
00894      KComponentData componentData(&aboutData);
00895      KSharedConfig::Ptr config = componentData.config(); // Enable translations.
00896 
00897      KConfigGroup cg(config, "General");
00898      if (args->isSet("check"))
00899      {
00900         // KUniqueApplication not wanted here.
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      // Thiago: reenable if such a thing exists in QtDBus in the future
00915      //KUniqueApplication::dcopClient()->setQtBridgeEnabled(false);
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); // Build data base
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      // Not sure why kded is created before KDEDApplication
00934      // but if it has to be, then it needs to be moved to the main thread
00935      // before it can use timers (DF)
00936      kded->moveToThread( k.thread() );
00937 
00938      int result = k.exec(); // keep running
00939 
00940      delete kded;
00941 
00942      return result;
00943 }
00944 
00945 #include "kded.moc"

KDED

Skip menu "KDED"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal