00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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;
00123
00124 kdDebug(780) << "kcmshell with modules '" <<
00125 m_dcopName << "' is already running." << endl;
00126
00127 dcopClient()->attach();
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;
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 );
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 );
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
00280
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