diff options
Diffstat (limited to 'kcmshell')
-rw-r--r-- | kcmshell/Makefile.am | 39 | ||||
-rw-r--r-- | kcmshell/main.cpp | 346 | ||||
-rw-r--r-- | kcmshell/main.h | 104 |
3 files changed, 489 insertions, 0 deletions
diff --git a/kcmshell/Makefile.am b/kcmshell/Makefile.am new file mode 100644 index 000000000..81b3e2c8e --- /dev/null +++ b/kcmshell/Makefile.am @@ -0,0 +1,39 @@ +# +# Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org> +# Copyright (c) 2000 Matthias Elter <elter@kde.org> +# Copyright (c) 2004 Frans Englich <frans.englich@telia.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +AM_CPPFLAGS = -I$(top_srcdir)/kutils $(all_includes) +METASOURCES = AUTO + +lib_LTLIBRARIES = +bin_PROGRAMS = +kdeinit_LTLIBRARIES = kcmshell.la + +kcmshell_la_SOURCES = main.cpp main.skel +kcmshell_la_LIBADD = ../kutils/libkutils.la +kcmshell_la_LDFLAGS = $(all_libraries) -module -avoid-version + +noinst_HEADERS = main.h + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kcmshell.pot + + +include $(top_srcdir)/admin/Doxyfile.am + diff --git a/kcmshell/main.cpp b/kcmshell/main.cpp new file mode 100644 index 000000000..e1b03d1e7 --- /dev/null +++ b/kcmshell/main.cpp @@ -0,0 +1,346 @@ +/* + Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org> + Copyright (c) 2000 Matthias Elter <elter@kde.org> + Copyright (c) 2004 Frans Englich <frans.englich@telia.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include <iostream> + +#include <qcstring.h> +#include <qfile.h> + +#include <dcopclient.h> +#include <qxembed.h> + +#include <kaboutdata.h> +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <kcmoduleinfo.h> +#include <kcmoduleloader.h> +#include <kcmoduleproxy.h> +#include <kcmultidialog.h> +#include <kdebug.h> +#include <kdialogbase.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kservice.h> +#include <kservicegroup.h> +#include <kstartupinfo.h> +#include <kwin.h> +#include <kglobal.h> + +#include "main.h" +#include "main.moc" + +using namespace std; + +KService::List m_modules; + +static KCmdLineOptions options[] = +{ + { "list", I18N_NOOP("List all possible modules"), 0}, + { "+module", I18N_NOOP("Configuration module to open"), 0 }, + { "lang <language>", I18N_NOOP("Specify a particular language"), 0 }, + { "embed <id>", I18N_NOOP("Embeds the module with buttons in window with id <id>"), 0 }, + { "embed-proxy <id>", I18N_NOOP("Embeds the module without buttons in window with id <id>"), 0 }, + { "silent", I18N_NOOP("Do not display main window"), 0 }, + KCmdLineLastOption +}; + +static void listModules(const QString &baseGroup) +{ + + KServiceGroup::Ptr group = KServiceGroup::group(baseGroup); + + if (!group || !group->isValid()) + return; + + KServiceGroup::List list = group->entries(true, true); + + for( KServiceGroup::List::ConstIterator it = list.begin(); + it != list.end(); it++) + { + KSycocaEntry *p = (*it); + if (p->isType(KST_KService)) + { + KService *s = static_cast<KService*>(p); + if (!kapp->authorizeControlModule(s->menuId())) + continue; + m_modules.append(s); + } + else if (p->isType(KST_KServiceGroup)) + listModules(p->entryPath()); + } +} + +static KService::Ptr locateModule(const QCString& module) +{ + QString path = QFile::decodeName(module); + + if (!path.endsWith(".desktop")) + path += ".desktop"; + + KService::Ptr service = KService::serviceByStorageId( path ); + if (!service) + { + kdWarning(780) << "Could not find module '" << module << "'." << endl; + return 0; + } + + // avoid finding random non-kde applications + if ( module.left( 4 ) != "kde-" && service->library().isEmpty() ) + return locateModule( "kde-" + module ); + + if(!KCModuleLoader::testModule( module )) + { + kdDebug(780) << "According to \"" << module << "\"'s test function, it should Not be loaded." << endl; + return 0; + } + + return service; +} + +bool KCMShell::isRunning() +{ + if( dcopClient()->appId() == m_dcopName ) + return false; // We are the one and only. + + kdDebug(780) << "kcmshell with modules '" << + m_dcopName << "' is already running." << endl; + + dcopClient()->attach(); // Reregister as anonymous + dcopClient()->setNotifications(true); + + QByteArray data; + QDataStream str( data, IO_WriteOnly ); + str << kapp->startupId(); + QCString replyType; + QByteArray replyData; + if (!dcopClient()->call(m_dcopName, "dialog", "activate(QCString)", + data, replyType, replyData)) + { + kdDebug(780) << "Calling DCOP function dialog::activate() failed." << endl; + return false; // Error, we have to do it ourselves. + } + + return true; +} + +KCMShellMultiDialog::KCMShellMultiDialog( int dialogFace, const QString& caption, + QWidget *parent, const char *name, bool modal) + : KCMultiDialog( dialogFace, caption, parent, name, modal ), + DCOPObject("dialog") +{ +} + +void KCMShellMultiDialog::activate( QCString asn_id ) +{ + kdDebug(780) << k_funcinfo << endl; + + KStartupInfo::setNewStartupId( this, asn_id ); +} + +void KCMShell::setDCOPName(const QCString &dcopName, bool rootMode ) +{ + m_dcopName = "kcmshell_"; + if( rootMode ) + m_dcopName += "rootMode_"; + + m_dcopName += dcopName; + + dcopClient()->registerAs(m_dcopName, false); +} + +void KCMShell::waitForExit() +{ + kdDebug(780) << k_funcinfo << endl; + + connect(dcopClient(), SIGNAL(applicationRemoved(const QCString&)), + SLOT( appExit(const QCString&) )); + exec(); +} + +void KCMShell::appExit(const QCString &appId) +{ + kdDebug(780) << k_funcinfo << endl; + + if( appId == m_dcopName ) + { + kdDebug(780) << "'" << appId << "' closed, dereferencing." << endl; + deref(); + } +} + +static void setIcon(QWidget *w, const QString &iconName) +{ + QPixmap icon = DesktopIcon(iconName); + QPixmap miniIcon = SmallIcon(iconName); + w->setIcon( icon ); //standard X11 +#if defined Q_WS_X11 && ! defined K_WS_QTONLY + KWin::setIcons(w->winId(), icon, miniIcon ); +#endif +} + +extern "C" KDE_EXPORT int kdemain(int _argc, char *_argv[]) +{ + KAboutData aboutData( "kcmshell", I18N_NOOP("KDE Control Module"), + 0, + I18N_NOOP("A tool to start single KDE control modules"), + KAboutData::License_GPL, + I18N_NOOP("(c) 1999-2004, The KDE Developers") ); + + aboutData.addAuthor("Frans Englich", I18N_NOOP("Maintainer"), "frans.englich@kde.org"); + aboutData.addAuthor("Daniel Molkentin", 0, "molkentin@kde.org"); + aboutData.addAuthor("Matthias Hoelzer-Kluepfel",0, "hoelzer@kde.org"); + aboutData.addAuthor("Matthias Elter",0, "elter@kde.org"); + aboutData.addAuthor("Matthias Ettrich",0, "ettrich@kde.org"); + aboutData.addAuthor("Waldo Bastian",0, "bastian@kde.org"); + + KGlobal::locale()->setMainCatalogue("kcmshell"); + + KCmdLineArgs::init(_argc, _argv, &aboutData); + KCmdLineArgs::addCmdLineOptions( options ); // Add our own options. + KCMShell app; + + const KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + const QCString lang = args->getOption("lang"); + if( !lang.isNull() ) + KGlobal::locale()->setLanguage(lang); + + if (args->isSet("list")) + { + cout << i18n("The following modules are available:").local8Bit() << endl; + + listModules( "Settings/" ); + + int maxLen=0; + + for( KService::List::ConstIterator it = m_modules.begin(); it != m_modules.end(); ++it) + { + int len = (*it)->desktopEntryName().length(); + if (len > maxLen) + maxLen = len; + } + + for( KService::List::ConstIterator it = m_modules.begin(); it != m_modules.end(); ++it) + { + QString entry("%1 - %2"); + + entry = entry.arg((*it)->desktopEntryName().leftJustify(maxLen, ' ')) + .arg(!(*it)->comment().isEmpty() ? (*it)->comment() + : i18n("No description available")); + + cout << entry.local8Bit() << endl; + } + return 0; + } + + if (args->count() < 1) + { + args->usage(); + return -1; + } + + QCString dcopName; + KService::List modules; + for (int i = 0; i < args->count(); i++) + { + KService::Ptr service = locateModule(args->arg(i)); + if( service ) + { + modules.append(service); + if( !dcopName.isEmpty() ) + dcopName += "_"; + + dcopName += args->arg(i); + } + } + + /* Check if this particular module combination is already running, but + * allow the same module to run when embedding(root mode) */ + app.setDCOPName(dcopName, + ( args->isSet( "embed-proxy" ) || args->isSet( "embed" ))); + if( app.isRunning() ) + { + app.waitForExit(); + return 0; + } + + KDialogBase::DialogType dtype = KDialogBase::Plain; + + if ( modules.count() < 1 ) + return 0; + else if( modules.count() > 1 ) + dtype = KDialogBase::IconList; + + bool idValid; + int id; + + if ( args->isSet( "embed-proxy" )) + { + id = args->getOption( "embed-proxy" ).toInt(&idValid); + if( idValid ) + { + KCModuleProxy *module = new KCModuleProxy( modules.first()->desktopEntryName() ); + module->realModule(); + QXEmbed::embedClientIntoWindow( module, id); + app.exec(); + delete module; + } + else + kdDebug(780) << "Supplied id '" << id << "' is not valid." << endl; + + return 0; + + } + + KCMShellMultiDialog *dlg = new KCMShellMultiDialog( dtype, + i18n("Configure - %1").arg(kapp->caption()), 0, "", true ); + + for (KService::List::ConstIterator it = modules.begin(); it != modules.end(); ++it) + dlg->addModule(KCModuleInfo(*it)); + + if ( args->isSet( "embed" )) + { + id = args->getOption( "embed" ).toInt(&idValid); + if( idValid ) + { + QXEmbed::embedClientIntoWindow( dlg, id ); + dlg->exec(); + delete dlg; + } + else + kdDebug(780) << "Supplied id '" << id << "' is not valid." << endl; + + } + else + { + + if (kapp->iconName() != kapp->name()) + setIcon(dlg, kapp->iconName()); + else if ( modules.count() == 1 ) + setIcon(dlg, KCModuleInfo( modules.first()).icon()); + + dlg->exec(); + delete dlg; + } + + return 0; +} +// vim: sw=4 et sts=4 diff --git a/kcmshell/main.h b/kcmshell/main.h new file mode 100644 index 000000000..6b4c944ee --- /dev/null +++ b/kcmshell/main.h @@ -0,0 +1,104 @@ +/* + Copyright (c) 2001 Waldo Bastian <bastian@kde.org> + Copyright (c) 2004 Frans Englich <frans.englich@telia.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef __kcmshell_h__ +#define __kcmshell_h__ + +#include <dcopobject.h> + +#include <kapplication.h> +#include <kcmultidialog.h> + +/** + * The KApplication instance for kcmshell. + */ +class KCMShell : public KApplication +{ + Q_OBJECT + +public: + + /** + * Sets m_dcopName basically to @p dcopName, + * and then registers with DCOP. + * + * @param dcopName name to set the DCOP name to + * @param rootMode true if the kcmshell is embedding + */ + void setDCOPName(const QCString &dcopName, bool rootMode ); + + /** + * Waits until the last instance of kcmshell with the same + * module as this one exits, and then exits. + */ + void waitForExit(); + + /** + * @return true if the shell is running + */ + bool isRunning(); + +private slots: + + /** + */ + void appExit( const QCString &appId ); + +private: + + /** + * The DCOP name which actually is registered. + * For example "kcmshell_mouse". + */ + QCString m_dcopName; + +}; + + +/** + * Essentially a plain KCMultiDialog, but has the additional functionality + * of allowing it to be told to request windows focus. + * + * @author Waldo Bastian <bastian@kde.org> + */ +class KCMShellMultiDialog : public KCMultiDialog, public DCOPObject +{ + Q_OBJECT + K_DCOP + +public: + + /** + */ + KCMShellMultiDialog( int dialogFace, const QString& caption, + QWidget *parent=0, const char *name=0, bool modal=false); + +k_dcop: + + /** + */ + virtual void activate( QCString asn_id ); + +}; + + +// vim: sw=4 et sts=4 +#endif //__kcmshell_h__ |