• Skip to content
  • Skip to link menu
KDE 4.3 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 #include "kbuildsycoca.h"
00025 
00026 #include "kresourcelist.h"
00027 #include <kcrash.h>
00028 
00029 #include <unistd.h>
00030 #include <stdlib.h>
00031 #include <signal.h>
00032 #include <time.h>
00033 
00034 #include <QtCore/QDir>
00035 #include <QtCore/QFile>
00036 #include <QtCore/QTimer>
00037 
00038 #include <QtDBus/QtDBus>
00039 
00040 #include <kuniqueapplication.h>
00041 #include <kapplication.h>
00042 #include <kcmdlineargs.h>
00043 #include <kaboutdata.h>
00044 #include <klocale.h>
00045 #include <kglobal.h>
00046 #include <kconfig.h>
00047 #include <kconfiggroup.h>
00048 #include <kdebug.h>
00049 #include <kdirwatch.h>
00050 #include <kstandarddirs.h>
00051 #include <kservicetypetrader.h>
00052 #include <ktoolinvocation.h>
00053 #include <kde_file.h>
00054 #include "klauncher_iface.h"
00055 
00056 #ifdef Q_WS_X11
00057 #include <qx11info_x11.h>
00058 #include <X11/Xlib.h>
00059 #include <fixx11h.h>
00060 #endif
00061 
00062 #define KDED_EXENAME "kded4"
00063 
00064 #define MODULES_PATH "/modules/"
00065 
00066 Kded *Kded::_self = 0;
00067 
00068 static bool checkStamps = true;
00069 static bool delayedCheck = false;
00070 static int HostnamePollInterval;
00071 static bool bCheckSycoca;
00072 static bool bCheckUpdates;
00073 static bool bCheckHostname;
00074 
00075 extern QDBUS_EXPORT void qDBusAddSpyHook(void (*)(const QDBusMessage&));
00076 
00077 static void runBuildSycoca(QObject *callBackObj=0, const char *callBackSlot=0)
00078 {
00079    const QString exe = KStandardDirs::findExe(KBUILDSYCOCA_EXENAME);
00080    Q_ASSERT(!exe.isEmpty());
00081    QStringList args;
00082    args.append("--incremental");
00083    if(checkStamps)
00084       args.append("--checkstamps");
00085    if(delayedCheck)
00086       args.append("--nocheckfiles");
00087    else
00088       checkStamps = false; // useful only during kded startup
00089    if (callBackObj)
00090    {
00091       QVariantList argList;
00092       argList << exe << args << QStringList() << QString();
00093       KToolInvocation::klauncher()->callWithCallback("kdeinit_exec_wait", argList, callBackObj,
00094                                                          callBackSlot);
00095    }
00096    else
00097    {
00098       KToolInvocation::kdeinitExecWait( exe, args );
00099 
00100       if (callBackObj && callBackSlot) {
00101           QTimer::singleShot(0, callBackObj, callBackSlot);
00102       }
00103    }
00104 }
00105 
00106 static void runKonfUpdate()
00107 {
00108    KToolInvocation::kdeinitExecWait( "kconf_update", QStringList(), 0, 0, "0" /*no startup notification*/ );
00109 }
00110 
00111 static void runDontChangeHostname(const QByteArray &oldName, const QByteArray &newName)
00112 {
00113    QStringList args;
00114    args.append(QFile::decodeName(oldName));
00115    args.append(QFile::decodeName(newName));
00116    KToolInvocation::kdeinitExecWait( "kdontchangethehostname", args );
00117 }
00118 
00119 Kded::Kded()
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 (!bCheckUpdates) 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   KBuildSycoca::clearCaches();
00473 
00474   if (!bCheckUpdates) 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       if (bCheckSycoca)
00520          runBuildSycoca();
00521       recreateDone();
00522       if(delayedCheck)
00523       {
00524          // do a proper ksycoca check after a delay
00525          QTimer::singleShot( 60000, this, SLOT(runDelayedCheck()));
00526          m_needDelayedCheck = true;
00527          delayedCheck = false;
00528       }
00529       else
00530          m_needDelayedCheck = false;
00531    }
00532 }
00533 
00534 void Kded::recreateDone()
00535 {
00536    updateResourceList();
00537 
00538    for(; m_recreateCount; m_recreateCount--)
00539    {
00540       QDBusMessage msg = m_recreateRequests.takeFirst();
00541       QDBusConnection::sessionBus().send(msg.createReply());
00542    }
00543    m_recreateBusy = false;
00544 
00545    // Did a new request come in while building?
00546    if (!m_recreateRequests.isEmpty())
00547    {
00548       m_pTimer->start(2000);
00549       m_recreateCount = m_recreateRequests.count();
00550    }
00551 }
00552 
00553 void Kded::dirDeleted(const QString& path)
00554 {
00555   update(path);
00556 }
00557 
00558 void Kded::update(const QString& )
00559 {
00560   if (!m_recreateBusy)
00561   {
00562     m_pTimer->start( 10000 );
00563   }
00564 }
00565 
00566 void Kded::recreate(const QDBusMessage &msg)
00567 {
00568    if (!m_recreateBusy)
00569    {
00570       if (m_recreateRequests.isEmpty())
00571       {
00572          m_pTimer->start(0);
00573          m_recreateCount = 0;
00574       }
00575       m_recreateCount++;
00576    }
00577    msg.setDelayedReply(true);
00578    m_recreateRequests.append(msg);
00579    return;
00580 }
00581 
00582 
00583 void Kded::readDirectory( const QString& _path )
00584 {
00585   QString path( _path );
00586   if ( !path.endsWith( '/' ) )
00587     path += '/';
00588 
00589   if ( m_pDirWatch->contains( path ) ) // Already seen this one?
00590      return;
00591 
00592   m_pDirWatch->addDir(path,KDirWatch::WatchFiles|KDirWatch::WatchSubDirs);          // add watch on this dir
00593   return; // KDirWatch now claims to also support recursive watching
00594 #if 0
00595   QDir d( _path, QString(), QDir::Unsorted, QDir::Readable | QDir::Executable | QDir::Dirs | QDir::Hidden );
00596   // set QDir ...
00597 
00598 
00599   //************************************************************************
00600   //                           Setting dirs
00601   //************************************************************************
00602 
00603   if ( !d.exists() )                            // exists&isdir?
00604   {
00605     kDebug(7020) << "Does not exist:" << _path;
00606     return;                             // return false
00607   }
00608 
00609   // Note: If some directory is gone, dirwatch will delete it from the list.
00610 
00611   //************************************************************************
00612   //                               Reading
00613   //************************************************************************
00614   QString file;
00615   unsigned int i;                           // counter and string length.
00616   unsigned int count = d.count();
00617   for( i = 0; i < count; i++ )                        // check all entries
00618   {
00619      if (d[i] == "." || d[i] == ".." || d[i] == "magic")
00620        continue;                          // discard those ".", "..", "magic"...
00621 
00622      file = path;                           // set full path
00623      file += d[i];                          // and add the file name.
00624 
00625      readDirectory( file );      // yes, dive into it.
00626   }
00627 #endif
00628 }
00629 
00630 /*
00631 bool Kded::isWindowRegistered(long windowId) const
00632 {
00633   return m_globalWindowIdList.contains(windowId);
00634 
00635 }
00636 */
00637 
00638 void Kded::registerWindowId(qlonglong windowId, const QString &sender)
00639 {
00640   m_globalWindowIdList.insert(windowId);
00641   QList<qlonglong> windowIds = m_windowIdList.value(sender);
00642   windowIds.append(windowId);
00643   m_windowIdList.insert(sender, windowIds);
00644 
00645   foreach( KDEDModule* module, m_modules )
00646   {
00647      //kDebug() << module->moduleName();
00648      emit module->windowRegistered(windowId);
00649   }
00650 }
00651 
00652 void Kded::unregisterWindowId(qlonglong windowId, const QString &sender)
00653 {
00654   m_globalWindowIdList.remove(windowId);
00655   QList<qlonglong> windowIds = m_windowIdList.value(sender);
00656   if (!windowIds.isEmpty())
00657   {
00658      windowIds.removeAll(windowId);
00659      if (windowIds.isEmpty())
00660         m_windowIdList.remove(sender);
00661      else
00662         m_windowIdList.insert(sender, windowIds);
00663   }
00664 
00665   foreach( KDEDModule* module, m_modules )
00666   {
00667     //kDebug() << module->moduleName();
00668     emit module->windowUnregistered(windowId);
00669   }
00670 }
00671 
00672 
00673 static void sighandler(int /*sig*/)
00674 {
00675     if (qApp)
00676        qApp->quit();
00677 }
00678 
00679 KUpdateD::KUpdateD()
00680 {
00681     m_pDirWatch = new KDirWatch;
00682     m_pTimer = new QTimer;
00683     m_pTimer->setSingleShot( true );
00684     connect(m_pTimer, SIGNAL(timeout()), this, SLOT(runKonfUpdate()));
00685     QObject::connect( m_pDirWatch, SIGNAL(dirty(const QString&)),
00686            this, SLOT(slotNewUpdateFile()));
00687 
00688     const QStringList dirs = KGlobal::dirs()->findDirs("data", "kconf_update");
00689     for( QStringList::ConstIterator it = dirs.begin();
00690          it != dirs.end();
00691          ++it )
00692     {
00693        QString path = *it;
00694        if (path[path.length()-1] != '/')
00695           path += '/';
00696 
00697        if (!m_pDirWatch->contains(path))
00698           m_pDirWatch->addDir(path,KDirWatch::WatchFiles|KDirWatch::WatchSubDirs);
00699     }
00700 }
00701 
00702 KUpdateD::~KUpdateD()
00703 {
00704     delete m_pDirWatch;
00705     delete m_pTimer;
00706 }
00707 
00708 void KUpdateD::runKonfUpdate()
00709 {
00710     ::runKonfUpdate();
00711 }
00712 
00713 void KUpdateD::slotNewUpdateFile()
00714 {
00715     m_pTimer->start( 500 );
00716 }
00717 
00718 KHostnameD::KHostnameD(int pollInterval)
00719 {
00720     m_Timer.start(pollInterval); // repetitive timer (not single-shot)
00721     connect(&m_Timer, SIGNAL(timeout()), this, SLOT(checkHostname()));
00722     checkHostname();
00723 }
00724 
00725 KHostnameD::~KHostnameD()
00726 {
00727     // Empty
00728 }
00729 
00730 void KHostnameD::checkHostname()
00731 {
00732     char buf[1024+1];
00733     if (gethostname(buf, 1024) != 0)
00734        return;
00735     buf[sizeof(buf)-1] = '\0';
00736 
00737     if (m_hostname.isEmpty())
00738     {
00739        m_hostname = buf;
00740        return;
00741     }
00742 
00743     if (m_hostname == buf)
00744        return;
00745 
00746     QByteArray newHostname = buf;
00747 
00748     runDontChangeHostname(m_hostname, newHostname);
00749     m_hostname = newHostname;
00750 }
00751 
00752 
00753 #if 0
00754 // Thiago: I have no idea what the following class is here for
00755 // David: the commit log was:
00756 //       Disable DCOP-Qt bridge but make sure that "dcopquit kded" continues to work.
00757 //       (see the setQtBridgeEnabled below)
00758 class KDEDQtDCOPObject : public DCOPObject
00759 {
00760 public:
00761   KDEDQtDCOPObject() : DCOPObject("qt/kded") { }
00762 
00763   virtual bool process(const DCOPCString &fun, const QByteArray &data,
00764                        DCOPCString& replyType, QByteArray &replyData)
00765     {
00766       if (qApp && (fun == "quit()"))
00767       {
00768         qApp->quit();
00769         replyType = "void";
00770         return true;
00771       }
00772       return DCOPObject::process(fun, data, replyType, replyData);
00773     }
00774 
00775   DCOPCStringList functions()
00776     {
00777        DCOPCStringList res = DCOPObject::functions();
00778        res += "void quit()";
00779        return res;
00780     }
00781 };
00782 #endif
00783 
00784 KBuildsycocaAdaptor::KBuildsycocaAdaptor(QObject *parent)
00785    : QDBusAbstractAdaptor(parent)
00786 {
00787 }
00788 
00789 void KBuildsycocaAdaptor::recreate(const QDBusMessage &msg)
00790 {
00791    Kded::self()->recreate(msg);
00792 }
00793 
00794 class KDEDApplication : public KUniqueApplication
00795 {
00796 public:
00797   KDEDApplication() : KUniqueApplication( )
00798     {
00799        startup = true;
00800     }
00801 
00802   int newInstance()
00803     {
00804        if (startup) {
00805           startup = false;
00806 
00807           // This long initialization has to be here, not in kdemain.
00808           // If it was in main, it would cause a dbus timeout when
00809           // our parent from KUniqueApplication tries to call our
00810           // newInstance method.
00811 
00812           Kded *kded = Kded::self();
00813 
00814           kded->recreate(true); // initial
00815 
00816           if (bCheckUpdates)
00817             (void) new KUpdateD; // Watch for updates
00818 
00819 #ifdef Q_WS_X11
00820           XEvent e;
00821           e.xclient.type = ClientMessage;
00822           e.xclient.message_type = XInternAtom( QX11Info::display(), "_KDE_SPLASH_PROGRESS", False );
00823           e.xclient.display = QX11Info::display();
00824           e.xclient.window = QX11Info::appRootWindow();
00825           e.xclient.format = 8;
00826           strcpy( e.xclient.data.b, "kded" );
00827           XSendEvent( QX11Info::display(), QX11Info::appRootWindow(), False, SubstructureNotifyMask, &e );
00828 #endif
00829 
00830           runKonfUpdate(); // Run it once.
00831 
00832 #ifdef Q_WS_X11
00833           e.xclient.type = ClientMessage;
00834           e.xclient.message_type = XInternAtom( QX11Info::display(), "_KDE_SPLASH_PROGRESS", False );
00835           e.xclient.display = QX11Info::display();
00836           e.xclient.window = QX11Info::appRootWindow();
00837           e.xclient.format = 8;
00838           strcpy( e.xclient.data.b, "confupdate" );
00839           XSendEvent( QX11Info::display(), QX11Info::appRootWindow(), False, SubstructureNotifyMask, &e );
00840 #endif
00841 
00842           if (bCheckHostname)
00843             (void) new KHostnameD(HostnamePollInterval); // Watch for hostname changes
00844 
00845           QObject::connect(QDBusConnection::sessionBus().interface(),
00846                           SIGNAL(serviceOwnerChanged(QString,QString,QString)),
00847                           kded, SLOT(slotApplicationRemoved(QString,QString,QString)));
00848 
00849           // During startup kdesktop waits for KDED to finish.
00850           // Send a notifyDatabaseChanged signal even if the database hasn't
00851           // changed.
00852           // If the database changed, kbuildsycoca's signal didn't go anywhere
00853           // anyway, because it was too early, so let's send this signal
00854           // unconditionnally (David)
00855 
00856           QDBusMessage msg = QDBusMessage::createSignal("/kbuildsycoca", "org.kde.KSycoca", "notifyDatabaseChanged" );
00857           msg << QStringList();
00858           QDBusConnection::sessionBus().send(msg);
00859 
00860           kded->initModules();
00861        } else
00862           runBuildSycoca();
00863 
00864        return 0;
00865     }
00866 
00867   bool startup;
00868 };
00869 
00870 extern "C" KDE_EXPORT int kdemain(int argc, char *argv[])
00871 {
00872      KAboutData aboutData( "kded" /*don't change this one to kded4! dbus registration should be org.kde.kded etc.*/,
00873         "kdelibs4", ki18n("KDE Daemon"),
00874         "$Id: kded.cpp 1031638 2009-10-05 16:59:11Z lunakl $",
00875         ki18n("KDE Daemon - triggers Sycoca database updates when needed"));
00876 
00877      KCmdLineOptions options;
00878      options.add("check", ki18n("Check Sycoca database only once"));
00879 
00880      KCmdLineArgs::init(argc, argv, &aboutData);
00881 
00882      KUniqueApplication::addCmdLineOptions();
00883 
00884      KCmdLineArgs::addCmdLineOptions( options );
00885 
00886      // WABA: Make sure not to enable session management.
00887      putenv(strdup("SESSION_MANAGER="));
00888 
00889      // Parse command line before checking DCOP
00890      KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
00891 
00892      KComponentData componentData(&aboutData);
00893      KSharedConfig::Ptr config = componentData.config(); // Enable translations.
00894 
00895      KConfigGroup cg(config, "General");
00896      if (args->isSet("check"))
00897      {
00898         // KUniqueApplication not wanted here.
00899         KApplication app;
00900         checkStamps = cg.readEntry("CheckFileStamps", true);
00901         runBuildSycoca();
00902         runKonfUpdate();
00903         return 0;
00904      }
00905 
00906      if (!KUniqueApplication::start())
00907      {
00908         fprintf(stderr, "KDE Daemon (kded) already running.\n");
00909         return 0;
00910      }
00911 
00912      // Thiago: reenable if such a thing exists in QtDBus in the future
00913      //KUniqueApplication::dcopClient()->setQtBridgeEnabled(false);
00914 
00915      HostnamePollInterval = cg.readEntry("HostnamePollInterval", 5000);
00916      bCheckSycoca = cg.readEntry("CheckSycoca", true);
00917      bCheckUpdates = cg.readEntry("CheckUpdates", true);
00918      bCheckHostname = cg.readEntry("CheckHostname", true);
00919      checkStamps = cg.readEntry("CheckFileStamps", true);
00920      delayedCheck = cg.readEntry("DelayedCheck", false);
00921 
00922      Kded *kded = new Kded(); // Build data base
00923 
00924      KDE_signal(SIGTERM, sighandler);
00925      KDE_signal(SIGHUP, sighandler);
00926      KDEDApplication k;
00927      k.setQuitOnLastWindowClosed(false);
00928 
00929      KCrash::setFlags(KCrash::AutoRestart);
00930 
00931      // Not sure why kded is created before KDEDApplication
00932      // but if it has to be, then it needs to be moved to the main thread
00933      // before it can use timers (DF)
00934      kded->moveToThread( k.thread() );
00935 
00936      int result = k.exec(); // keep running
00937 
00938      delete kded;
00939 
00940      return result;
00941 }
00942 
00943 #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
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
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