• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.8.3 API Reference
  • KDE Home
  • Contact Us
 

Kontact Plugin Interface Library

uniqueapphandler.cpp
00001 /*
00002   This file is part of the KDE Kontact Plugin Interface Library.
00003 
00004   Copyright (c) 2003,2008 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 <qdbusabstractadaptor.h>
00024 #include "core.h"
00025 
00026 #include <kpimutils/processes.h>
00027 
00028 #include <kapplication.h>
00029 #include <kcmdlineargs.h>
00030 #include <kdebug.h>
00031 #include <kstartupinfo.h>
00032 #include <kuniqueapplication.h>
00033 #include <kwindowsystem.h>
00034 
00035 #include <QDBusConnection>
00036 #include <QDBusConnectionInterface>
00037 
00038 #ifdef Q_WS_WIN
00039 #  include <process.h>
00040 #endif
00041 
00042 /*
00043  Test plan for the various cases of interaction between standalone apps and kontact:
00044 
00045  1) start kontact, select "Mail".
00046  1a) type "korganizer" -> it switches to korganizer
00047  1b) type "kmail" -> it switches to kmail
00048  1c) type "kaddressbook" -> it switches to kaddressbook
00049  1d) type "kmail foo@kde.org" -> it opens a kmail composer, without switching
00050  1e) type "knode" -> it switches to knode [unless configured to be external]
00051  1f) type "kaddressbook --new-contact" -> it opens a kaddressbook contact window
00052  1g) type "knode news://foobar/group" -> it pops up "can't resolve hostname"
00053 
00054  2) close kontact. Launch kmail. Launch kontact again.
00055  2a) click "Mail" icon -> kontact doesn't load a part, but activates the kmail window
00056  2b) type "kmail foo@kde.org" -> standalone kmail opens composer.
00057  2c) close kmail, click "Mail" icon -> kontact loads the kmail part.
00058  2d) type "kmail" -> kontact is brought to front
00059 
00060  3) close kontact. Launch korganizer, then kontact.
00061  3a) both Todo and Calendar activate the running korganizer.
00062  3b) type "korganizer" -> standalone korganizer is brought to front
00063  3c) close korganizer, click Calendar or Todo -> kontact loads part.
00064  3d) type "korganizer" -> kontact is brought to front
00065 
00066  4) close kontact. Launch kaddressbook, then kontact.
00067  4a) "Contacts" icon activate the running kaddressbook.
00068  4b) type "kaddressbook" -> standalone kaddressbook is brought to front
00069  4c) close kaddressbook, type "kaddressbook -a foo@kde.org" -> kontact loads part and opens editor
00070  4d) type "kaddressbook" -> kontact is brought to front
00071 
00072  5) close kontact. Launch knode, then kontact.
00073  5a) "News" icon activate the running knode.
00074  5b) type "knode" -> standalone knode is brought to front
00075  5c) close knode, type "knode news://foobar/group" -> kontact loads knode and pops up msgbox
00076  5d) type "knode" -> kontact is brought to front
00077 
00078  6) start "kontact --module summaryplugin"
00079  6a) type "qdbus org.kde.kmail /kmail_PimApplication newInstance '' ''" ->
00080      kontact switches to kmail (#103775)
00081  6b) type "kmail" -> kontact is brought to front
00082  6c) type "kontact" -> kontact is brought to front
00083  6d) type "kontact --module summaryplugin" -> kontact switches to summary
00084 
00085 */
00086 
00087 using namespace KontactInterface;
00088 
00089 //@cond PRIVATE
00090 class UniqueAppHandler::Private
00091 {
00092   public:
00093     Plugin *mPlugin;
00094 };
00095 //@endcond
00096 
00097 UniqueAppHandler::UniqueAppHandler( Plugin *plugin )
00098  : QObject( plugin ), d( new Private )
00099 {
00100   //kDebug() << "plugin->objectName():" << plugin->objectName();
00101 
00102   d->mPlugin = plugin;
00103   QDBusConnection session = QDBusConnection::sessionBus();
00104   const QString appName = plugin->objectName();
00105   session.registerService( "org.kde." + appName );
00106   const QString objectName = QString( '/' ) + appName + "_PimApplication";
00107   session.registerObject( objectName, this, QDBusConnection::ExportAllSlots );
00108 }
00109 
00110 UniqueAppHandler::~UniqueAppHandler()
00111 {
00112   QDBusConnection session = QDBusConnection::sessionBus();
00113   const QString appName = parent()->objectName();
00114   session.unregisterService( "org.kde." + appName );
00115   delete d;
00116 }
00117 
00118 // DBUS call
00119 int UniqueAppHandler::newInstance( const QByteArray &asn_id, const QByteArray &args )
00120 {
00121   if ( !asn_id.isEmpty() ) {
00122     kapp->setStartupId( asn_id );
00123   }
00124 
00125   KCmdLineArgs::reset(); // forget options defined by other "applications"
00126   loadCommandLineOptions(); // implemented by plugin
00127 
00128   // This bit is duplicated from KUniqueApplicationAdaptor::newInstance()
00129   QDataStream ds( args );
00130   KCmdLineArgs::loadAppArgs( ds );
00131 
00132   return newInstance();
00133 }
00134 
00135 static QWidget *s_mainWidget = 0;
00136 
00137 // Plugin-specific newInstance implementation, called by above method
00138 int KontactInterface::UniqueAppHandler::newInstance()
00139 {
00140   if ( s_mainWidget ) {
00141     s_mainWidget->show();
00142     KWindowSystem::forceActiveWindow( s_mainWidget->winId() );
00143     KStartupInfo::appStarted();
00144   }
00145 
00146   // Then ensure the part appears in kontact
00147   d->mPlugin->core()->selectPlugin( d->mPlugin );
00148   return 0;
00149 }
00150 
00151 Plugin *UniqueAppHandler::plugin() const
00152 {
00153   return d->mPlugin;
00154 }
00155 
00156 bool KontactInterface::UniqueAppHandler::load()
00157 {
00158   (void)d->mPlugin->part(); // load the part without bringing it to front
00159   return true;
00160 }
00161 
00162 //@cond PRIVATE
00163 class UniqueAppWatcher::Private
00164 {
00165   public:
00166     UniqueAppHandlerFactoryBase *mFactory;
00167     Plugin *mPlugin;
00168     bool mRunningStandalone;
00169 };
00170 //@endcond
00171 
00172 UniqueAppWatcher::UniqueAppWatcher( UniqueAppHandlerFactoryBase *factory, Plugin *plugin )
00173   : QObject( plugin ), d( new Private )
00174 {
00175   d->mFactory = factory;
00176   d->mPlugin = plugin;
00177 
00178   // The app is running standalone if 1) that name is known to D-Bus
00179   const QString serviceName = "org.kde." + plugin->objectName();
00180   //Needed for wince build
00181   #undef interface
00182   d->mRunningStandalone =
00183     QDBusConnection::sessionBus().interface()->isServiceRegistered( serviceName );
00184 #ifdef Q_WS_WIN
00185   if ( d->mRunningStandalone ) {
00186     QList<int> pids;
00187     KPIMUtils::getProcessesIdForName( plugin->objectName(), pids );
00188     const int mypid = getpid();
00189     bool processExits = false;
00190     foreach ( int pid, pids ) {
00191       if ( mypid != pid ) {
00192         processExits = true;
00193         break;
00194       }
00195     }
00196     if ( !processExits ) {
00197       d->mRunningStandalone = false;
00198     }
00199   }
00200 #endif
00201 
00202   QString owner = QDBusConnection::sessionBus().interface()->serviceOwner( serviceName );
00203   if ( d->mRunningStandalone && ( owner == QDBusConnection::sessionBus().baseService() ) ) {
00204     d->mRunningStandalone = false;
00205   }
00206   //kDebug() << " plugin->objectName()=" << plugin->objectName()
00207   //         << " running standalone:" << d->mRunningStandalone;
00208 
00209   if ( d->mRunningStandalone ) {
00210     QObject::connect( QDBusConnection::sessionBus().interface(),
00211                       SIGNAL(serviceOwnerChanged(QString,QString,QString)),
00212                       this, SLOT(slotApplicationRemoved(QString,QString,QString)) );
00213   } else {
00214     d->mFactory->createHandler( d->mPlugin );
00215   }
00216 }
00217 
00218 UniqueAppWatcher::~UniqueAppWatcher()
00219 {
00220   delete d->mFactory;
00221   delete d;
00222 }
00223 
00224 bool UniqueAppWatcher::isRunningStandalone() const
00225 {
00226   return d->mRunningStandalone;
00227 }
00228 
00229 void KontactInterface::UniqueAppWatcher::slotApplicationRemoved( const QString &name,
00230                                                                  const QString &oldOwner,
00231                                                                  const QString &newOwner )
00232 {
00233   if ( oldOwner.isEmpty() || !newOwner.isEmpty() ) {
00234     return;
00235   }
00236 
00237   const QString serviceName = "org.kde." + d->mPlugin->objectName();
00238   if ( name == serviceName && d->mRunningStandalone ) {
00239     d->mFactory->createHandler( d->mPlugin );
00240     d->mRunningStandalone = false;
00241   }
00242 }
00243 
00244 void KontactInterface::UniqueAppHandler::setMainWidget( QWidget *widget )
00245 {
00246   s_mainWidget = widget;
00247 }
00248 
00249 QWidget *KontactInterface::UniqueAppHandler::mainWidget()
00250 {
00251   return s_mainWidget;
00252 }
00253 
00254 #include "uniqueapphandler.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon May 14 2012 04:51:33 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Kontact Plugin Interface Library

Skip menu "Kontact Plugin Interface Library"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Related Pages

kdepimlibs-4.8.3 API Reference

Skip menu "kdepimlibs-4.8.3 API Reference"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal