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

Kontact Plugin Interface Library

  • kontactinterface
uniqueapphandler.cpp
1/*
2 This file is part of the KDE Kontact Plugin Interface Library.
3
4 Copyright (c) 2003,2008 David Faure <faure@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22#include "uniqueapphandler.h"
23#include <qdbusabstractadaptor.h>
24#include "core.h"
25
26#include <kpimutils/processes.h>
27
28#include <kapplication.h>
29#include <kcmdlineargs.h>
30#include <kdebug.h>
31#include <kstartupinfo.h>
32#include <kuniqueapplication.h>
33#include <kwindowsystem.h>
34
35#include <QDBusConnection>
36#include <QDBusConnectionInterface>
37
38#ifdef Q_WS_WIN
39# include <process.h>
40#endif
41
42/*
43 Test plan for the various cases of interaction between standalone apps and kontact:
44
45 1) start kontact, select "Mail".
46 1a) type "korganizer" -> it switches to korganizer
47 1b) type "kmail" -> it switches to kmail
48 1c) type "kaddressbook" -> it switches to kaddressbook
49 1d) type "kmail foo@kde.org" -> it opens a kmail composer, without switching
50 1e) type "knode" -> it switches to knode [unless configured to be external]
51 1f) type "kaddressbook --new-contact" -> it opens a kaddressbook contact window
52 1g) type "knode news://foobar/group" -> it pops up "can't resolve hostname"
53
54 2) close kontact. Launch kmail. Launch kontact again.
55 2a) click "Mail" icon -> kontact doesn't load a part, but activates the kmail window
56 2b) type "kmail foo@kde.org" -> standalone kmail opens composer.
57 2c) close kmail, click "Mail" icon -> kontact loads the kmail part.
58 2d) type "kmail" -> kontact is brought to front
59
60 3) close kontact. Launch korganizer, then kontact.
61 3a) both Todo and Calendar activate the running korganizer.
62 3b) type "korganizer" -> standalone korganizer is brought to front
63 3c) close korganizer, click Calendar or Todo -> kontact loads part.
64 3d) type "korganizer" -> kontact is brought to front
65
66 4) close kontact. Launch kaddressbook, then kontact.
67 4a) "Contacts" icon activate the running kaddressbook.
68 4b) type "kaddressbook" -> standalone kaddressbook is brought to front
69 4c) close kaddressbook, type "kaddressbook -a foo@kde.org" -> kontact loads part and opens editor
70 4d) type "kaddressbook" -> kontact is brought to front
71
72 5) close kontact. Launch knode, then kontact.
73 5a) "News" icon activate the running knode.
74 5b) type "knode" -> standalone knode is brought to front
75 5c) close knode, type "knode news://foobar/group" -> kontact loads knode and pops up msgbox
76 5d) type "knode" -> kontact is brought to front
77
78 6) start "kontact --module summaryplugin"
79 6a) type "qdbus org.kde.kmail /kmail_PimApplication newInstance '' ''" ->
80 kontact switches to kmail (#103775)
81 6b) type "kmail" -> kontact is brought to front
82 6c) type "kontact" -> kontact is brought to front
83 6d) type "kontact --module summaryplugin" -> kontact switches to summary
84
85*/
86
87using namespace KontactInterface;
88
89//@cond PRIVATE
90class UniqueAppHandler::Private
91{
92 public:
93 Plugin *mPlugin;
94};
95//@endcond
96
97UniqueAppHandler::UniqueAppHandler( Plugin *plugin )
98 : QObject( plugin ), d( new Private )
99{
100 //kDebug() << "plugin->objectName():" << plugin->objectName();
101
102 d->mPlugin = plugin;
103 QDBusConnection session = QDBusConnection::sessionBus();
104 const QString appName = plugin->objectName();
105 session.registerService( QLatin1String("org.kde.") + appName );
106 const QString objectName = QLatin1Char( '/' ) + appName + QLatin1String("_PimApplication");
107 session.registerObject( objectName, this, QDBusConnection::ExportAllSlots );
108}
109
110UniqueAppHandler::~UniqueAppHandler()
111{
112 QDBusConnection session = QDBusConnection::sessionBus();
113 const QString appName = parent()->objectName();
114 session.unregisterService( QLatin1String("org.kde.") + appName );
115 delete d;
116}
117
118// DBUS call
119int UniqueAppHandler::newInstance( const QByteArray &asn_id, const QByteArray &args )
120{
121 if ( !asn_id.isEmpty() ) {
122 kapp->setStartupId( asn_id );
123 }
124
125 KCmdLineArgs::reset(); // forget options defined by other "applications"
126 loadCommandLineOptions(); // implemented by plugin
127
128 // This bit is duplicated from KUniqueApplicationAdaptor::newInstance()
129 QDataStream ds( args );
130 KCmdLineArgs::loadAppArgs( ds );
131
132 return newInstance();
133}
134
135static QWidget *s_mainWidget = 0;
136
137// Plugin-specific newInstance implementation, called by above method
138int KontactInterface::UniqueAppHandler::newInstance()
139{
140 if ( s_mainWidget ) {
141 s_mainWidget->show();
142 KWindowSystem::forceActiveWindow( s_mainWidget->winId() );
143 KStartupInfo::appStarted();
144 }
145
146 // Then ensure the part appears in kontact
147 d->mPlugin->core()->selectPlugin( d->mPlugin );
148 return 0;
149}
150
151Plugin *UniqueAppHandler::plugin() const
152{
153 return d->mPlugin;
154}
155
156bool KontactInterface::UniqueAppHandler::load()
157{
158 (void)d->mPlugin->part(); // load the part without bringing it to front
159 return true;
160}
161
162//@cond PRIVATE
163class UniqueAppWatcher::Private
164{
165 public:
166 UniqueAppHandlerFactoryBase *mFactory;
167 Plugin *mPlugin;
168 bool mRunningStandalone;
169};
170//@endcond
171
172UniqueAppWatcher::UniqueAppWatcher( UniqueAppHandlerFactoryBase *factory, Plugin *plugin )
173 : QObject( plugin ), d( new Private )
174{
175 d->mFactory = factory;
176 d->mPlugin = plugin;
177
178 // The app is running standalone if 1) that name is known to D-Bus
179 const QString serviceName = QLatin1String("org.kde.") + plugin->objectName();
180 //Needed for wince build
181 #undef interface
182 d->mRunningStandalone =
183 QDBusConnection::sessionBus().interface()->isServiceRegistered( serviceName );
184#ifdef Q_WS_WIN
185 if ( d->mRunningStandalone ) {
186 QList<int> pids;
187 KPIMUtils::getProcessesIdForName( plugin->objectName(), pids );
188 const int mypid = getpid();
189 bool processExits = false;
190 foreach ( int pid, pids ) {
191 if ( mypid != pid ) {
192 processExits = true;
193 break;
194 }
195 }
196 if ( !processExits ) {
197 d->mRunningStandalone = false;
198 }
199 }
200#endif
201
202 QString owner = QDBusConnection::sessionBus().interface()->serviceOwner( serviceName );
203 if ( d->mRunningStandalone && ( owner == QDBusConnection::sessionBus().baseService() ) ) {
204 d->mRunningStandalone = false;
205 }
206 //kDebug() << " plugin->objectName()=" << plugin->objectName()
207 // << " running standalone:" << d->mRunningStandalone;
208
209 if ( d->mRunningStandalone ) {
210 QObject::connect( QDBusConnection::sessionBus().interface(),
211 SIGNAL(serviceOwnerChanged(QString,QString,QString)),
212 this, SLOT(slotApplicationRemoved(QString,QString,QString)) );
213 } else {
214 d->mFactory->createHandler( d->mPlugin );
215 }
216}
217
218UniqueAppWatcher::~UniqueAppWatcher()
219{
220 delete d->mFactory;
221 delete d;
222}
223
224bool UniqueAppWatcher::isRunningStandalone() const
225{
226 return d->mRunningStandalone;
227}
228
229void KontactInterface::UniqueAppWatcher::slotApplicationRemoved( const QString &name,
230 const QString &oldOwner,
231 const QString &newOwner )
232{
233 if ( oldOwner.isEmpty() || !newOwner.isEmpty() ) {
234 return;
235 }
236
237 const QString serviceName = QLatin1String("org.kde.") + d->mPlugin->objectName();
238 if ( name == serviceName && d->mRunningStandalone ) {
239 d->mFactory->createHandler( d->mPlugin );
240 d->mRunningStandalone = false;
241 }
242}
243
244void KontactInterface::UniqueAppHandler::setMainWidget( QWidget *widget )
245{
246 s_mainWidget = widget;
247}
248
249QWidget *KontactInterface::UniqueAppHandler::mainWidget()
250{
251 return s_mainWidget;
252}
253
KontactInterface::Plugin
Base class for all Plugins in Kontact.
Definition plugin.h:78
KontactInterface::UniqueAppHandlerFactoryBase
Base class for UniqueAppHandler.
Definition uniqueapphandler.h:78
KontactInterface::UniqueAppHandler::loadCommandLineOptions
virtual void loadCommandLineOptions()=0
This must be reimplemented so that app-specific command line options can be parsed.
KontactInterface::UniqueAppHandler::setMainWidget
static void setMainWidget(QWidget *widget)
Sets the main QWidget widget associated with this application.
Definition uniqueapphandler.cpp:244
KontactInterface::UniqueAppHandler::mainWidget
QWidget * mainWidget()
Returns the main widget, which will zero if setMainWidget() has not be called yet.
Definition uniqueapphandler.cpp:249
KontactInterface::UniqueAppWatcher::UniqueAppWatcher
UniqueAppWatcher(UniqueAppHandlerFactoryBase *factory, Plugin *plugin)
Create an instance of UniqueAppWatcher, which does everything necessary for the "unique application" ...
Definition uniqueapphandler.cpp:172
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Wed Jan 24 2024 00:00:00 by doxygen 1.10.0 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.14.10 API Reference

Skip menu "kdepimlibs-4.14.10 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • 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