kontact

uniqueapphandler.cpp

00001 /*
00002    This file is part of KDE Kontact.
00003 
00004    Copyright (c) 2003 David Faure <faure@kde.org>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 
00011    This library 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 GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019    Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include "uniqueapphandler.h"
00023 #include <kstartupinfo.h>
00024 #include <kapplication.h>
00025 #include <kcmdlineargs.h>
00026 #include "core.h"
00027 #include <kwin.h>
00028 #include <dcopclient.h>
00029 #include <kdebug.h>
00030 #include <klocale.h>
00031 #include <kuniqueapplication.h>
00032 
00033 /*
00034  Test plan for the various cases of interaction between standalone apps and kontact:
00035 
00036  1) start kontact, select "Mail".
00037  1a) type "korganizer" -> it switches to korganizer
00038  1b) type "kmail" -> it switches to kmail
00039  1c) type "kaddressbook" -> it switches to kaddressbook
00040  1d) type "kmail foo@kde.org" -> it opens a kmail composer, without switching
00041  1e) type "knode" -> it switches to knode
00042  1f) type "kaddressbook --new-contact" -> it opens a kaddressbook contact window
00043  1g) type "knode news://foobar/group" -> it pops up "can't resolve hostname"
00044 
00045  2) close kontact. Launch kmail. Launch kontact again.
00046  2a) click "Mail" icon -> kontact doesn't load a part, but activates the kmail window
00047  2b) type "kmail foo@kde.org" -> standalone kmail opens composer.
00048  2c) close kmail, click "Mail" icon -> kontact loads the kmail part.
00049  2d) type "kmail" -> kontact is brought to front
00050 
00051  3) close kontact. Launch korganizer, then kontact.
00052  3a) both Todo and Calendar activate the running korganizer.
00053  3b) type "korganizer" -> standalone korganizer is brought to front
00054  3c) close korganizer, click Calendar or Todo -> kontact loads part.
00055  3d) type "korganizer" -> kontact is brought to front
00056 
00057  4) close kontact. Launch kaddressbook, then kontact.
00058  4a) "Contacts" icon activate the running kaddressbook.
00059  4b) type "kaddressbook" -> standalone kaddressbook is brought to front
00060  4c) close kaddressbook, type "kaddressbook -a foo@kde.org" -> kontact loads part and opens editor
00061  4d) type "kaddressbook" -> kontact is brought to front
00062 
00063  5) close kontact. Launch knode, then kontact.
00064  5a) "News" icon activate the running knode.
00065  5b) type "knode" -> standalone knode is brought to front
00066  5c) close knode, type "knode news://foobar/group" -> kontact loads knode and pops up msgbox
00067  5d) type "knode" -> kontact is brought to front
00068 
00069  6) start "kontact --module summaryplugin"
00070  6a) type "dcop kmail kmail newInstance" -> kontact switches to kmail (#103775)
00071  6b) type "kmail" -> kontact is brought to front
00072  6c) type "kontact" -> kontact is brought to front
00073  6d) type "kontact --module summaryplugin" -> kontact switches to summary
00074 
00075 */
00076 
00077 using namespace Kontact;
00078 
00079 int UniqueAppHandler::newInstance()
00080 {
00081   // This bit is duplicated from KUniqueApplication::newInstance()
00082   if ( kapp->mainWidget() ) {
00083     kapp->mainWidget()->show();
00084     KWin::forceActiveWindow( kapp->mainWidget()->winId() );
00085     KStartupInfo::appStarted();
00086   }
00087 
00088   // Then ensure the part appears in kontact
00089   mPlugin->core()->selectPlugin( mPlugin );
00090   return 0;
00091 }
00092 
00093 bool UniqueAppHandler::process( const QCString &fun, const QByteArray &data,
00094                                 QCString& replyType, QByteArray &replyData )
00095 {
00096   if ( fun == "newInstance()" ) {
00097     replyType = "int";
00098 
00099     KCmdLineArgs::reset(); // forget options defined by other "applications"
00100     loadCommandLineOptions(); // implemented by plugin
00101 
00102     // This bit is duplicated from KUniqueApplication::processDelayed()
00103     QDataStream ds( data, IO_ReadOnly );
00104     KCmdLineArgs::loadAppArgs( ds );
00105     if ( !ds.atEnd() ) { // backwards compatibility
00106       QCString asn_id;
00107       ds >> asn_id;
00108       kapp->setStartupId( asn_id );
00109     }
00110 
00111     QDataStream _replyStream( replyData, IO_WriteOnly );
00112     _replyStream << newInstance();
00113 
00114     // OK, we're done, reload the initial kontact command line options,
00115     // so that "kontact --module foo" keeps working (#103775).
00116 
00117     KCmdLineArgs::reset(); // forget options defined above
00118     loadKontactCommandLineOptions();
00119 
00120   } else if ( fun == "load()" ) {
00121     replyType = "bool";
00122     (void)mPlugin->part(); // load the part without bringing it to front
00123 
00124     QDataStream _replyStream( replyData, IO_WriteOnly );
00125     _replyStream << true;
00126   } else {
00127     return DCOPObject::process( fun, data, replyType, replyData );
00128   }
00129   return true;
00130 }
00131 
00132 QCStringList UniqueAppHandler::interfaces()
00133 {
00134   QCStringList ifaces = DCOPObject::interfaces();
00135   ifaces += "Kontact::UniqueAppHandler";
00136   return ifaces;
00137 }
00138 
00139 QCStringList UniqueAppHandler::functions()
00140 {
00141   QCStringList funcs = DCOPObject::functions();
00142   funcs << "int newInstance()";
00143   funcs << "bool load()";
00144   return funcs;
00145 }
00146 
00147 UniqueAppWatcher::UniqueAppWatcher( UniqueAppHandlerFactoryBase* factory, Plugin* plugin )
00148     : QObject( plugin ), mFactory( factory ), mPlugin( plugin )
00149 {
00150   // The app is running standalone if 1) that name is known to DCOP
00151   mRunningStandalone = kapp->dcopClient()->isApplicationRegistered( plugin->name() );
00152 
00153   // and 2) it's not registered by kontact (e.g. in another plugin)
00154   if ( mRunningStandalone && kapp->dcopClient()->findLocalClient( plugin->name() ) )
00155       mRunningStandalone = false;
00156 
00157   if ( mRunningStandalone ) {
00158     kapp->dcopClient()->setNotifications( true );
00159     connect( kapp->dcopClient(), SIGNAL( applicationRemoved( const QCString& ) ),
00160              this, SLOT( unregisteredFromDCOP( const QCString& ) ) );
00161   } else {
00162     mFactory->createHandler( mPlugin );
00163   }
00164 }
00165 
00166 UniqueAppWatcher::~UniqueAppWatcher()
00167 {
00168   if ( mRunningStandalone )
00169     kapp->dcopClient()->setNotifications( false );
00170 
00171   delete mFactory;
00172 }
00173 
00174 void UniqueAppWatcher::unregisteredFromDCOP( const QCString& appId )
00175 {
00176   if ( appId == mPlugin->name() && mRunningStandalone ) {
00177     disconnect( kapp->dcopClient(), SIGNAL( applicationRemoved( const QCString& ) ),
00178                 this, SLOT( unregisteredFromDCOP( const QCString& ) ) );
00179     kdDebug(5601) << k_funcinfo << appId << endl;
00180     mFactory->createHandler( mPlugin );
00181     kapp->dcopClient()->setNotifications( false );
00182     mRunningStandalone = false;
00183   }
00184 }
00185 
00186 static KCmdLineOptions options[] =
00187 {
00188     { "module <module>",   I18N_NOOP( "Start with a specific Kontact module" ), 0 },
00189     { "iconify",   I18N_NOOP( "Start in iconified (minimized) mode" ), 0 },
00190     { "list", I18N_NOOP( "List all possible modules and exit" ), 0 },
00191     KCmdLineLastOption
00192 };
00193 
00194 void Kontact::UniqueAppHandler::loadKontactCommandLineOptions()
00195 {
00196   KCmdLineArgs::addCmdLineOptions( options );
00197   KUniqueApplication::addCmdLineOptions();
00198   KApplication::addCmdLineOptions();
00199 }
00200 
00201 #include "uniqueapphandler.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys