diff options
Diffstat (limited to 'kontact/interfaces/uniqueapphandler.cpp')
-rw-r--r-- | kontact/interfaces/uniqueapphandler.cpp | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/kontact/interfaces/uniqueapphandler.cpp b/kontact/interfaces/uniqueapphandler.cpp new file mode 100644 index 000000000..de77df7d5 --- /dev/null +++ b/kontact/interfaces/uniqueapphandler.cpp @@ -0,0 +1,201 @@ +/* + This file is part of KDE Kontact. + + Copyright (c) 2003 David Faure <faure@kde.org> + + 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. +*/ + +#include "uniqueapphandler.h" +#include <kstartupinfo.h> +#include <kapplication.h> +#include <kcmdlineargs.h> +#include "core.h" +#include <kwin.h> +#include <dcopclient.h> +#include <kdebug.h> +#include <klocale.h> +#include <kuniqueapplication.h> + +/* + Test plan for the various cases of interaction between standalone apps and kontact: + + 1) start kontact, select "Mail". + 1a) type "korganizer" -> it switches to korganizer + 1b) type "kmail" -> it switches to kmail + 1c) type "kaddressbook" -> it switches to kaddressbook + 1d) type "kmail foo@kde.org" -> it opens a kmail composer, without switching + 1e) type "knode" -> it switches to knode + 1f) type "kaddressbook --new-contact" -> it opens a kaddressbook contact window + 1g) type "knode news://foobar/group" -> it pops up "can't resolve hostname" + + 2) close kontact. Launch kmail. Launch kontact again. + 2a) click "Mail" icon -> kontact doesn't load a part, but activates the kmail window + 2b) type "kmail foo@kde.org" -> standalone kmail opens composer. + 2c) close kmail, click "Mail" icon -> kontact loads the kmail part. + 2d) type "kmail" -> kontact is brought to front + + 3) close kontact. Launch korganizer, then kontact. + 3a) both Todo and Calendar activate the running korganizer. + 3b) type "korganizer" -> standalone korganizer is brought to front + 3c) close korganizer, click Calendar or Todo -> kontact loads part. + 3d) type "korganizer" -> kontact is brought to front + + 4) close kontact. Launch kaddressbook, then kontact. + 4a) "Contacts" icon activate the running kaddressbook. + 4b) type "kaddressbook" -> standalone kaddressbook is brought to front + 4c) close kaddressbook, type "kaddressbook -a foo@kde.org" -> kontact loads part and opens editor + 4d) type "kaddressbook" -> kontact is brought to front + + 5) close kontact. Launch knode, then kontact. + 5a) "News" icon activate the running knode. + 5b) type "knode" -> standalone knode is brought to front + 5c) close knode, type "knode news://foobar/group" -> kontact loads knode and pops up msgbox + 5d) type "knode" -> kontact is brought to front + + 6) start "kontact --module summaryplugin" + 6a) type "dcop kmail kmail newInstance" -> kontact switches to kmail (#103775) + 6b) type "kmail" -> kontact is brought to front + 6c) type "kontact" -> kontact is brought to front + 6d) type "kontact --module summaryplugin" -> kontact switches to summary + +*/ + +using namespace Kontact; + +int UniqueAppHandler::newInstance() +{ + // This bit is duplicated from KUniqueApplication::newInstance() + if ( kapp->mainWidget() ) { + kapp->mainWidget()->show(); + KWin::forceActiveWindow( kapp->mainWidget()->winId() ); + KStartupInfo::appStarted(); + } + + // Then ensure the part appears in kontact + mPlugin->core()->selectPlugin( mPlugin ); + return 0; +} + +bool UniqueAppHandler::process( const QCString &fun, const QByteArray &data, + QCString& replyType, QByteArray &replyData ) +{ + if ( fun == "newInstance()" ) { + replyType = "int"; + + KCmdLineArgs::reset(); // forget options defined by other "applications" + loadCommandLineOptions(); // implemented by plugin + + // This bit is duplicated from KUniqueApplication::processDelayed() + QDataStream ds( data, IO_ReadOnly ); + KCmdLineArgs::loadAppArgs( ds ); + if ( !ds.atEnd() ) { // backwards compatibility + QCString asn_id; + ds >> asn_id; + kapp->setStartupId( asn_id ); + } + + QDataStream _replyStream( replyData, IO_WriteOnly ); + _replyStream << newInstance(); + + // OK, we're done, reload the initial kontact command line options, + // so that "kontact --module foo" keeps working (#103775). + + KCmdLineArgs::reset(); // forget options defined above + loadKontactCommandLineOptions(); + + } else if ( fun == "load()" ) { + replyType = "bool"; + (void)mPlugin->part(); // load the part without bringing it to front + + QDataStream _replyStream( replyData, IO_WriteOnly ); + _replyStream << true; + } else { + return DCOPObject::process( fun, data, replyType, replyData ); + } + return true; +} + +QCStringList UniqueAppHandler::interfaces() +{ + QCStringList ifaces = DCOPObject::interfaces(); + ifaces += "Kontact::UniqueAppHandler"; + return ifaces; +} + +QCStringList UniqueAppHandler::functions() +{ + QCStringList funcs = DCOPObject::functions(); + funcs << "int newInstance()"; + funcs << "bool load()"; + return funcs; +} + +UniqueAppWatcher::UniqueAppWatcher( UniqueAppHandlerFactoryBase* factory, Plugin* plugin ) + : QObject( plugin ), mFactory( factory ), mPlugin( plugin ) +{ + // The app is running standalone if 1) that name is known to DCOP + mRunningStandalone = kapp->dcopClient()->isApplicationRegistered( plugin->name() ); + + // and 2) it's not registered by kontact (e.g. in another plugin) + if ( mRunningStandalone && kapp->dcopClient()->findLocalClient( plugin->name() ) ) + mRunningStandalone = false; + + if ( mRunningStandalone ) { + kapp->dcopClient()->setNotifications( true ); + connect( kapp->dcopClient(), SIGNAL( applicationRemoved( const QCString& ) ), + this, SLOT( unregisteredFromDCOP( const QCString& ) ) ); + } else { + mFactory->createHandler( mPlugin ); + } +} + +UniqueAppWatcher::~UniqueAppWatcher() +{ + if ( mRunningStandalone ) + kapp->dcopClient()->setNotifications( false ); + + delete mFactory; +} + +void UniqueAppWatcher::unregisteredFromDCOP( const QCString& appId ) +{ + if ( appId == mPlugin->name() && mRunningStandalone ) { + disconnect( kapp->dcopClient(), SIGNAL( applicationRemoved( const QCString& ) ), + this, SLOT( unregisteredFromDCOP( const QCString& ) ) ); + kdDebug(5601) << k_funcinfo << appId << endl; + mFactory->createHandler( mPlugin ); + kapp->dcopClient()->setNotifications( false ); + mRunningStandalone = false; + } +} + +static KCmdLineOptions options[] = +{ + { "module <module>", I18N_NOOP( "Start with a specific Kontact module" ), 0 }, + { "iconify", I18N_NOOP( "Start in iconified (minimized) mode" ), 0 }, + { "list", I18N_NOOP( "List all possible modules and exit" ), 0 }, + KCmdLineLastOption +}; + +void Kontact::UniqueAppHandler::loadKontactCommandLineOptions() +{ + KCmdLineArgs::addCmdLineOptions( options ); + KUniqueApplication::addCmdLineOptions(); + KApplication::addCmdLineOptions(); +} + +#include "uniqueapphandler.moc" |