• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • 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 <qdir.h>
00021 
00022 #include "kded.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 <qfile.h>
00034 #include <qtimer.h>
00035 
00036 #include <dcopclient.h>
00037 
00038 #include <kuniqueapplication.h>
00039 #include <kcmdlineargs.h>
00040 #include <kaboutdata.h>
00041 #include <klocale.h>
00042 #include <kglobal.h>
00043 #include <kprocess.h>
00044 #include <kdebug.h>
00045 #include <kdirwatch.h>
00046 #include <kstandarddirs.h>
00047 #include <kdatastream.h>
00048 #include <kio/global.h>
00049 #include <kservicetype.h>
00050 
00051 #ifdef Q_WS_X11
00052 #include <X11/Xlib.h>
00053 #include <fixx11h.h>
00054 #endif
00055 
00056 Kded *Kded::_self = 0;
00057 
00058 static bool checkStamps = true;
00059 static bool delayedCheck = false;
00060 
00061 static void runBuildSycoca(QObject *callBackObj=0, const char *callBackSlot=0)
00062 {
00063    QStringList args;
00064    args.append("--incremental");
00065    if(checkStamps)
00066       args.append("--checkstamps");
00067    if(delayedCheck)
00068       args.append("--nocheckfiles");
00069    else
00070       checkStamps = false; // useful only during kded startup
00071    if (callBackObj)
00072    {
00073       QByteArray data;
00074       QDataStream dataStream( data, IO_WriteOnly );
00075       dataStream << QString("kbuildsycoca") << args;
00076       QCString _launcher = KApplication::launcher();
00077 
00078       kapp->dcopClient()->callAsync(_launcher, _launcher, "kdeinit_exec_wait(QString,QStringList)", data, callBackObj, callBackSlot);
00079    }
00080    else
00081    {
00082       KApplication::kdeinitExecWait( "kbuildsycoca", args );
00083    }
00084 }
00085 
00086 static void runKonfUpdate()
00087 {
00088    KApplication::kdeinitExecWait( "kconf_update", QStringList(), 0, 0, "0" /*no startup notification*/ );
00089 }
00090 
00091 static void runDontChangeHostname(const QCString &oldName, const QCString &newName)
00092 {
00093    QStringList args;
00094    args.append(QFile::decodeName(oldName));
00095    args.append(QFile::decodeName(newName));
00096    KApplication::kdeinitExecWait( "kdontchangethehostname", args );
00097 }
00098 
00099 Kded::Kded(bool checkUpdates, bool new_startup)
00100   : DCOPObject("kbuildsycoca"), DCOPObjectProxy(),
00101     b_checkUpdates(checkUpdates),
00102     m_needDelayedCheck(false),
00103     m_newStartup( new_startup )
00104 {
00105   _self = this;
00106   QCString cPath;
00107   QCString ksycoca_env = getenv("KDESYCOCA");
00108   if (ksycoca_env.isEmpty())
00109      cPath = QFile::encodeName(KGlobal::dirs()->saveLocation("tmp")+"ksycoca");
00110   else
00111      cPath = ksycoca_env;
00112   m_pTimer = new QTimer(this);
00113   connect(m_pTimer, SIGNAL(timeout()), this, SLOT(recreate()));
00114 
00115   QTimer::singleShot(100, this, SLOT(installCrashHandler()));
00116 
00117   m_pDirWatch = 0;
00118 
00119   m_windowIdList.setAutoDelete(true);
00120 
00121   m_recreateCount = 0;
00122   m_recreateBusy = false;
00123 }
00124 
00125 Kded::~Kded()
00126 {
00127   _self = 0;
00128   m_pTimer->stop();
00129   delete m_pTimer;
00130   delete m_pDirWatch;
00131   // We have to delete the modules while we're still able to process incoming
00132   // DCOP messages, since modules might make DCOP calls in their destructors.
00133   QAsciiDictIterator<KDEDModule> it(m_modules);
00134   while (!it.isEmpty()) 
00135     delete it.toFirst();
00136 }
00137 
00138 bool Kded::process(const QCString &obj, const QCString &fun,
00139                    const QByteArray &data,
00140                    QCString &replyType, QByteArray &replyData)
00141 {
00142   if (obj == "ksycoca") return false; // Ignore this one.
00143 
00144   if (m_dontLoad[obj])
00145      return false;
00146 
00147   KDEDModule *module = loadModule(obj, true);
00148   if (!module)
00149      return false;
00150 
00151   module->setCallingDcopClient(kapp->dcopClient());
00152   return module->process(fun, data, replyType, replyData);
00153 }
00154 
00155 void Kded::initModules()
00156 {
00157      m_dontLoad.clear();
00158      KConfig *config = kapp->config();
00159      bool kde_running = !( getenv( "KDE_FULL_SESSION" ) == NULL || getenv( "KDE_FULL_SESSION" )[ 0 ] == '\0' );
00160     // not the same user like the one running the session (most likely we're run via sudo or something)
00161     if( getenv( "KDE_SESSION_UID" ) != NULL && uid_t( atoi( getenv( "KDE_SESSION_UID" ))) != getuid())
00162         kde_running = false;
00163      // Preload kded modules.
00164      KService::List kdedModules = KServiceType::offers("KDEDModule");
00165      for(KService::List::ConstIterator it = kdedModules.begin(); it != kdedModules.end(); ++it)
00166      {
00167          KService::Ptr service = *it;
00168          bool autoload = service->property("X-KDE-Kded-autoload", QVariant::Bool).toBool();
00169          config->setGroup(QString("Module-%1").arg(service->desktopEntryName()));
00170          autoload = config->readBoolEntry("autoload", autoload);
00171          if( m_newStartup )
00172          {
00173             // see ksmserver's README for description of the phases
00174             QVariant phasev = service->property("X-KDE-Kded-phase", QVariant::Int );
00175             int phase = phasev.isValid() ? phasev.toInt() : 2;
00176             bool prevent_autoload = false;
00177             switch( phase )
00178             {
00179                 case 0: // always autoload
00180                     break;
00181                 case 1: // autoload only in KDE
00182                     if( !kde_running )
00183                         prevent_autoload = true;
00184                     break;
00185                 case 2: // autoload delayed, only in KDE
00186                 default:
00187                     prevent_autoload = true;
00188                     break;   
00189             }
00190             if (autoload && !prevent_autoload)
00191                loadModule(service, false);
00192          }
00193          else
00194          {
00195             if (autoload && kde_running)
00196                loadModule(service, false);
00197          }
00198          bool dontLoad = false;
00199          QVariant p = service->property("X-KDE-Kded-load-on-demand", QVariant::Bool);
00200          if (p.isValid() && (p.toBool() == false))
00201             dontLoad = true;
00202          if (dontLoad)
00203             noDemandLoad(service->desktopEntryName());
00204 
00205          if (dontLoad && !autoload)
00206             unloadModule(service->desktopEntryName().latin1());
00207      }
00208 }
00209 
00210 void Kded::loadSecondPhase()
00211 {
00212      kdDebug(7020) << "Loading second phase autoload" << endl;
00213      KConfig *config = kapp->config();
00214      KService::List kdedModules = KServiceType::offers("KDEDModule");
00215      for(KService::List::ConstIterator it = kdedModules.begin(); it != kdedModules.end(); ++it)
00216      {
00217          KService::Ptr service = *it;
00218          bool autoload = service->property("X-KDE-Kded-autoload", QVariant::Bool).toBool();
00219          config->setGroup(QString("Module-%1").arg(service->desktopEntryName()));
00220          autoload = config->readBoolEntry("autoload", autoload);
00221          QVariant phasev = service->property("X-KDE-Kded-phase", QVariant::Int );
00222          int phase = phasev.isValid() ? phasev.toInt() : 2;
00223          if( phase == 2 && autoload )
00224             loadModule(service, false);
00225      }
00226 }
00227 
00228 void Kded::noDemandLoad(const QString &obj)
00229 {
00230   m_dontLoad.insert(obj.latin1(), this);
00231 }
00232 
00233 KDEDModule *Kded::loadModule(const QCString &obj, bool onDemand)
00234 {
00235   KDEDModule *module = m_modules.find(obj);
00236   if (module)
00237      return module;
00238   KService::Ptr s = KService::serviceByDesktopPath("kded/"+obj+".desktop");
00239   return loadModule(s, onDemand);
00240 }
00241 
00242 KDEDModule *Kded::loadModule(const KService *s, bool onDemand)
00243 {
00244   KDEDModule *module = 0;
00245   if (s && !s->library().isEmpty())
00246   {
00247     QCString obj = s->desktopEntryName().latin1();
00248     KDEDModule *oldModule = m_modules.find(obj);
00249     if (oldModule)
00250        return oldModule;
00251 
00252     if (onDemand)
00253     {
00254       QVariant p = s->property("X-KDE-Kded-load-on-demand", QVariant::Bool);
00255       if (p.isValid() && (p.toBool() == false))
00256       {
00257          noDemandLoad(s->desktopEntryName());
00258          return 0;
00259       }
00260     }
00261     // get the library loader instance
00262 
00263     KLibLoader *loader = KLibLoader::self();
00264 
00265     QVariant v = s->property("X-KDE-FactoryName", QVariant::String);
00266     QString factory = v.isValid() ? v.toString() : QString::null;
00267     if (factory.isEmpty())
00268     {
00269        // Stay bugward compatible
00270        v = s->property("X-KDE-Factory", QVariant::String);
00271        factory = v.isValid() ? v.toString() : QString::null;
00272     }
00273     if (factory.isEmpty())
00274       factory = s->library();
00275 
00276     factory = "create_" + factory;
00277     QString libname = "kded_"+s->library();
00278 
00279     KLibrary *lib = loader->library(QFile::encodeName(libname));
00280     if (!lib)
00281     {
00282       kdWarning() << k_funcinfo << "Could not load library. [ "
00283           << loader->lastErrorMessage() << " ]" << endl;
00284       libname.prepend("lib");
00285       lib = loader->library(QFile::encodeName(libname));
00286     }
00287     if (lib)
00288     {
00289       // get the create_ function
00290       void *create = lib->symbol(QFile::encodeName(factory));
00291 
00292       if (create)
00293       {
00294         // create the module
00295         KDEDModule* (*func)(const QCString &);
00296         func = (KDEDModule* (*)(const QCString &)) create;
00297         module = func(obj);
00298         if (module)
00299         {
00300           m_modules.insert(obj, module);
00301           m_libs.insert(obj, lib);
00302           connect(module, SIGNAL(moduleDeleted(KDEDModule *)), SLOT(slotKDEDModuleRemoved(KDEDModule *)));
00303           kdDebug(7020) << "Successfully loaded module '" << obj << "'\n";
00304           return module;
00305         }
00306       }
00307       loader->unloadLibrary(QFile::encodeName(libname));
00308     }
00309     else
00310     {
00311     kdWarning() << k_funcinfo << "Could not load library. [ "
00312             << loader->lastErrorMessage() << " ]" << endl;
00313     }
00314     kdDebug(7020) << "Could not load module '" << obj << "'\n";
00315   }
00316   return 0;
00317 }
00318 
00319 bool Kded::unloadModule(const QCString &obj)
00320 {
00321   KDEDModule *module = m_modules.take(obj);
00322   if (!module)
00323      return false;
00324   kdDebug(7020) << "Unloading module '" << obj << "'\n";
00325   delete module;
00326   return true;
00327 }
00328 
00329 // DCOP
00330 QCStringList Kded::loadedModules()
00331 {
00332     QCStringList modules;
00333     QAsciiDictIterator<KDEDModule> it( m_modules );
00334     for ( ; it.current(); ++it)
00335         modules.append( it.currentKey() );
00336 
00337     return modules;
00338 }
00339 
00340 QCStringList Kded::functions()
00341 {
00342     QCStringList res = DCOPObject::functions();
00343     res += "ASYNC recreate()";
00344     return res;
00345 }
00346 
00347 void Kded::slotKDEDModuleRemoved(KDEDModule *module)
00348 {
00349   m_modules.remove(module->objId());
00350   KLibrary *lib = m_libs.take(module->objId());
00351   if (lib)
00352      lib->unload();
00353 }
00354 
00355 void Kded::slotApplicationRemoved(const QCString &appId)
00356 {
00357   for(QAsciiDictIterator<KDEDModule> it(m_modules); it.current(); ++it)
00358   {
00359      it.current()->removeAll(appId);
00360   }
00361 
00362   QValueList<long> *windowIds = m_windowIdList.find(appId);
00363   if (windowIds)
00364   {
00365      for( QValueList<long>::ConstIterator it = windowIds->begin();
00366           it != windowIds->end(); ++it)
00367      {
00368         long windowId = *it;
00369         m_globalWindowIdList.remove(windowId);
00370         for(QAsciiDictIterator<KDEDModule> it(m_modules); it.current(); ++it)
00371         {
00372             emit it.current()->windowUnregistered(windowId);
00373         }
00374      }
00375      m_windowIdList.remove(appId);
00376   }
00377 }
00378 
00379 void Kded::updateDirWatch()
00380 {
00381   if (!b_checkUpdates) return;
00382 
00383   delete m_pDirWatch;
00384   m_pDirWatch = new KDirWatch;
00385 
00386   QObject::connect( m_pDirWatch, SIGNAL(dirty(const QString&)),
00387            this, SLOT(update(const QString&)));
00388   QObject::connect( m_pDirWatch, SIGNAL(created(const QString&)),
00389            this, SLOT(update(const QString&)));
00390   QObject::connect( m_pDirWatch, SIGNAL(deleted(const QString&)),
00391            this, SLOT(dirDeleted(const QString&)));
00392 
00393   // For each resource
00394   for( QStringList::ConstIterator it = m_allResourceDirs.begin();
00395        it != m_allResourceDirs.end();
00396        ++it )
00397   {
00398      readDirectory( *it );
00399   }
00400 }
00401 
00402 void Kded::updateResourceList()
00403 {
00404   delete KSycoca::self();
00405 
00406   if (!b_checkUpdates) return;
00407 
00408   if (delayedCheck) return;
00409 
00410   QStringList dirs = KSycoca::self()->allResourceDirs();
00411   // For each resource
00412   for( QStringList::ConstIterator it = dirs.begin();
00413        it != dirs.end();
00414        ++it )
00415   {
00416      if (m_allResourceDirs.find(*it) == m_allResourceDirs.end())
00417      {
00418         m_allResourceDirs.append(*it);
00419         readDirectory(*it);
00420      }
00421   }
00422 }
00423 
00424 void Kded::crashHandler(int)
00425 {
00426    DCOPClient::emergencyClose();
00427    if (_self) // Don't restart if we were closing down
00428       system("kded");
00429 qWarning("Last DCOP call before KDED crash was from application '%s'\n"
00430          "to object '%s', function '%s'.",
00431          DCOPClient::postMortemSender(),
00432          DCOPClient::postMortemObject(),
00433          DCOPClient::postMortemFunction());
00434 }
00435 
00436 void Kded::installCrashHandler()
00437 {
00438    KCrash::setEmergencySaveFunction(crashHandler);
00439 }
00440 
00441 void Kded::recreate()
00442 {
00443    recreate(false);
00444 }
00445 
00446 void Kded::runDelayedCheck()
00447 {
00448    if( m_needDelayedCheck )
00449       recreate(false);
00450    m_needDelayedCheck = false;
00451 }
00452 
00453 void Kded::recreate(bool initial)
00454 {
00455    m_recreateBusy = true;
00456    // Using KLauncher here is difficult since we might not have a
00457    // database
00458 
00459    if (!initial)
00460    {
00461       updateDirWatch(); // Update tree first, to be sure to miss nothing.
00462       runBuildSycoca(this, SLOT(recreateDone()));
00463    }
00464    else
00465    {
00466       if(!delayedCheck)
00467          updateDirWatch(); // this would search all the directories
00468       runBuildSycoca();
00469       recreateDone();
00470       if(delayedCheck)
00471       {
00472          // do a proper ksycoca check after a delay
00473          QTimer::singleShot( 60000, this, SLOT( runDelayedCheck()));
00474          m_needDelayedCheck = true;
00475          delayedCheck = false;
00476       }
00477       else
00478          m_needDelayedCheck = false;
00479    }
00480 }
00481 
00482 void Kded::recreateDone()
00483 {
00484    updateResourceList();
00485 
00486    for(; m_recreateCount; m_recreateCount--)
00487    {
00488       QCString replyType = "void";
00489       QByteArray replyData;
00490       DCOPClientTransaction *transaction = m_recreateRequests.first();
00491       if (transaction)
00492          kapp->dcopClient()->endTransaction(transaction, replyType, replyData);
00493       m_recreateRequests.remove(m_recreateRequests.begin());
00494    }
00495    m_recreateBusy = false;
00496 
00497    // Did a new request come in while building?
00498    if (!m_recreateRequests.isEmpty())
00499    {
00500       m_pTimer->start(2000, true /* single shot */ );
00501       m_recreateCount = m_recreateRequests.count();
00502    }
00503 }
00504 
00505 void Kded::dirDeleted(const QString& path)
00506 {
00507   update(path);
00508 }
00509 
00510 void Kded::update(const QString& )
00511 {
00512   if (!m_recreateBusy)
00513   {
00514     m_pTimer->start( 2000, true /* single shot */ );
00515   }
00516   else
00517   {
00518     m_recreateRequests.append(0);
00519   }
00520 }
00521 
00522 bool Kded::process(const QCString &fun, const QByteArray &data,
00523                            QCString &replyType, QByteArray &replyData)
00524 {
00525   if (fun == "recreate()") {
00526     if (!m_recreateBusy)
00527     {
00528        if (m_recreateRequests.isEmpty())
00529        {
00530           m_pTimer->start(0, true /* single shot */ );
00531           m_recreateCount = 0;
00532        }
00533        m_recreateCount++;
00534     }
00535     m_recreateRequests.append(kapp->dcopClient()->beginTransaction());
00536     replyType = "void";
00537     return true;
00538   } else {
00539     return DCOPObject::process(fun, data, replyType, replyData);
00540   }
00541 }
00542 
00543 
00544 void Kded::readDirectory( const QString& _path )
00545 {
00546   QString path( _path );
00547   if ( path.right(1) != "/" )
00548     path += "/";
00549 
00550   if ( m_pDirWatch->contains( path ) ) // Already seen this one?
00551      return;
00552 
00553   QDir d( _path, QString::null, QDir::Unsorted, QDir::Readable | QDir::Executable | QDir::Dirs | QDir::Hidden );
00554   // set QDir ...
00555 
00556 
00557   //************************************************************************
00558   //                           Setting dirs
00559   //************************************************************************
00560 
00561   m_pDirWatch->addDir(path);          // add watch on this dir
00562 
00563   if ( !d.exists() )                            // exists&isdir?
00564   {
00565     kdDebug(7020) << QString("Does not exist! (%1)").arg(_path) << endl;
00566     return;                             // return false
00567   }
00568 
00569   // Note: If some directory is gone, dirwatch will delete it from the list.
00570 
00571   //************************************************************************
00572   //                               Reading
00573   //************************************************************************
00574   QString file;
00575   unsigned int i;                           // counter and string length.
00576   unsigned int count = d.count();
00577   for( i = 0; i < count; i++ )                        // check all entries
00578   {
00579      if (d[i] == "." || d[i] == ".." || d[i] == "magic")
00580        continue;                          // discard those ".", "..", "magic"...
00581 
00582      file = path;                           // set full path
00583      file += d[i];                          // and add the file name.
00584 
00585      readDirectory( file );      // yes, dive into it.
00586   }
00587 }
00588 
00589 bool Kded::isWindowRegistered(long windowId)
00590 {
00591   return m_globalWindowIdList.find(windowId) != 0;
00592 
00593 }
00594 
00595 // DCOP
00596 void Kded::registerWindowId(long windowId)
00597 {
00598   m_globalWindowIdList.replace(windowId, &windowId);
00599   QCString sender = callingDcopClient()->senderId();
00600   if( sender.isEmpty()) // local call
00601       sender = callingDcopClient()->appId();
00602   QValueList<long> *windowIds = m_windowIdList.find(sender);
00603   if (!windowIds)
00604   {
00605     windowIds = new QValueList<long>;
00606     m_windowIdList.insert(sender, windowIds);
00607   }
00608   windowIds->append(windowId);
00609 
00610 
00611   for(QAsciiDictIterator<KDEDModule> it(m_modules); it.current(); ++it)
00612   {
00613      emit it.current()->windowRegistered(windowId);
00614   }
00615 }
00616 
00617 // DCOP
00618 void Kded::unregisterWindowId(long windowId)
00619 {
00620   m_globalWindowIdList.remove(windowId);
00621   QCString sender = callingDcopClient()->senderId();
00622   if( sender.isEmpty()) // local call
00623       sender = callingDcopClient()->appId();
00624   QValueList<long> *windowIds = m_windowIdList.find(sender);
00625   if (windowIds)
00626   {
00627      windowIds->remove(windowId);
00628      if (windowIds->isEmpty())
00629         m_windowIdList.remove(sender);
00630   }
00631 
00632   for(QAsciiDictIterator<KDEDModule> it(m_modules); it.current(); ++it)
00633   {
00634     emit it.current()->windowUnregistered(windowId);
00635   }
00636 }
00637 
00638 
00639 static void sighandler(int /*sig*/)
00640 {
00641     if (kapp)
00642        kapp->quit();
00643 }
00644 
00645 KUpdateD::KUpdateD()
00646 {
00647     m_pDirWatch = new KDirWatch;
00648     m_pTimer = new QTimer;
00649     connect(m_pTimer, SIGNAL(timeout()), this, SLOT(runKonfUpdate()));
00650     QObject::connect( m_pDirWatch, SIGNAL(dirty(const QString&)),
00651            this, SLOT(slotNewUpdateFile()));
00652 
00653     QStringList dirs = KGlobal::dirs()->findDirs("data", "kconf_update");
00654     for( QStringList::ConstIterator it = dirs.begin();
00655          it != dirs.end();
00656          ++it )
00657     {
00658        QString path = *it;
00659        if (path[path.length()-1] != '/')
00660           path += "/";
00661 
00662        if (!m_pDirWatch->contains(path))
00663           m_pDirWatch->addDir(path);
00664     }
00665 }
00666 
00667 KUpdateD::~KUpdateD()
00668 {
00669     delete m_pDirWatch;
00670     delete m_pTimer;
00671 }
00672 
00673 void KUpdateD::runKonfUpdate()
00674 {
00675     ::runKonfUpdate();
00676 }
00677 
00678 void KUpdateD::slotNewUpdateFile()
00679 {
00680     m_pTimer->start( 500, true /* single shot */ );
00681 }
00682 
00683 KHostnameD::KHostnameD(int pollInterval)
00684 {
00685     m_Timer.start(pollInterval, false /* repetitive */ );
00686     connect(&m_Timer, SIGNAL(timeout()), this, SLOT(checkHostname()));
00687     checkHostname();
00688 }
00689 
00690 KHostnameD::~KHostnameD()
00691 {
00692     // Empty
00693 }
00694 
00695 void KHostnameD::checkHostname()
00696 {
00697     char buf[1024+1];
00698     if (gethostname(buf, 1024) != 0)
00699        return;
00700     buf[sizeof(buf)-1] = '\0';
00701 
00702     if (m_hostname.isEmpty())
00703     {
00704        m_hostname = buf;
00705        return;
00706     }
00707 
00708     if (m_hostname == buf)
00709        return;
00710 
00711     QCString newHostname = buf;
00712 
00713     runDontChangeHostname(m_hostname, newHostname);
00714     m_hostname = newHostname;
00715 }
00716 
00717 
00718 static KCmdLineOptions options[] =
00719 {
00720   { "check", I18N_NOOP("Check Sycoca database only once"), 0 },
00721   { "new-startup", "Internal", 0 },
00722   KCmdLineLastOption
00723 };
00724 
00725 class KDEDQtDCOPObject : public DCOPObject
00726 {
00727 public:
00728   KDEDQtDCOPObject() : DCOPObject("qt/kded") { }
00729 
00730   virtual bool process(const QCString &fun, const QByteArray &data,
00731                        QCString& replyType, QByteArray &replyData)
00732     {
00733       if ( kapp && (fun == "quit()") )
00734       {
00735         kapp->quit();
00736         replyType = "void";
00737         return true;
00738       }
00739       return DCOPObject::process(fun, data, replyType, replyData);
00740     }
00741 
00742   QCStringList functions()
00743     {
00744        QCStringList res = DCOPObject::functions();
00745        res += "void quit()";
00746        return res;
00747     }
00748 };
00749 
00750 class KDEDApplication : public KUniqueApplication
00751 {
00752 public:
00753   KDEDApplication() : KUniqueApplication( )
00754     {
00755        startup = true;
00756        dcopClient()->connectDCOPSignal( "DCOPServer", "", "terminateKDE()",
00757                                         objId(), "quit()", false );
00758     }
00759 
00760   int newInstance()
00761     {
00762        if (startup) {
00763           startup = false;
00764           if( Kded::self()->newStartup())
00765              Kded::self()->initModules();
00766           else
00767          QTimer::singleShot(500, Kded::self(), SLOT(initModules()));
00768        } else 
00769           runBuildSycoca();
00770 
00771        return 0;
00772     }
00773 
00774   QCStringList functions()
00775     {
00776        QCStringList res = KUniqueApplication::functions();
00777        res += "bool loadModule(QCString)";
00778        res += "bool unloadModule(QCString)";
00779        res += "void registerWindowId(long int)";
00780        res += "void unregisterWindowId(long int)";
00781        res += "QCStringList loadedModules()";
00782        res += "void reconfigure()";
00783        res += "void loadSecondPhase()";
00784        res += "void quit()";
00785        return res;
00786     }
00787 
00788   bool process(const QCString &fun, const QByteArray &data,
00789                QCString &replyType, QByteArray &replyData)
00790   {
00791     if (fun == "loadModule(QCString)") {
00792       QCString module;
00793       QDataStream arg( data, IO_ReadOnly );
00794       arg >> module;
00795       bool result = (Kded::self()->loadModule(module, false) != 0);
00796       replyType = "bool";
00797       QDataStream _replyStream( replyData, IO_WriteOnly );
00798       _replyStream << result;
00799       return true;
00800     }
00801     else if (fun == "unloadModule(QCString)") {
00802       QCString module;
00803       QDataStream arg( data, IO_ReadOnly );
00804       arg >> module;
00805       bool result = Kded::self()->unloadModule(module);
00806       replyType = "bool";
00807       QDataStream _replyStream( replyData, IO_WriteOnly );
00808       _replyStream << result;
00809       return true;
00810     }
00811     else if (fun == "registerWindowId(long int)") {
00812       long windowId;
00813       QDataStream arg( data, IO_ReadOnly );
00814       arg >> windowId;
00815       Kded::self()->setCallingDcopClient(callingDcopClient());
00816       Kded::self()->registerWindowId(windowId);
00817       replyType = "void";
00818       return true;
00819     }
00820      else if (fun == "unregisterWindowId(long int)") {
00821       long windowId;
00822       QDataStream arg( data, IO_ReadOnly );
00823       arg >> windowId;
00824       Kded::self()->setCallingDcopClient(callingDcopClient());
00825       Kded::self()->unregisterWindowId(windowId);
00826       replyType = "void";
00827       return true;
00828     }
00829     else if (fun == "loadedModules()") {
00830       replyType = "QCStringList";
00831       QDataStream _replyStream(replyData, IO_WriteOnly);
00832       _replyStream << Kded::self()->loadedModules();
00833       return true;
00834     }
00835     else if (fun == "reconfigure()") {
00836       config()->reparseConfiguration();
00837       Kded::self()->initModules();
00838       replyType = "void";
00839       return true;
00840     }
00841     else if (fun == "loadSecondPhase()") {
00842       Kded::self()->loadSecondPhase();
00843       replyType = "void";
00844       return true;
00845     }
00846     else if (fun == "quit()") {
00847       quit();
00848       replyType = "void";
00849       return true;
00850     }
00851     return KUniqueApplication::process(fun, data, replyType, replyData);
00852   }
00853 
00854   bool startup;
00855   KDEDQtDCOPObject kdedQtDcopObject;
00856 };
00857 
00858 extern "C" KDE_EXPORT int kdemain(int argc, char *argv[])
00859 {
00860      KAboutData aboutData( "kded", I18N_NOOP("KDE Daemon"),
00861         "$Id: kded.cpp 711061 2007-09-11 09:42:51Z tpatzig $",
00862         I18N_NOOP("KDE Daemon - triggers Sycoca database updates when needed"));
00863 
00864      KApplication::installSigpipeHandler();
00865 
00866      KCmdLineArgs::init(argc, argv, &aboutData);
00867 
00868      KUniqueApplication::addCmdLineOptions();
00869 
00870      KCmdLineArgs::addCmdLineOptions( options );
00871 
00872      // this program is in kdelibs so it uses kdelibs as catalog
00873      KLocale::setMainCatalogue("kdelibs");
00874 
00875      // WABA: Make sure not to enable session management.
00876      putenv(strdup("SESSION_MANAGER="));
00877 
00878      // Parse command line before checking DCOP
00879      KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
00880 
00881      // Check DCOP communication.
00882      {
00883         DCOPClient testDCOP;
00884         QCString dcopName = testDCOP.registerAs("kded", false);
00885         if (dcopName.isEmpty())
00886         {
00887            kdFatal() << "DCOP communication problem!" << endl;
00888            return 1;
00889         }
00890      }
00891 
00892      KInstance *instance = new KInstance(&aboutData);
00893      KConfig *config = instance->config(); // Enable translations.
00894 
00895      if (args->isSet("check"))
00896      {
00897         config->setGroup("General");
00898         checkStamps = config->readBoolEntry("CheckFileStamps", true);
00899         runBuildSycoca();
00900         runKonfUpdate();
00901         exit(0);
00902      }
00903 
00904      if (!KUniqueApplication::start())
00905      {
00906         fprintf(stderr, "KDE Daemon (kded) already running.\n");
00907         exit(0);
00908      }
00909 
00910      KUniqueApplication::dcopClient()->setQtBridgeEnabled(false);
00911 
00912      config->setGroup("General");
00913      int HostnamePollInterval = config->readNumEntry("HostnamePollInterval", 5000);
00914      bool bCheckSycoca = config->readBoolEntry("CheckSycoca", true);
00915      bool bCheckUpdates = config->readBoolEntry("CheckUpdates", true);
00916      bool bCheckHostname = config->readBoolEntry("CheckHostname", true);
00917      checkStamps = config->readBoolEntry("CheckFileStamps", true);
00918      delayedCheck = config->readBoolEntry("DelayedCheck", false);
00919 
00920      Kded *kded = new Kded(bCheckSycoca, args->isSet("new-startup")); // Build data base
00921 
00922      signal(SIGTERM, sighandler);
00923      signal(SIGHUP, sighandler);
00924      KDEDApplication k;
00925 
00926      kded->recreate(true); // initial
00927 
00928      if (bCheckUpdates)
00929         (void) new KUpdateD; // Watch for updates
00930 
00931      runKonfUpdate(); // Run it once.
00932 
00933      if (bCheckHostname)
00934         (void) new KHostnameD(HostnamePollInterval); // Watch for hostname changes
00935 
00936      DCOPClient *client = kapp->dcopClient();
00937      QObject::connect(client, SIGNAL(applicationRemoved(const QCString&)),
00938              kded, SLOT(slotApplicationRemoved(const QCString&)));
00939      client->setNotifications(true);
00940      client->setDaemonMode( true );
00941 
00942      // During startup kdesktop waits for KDED to finish.
00943      // Send a notifyDatabaseChanged signal even if the database hasn't
00944      // changed.
00945      // If the database changed, kbuildsycoca's signal didn't go anywhere
00946      // anyway, because it was too early, so let's send this signal
00947      // unconditionnally (David)
00948      QByteArray data;
00949      client->send( "*", "ksycoca", "notifyDatabaseChanged()", data );
00950      client->send( "ksplash", "", "upAndRunning(QString)",  QString("kded"));
00951 #ifdef Q_WS_X11
00952      XEvent e;
00953      e.xclient.type = ClientMessage;
00954      e.xclient.message_type = XInternAtom( qt_xdisplay(), "_KDE_SPLASH_PROGRESS", False );
00955      e.xclient.display = qt_xdisplay();
00956      e.xclient.window = qt_xrootwin();
00957      e.xclient.format = 8;
00958      strcpy( e.xclient.data.b, "kded" );
00959      XSendEvent( qt_xdisplay(), qt_xrootwin(), False, SubstructureNotifyMask, &e );
00960 #endif
00961      int result = k.exec(); // keep running
00962 
00963      delete kded;
00964      delete instance; // Deletes config as well
00965 
00966      return result;
00967 }
00968 
00969 #include "kded.moc"

KDED

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

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
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