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