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