main.cpp

00001 /*
00002   Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
00003   Copyright (c) 2000 Matthias Elter <elter@kde.org>
00004   Copyright (c) 2004 Frans Englich <frans.englich@telia.com>
00005 
00006   This program is free software; you can redistribute it and/or modify
00007   it under the terms of the GNU General Public License as published by
00008   the Free Software Foundation; either version 2 of the License, or
00009   (at your option) any later version.
00010 
00011   This program is distributed in the hope that it will be useful,
00012   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014   GNU General Public License for more details.
00015 
00016   You should have received a copy of the GNU General Public License
00017   along with this program; if not, write to the Free Software
00018   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019 
00020 */
00021 
00022 #include <iostream>
00023 
00024 #include <qcstring.h>
00025 #include <qfile.h> 
00026 
00027 #include <dcopclient.h>
00028 #include <qxembed.h>
00029 
00030 #include <kaboutdata.h>
00031 #include <kapplication.h>
00032 #include <kcmdlineargs.h>
00033 #include <kcmoduleinfo.h>
00034 #include <kcmoduleloader.h>
00035 #include <kcmoduleproxy.h>
00036 #include <kcmultidialog.h>
00037 #include <kdebug.h>
00038 #include <kdialogbase.h>
00039 #include <kiconloader.h>
00040 #include <klocale.h>
00041 #include <kservice.h>
00042 #include <kservicegroup.h>
00043 #include <kstartupinfo.h>
00044 #include <kwin.h>
00045 #include <kglobal.h>
00046 
00047 #include "main.h"
00048 #include "main.moc"
00049 
00050 using namespace std;
00051 
00052 KService::List m_modules;
00053 
00054 static KCmdLineOptions options[] =
00055 {
00056     { "list", I18N_NOOP("List all possible modules"), 0},
00057     { "+module", I18N_NOOP("Configuration module to open"), 0 },
00058     { "lang <language>", I18N_NOOP("Specify a particular language"), 0 },
00059     { "embed <id>", I18N_NOOP("Embeds the module with buttons in window with id <id>"), 0 },
00060     { "embed-proxy <id>", I18N_NOOP("Embeds the module without buttons in window with id <id>"), 0 },
00061     { "silent", I18N_NOOP("Do not display main window"), 0 },
00062     KCmdLineLastOption
00063 };
00064 
00065 static void listModules(const QString &baseGroup)
00066 {
00067 
00068   KServiceGroup::Ptr group = KServiceGroup::group(baseGroup);
00069 
00070   if (!group || !group->isValid())
00071       return;
00072 
00073   KServiceGroup::List list = group->entries(true, true);
00074 
00075   for( KServiceGroup::List::ConstIterator it = list.begin();
00076        it != list.end(); it++)
00077   {
00078      KSycocaEntry *p = (*it);
00079      if (p->isType(KST_KService))
00080      {
00081         KService *s = static_cast<KService*>(p);
00082         if (!kapp->authorizeControlModule(s->menuId()))
00083            continue;
00084         m_modules.append(s);
00085      }
00086      else if (p->isType(KST_KServiceGroup))
00087         listModules(p->entryPath());
00088   }
00089 }
00090 
00091 static KService::Ptr locateModule(const QCString& module)
00092 {
00093     QString path = QFile::decodeName(module);
00094 
00095     if (!path.endsWith(".desktop"))
00096         path += ".desktop";
00097 
00098     KService::Ptr service = KService::serviceByStorageId( path );
00099     if (!service)
00100     {
00101         kdWarning(780) << "Could not find module '" << module << "'." << endl;
00102         return 0;
00103     }
00104 
00105     if(!KCModuleLoader::testModule( module ))
00106     {
00107         kdDebug(780) << "According to \"" << module << "\"'s test function, it should Not be loaded." << endl;
00108         return 0;
00109     }
00110 
00111     return service;
00112 }
00113 
00114 bool KCMShell::isRunning()
00115 {
00116     if( dcopClient()->appId() == m_dcopName )
00117         return false; // We are the one and only.
00118 
00119     kdDebug(780) << "kcmshell with modules '" << 
00120         m_dcopName << "' is already running." << endl;
00121 
00122     dcopClient()->attach(); // Reregister as anonymous
00123     dcopClient()->setNotifications(true);
00124 
00125     QByteArray data;
00126     QDataStream str( data, IO_WriteOnly );
00127     str << kapp->startupId();
00128     QCString replyType;
00129     QByteArray replyData;
00130     if (!dcopClient()->call(m_dcopName, "dialog", "activate(QCString)", 
00131                 data, replyType, replyData))
00132     {
00133         kdDebug(780) << "Calling DCOP function dialog::activate() failed." << endl;
00134         return false; // Error, we have to do it ourselves.
00135     }
00136 
00137     return true;
00138 }
00139 
00140 KCMShellMultiDialog::KCMShellMultiDialog( int dialogFace, const QString& caption,
00141         QWidget *parent, const char *name, bool modal)
00142     : KCMultiDialog( dialogFace, caption, parent, name, modal ),
00143         DCOPObject("dialog")
00144 {
00145 }
00146 
00147 void KCMShellMultiDialog::activate( QCString asn_id )
00148 {
00149     kdDebug(780) << k_funcinfo << endl;
00150 
00151     KStartupInfo::setNewStartupId( this, asn_id );
00152 }
00153 
00154 void KCMShell::setDCOPName(const QCString &dcopName, bool rootMode )
00155 {
00156     m_dcopName = "kcmshell_";
00157     if( rootMode )
00158         m_dcopName += "rootMode_";
00159 
00160     m_dcopName += dcopName;
00161     
00162     dcopClient()->registerAs(m_dcopName, false);
00163 }
00164 
00165 void KCMShell::waitForExit()
00166 {
00167     kdDebug(780) << k_funcinfo << endl;
00168 
00169     connect(dcopClient(), SIGNAL(applicationRemoved(const QCString&)),
00170             SLOT( appExit(const QCString&) ));
00171     exec();
00172 }
00173 
00174 void KCMShell::appExit(const QCString &appId)
00175 {
00176     kdDebug(780) << k_funcinfo << endl;
00177 
00178     if( appId == m_dcopName )
00179     {
00180         kdDebug(780) << "'" << appId << "' closed, dereferencing." << endl;
00181         deref();
00182     }
00183 }
00184 
00185 static void setIcon(QWidget *w, const QString &iconName)
00186 {
00187     QPixmap icon = DesktopIcon(iconName);
00188     QPixmap miniIcon = SmallIcon(iconName);
00189     w->setIcon( icon ); //standard X11
00190 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00191     KWin::setIcons(w->winId(), icon, miniIcon );
00192 #endif
00193 }
00194 
00195 extern "C" KDE_EXPORT int kdemain(int _argc, char *_argv[])
00196 {
00197     KAboutData aboutData( "kcmshell", I18N_NOOP("KDE Control Module"),
00198                           0,
00199                           I18N_NOOP("A tool to start single KDE control modules"),
00200                           KAboutData::License_GPL,
00201                           I18N_NOOP("(c) 1999-2004, The KDE Developers") );
00202 
00203     aboutData.addAuthor("Frans Englich", I18N_NOOP("Maintainer"), "frans.englich@kde.org");
00204     aboutData.addAuthor("Daniel Molkentin", 0, "molkentin@kde.org");
00205     aboutData.addAuthor("Matthias Hoelzer-Kluepfel",0, "hoelzer@kde.org");
00206     aboutData.addAuthor("Matthias Elter",0, "elter@kde.org");
00207     aboutData.addAuthor("Matthias Ettrich",0, "ettrich@kde.org");
00208     aboutData.addAuthor("Waldo Bastian",0, "bastian@kde.org");
00209     
00210     KGlobal::locale()->setMainCatalogue("kcmshell");
00211 
00212     KCmdLineArgs::init(_argc, _argv, &aboutData);
00213     KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
00214     KCMShell app;
00215 
00216     const KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
00217 
00218     const QCString lang = args->getOption("lang");
00219     if( !lang.isNull() )
00220         KGlobal::locale()->setLanguage(lang);
00221 
00222     if (args->isSet("list"))
00223     {
00224         cout << i18n("The following modules are available:").local8Bit() << endl;
00225 
00226         listModules( "Settings/" );
00227 
00228         int maxLen=0;
00229 
00230         for( KService::List::ConstIterator it = m_modules.begin(); it != m_modules.end(); ++it)
00231         {
00232             int len = (*it)->desktopEntryName().length();
00233             if (len > maxLen)
00234                 maxLen = len;
00235         }
00236 
00237         for( KService::List::ConstIterator it = m_modules.begin(); it != m_modules.end(); ++it)
00238         {
00239             QString entry("%1 - %2");
00240 
00241             entry = entry.arg((*it)->desktopEntryName().leftJustify(maxLen, ' '))
00242                          .arg(!(*it)->comment().isEmpty() ? (*it)->comment() 
00243                                  : i18n("No description available"));
00244 
00245             cout << entry.local8Bit() << endl;
00246         }
00247         return 0;
00248     }
00249 
00250     if (args->count() < 1)
00251     {
00252         args->usage();
00253         return -1;
00254     }
00255 
00256     QCString dcopName;
00257     KService::List modules;
00258     for (int i = 0; i < args->count(); i++)
00259     {
00260         KService::Ptr service = locateModule(args->arg(i));
00261         if( service )
00262         {
00263             modules.append(service);
00264             if( !dcopName.isEmpty() )
00265                 dcopName += "_";
00266 
00267             dcopName += args->arg(i);
00268         }
00269     }
00270 
00271     /* Check if this particular module combination is already running, but 
00272      * allow the same module to run when embedding(root mode) */
00273     app.setDCOPName(dcopName, 
00274             ( args->isSet( "embed-proxy" ) || args->isSet( "embed" )));
00275     if( app.isRunning() )
00276     {
00277         app.waitForExit();
00278         return 0;
00279     }
00280 
00281     KDialogBase::DialogType dtype = KDialogBase::Plain;
00282 
00283     if ( modules.count() < 1 )
00284         return 0;
00285     else if( modules.count() > 1 )
00286         dtype = KDialogBase::IconList;
00287 
00288     bool idValid;
00289     int id;
00290 
00291     if ( args->isSet( "embed-proxy" ))
00292     {
00293         id = args->getOption( "embed-proxy" ).toInt(&idValid);    
00294         if( idValid )
00295         {
00296             KCModuleProxy *module = new KCModuleProxy( modules.first()->desktopEntryName() );
00297             module->realModule();
00298             QXEmbed::embedClientIntoWindow( module, id);
00299             app.exec();
00300             delete module;
00301         }
00302         else
00303             kdDebug(780) << "Supplied id '" << id << "' is not valid." << endl;
00304 
00305         return 0;
00306 
00307     }
00308 
00309     KCMShellMultiDialog *dlg = new KCMShellMultiDialog( dtype, 
00310             i18n("Configure - %1").arg(kapp->caption()), 0, "", true );
00311 
00312     for (KService::List::ConstIterator it = modules.begin(); it != modules.end(); ++it)
00313         dlg->addModule(KCModuleInfo(*it));
00314 
00315     if ( args->isSet( "embed" ))
00316     {
00317         id = args->getOption( "embed" ).toInt(&idValid);    
00318         if( idValid )
00319         {
00320             QXEmbed::embedClientIntoWindow( dlg, id );
00321             dlg->exec();
00322             delete dlg;
00323         }
00324         else
00325             kdDebug(780) << "Supplied id '" << id << "' is not valid." << endl;
00326 
00327     }
00328     else
00329     {
00330 
00331         if (kapp->iconName() != kapp->name())
00332             setIcon(dlg, kapp->iconName());
00333         else if ( modules.count() == 1 )
00334             setIcon(dlg, KCModuleInfo( modules.first()).icon());
00335 
00336         dlg->exec();
00337         delete dlg;
00338     }
00339 
00340     return 0;
00341 }
00342 // vim: sw=4 et sts=4
KDE Home | KDE Accessibility Home | Description of Access Keys