diff --git a/kontactinterface/plugin.cpp b/kontactinterface/plugin.cpp index 1476d8754..1fbaee4de 100644 --- a/kontactinterface/plugin.cpp +++ b/kontactinterface/plugin.cpp @@ -1,325 +1,325 @@ /* This file is part of the KDE Kontact Plugin Interface Library. Copyright (c) 2001 Matthias Hoelzer-Kluepfel Copyright (c) 2002-2003 Daniel Molkentin 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 "plugin.h" #include "core.h" #include #include #include #include #include #include #include #include #include #include #include using namespace Kontact; /** Private class that helps to provide binary compatibility between releases. @internal */ //@cond PRIVATE class Plugin::Private { public: void partDestroyed(); Core *core; QList *newActions; QList *syncActions; QString identifier; QString title; QString icon; QString executableName; QString serviceName; QByteArray partLibraryName; bool hasPart; KParts::ReadOnlyPart *part; bool disabled; }; //@endcond Plugin::Plugin( Core *core, QObject *parent, const char *name ) : KXMLGUIClient( core ), QObject( parent ), d( new Private ) { setObjectName( name ); core->factory()->addClient( this ); KGlobal::locale()->insertCatalog( name ); d->core = core; d->newActions = new QList; d->syncActions = new QList; d->hasPart = true; d->part = 0; d->disabled = false; } Plugin::~Plugin() { delete d->part; delete d; } void Plugin::setIdentifier( const QString &identifier ) { d->identifier = identifier; } QString Plugin::identifier() const { return d->identifier; } void Plugin::setTitle( const QString &title ) { d->title = title; } QString Plugin::title() const { return d->title; } void Plugin::setIcon( const QString &icon ) { d->icon = icon; } QString Plugin::icon() const { return d->icon; } void Plugin::setExecutableName( const QString &bin ) { d->executableName = bin; } QString Plugin::executableName() const { return d->executableName; } void Plugin::setPartLibraryName( const QByteArray &libName ) { d->partLibraryName = libName; } bool Plugin::createDBUSInterface( const QString &serviceType ) { Q_UNUSED( serviceType ); return false; } bool Plugin::isRunningStandalone() { return false; } KParts::ReadOnlyPart *Plugin::loadPart() { return core()->createPart( d->partLibraryName ); } const KAboutData *Plugin::aboutData() { KPluginLoader loader( d->partLibraryName ); KPluginFactory *factory = loader.factory(); kDebug() << "filename:" << loader.fileName(); kDebug() << "libname:" << d->partLibraryName; if ( factory ) { if ( factory->componentData().isValid() ) { kDebug() << "returning factory component aboutdata"; return factory->componentData().aboutData(); } else { // If the componentData of the factory is invalid, the likely cause is that // the part has not been ported to use K_PLUGIN_FACTORY/K_EXPORT_PLUGIN yet. // In that case, fallback to the old method of loading component data, which // does only work for old-style parts. kDebug() << "Unable to load component data for" << loader.fileName() << "trying to use the old style plugin system now."; const KComponentData instance = KParts::Factory::partComponentDataFromLibrary( d->partLibraryName ); if ( instance.isValid() ) { return instance.aboutData(); } else { kDebug() << "Invalid instance, unable to get about information!"; } } } kError() << "Cannot load instance for" << title(); return 0; } KParts::ReadOnlyPart *Plugin::part() { if ( !d->part ) { d->part = createPart(); if ( d->part ) { connect( d->part, SIGNAL(destroyed()), SLOT(partDestroyed()) ); core()->partLoaded( this, d->part ); } } return d->part; } QString Plugin::tipFile() const { return QString(); } QString Plugin::registerClient() { if ( d->serviceName.isEmpty() ) { d->serviceName = "org.kde." + objectName().toLatin1(); #ifdef Q_WS_WIN - const QString pid = QString::number(getpid()); - d->serviceName.append(".unique-" + pid); + const QString pid = QString::number( getpid() ); + d->serviceName.append( ".unique-" + pid ); #endif QDBusConnection::sessionBus().registerService( d->serviceName ); } return d->serviceName; } int Plugin::weight() const { return 0; } void Plugin::insertNewAction( KAction *action ) { d->newActions->append( action ); } void Plugin::insertSyncAction( KAction *action ) { d->syncActions->append( action ); } QList *Plugin::newActions() const { return d->newActions; } QList *Plugin::syncActions() const { return d->syncActions; } QStringList Plugin::invisibleToolbarActions() const { return QStringList(); } bool Plugin::canDecodeMimeData( const QMimeData *data ) { Q_UNUSED( data ); return false; } Core *Plugin::core() const { return d->core; } void Plugin::select() { } void Plugin::configUpdated() { } //@cond PRIVATE void Plugin::Private::partDestroyed() { part = 0; } //@endcond void Plugin::slotConfigUpdated() { configUpdated(); } void Plugin::bringToForeground() { if ( d->executableName.isEmpty() ) { return; } #ifdef Q_WS_WIN KPIM::Utils::activateWindowForProcess( d->executableName ); #else KRun::runCommand( d->executableName, 0 ); #endif } Summary *Plugin::createSummaryWidget( QWidget *parent ) { Q_UNUSED( parent ); return 0; } bool Plugin::showInSideBar() const { return d->hasPart; } void Plugin::setShowInSideBar( bool hasPart ) { d->hasPart = hasPart; } bool Plugin::queryClose() const { return true; } void Plugin::setDisabled( bool disabled ) { d->disabled = disabled; } bool Plugin::disabled() const { return d->disabled; } void Plugin::virtual_hook( int, void * ) { //BASE::virtual_hook( id, data ); } #include "plugin.moc" // vim: sw=2 et sts=2 tw=80 diff --git a/kontactinterface/summary.cpp b/kontactinterface/summary.cpp index b219f35bc..02b3af725 100644 --- a/kontactinterface/summary.cpp +++ b/kontactinterface/summary.cpp @@ -1,172 +1,171 @@ /* This file is part of the KDE Kontact Plugin Interface Library. Copyright (c) 2003 Cornelius Schumacher Copyright (c) 2003 Daniel Molkentin 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 "summary.h" #include #include #include #include #include #include #include #include #include #include #include #include using namespace Kontact; //@cond PRIVATE namespace Kontact { class SummaryMimeData : public QMimeData { public: virtual bool hasFormat( const QString &format ) const { if ( format == "application/x-kontact-summary" ) { return true; } return false; } }; } //@endcond //@cond PRIVATE class Summary::Private { public: KStatusBar *mStatusBar; QPoint mDragStartPoint; }; //@endcond Summary::Summary( QWidget *parent ) : QWidget( parent ), d( new Private ) { setFont( KGlobalSettings::generalFont() ); setAcceptDrops( true ); } Summary::~Summary() { delete d; } int Summary::summaryHeight() const { return 1; } QWidget *Summary::createHeader( QWidget *parent, const QString &iconname, const QString &heading ) { setStyleSheet( "KHBox {" "border: 1px solid palette(window);" "border-top: 0px solid white;" "border-left: 0px solid white;" "border-right: 0px solid white;" "font: bold large;" "padding: 2px;" "}" - "KHBox > QLabel { font: bold larger; } " - ); + "KHBox > QLabel { font: bold larger; } " ); KHBox *hbox = new KHBox( parent ); //hbox->setMargin( 2 ); //hbox->setAutoFillBackground( true ); QLabel *label = new QLabel( hbox ); label->setPixmap( KIconLoader::global()->loadIcon( iconname, KIconLoader::Toolbar ) ); label->setFixedSize( label->sizeHint() ); label->setAcceptDrops( true ); label = new QLabel( heading, hbox ); label->setAlignment( Qt::AlignLeft | Qt::AlignVCenter ); label->setIndent( KDialog::spacingHint() ); hbox->setMaximumHeight( hbox->minimumSizeHint().height() ); return hbox; } QStringList Summary::configModules() const { return QStringList(); } void Summary::updateSummary( bool force ) { Q_UNUSED( force ); } void Summary::mousePressEvent( QMouseEvent *event ) { d->mDragStartPoint = event->pos(); QWidget::mousePressEvent( event ); } void Summary::mouseMoveEvent( QMouseEvent *event ) { if ( ( event->buttons() & Qt::LeftButton ) && ( event->pos() - d->mDragStartPoint ).manhattanLength() > 4 ) { QDrag *drag = new QDrag( this ); drag->setMimeData( new SummaryMimeData() ); drag->setObjectName( "SummaryWidgetDrag" ); QPixmap pm = QPixmap::grabWidget( this ); if ( pm.width() > 300 ) { pm = QPixmap::fromImage( pm.toImage().scaled( 300, 300, Qt::KeepAspectRatio, Qt::SmoothTransformation ) ); } QPainter painter; painter.begin( &pm ); painter.setPen( QPalette::AlternateBase ); painter.drawRect( 0, 0, pm.width(), pm.height() ); painter.end(); drag->setPixmap( pm ); drag->start( Qt::MoveAction ); } else { QWidget::mouseMoveEvent( event ); } } void Summary::dragEnterEvent( QDragEnterEvent *event ) { if ( event->mimeData()->hasFormat( "application/x-kontact-summary" ) ) { event->acceptProposedAction(); } } void Summary::dropEvent( QDropEvent *event ) { int alignment = ( event->pos().y() < ( height() / 2 ) ? Qt::AlignTop : Qt::AlignBottom ); emit summaryWidgetDropped( this, event->source(), alignment ); } #include "summary.moc" diff --git a/kontactinterface/uniqueapphandler.cpp b/kontactinterface/uniqueapphandler.cpp index 8b874acbc..9ee2c5d1c 100644 --- a/kontactinterface/uniqueapphandler.cpp +++ b/kontactinterface/uniqueapphandler.cpp @@ -1,242 +1,243 @@ /* This file is part of the KDE Kontact Plugin Interface Library. Copyright (c) 2003,2008 David Faure 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 #include "core.h" #include "libkdepim/utils.h" #include #include #include #include #include #include #include #include #ifdef Q_WS_WIN # include #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) + 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 Kontact; //@cond PRIVATE class UniqueAppHandler::Private { public: Plugin *mPlugin; }; //@endcond UniqueAppHandler::UniqueAppHandler( Plugin *plugin ) : d( new Private ) { //kDebug() << "plugin->objectName():" << plugin->objectName(); d->mPlugin = plugin; QDBusConnection session = QDBusConnection::sessionBus(); const QString appName = plugin->objectName(); session.registerService( "org.kde." + appName ); const QString objectName = QString( '/' ) + appName + "_PimApplication"; session.registerObject( objectName, this, QDBusConnection::ExportAllSlots ); } UniqueAppHandler::~UniqueAppHandler() { 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 Kontact::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 Kontact::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 = "org.kde." + plugin->objectName(); d->mRunningStandalone = QDBusConnection::sessionBus().interface()->isServiceRegistered( serviceName ); #ifdef Q_WS_WIN if ( d->mRunningStandalone ) { QList pids; KPIM::Utils::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 Kontact::UniqueAppWatcher::slotApplicationRemoved( const QString &name, const QString &oldOwner, const QString &newOwner ) { if ( oldOwner.isEmpty() || !newOwner.isEmpty() ) { return; } const QString serviceName = "org.kde." + d->mPlugin->objectName(); if ( name == serviceName && d->mRunningStandalone ) { d->mFactory->createHandler( d->mPlugin ); d->mRunningStandalone = false; } } void Kontact::UniqueAppHandler::setMainWidget( QWidget *widget ) { s_mainWidget = widget; } #include "uniqueapphandler.moc"