kded.cpp

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