mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-23 18:32:51 +00:00
253 lines
7.9 KiB
C++
253 lines
7.9 KiB
C++
/*
|
|
This file is part of the KDE Kontact Plugin Interface Library.
|
|
|
|
Copyright (c) 2003,2008 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 <qdbusabstractadaptor.h>
|
|
#include "core.h"
|
|
|
|
#include <kpimutils/processes.h>
|
|
|
|
#include <kapplication.h>
|
|
#include <kcmdlineargs.h>
|
|
#include <kdebug.h>
|
|
#include <kstartupinfo.h>
|
|
#include <kuniqueapplication.h>
|
|
#include <kwindowsystem.h>
|
|
|
|
#include <QDBusConnection>
|
|
#include <QDBusConnectionInterface>
|
|
|
|
#ifdef Q_WS_WIN
|
|
# include <process.h>
|
|
#endif
|
|
|
|
/*
|
|
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 [unless configured to be external]
|
|
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 "qdbus org.kde.kmail /kmail_PimApplication 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 KontactInterface;
|
|
|
|
//@cond PRIVATE
|
|
class UniqueAppHandler::Private
|
|
{
|
|
public:
|
|
Plugin *mPlugin;
|
|
};
|
|
//@endcond
|
|
|
|
UniqueAppHandler::UniqueAppHandler( Plugin *plugin )
|
|
: QObject( plugin ), d( new Private )
|
|
{
|
|
//kDebug() << "plugin->objectName():" << plugin->objectName();
|
|
|
|
d->mPlugin = plugin;
|
|
QDBusConnection session = QDBusConnection::sessionBus();
|
|
const QString appName = plugin->objectName();
|
|
session.registerService( QLatin1String("org.kde.") + appName );
|
|
const QString objectName = QLatin1Char( '/' ) + appName + QLatin1String("_PimApplication");
|
|
session.registerObject( objectName, this, QDBusConnection::ExportAllSlots );
|
|
}
|
|
|
|
UniqueAppHandler::~UniqueAppHandler()
|
|
{
|
|
QDBusConnection session = QDBusConnection::sessionBus();
|
|
const QString appName = parent()->objectName();
|
|
session.unregisterService( QLatin1String("org.kde.") + appName );
|
|
delete d;
|
|
}
|
|
|
|
// DBUS call
|
|
int UniqueAppHandler::newInstance( const QByteArray &asn_id, const QByteArray &args )
|
|
{
|
|
if ( !asn_id.isEmpty() ) {
|
|
kapp->setStartupId( asn_id );
|
|
}
|
|
|
|
KCmdLineArgs::reset(); // forget options defined by other "applications"
|
|
loadCommandLineOptions(); // implemented by plugin
|
|
|
|
// This bit is duplicated from KUniqueApplicationAdaptor::newInstance()
|
|
QDataStream ds( args );
|
|
KCmdLineArgs::loadAppArgs( ds );
|
|
|
|
return newInstance();
|
|
}
|
|
|
|
static QWidget *s_mainWidget = 0;
|
|
|
|
// Plugin-specific newInstance implementation, called by above method
|
|
int KontactInterface::UniqueAppHandler::newInstance()
|
|
{
|
|
if ( s_mainWidget ) {
|
|
s_mainWidget->show();
|
|
KWindowSystem::forceActiveWindow( s_mainWidget->winId() );
|
|
KStartupInfo::appStarted();
|
|
}
|
|
|
|
// Then ensure the part appears in kontact
|
|
d->mPlugin->core()->selectPlugin( d->mPlugin );
|
|
return 0;
|
|
}
|
|
|
|
Plugin *UniqueAppHandler::plugin() const
|
|
{
|
|
return d->mPlugin;
|
|
}
|
|
|
|
bool KontactInterface::UniqueAppHandler::load()
|
|
{
|
|
(void)d->mPlugin->part(); // load the part without bringing it to front
|
|
return true;
|
|
}
|
|
|
|
//@cond PRIVATE
|
|
class UniqueAppWatcher::Private
|
|
{
|
|
public:
|
|
UniqueAppHandlerFactoryBase *mFactory;
|
|
Plugin *mPlugin;
|
|
bool mRunningStandalone;
|
|
};
|
|
//@endcond
|
|
|
|
UniqueAppWatcher::UniqueAppWatcher( UniqueAppHandlerFactoryBase *factory, Plugin *plugin )
|
|
: QObject( plugin ), d( new Private )
|
|
{
|
|
d->mFactory = factory;
|
|
d->mPlugin = plugin;
|
|
|
|
// The app is running standalone if 1) that name is known to D-Bus
|
|
const QString serviceName = QLatin1String("org.kde.") + plugin->objectName();
|
|
//Needed for wince build
|
|
#undef interface
|
|
d->mRunningStandalone =
|
|
QDBusConnection::sessionBus().interface()->isServiceRegistered( serviceName );
|
|
#ifdef Q_WS_WIN
|
|
if ( d->mRunningStandalone ) {
|
|
QList<int> pids;
|
|
KPIMUtils::getProcessesIdForName( plugin->objectName(), pids );
|
|
const int mypid = getpid();
|
|
bool processExits = false;
|
|
foreach ( int pid, pids ) {
|
|
if ( mypid != pid ) {
|
|
processExits = true;
|
|
break;
|
|
}
|
|
}
|
|
if ( !processExits ) {
|
|
d->mRunningStandalone = false;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
QString owner = QDBusConnection::sessionBus().interface()->serviceOwner( serviceName );
|
|
if ( d->mRunningStandalone && ( owner == QDBusConnection::sessionBus().baseService() ) ) {
|
|
d->mRunningStandalone = false;
|
|
}
|
|
//kDebug() << " plugin->objectName()=" << plugin->objectName()
|
|
// << " running standalone:" << d->mRunningStandalone;
|
|
|
|
if ( d->mRunningStandalone ) {
|
|
QObject::connect( QDBusConnection::sessionBus().interface(),
|
|
SIGNAL(serviceOwnerChanged(QString,QString,QString)),
|
|
this, SLOT(slotApplicationRemoved(QString,QString,QString)) );
|
|
} else {
|
|
d->mFactory->createHandler( d->mPlugin );
|
|
}
|
|
}
|
|
|
|
UniqueAppWatcher::~UniqueAppWatcher()
|
|
{
|
|
delete d->mFactory;
|
|
delete d;
|
|
}
|
|
|
|
bool UniqueAppWatcher::isRunningStandalone() const
|
|
{
|
|
return d->mRunningStandalone;
|
|
}
|
|
|
|
void KontactInterface::UniqueAppWatcher::slotApplicationRemoved( const QString &name,
|
|
const QString &oldOwner,
|
|
const QString &newOwner )
|
|
{
|
|
if ( oldOwner.isEmpty() || !newOwner.isEmpty() ) {
|
|
return;
|
|
}
|
|
|
|
const QString serviceName = QLatin1String("org.kde.") + d->mPlugin->objectName();
|
|
if ( name == serviceName && d->mRunningStandalone ) {
|
|
d->mFactory->createHandler( d->mPlugin );
|
|
d->mRunningStandalone = false;
|
|
}
|
|
}
|
|
|
|
void KontactInterface::UniqueAppHandler::setMainWidget( QWidget *widget )
|
|
{
|
|
s_mainWidget = widget;
|
|
}
|
|
|
|
QWidget *KontactInterface::UniqueAppHandler::mainWidget()
|
|
{
|
|
return s_mainWidget;
|
|
}
|
|
|