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

KDED

kded.cpp

Go to the documentation of this file.
00001 /*  This file is part of the KDE libraries
00002  *  Copyright (C) 1999 David Faure <faure@kde.org>
00003  *  Copyright (C) 2000 Waldo Bastian <bastian@kde.org>
00004  *
00005  *  This library is free software; you can redistribute it and/or
00006  *  modify it under the terms of the GNU Library General Public
00007  *  License version 2 as published by the Free Software Foundation;
00008  *
00009  *  This library is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  *  Library General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU Library General Public License
00015  *  along with this library; see the file COPYING.LIB.  If not, write to
00016  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  *  Boston, MA 02110-1301, USA.
00018  **/
00019 
00020 #include "kded.h"
00021 #include "kdedadaptor.h"
00022 #include "kdedmodule.h"
00023 
00024 #include "kresourcelist.h"
00025 #include <kcrash.h>
00026 
00027 #include <unistd.h>
00028 #include <stdlib.h>
00029 #include <signal.h>
00030 #include <time.h>
00031 
00032 #include <QtCore/QDir>
00033 #include <QtCore/QFile>
00034 #include <QtCore/QTimer>
00035 
00036 #include <QtDBus/QtDBus>
00037 
00038 #include <kuniqueapplication.h>
00039 #include <kapplication.h>
00040 #include <kcmdlineargs.h>
00041 #include <kaboutdata.h>
00042 #include <klocale.h>
00043 #include <kglobal.h>
00044 #include <kconfig.h>
00045 #include <kconfiggroup.h>
00046 #include <kdebug.h>
00047 #include <kdirwatch.h>
00048 #include <kstandarddirs.h>
00049 #include <kservicetypetrader.h>
00050 #include <ktoolinvocation.h>
00051 #include <kde_file.h>
00052 #include "klauncher_iface.h"
00053 
00054 #ifdef Q_WS_X11
00055 #include <qx11info_x11.h>
00056 #include <X11/Xlib.h>
00057 #include <fixx11h.h>
00058 #endif
00059 
00060 #define KDED_EXENAME "kded4"
00061 
00062 #define MODULES_PATH "/modules/"
00063 
00064 Kded *Kded::_self = 0;
00065 
00066 static bool checkStamps = true;
00067 static bool delayedCheck = false;
00068 
00069 extern QDBUS_EXPORT void qDBusAddSpyHook(void (*)(const QDBusMessage&));
00070 
00071 static void runBuildSycoca(QObject *callBackObj=0, const char *callBackSlot=0)
00072 {
00073    const QString exe = KStandardDirs::findExe(KBUILDSYCOCA_EXENAME);
00074    Q_ASSERT(!exe.isEmpty());
00075    QStringList args;
00076    args.append("--incremental");
00077    if(checkStamps)
00078       args.append("--checkstamps");
00079    if(delayedCheck)
00080       args.append("--nocheckfiles");
00081    else
00082       checkStamps = false; // useful only during kded startup
00083    if (callBackObj)
00084    {
00085       QVariantList argList;
00086       argList << exe << args << QStringList() << QString();
00087       KToolInvocation::klauncher()->callWithCallback("kdeinit_exec_wait", argList, callBackObj,
00088                                                          callBackSlot);
00089    }
00090    else
00091    {
00092       KToolInvocation::kdeinitExecWait( exe, args );
00093    }
00094 }
00095 
00096 static void runKonfUpdate()
00097 {
00098    KToolInvocation::kdeinitExecWait( "kconf_update", QStringList(), 0, 0, "0" /*no startup notification*/ );
00099 }
00100 
00101 static void runDontChangeHostname(const QByteArray &oldName, const QByteArray &newName)
00102 {
00103    QStringList args;
00104    args.append(QFile::decodeName(oldName));
00105    args.append(QFile::decodeName(newName));
00106    KToolInvocation::kdeinitExecWait( "kdontchangethehostname", args );
00107 }
00108 
00109 Kded::Kded(bool checkUpdates)
00110   : b_checkUpdates(checkUpdates),
00111     m_needDelayedCheck(false)
00112 {
00113   _self = this;
00114 
00115   new KBuildsycocaAdaptor(this);
00116   new KdedAdaptor(this);
00117 
00118   QDBusConnection session = QDBusConnection::sessionBus();
00119   session.registerObject("/kbuildsycoca", this);
00120   session.registerObject("/kded", this);
00121 
00122   qDBusAddSpyHook(messageFilter);
00123 
00124   m_pTimer = new QTimer(this);
00125   m_pTimer->setSingleShot( true );
00126   connect(m_pTimer, SIGNAL(timeout()), this, SLOT(recreate()));
00127 
00128   m_pDirWatch = 0;
00129 
00130   m_recreateCount = 0;
00131   m_recreateBusy = false;
00132 }
00133 
00134 Kded::~Kded()
00135 {
00136   _self = 0;
00137   m_pTimer->stop();
00138   delete m_pTimer;
00139   delete m_pDirWatch;
00140 
00141   for (QHash<QByteArray,KDEDModule*>::iterator
00142            it(m_modules.begin()), itEnd(m_modules.end());
00143        it != itEnd; ++it)
00144   {
00145       KDEDModule* module(it.value());
00146 
00147       // first disconnect otherwise slotKDEDModuleRemoved() is called
00148       // and changes m_modules while we're iterating over it
00149       disconnect(module, SIGNAL(moduleDeleted(KDEDModule*)),
00150                  this, SLOT(slotKDEDModuleRemoved(KDEDModule*)));
00151 
00152       delete module;
00153   }
00154 }
00155 
00156 // on-demand module loading
00157 // this function is called by the D-Bus message processing function before
00158 // calls are delivered to objects
00159 void Kded::messageFilter(const QDBusMessage &message)
00160 {
00161   if (message.type() != QDBusMessage::MethodCallMessage)
00162      return;
00163 
00164   QString obj = message.path();
00165   if (!obj.startsWith(MODULES_PATH))
00166      return;
00167 
00168   obj = obj.mid(strlen(MODULES_PATH));
00169   if (obj == "ksycoca")
00170      return; // Ignore this one.
00171 
00172   if (self()->m_dontLoad.value(obj, 0))
00173      return;
00174 
00175   KDEDModule *module = self()->loadModule(obj, true);
00176   Q_UNUSED(module);
00177 }
00178 
00179 void Kded::initModules()
00180 {
00181      m_dontLoad.clear();
00182      KSharedConfig::Ptr config = KGlobal::config();
00183      bool kde_running = !qgetenv( "KDE_FULL_SESSION" ).isEmpty();
00184     // not the same user like the one running the session (most likely we're run via sudo or something)
00185     const QByteArray sessionUID = qgetenv( "KDE_SESSION_UID" );
00186     if( !sessionUID.isEmpty() && uid_t( sessionUID.toInt() ) != getuid())
00187         kde_running = false;
00188      // Preload kded modules.
00189      KService::List kdedModules = KServiceTypeTrader::self()->query("KDEDModule");
00190      for(KService::List::ConstIterator it = kdedModules.begin(); it != kdedModules.end(); ++it)
00191      {
00192          KService::Ptr service = *it;
00193          bool autoload = service->property("X-KDE-Kded-autoload", QVariant::Bool).toBool();
00194          KConfigGroup cg(config, QString("Module-%1").arg(service->desktopEntryName()));
00195          autoload = cg.readEntry("autoload", autoload);
00196          // see ksmserver's README for description of the phases
00197          QVariant phasev = service->property("X-KDE-Kded-phase", QVariant::Int );
00198          int phase = phasev.isValid() ? phasev.toInt() : 2;
00199          bool prevent_autoload = false;
00200          switch( phase )
00201          {
00202              case 0: // always autoload
00203                  break;
00204              case 1: // autoload only in KDE
00205                  if( !kde_running )
00206                      prevent_autoload = true;
00207                  break;
00208              case 2: // autoload delayed, only in KDE
00209              default:
00210                  prevent_autoload = true;
00211                  break;
00212          }
00213          if (autoload && !prevent_autoload)
00214             loadModule(service, false);
00215 
00216          bool dontLoad = false;
00217          QVariant p = service->property("X-KDE-Kded-load-on-demand", QVariant::Bool);
00218          if (p.isValid() && (p.toBool() == false))
00219             dontLoad = true;
00220          if (dontLoad)
00221             noDemandLoad(service->desktopEntryName());
00222 
00223          if (dontLoad && !autoload)
00224             unloadModule(service->desktopEntryName().toLatin1());
00225      }
00226 }
00227 
00228 void Kded::loadSecondPhase()
00229 {
00230      kDebug(7020) << "Loading second phase autoload";
00231      KSharedConfig::Ptr config = KGlobal::config();
00232      KService::List kdedModules = KServiceTypeTrader::self()->query("KDEDModule");
00233      for(KService::List::ConstIterator it = kdedModules.begin(); it != kdedModules.end(); ++it)
00234      {
00235          KService::Ptr service = *it;
00236          bool autoload = service->property("X-KDE-Kded-autoload", QVariant::Bool).toBool();
00237          KConfigGroup cg(config, QString("Module-%1").arg(service->desktopEntryName()));
00238          autoload = cg.readEntry("autoload", autoload);
00239          QVariant phasev = service->property("X-KDE-Kded-phase", QVariant::Int );
00240          int phase = phasev.isValid() ? phasev.toInt() : 2;
00241          if( phase == 2 && autoload )
00242             loadModule(service, false);
00243      }
00244 }
00245 
00246 void Kded::noDemandLoad(const QString &obj)
00247 {
00248   m_dontLoad.insert(obj.toLatin1(), this);
00249 }
00250 
00251 KDEDModule *Kded::loadModule(const QString &obj, bool onDemand)
00252 {
00253   KDEDModule *module = m_modules.value(obj, 0);
00254   if (module)
00255      return module;
00256   KService::Ptr s = KService::serviceByDesktopPath("kded/"+obj+".desktop");
00257   return loadModule(s, onDemand);
00258 }
00259 
00260 KDEDModule *Kded::loadModule(const KService::Ptr& s, bool onDemand)
00261 {
00262     if (s && !s->library().isEmpty())
00263     {
00264         QString obj = s->desktopEntryName();
00265         KDEDModule *oldModule = m_modules.value(obj, 0);
00266         if (oldModule)
00267             return oldModule;
00268 
00269         if (onDemand)
00270         {
00271             QVariant p = s->property("X-KDE-Kded-load-on-demand", QVariant::Bool);
00272             if (p.isValid() && (p.toBool() == false))
00273             {
00274                 noDemandLoad(s->desktopEntryName());
00275                 return 0;
00276             }
00277         }
00278 
00279         KDEDModule *module = 0;
00280         QString libname = "kded_"+s->library();
00281         KPluginLoader loader(libname);
00282 
00283         KPluginFactory *factory = loader.factory();
00284         if (!factory) {
00285             // kde3 compat
00286             QString factoryName = s->property("X-KDE-FactoryName", QVariant::String).toString();
00287             if (factoryName.isEmpty())
00288                 factoryName = s->library();
00289             factoryName = "create_" + factoryName;
00290             KLibrary* lib = KLibLoader::self()->library(libname);
00291             KDEDModule* (*create)();
00292             if (lib) {
00293                 create = (KDEDModule* (*)())lib->resolveFunction(QFile::encodeName(factoryName));
00294                 if (create)
00295                     module = create();
00296             }
00297             if (!module) {
00298                 kWarning() << "Could not load library" << libname << ". ["
00299                            << loader.errorString() << "]";
00300             }
00301         } else {
00302             // create the module
00303             module = factory->create<KDEDModule>(this);
00304         }
00305         if (module) {
00306             module->setModuleName(obj);
00307             m_modules.insert(obj, module);
00308             //m_libs.insert(obj, lib);
00309             connect(module, SIGNAL(moduleDeleted(KDEDModule *)), SLOT(slotKDEDModuleRemoved(KDEDModule *)));
00310             kDebug(7020) << "Successfully loaded module" << obj;
00311             return module;
00312         } else {
00313             kDebug(7020) << "Could not load module" << obj;
00314             //loader.unload();
00315         }
00316     }
00317     return 0;
00318 }
00319 
00320 bool Kded::unloadModule(const QString &obj)
00321 {
00322   KDEDModule *module = m_modules.value(obj, 0);
00323   if (!module)
00324      return false;
00325   kDebug(7020) << "Unloading module" << obj;
00326   m_modules.remove(obj);
00327   delete module;
00328   return true;
00329 }
00330 
00331 QStringList Kded::loadedModules()
00332 {
00333     return m_modules.keys();
00334 }
00335 
00336 void Kded::slotKDEDModuleRemoved(KDEDModule *module)
00337 {
00338   m_modules.remove(module->moduleName());
00339   //KLibrary *lib = m_libs.take(module->moduleName());
00340   //if (lib)
00341   //   lib->unload();
00342 }
00343 
00344 void Kded::slotApplicationRemoved(const QString &name, const QString &oldOwner,
00345                                   const QString &newOwner)
00346 {
00347 #if 0 // see kdedmodule.cpp (KDED_OBJECTS)
00348   foreach( KDEDModule* module, m_modules )
00349   {
00350      module->removeAll(appId);
00351   }
00352 #endif
00353   if (oldOwner.isEmpty() || !newOwner.isEmpty())
00354      return;
00355 
00356   const QList<qlonglong> windowIds = m_windowIdList.value(name);
00357   for( QList<qlonglong>::ConstIterator it = windowIds.begin();
00358        it != windowIds.end(); ++it)
00359   {
00360       qlonglong windowId = *it;
00361       m_globalWindowIdList.remove(windowId);
00362       foreach( KDEDModule* module, m_modules )
00363       {
00364           emit module->windowUnregistered(windowId);
00365       }
00366   }
00367   m_windowIdList.remove(name);
00368 }
00369 
00370 void Kded::updateDirWatch()
00371 {
00372   if (!b_checkUpdates) return;
00373 
00374   delete m_pDirWatch;
00375   m_pDirWatch = new KDirWatch;
00376 
00377   QObject::connect( m_pDirWatch, SIGNAL(dirty(const QString&)),
00378            this, SLOT(update(const QString&)));
00379   QObject::connect( m_pDirWatch, SIGNAL(created(const QString&)),
00380            this, SLOT(update(const QString&)));
00381   QObject::connect( m_pDirWatch, SIGNAL(deleted(const QString&)),
00382            this, SLOT(dirDeleted(const QString&)));
00383 
00384   // For each resource
00385   for( QStringList::ConstIterator it = m_allResourceDirs.begin();
00386        it != m_allResourceDirs.end();
00387        ++it )
00388   {
00389      readDirectory( *it );
00390   }
00391 }
00392 
00393 void Kded::updateResourceList()
00394 {
00395   delete KSycoca::self();
00396 
00397   if (!b_checkUpdates) return;
00398 
00399   if (delayedCheck) return;
00400 
00401   const QStringList dirs = KSycoca::self()->allResourceDirs();
00402   // For each resource
00403   for( QStringList::ConstIterator it = dirs.begin();
00404        it != dirs.end();
00405        ++it )
00406   {
00407      if (!m_allResourceDirs.contains(*it))
00408      {
00409         m_allResourceDirs.append(*it);
00410         readDirectory(*it);
00411      }
00412   }
00413 }
00414 
00415 void Kded::recreate()
00416 {
00417    recreate(false);
00418 }
00419 
00420 void Kded::runDelayedCheck()
00421 {
00422    if( m_needDelayedCheck )
00423       recreate(false);
00424    m_needDelayedCheck = false;
00425 }
00426 
00427 void Kded::recreate(bool initial)
00428 {
00429    m_recreateBusy = true;
00430    // Using KLauncher here is difficult since we might not have a
00431    // database
00432 
00433    if (!initial)
00434    {
00435       updateDirWatch(); // Update tree first, to be sure to miss nothing.
00436       runBuildSycoca(this, SLOT(recreateDone()));
00437    }
00438    else
00439    {
00440       if(!delayedCheck)
00441          updateDirWatch(); // this would search all the directories
00442       runBuildSycoca();
00443       recreateDone();
00444       if(delayedCheck)
00445       {
00446          // do a proper ksycoca check after a delay
00447          QTimer::singleShot( 60000, this, SLOT(runDelayedCheck()));
00448          m_needDelayedCheck = true;
00449          delayedCheck = false;
00450       }
00451       else
00452          m_needDelayedCheck = false;
00453    }
00454 }
00455 
00456 void Kded::recreateDone()
00457 {
00458    updateResourceList();
00459 
00460    for(; m_recreateCount; m_recreateCount--)
00461    {
00462       QDBusMessage msg = m_recreateRequests.takeFirst();
00463       QDBusConnection::sessionBus().send(msg.createReply());
00464    }
00465    m_recreateBusy = false;
00466 
00467    // Did a new request come in while building?
00468    if (!m_recreateRequests.isEmpty())
00469    {
00470       m_pTimer->start(2000);
00471       m_recreateCount = m_recreateRequests.count();
00472    }
00473 }
00474 
00475 void Kded::dirDeleted(const QString& path)
00476 {
00477   update(path);
00478 }
00479 
00480 void Kded::update(const QString& )
00481 {
00482   if (!m_recreateBusy)
00483   {
00484     m_pTimer->start( 10000 );
00485   }
00486 }
00487 
00488 void Kded::recreate(const QDBusMessage &msg)
00489 {
00490    if (!m_recreateBusy)
00491    {
00492       if (m_recreateRequests.isEmpty())
00493       {
00494          m_pTimer->start(0);
00495          m_recreateCount = 0;
00496       }
00497       m_recreateCount++;
00498    }
00499    msg.setDelayedReply(true);
00500    m_recreateRequests.append(msg);
00501    return;
00502 }
00503 
00504 
00505 void Kded::readDirectory( const QString& _path )
00506 {
00507   QString path( _path );
00508   if ( !path.endsWith( '/' ) )
00509     path += '/';
00510 
00511   if ( m_pDirWatch->contains( path ) ) // Already seen this one?
00512      return;
00513 
00514   m_pDirWatch->addDir(path,KDirWatch::WatchFiles|KDirWatch::WatchSubDirs);          // add watch on this dir
00515   return; // KDirWatch now claims to also support recursive watching
00516 #if 0
00517   QDir d( _path, QString(), QDir::Unsorted, QDir::Readable | QDir::Executable | QDir::Dirs | QDir::Hidden );
00518   // set QDir ...
00519 
00520 
00521   //************************************************************************
00522   //                           Setting dirs
00523   //************************************************************************
00524 
00525   if ( !d.exists() )                            // exists&isdir?
00526   {
00527     kDebug(7020) << "Does not exist:" << _path;
00528     return;                             // return false
00529   }
00530 
00531   // Note: If some directory is gone, dirwatch will delete it from the list.
00532 
00533   //************************************************************************
00534   //                               Reading
00535   //************************************************************************
00536   QString file;
00537   unsigned int i;                           // counter and string length.
00538   unsigned int count = d.count();
00539   for( i = 0; i < count; i++ )                        // check all entries
00540   {
00541      if (d[i] == "." || d[i] == ".." || d[i] == "magic")
00542        continue;                          // discard those ".", "..", "magic"...
00543 
00544      file = path;                           // set full path
00545      file += d[i];                          // and add the file name.
00546 
00547      readDirectory( file );      // yes, dive into it.
00548   }
00549 #endif
00550 }
00551 
00552 /*
00553 bool Kded::isWindowRegistered(long windowId) const
00554 {
00555   return m_globalWindowIdList.contains(windowId);
00556 
00557 }
00558 */
00559 
00560 void Kded::registerWindowId(qlonglong windowId, const QString &sender)
00561 {
00562   m_globalWindowIdList.insert(windowId);
00563   QList<qlonglong> windowIds = m_windowIdList.value(sender);
00564   windowIds.append(windowId);
00565   m_windowIdList.insert(sender, windowIds);
00566 
00567   foreach( KDEDModule* module, m_modules )
00568   {
00569      emit module->windowRegistered(windowId);
00570   }
00571 }
00572 
00573 void Kded::unregisterWindowId(qlonglong windowId, const QString &sender)
00574 {
00575   m_globalWindowIdList.remove(windowId);
00576   QList<qlonglong> windowIds = m_windowIdList.value(sender);
00577   if (!windowIds.isEmpty())
00578   {
00579      windowIds.removeAll(windowId);
00580      if (windowIds.isEmpty())
00581         m_windowIdList.remove(sender);
00582      else
00583         m_windowIdList.insert(sender, windowIds);
00584   }
00585 
00586   foreach( KDEDModule* module, m_modules )
00587   {
00588     emit module->windowUnregistered(windowId);
00589   }
00590 }
00591 
00592 
00593 static void sighandler(int /*sig*/)
00594 {
00595     if (qApp)
00596        qApp->quit();
00597 }
00598 
00599 KUpdateD::KUpdateD()
00600 {
00601     m_pDirWatch = new KDirWatch;
00602     m_pTimer = new QTimer;
00603     m_pTimer->setSingleShot( true );
00604     connect(m_pTimer, SIGNAL(timeout()), this, SLOT(runKonfUpdate()));
00605     QObject::connect( m_pDirWatch, SIGNAL(dirty(const QString&)),
00606            this, SLOT(slotNewUpdateFile()));
00607 
00608     QStringList dirs = KGlobal::dirs()->findDirs("data", "kconf_update");
00609     for( QStringList::ConstIterator it = dirs.begin();
00610          it != dirs.end();
00611          ++it )
00612     {
00613        QString path = *it;
00614        if (path[path.length()-1] != '/')
00615           path += '/';
00616 
00617        if (!m_pDirWatch->contains(path))
00618           m_pDirWatch->addDir(path,KDirWatch::WatchFiles|KDirWatch::WatchSubDirs);
00619     }
00620 }
00621 
00622 KUpdateD::~KUpdateD()
00623 {
00624     delete m_pDirWatch;
00625     delete m_pTimer;
00626 }
00627 
00628 void KUpdateD::runKonfUpdate()
00629 {
00630     ::runKonfUpdate();
00631 }
00632 
00633 void KUpdateD::slotNewUpdateFile()
00634 {
00635     m_pTimer->start( 500 );
00636 }
00637 
00638 KHostnameD::KHostnameD(int pollInterval)
00639 {
00640     m_Timer.start(pollInterval); // repetitive timer (not single-shot)
00641     connect(&m_Timer, SIGNAL(timeout()), this, SLOT(checkHostname()));
00642     checkHostname();
00643 }
00644 
00645 KHostnameD::~KHostnameD()
00646 {
00647     // Empty
00648 }
00649 
00650 void KHostnameD::checkHostname()
00651 {
00652     char buf[1024+1];
00653     if (gethostname(buf, 1024) != 0)
00654        return;
00655     buf[sizeof(buf)-1] = '\0';
00656 
00657     if (m_hostname.isEmpty())
00658     {
00659        m_hostname = buf;
00660        return;
00661     }
00662 
00663     if (m_hostname == buf)
00664        return;
00665 
00666     QByteArray newHostname = buf;
00667 
00668     runDontChangeHostname(m_hostname, newHostname);
00669     m_hostname = newHostname;
00670 }
00671 
00672 
00673 #if 0
00674 // Thiago: I have no idea what the following class is here for
00675 // David: the commit log was:
00676 //       Disable DCOP-Qt bridge but make sure that "dcopquit kded" continues to work.
00677 //       (see the setQtBridgeEnabled below)
00678 class KDEDQtDCOPObject : public DCOPObject
00679 {
00680 public:
00681   KDEDQtDCOPObject() : DCOPObject("qt/kded") { }
00682 
00683   virtual bool process(const DCOPCString &fun, const QByteArray &data,
00684                        DCOPCString& replyType, QByteArray &replyData)
00685     {
00686       if (qApp && (fun == "quit()"))
00687       {
00688         qApp->quit();
00689         replyType = "void";
00690         return true;
00691       }
00692       return DCOPObject::process(fun, data, replyType, replyData);
00693     }
00694 
00695   DCOPCStringList functions()
00696     {
00697        DCOPCStringList res = DCOPObject::functions();
00698        res += "void quit()";
00699        return res;
00700     }
00701 };
00702 #endif
00703 
00704 KBuildsycocaAdaptor::KBuildsycocaAdaptor(QObject *parent)
00705    : QDBusAbstractAdaptor(parent)
00706 {
00707 }
00708 
00709 void KBuildsycocaAdaptor::recreate(const QDBusMessage &msg)
00710 {
00711    Kded::self()->recreate(msg);
00712 }
00713 
00714 class KDEDApplication : public KUniqueApplication
00715 {
00716 public:
00717   KDEDApplication() : KUniqueApplication( )
00718     {
00719        startup = true;
00720     }
00721 
00722   int newInstance()
00723     {
00724        if (startup) {
00725           startup = false;
00726           Kded::self()->initModules();
00727        } else
00728           runBuildSycoca();
00729 
00730        return 0;
00731     }
00732 
00733   bool startup;
00734 };
00735 
00736 extern "C" KDE_EXPORT int kdemain(int argc, char *argv[])
00737 {
00738      KAboutData aboutData( "kded" /*don't change this one to kded4! dbus registration should be org.kde.kded etc.*/,
00739         "kdelibs4", ki18n("KDE Daemon"),
00740         "$Id: kded.cpp 825113 2008-06-27 13:30:46Z dfaure $",
00741         ki18n("KDE Daemon - triggers Sycoca database updates when needed"));
00742 
00743      KCmdLineOptions options;
00744      options.add("check", ki18n("Check Sycoca database only once"));
00745 
00746      KCmdLineArgs::init(argc, argv, &aboutData);
00747 
00748      KUniqueApplication::addCmdLineOptions();
00749 
00750      KCmdLineArgs::addCmdLineOptions( options );
00751 
00752      // WABA: Make sure not to enable session management.
00753      putenv(strdup("SESSION_MANAGER="));
00754 
00755      // Parse command line before checking DCOP
00756      KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
00757 
00758      KComponentData componentData(&aboutData);
00759      KSharedConfig::Ptr config = componentData.config(); // Enable translations.
00760 
00761      KConfigGroup cg(config, "General");
00762      if (args->isSet("check"))
00763      {
00764         // KUniqueApplication not wanted here.
00765         KApplication app;
00766         checkStamps = cg.readEntry("CheckFileStamps", true);
00767         runBuildSycoca();
00768         runKonfUpdate();
00769         return 0;
00770      }
00771 
00772      if (!KUniqueApplication::start())
00773      {
00774         fprintf(stderr, "KDE Daemon (kded) already running.\n");
00775         return 0;
00776      }
00777 
00778      // Thiago: reenable if such a thing exists in QtDBus in the future
00779      //KUniqueApplication::dcopClient()->setQtBridgeEnabled(false);
00780 
00781      int HostnamePollInterval = cg.readEntry("HostnamePollInterval", 5000);
00782      bool bCheckSycoca = cg.readEntry("CheckSycoca", true);
00783      bool bCheckUpdates = cg.readEntry("CheckUpdates", true);
00784      bool bCheckHostname = cg.readEntry("CheckHostname", true);
00785      checkStamps = cg.readEntry("CheckFileStamps", true);
00786      delayedCheck = cg.readEntry("DelayedCheck", false);
00787 
00788      Kded *kded = new Kded(bCheckSycoca); // Build data base
00789 
00790      KDE_signal(SIGTERM, sighandler);
00791      KDE_signal(SIGHUP, sighandler);
00792      KDEDApplication k;
00793      k.setQuitOnLastWindowClosed(false);
00794 
00795      KCrash::setFlags(KCrash::AutoRestart);
00796 
00797      // Not sure why kded is created before KDEDApplication
00798      // but if it has to be, then it needs to be moved to the main thread
00799      // before it can use timers (DF)
00800      kded->moveToThread( k.thread() );
00801 
00802      kded->recreate(true); // initial
00803 
00804      if (bCheckUpdates)
00805         (void) new KUpdateD; // Watch for updates
00806 
00807 #ifdef Q_WS_X11
00808      XEvent e;
00809      e.xclient.type = ClientMessage;
00810      e.xclient.message_type = XInternAtom( QX11Info::display(), "_KDE_SPLASH_PROGRESS", False );
00811      e.xclient.display = QX11Info::display();
00812      e.xclient.window = QX11Info::appRootWindow();
00813      e.xclient.format = 8;
00814      strcpy( e.xclient.data.b, "kded" );
00815      XSendEvent( QX11Info::display(), QX11Info::appRootWindow(), False, SubstructureNotifyMask, &e );
00816 #endif
00817 
00818      runKonfUpdate(); // Run it once.
00819 
00820 #ifdef Q_WS_X11
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, "confupdate" );
00827      XSendEvent( QX11Info::display(), QX11Info::appRootWindow(), False, SubstructureNotifyMask, &e );
00828 #endif
00829 
00830      if (bCheckHostname)
00831         (void) new KHostnameD(HostnamePollInterval); // Watch for hostname changes
00832 
00833      QObject::connect(QDBusConnection::sessionBus().interface(),
00834                       SIGNAL(serviceOwnerChanged(QString,QString,QString)),
00835                       kded, SLOT(slotApplicationRemoved(QString,QString,QString)));
00836 
00837      // During startup kdesktop waits for KDED to finish.
00838      // Send a notifyDatabaseChanged signal even if the database hasn't
00839      // changed.
00840      // If the database changed, kbuildsycoca's signal didn't go anywhere
00841      // anyway, because it was too early, so let's send this signal
00842      // unconditionnally (David)
00843 
00844      QDBusMessage msg = QDBusMessage::createSignal("/kbuildsycoca", "org.kde.KSycoca", "notifyDatabaseChanged" );
00845      msg << QStringList();
00846      QDBusConnection::sessionBus().send(msg);
00847      int result = k.exec(); // keep running
00848 
00849      delete kded;
00850 
00851      return result;
00852 }
00853 
00854 #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
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
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