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