diff options
Diffstat (limited to 'kontact/interfaces')
-rw-r--r-- | kontact/interfaces/Makefile.am | 15 | ||||
-rw-r--r-- | kontact/interfaces/core.cpp | 129 | ||||
-rw-r--r-- | kontact/interfaces/core.h | 102 | ||||
-rw-r--r-- | kontact/interfaces/kontactplugin.desktop | 71 | ||||
-rw-r--r-- | kontact/interfaces/plugin.cpp | 259 | ||||
-rw-r--r-- | kontact/interfaces/plugin.h | 291 | ||||
-rw-r--r-- | kontact/interfaces/summary.cpp | 116 | ||||
-rw-r--r-- | kontact/interfaces/summary.h | 94 | ||||
-rw-r--r-- | kontact/interfaces/uniqueapphandler.cpp | 201 | ||||
-rw-r--r-- | kontact/interfaces/uniqueapphandler.h | 123 |
10 files changed, 1401 insertions, 0 deletions
diff --git a/kontact/interfaces/Makefile.am b/kontact/interfaces/Makefile.am new file mode 100644 index 000000000..94a15dda3 --- /dev/null +++ b/kontact/interfaces/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I$(top_srcdir) $(all_includes) + +lib_LTLIBRARIES = libkpinterfaces.la + +libkpinterfaces_la_SOURCES = core.cpp plugin.cpp summary.cpp uniqueapphandler.cpp +libkpinterfaces_la_LDFLAGS = $(all_libraries) -no-undefined -version-info 1:0:0 +libkpinterfaces_la_LIBADD = ../../libkdepim/libkdepim.la $(LIB_KPARTS) + +kpincludedir = $(includedir)/kontact +kpinclude_HEADERS = core.h plugin.h summary.h + +METASOURCES = AUTO + +servicetypedir = $(kde_servicetypesdir) +servicetype_DATA = kontactplugin.desktop diff --git a/kontact/interfaces/core.cpp b/kontact/interfaces/core.cpp new file mode 100644 index 000000000..19ed8bade --- /dev/null +++ b/kontact/interfaces/core.cpp @@ -0,0 +1,129 @@ +/* + This file is part of KDE Kontact. + + Copyright (c) 2001 Matthias Hoelzer-Kluepfel <mhk@kde.org> + Copyright (c) 2002-2003 Daniel Molkentin <molkentin@kde.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@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 "core.h" + +#include <kparts/part.h> +#include <kparts/componentfactory.h> +#include <kdebug.h> +#include <qtimer.h> +#include <klocale.h> + +using namespace Kontact; + +class Core::Private +{ +public: + QString lastErrorMessage; +}; + +Core::Core( QWidget *parent, const char *name ) + : KParts::MainWindow( parent, name ) +{ + d = new Private; + QTimer* timer = new QTimer( this ); + mLastDate = QDate::currentDate(); + connect(timer, SIGNAL( timeout() ), SLOT( checkNewDay() ) ); + timer->start( 1000*60 ); +} + +Core::~Core() +{ + delete d; +} + +KParts::ReadOnlyPart *Core::createPart( const char *libname ) +{ + kdDebug(5601) << "Core::createPart(): " << libname << endl; + + QMap<QCString,KParts::ReadOnlyPart *>::ConstIterator it; + it = mParts.find( libname ); + if ( it != mParts.end() ) return it.data(); + + kdDebug(5601) << "Creating new KPart" << endl; + + int error = 0; + KParts::ReadOnlyPart *part = + KParts::ComponentFactory:: + createPartInstanceFromLibrary<KParts::ReadOnlyPart> + ( libname, this, 0, this, "kontact", QStringList(), &error ); + + KParts::ReadOnlyPart *pimPart = dynamic_cast<KParts::ReadOnlyPart*>( part ); + if ( pimPart ) { + mParts.insert( libname, pimPart ); + QObject::connect( pimPart, SIGNAL( destroyed( QObject * ) ), + SLOT( slotPartDestroyed( QObject * ) ) ); + } else { + // TODO move to KParts::ComponentFactory + switch( error ) { + case KParts::ComponentFactory::ErrNoServiceFound: + d->lastErrorMessage = i18n( "No service found" ); + break; + case KParts::ComponentFactory::ErrServiceProvidesNoLibrary: + d->lastErrorMessage = i18n( "Program error: the .desktop file for the service does not have a Library key." ); + break; + case KParts::ComponentFactory::ErrNoLibrary: + d->lastErrorMessage = KLibLoader::self()->lastErrorMessage(); + break; + case KParts::ComponentFactory::ErrNoFactory: + d->lastErrorMessage = i18n( "Program error: the library %1 does not provide a factory." ).arg( libname ); + break; + case KParts::ComponentFactory::ErrNoComponent: + d->lastErrorMessage = i18n( "Program error: the library %1 does not support creating components of the specified type" ).arg( libname ); + break; + } + kdWarning(5601) << d->lastErrorMessage << endl; + } + + return pimPart; +} + +void Core::slotPartDestroyed( QObject * obj ) +{ + // the part was deleted, we need to remove it from the part map to not return + // a dangling pointer in createPart + QMap<QCString, KParts::ReadOnlyPart*>::Iterator end = mParts.end(); + QMap<QCString, KParts::ReadOnlyPart*>::Iterator it = mParts.begin(); + for ( ; it != end; ++it ) { + if ( it.data() == obj ) { + mParts.remove( it ); + return; + } + } +} + +void Core::checkNewDay() +{ + if ( mLastDate != QDate::currentDate() ) + emit dayChanged( QDate::currentDate() ); + + mLastDate = QDate::currentDate(); +} + +QString Core::lastErrorMessage() const +{ + return d->lastErrorMessage; +} + +#include "core.moc" +// vim: sw=2 sts=2 et tw=80 diff --git a/kontact/interfaces/core.h b/kontact/interfaces/core.h new file mode 100644 index 000000000..2ebe088f9 --- /dev/null +++ b/kontact/interfaces/core.h @@ -0,0 +1,102 @@ +/* + This file is part of KDE Kontact. + + Copyright (c) 2001 Matthias Hoelzer-Kluepfel <mhk@kde.org> + Copyright (c) 2002-2003 Daniel Molkentin <molkentin@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. + +*/ +#ifndef KONTACT_CORE_H +#define KONTACT_CORE_H + +#include <qdatetime.h> +#include <kdepimmacros.h> +#include <kparts/mainwindow.h> +#include <kparts/part.h> + +class KAction; + +namespace Kontact +{ + +class Plugin; + +/** + This class provides the interface to the Kontact core for the plugins. +*/ +class KDE_EXPORT Core : public KParts::MainWindow +{ + Q_OBJECT + public: + virtual ~Core(); + + /** + Selects the given plugin @param plugin and raises the associated + part. + */ + virtual void selectPlugin( Kontact::Plugin *plugin ) = 0; + + /** + This is an overloaded member function. It behaves essentially like the + above function. + */ + virtual void selectPlugin( const QString &plugin ) = 0; + + /** + Returns the pointer list of available plugins. + */ + virtual QValueList<Kontact::Plugin*> pluginList() const = 0; + + /** + @internal (for Plugin) + */ + KParts::ReadOnlyPart *createPart( const char *libname ); + + /** + @internal (for Plugin) + Tell kontact that a part was loaded + */ + virtual void partLoaded( Plugin* plugin, KParts::ReadOnlyPart * part ) = 0; + + signals: + /** + Emitted when a new day starts + */ + void dayChanged( const QDate& ); + + protected: + Core( QWidget *parentWidget = 0, const char *name = 0 ); + + QString lastErrorMessage() const; + + private slots: + void slotPartDestroyed( QObject * ); + void checkNewDay(); + + private: + QMap<QCString,KParts::ReadOnlyPart *> mParts; + QDate mLastDate; + + class Private; + Private *d; +}; + +} + +#endif + +// vim: sw=2 sts=2 et tw=80 diff --git a/kontact/interfaces/kontactplugin.desktop b/kontact/interfaces/kontactplugin.desktop new file mode 100644 index 000000000..28803bc6d --- /dev/null +++ b/kontact/interfaces/kontactplugin.desktop @@ -0,0 +1,71 @@ +[Desktop Entry] +Type=ServiceType +X-KDE-ServiceType=Kontact/Plugin +Name=Kontact Plugin +Name[af]=Kontact inprop module +Name[ar]=قابس Kontact +Name[be]=Дапаўненне Кантакту +Name[bg]=Приставка на Kontact +Name[br]=Lugent Kontact +Name[bs]=Dodatak za Kontact +Name[ca]=Endollable Kontact +Name[cs]=Modul aplikace Kontact +Name[cy]=Ategyn Kontact +Name[da]=Kontact-plugin +Name[de]=Kontact-Modul +Name[el]=Πρόσθετο Kontact +Name[es]=Plugin Kontact +Name[et]=Kontacti plugin +Name[eu]=Kontact plugin-a +Name[fa]=وصلۀ Kontact +Name[fi]=Kontact-liitännäinen +Name[fr]=Module Kontact +Name[ga]=Breiseán Kontact +Name[gl]=Extensión de Kontact +Name[he]=תוסף Kontact +Name[hi]=कॉन्टेक्ट प्लगइन +Name[hu]=Kontact-bővítőmodul +Name[is]=Kontact íforrit +Name[it]=Plugin Kontact +Name[ja]=Kontact プラグイン +Name[ka]=Kontact მოდული +Name[kk]=Kontact модулі +Name[km]=កម្មវិធីជំនួយ Kontact +Name[lt]=Kontact priedas +Name[mk]=Приклучок за Контакт +Name[ms]=Plugin Kontact +Name[nb]=Kontact-programtillegg +Name[nds]=Kontact-Moduul +Name[ne]=सम्पर्क प्लगइन +Name[nn]=Kontact-programtillegg +Name[pl]=Wtyczka Kontakt +Name[pt]='Plugin' do Kontact +Name[pt_BR]=Plug-in do Kontact +Name[ro]=Modul Kontact +Name[ru]=Модуль Kontact +Name[se]=Kontact-lassemoduvla +Name[sl]=Vstavek za Kontact +Name[sr]=Прикључак Kontact-а +Name[sr@Latn]=Priključak Kontact-a +Name[sv]=Kontact-insticksprogram +Name[ta]=சொருகுப்பொருளை தொடர்புக்கொள் +Name[tg]=Модули Kontact +Name[tr]=Kontact Eklentisi +Name[uk]=Втулок Kontact +Name[uz]=Kontact uchun plagin +Name[uz@cyrillic]=Kontact учун плагин +Name[zh_CN]=Kontact 插件 +Name[zh_TW]=Kontack 外掛程式 + +[PropertyDef::X-KDE-KontactPluginVersion] +Type=int +[PropertyDef::X-KDE-KontactPartLibraryName] +Type=QString +[PropertyDef::X-KDE-KontactPartExecutableName] +Type=QString +[PropertyDef::X-KDE-KontactPartLoadOnStart] +Type=bool +[PropertyDef::X-KDE-KontactPluginHasSummary] +Type=bool +[PropertyDef::X-KDE-KontactPluginHasPart] +Type=bool diff --git a/kontact/interfaces/plugin.cpp b/kontact/interfaces/plugin.cpp new file mode 100644 index 000000000..33662015c --- /dev/null +++ b/kontact/interfaces/plugin.cpp @@ -0,0 +1,259 @@ +/* + This file is part of KDE Kontact. + + Copyright (c) 2001 Matthias Hoelzer-Kluepfel <mhk@kde.org> + Copyright (c) 2002-2003 Daniel Molkentin <molkentin@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 <qobjectlist.h> + +#include <dcopclient.h> +#include <kaboutdata.h> +#include <kglobal.h> +#include <kparts/componentfactory.h> +#include <kdebug.h> +#include <kinstance.h> +#include <krun.h> + +#include "core.h" +#include "plugin.h" + +using namespace Kontact; + +class Plugin::Private +{ + public: + Kontact::Core *core; + DCOPClient *dcopClient; + QPtrList<KAction> *newActions; + QPtrList<KAction> *syncActions; + QString identifier; + QString title; + QString icon; + QString executableName; + QCString partLibraryName; + bool hasPart; + KParts::ReadOnlyPart *part; + bool disabled; +}; + + +Plugin::Plugin( Kontact::Core *core, QObject *parent, const char *name ) + : KXMLGUIClient( core ), QObject( parent, name ), d( new Private ) +{ + core->factory()->addClient( this ); + KGlobal::locale()->insertCatalogue(name); + + d->core = core; + d->dcopClient = 0; + d->newActions = new QPtrList<KAction>; + d->syncActions = new QPtrList<KAction>; + d->hasPart = true; + d->part = 0; + d->disabled = false; +} + + +Plugin::~Plugin() +{ + delete d->part; + delete d->dcopClient; + 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 QCString &libName ) +{ + d->partLibraryName = libName; +} + +KParts::ReadOnlyPart *Plugin::loadPart() +{ + return core()->createPart( d->partLibraryName ); +} + +const KAboutData *Plugin::aboutData() +{ + kdDebug(5601) << "Plugin::aboutData(): libname: " << d->partLibraryName << endl; + + const KInstance *instance = + KParts::Factory::partInstanceFromLibrary( d->partLibraryName ); + + if ( instance ) { + return instance->aboutData(); + } else { + kdError() << "Plugin::aboutData(): Can't load instance for " + << title() << endl; + 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::null; +} + + +DCOPClient* Plugin::dcopClient() const +{ + if ( !d->dcopClient ) { + d->dcopClient = new DCOPClient(); + // ### Note: maybe we could use executableName().latin1() instead here. + // But this requires that dcopClient is NOT called by the constructor, + // and is called by some new virtual void init() later on. + d->dcopClient->registerAs( name(), false ); + } + + return d->dcopClient; +} + +void Plugin::insertNewAction( KAction *action ) +{ + d->newActions->append( action ); +} + +void Plugin::insertSyncAction( KAction *action ) +{ + d->syncActions->append( action ); +} + +QPtrList<KAction> *Plugin::newActions() const +{ + return d->newActions; +} + +QPtrList<KAction> *Plugin::syncActions() const +{ + return d->syncActions; +} + +Kontact::Core *Plugin::core() const +{ + return d->core; +} + +void Plugin::select() +{ +} + +void Plugin::configUpdated() +{ +} + +void Plugin::partDestroyed() +{ + d->part = 0; +} + +void Plugin::slotConfigUpdated() +{ + configUpdated(); +} + +void Plugin::bringToForeground() +{ + if (!d->executableName.isEmpty()) + KRun::runCommand(d->executableName); +} + +bool Kontact::Plugin::showInSideBar() const +{ + return d->hasPart; +} + +void Kontact::Plugin::setShowInSideBar( bool hasPart ) +{ + d->hasPart = hasPart; +} + +void Kontact::Plugin::setDisabled( bool disabled ) +{ + d->disabled = disabled; +} + +bool Kontact::Plugin::disabled() const +{ + return d->disabled; +} + +void Kontact::Plugin::loadProfile( const QString& ) +{ +} + +void Kontact::Plugin::saveToProfile( const QString& ) const +{ +} + +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/kontact/interfaces/plugin.h b/kontact/interfaces/plugin.h new file mode 100644 index 000000000..c80227984 --- /dev/null +++ b/kontact/interfaces/plugin.h @@ -0,0 +1,291 @@ +/* + This file is part of KDE Kontact. + + Copyright (c) 2001 Matthias Hoelzer-Kluepfel <mhk@kde.org> + Copyright (c) 2002-2003 Daniel Molkentin <molkentin@kde.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@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. +*/ + +#ifndef KONTACT_PLUGIN_H +#define KONTACT_PLUGIN_H + +#include <qobject.h> +#include <kxmlguiclient.h> +#include <kdepimmacros.h> +#include <qptrlist.h> + +class QStringList; +class DCOPClient; +class DCOPObject; +class KAboutData; +class KAction; +class KConfig; +class QWidget; +namespace KParts { class ReadOnlyPart; } + +/** + Increase this version number whenever you make a change + in the API. + */ +#define KONTACT_PLUGIN_VERSION 6 + +namespace Kontact +{ + +class Core; +class Summary; + +/** + Base class for all Plugins in Kontact. Inherit from it + to get a plugin. It can insert an icon into the sidepane, + add widgets to the widgetstack and add menu items via XMLGUI. + */ +class KDE_EXPORT Plugin : public QObject, virtual public KXMLGUIClient +{ + Q_OBJECT + + public: + /** + Creates a new Plugin, note that name parameter name is required if + you want your plugin to do dcop via it's own instance of + DCOPClient by calling dcopClient. + @note name MUST be the name of the application that + provides the part! This is the name used for DCOP registration. + It's ok to have several plugins using the same application name. + */ + Plugin( Core *core, QObject *parent, const char *name ); + + ~Plugin(); + + /** + Sets the identifier. + */ + void setIdentifier( const QString &identifier ); + + /** + Returns the identifier. It is used as argument for several + methods of Kontacts core. + */ + QString identifier() const; + + /** + Sets the localized title. + */ + void setTitle( const QString &title ); + + /** + Returns the localized title. + */ + QString title() const; + + /** + Sets the icon name. + */ + void setIcon( const QString &icon ); + + /** + Returns the icon name. + */ + QString icon() const; + + /** + Sets the name of executable (if existant). + */ + void setExecutableName( const QString &bin ); + + /** + Returns the name of the binary (if existant). + */ + QString executableName() const; + + /** + Set name of library which contains the KPart used by this plugin. + */ + void setPartLibraryName( const QCString & ); + + /** + Create the DCOP interface for the given @p serviceType, if this + plugin provides it. Return false otherwise. + */ + virtual bool createDCOPInterface( const QString& /*serviceType*/ ) { return false; } + + /** + Reimplement this method and return wether a standalone application is still running + This is only required if your part is also available as standalone application. + */ + virtual bool isRunningStandalone() { return false; } + + /** + Reimplement this method if your application needs a different approach to be brought + in the foreground. The default behaviour is calling the binary. + This is only required if your part is also available as standalone application. + */ + virtual void bringToForeground(); + + /** + Reimplement this method if you want to add your credits to the Kontact + about dialog. + */ + virtual const KAboutData *aboutData(); + + /** + You can use this method if you need to access the current part. You can be + sure that you always get the same pointer as long as the part has not been + deleted. + */ + KParts::ReadOnlyPart *part(); + + /** + Reimplement this method and return the a path relative to "data" to the tips file. + */ + virtual QString tipFile() const; + + /** + This function is called when the plugin is selected by the user before the + widget of the KPart belonging to the plugin is raised. + */ + virtual void select(); + + /** + This function is called whenever the config dialog has been closed + successfully. + */ + virtual void configUpdated(); + + /** + Reimplement this method if you want to add a widget for your application + to Kontact's summary page. + */ + virtual Summary *createSummaryWidget( QWidget * /*parent*/ ) { return 0; } + + /** + Returns wether the plugin provides a part that should be shown in the sidebar. + */ + virtual bool showInSideBar() const; + + /** + Set if the plugin provides a part that should be shown in the sidebar. + */ + void setShowInSideBar( bool hasPart ); + + /** + Reimplement this method if you want to add checks before closing down the main kontact + window. Return true if it's OK to close the window. If any loaded plugin returns false + from this method, then the main kontact window will not close. + */ + virtual bool queryClose() const { return true; } + + /** + Retrieve the current DCOP Client for the plugin. + + The clients name is taken from the name argument in the constructor. + @note: The DCOPClient object will only be created when this method is + called for the first time. Make sure that the part has been loaded + before calling this method, if it's the one that contains the DCOP + interface that other parts might use. + */ + DCOPClient *dcopClient() const; + + /** + Return the weight of the plugin. The higher the weight the lower it will + be displayed in the sidebar. The default implementation returns 0. + */ + virtual int weight() const { return 0; } + + /** + Insert "New" action. + */ + void insertNewAction( KAction *action ); + + /** + Insert "Sync" action. + */ + void insertSyncAction( KAction *action ); + + /** + FIXME: write API doc for Kontact::Plugin::newActions(). + */ + QPtrList<KAction>* newActions() const; + + /** + FIXME: write API doc for Kontact::Plugin::syncActions(). + */ + QPtrList<KAction>* syncActions() const; + + /** + Returns a list of action name which shall be hidden in the main toolbar. + */ + virtual QStringList invisibleToolbarActions() const { return QStringList(); } + + /** + Return, if the plugin can handle the drag object of the given mime type. + */ + virtual bool canDecodeDrag( QMimeSource * ) { return false; } + + /** + Process drop event. + */ + virtual void processDropEvent( QDropEvent * ) {} + + virtual void loadProfile( const QString& directoryPath ); + + virtual void saveToProfile( const QString& directoryPath ) const; + + /** + * Session management: read properties + */ + virtual void readProperties( KConfig * ) {} + + /** + * Session management: save properties + */ + virtual void saveProperties( KConfig * ) {} + + Core *core() const; + + bool disabled() const; + void setDisabled( bool v ); + + public slots: + /** + internal usage + */ + void slotConfigUpdated(); + + protected: + /** + Reimplement and return the part here. Reimplementing createPart() is + mandatory! + */ + virtual KParts::ReadOnlyPart *createPart() = 0; + + KParts::ReadOnlyPart *loadPart(); + + virtual void virtual_hook( int id, void* data ); + + private slots: + void partDestroyed(); + + private: + class Private; + Private *d; +}; + +} + +#endif diff --git a/kontact/interfaces/summary.cpp b/kontact/interfaces/summary.cpp new file mode 100644 index 000000000..f4e38771d --- /dev/null +++ b/kontact/interfaces/summary.cpp @@ -0,0 +1,116 @@ +/* + This file is part of KDE Kontact. + + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + Copyright (c) 2003 Daniel Molkentin <molkentin@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 "summary.h" + +#include <qimage.h> +#include <qdragobject.h> +#include <qhbox.h> +#include <qfont.h> +#include <qlabel.h> +#include <qpainter.h> + +#include <kiconloader.h> +#include <kdialog.h> + +using namespace Kontact; + +Summary::Summary( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + setAcceptDrops( true ); +} + +Summary::~Summary() +{ +} + +QWidget* Summary::createHeader(QWidget *parent, const QPixmap& icon, const QString& heading) +{ + QHBox* hbox = new QHBox( parent ); + hbox->setMargin( 2 ); + + QFont boldFont; + boldFont.setBold( true ); + boldFont.setPointSize( boldFont.pointSize() + 2 ); + + QLabel *label = new QLabel( hbox ); + label->setPixmap( icon ); + label->setFixedSize( label->sizeHint() ); + label->setPaletteBackgroundColor( colorGroup().mid() ); + label->setAcceptDrops( true ); + + label = new QLabel( heading, hbox ); + label->setAlignment( AlignLeft|AlignVCenter ); + label->setIndent( KDialog::spacingHint() ); + label->setFont( boldFont ); + label->setPaletteForegroundColor( colorGroup().light() ); + label->setPaletteBackgroundColor( colorGroup().mid() ); + + hbox->setPaletteBackgroundColor( colorGroup().mid() ); + + hbox->setMaximumHeight( hbox->minimumSizeHint().height() ); + + return hbox; +} + +void Summary::mousePressEvent( QMouseEvent *event ) +{ + mDragStartPoint = event->pos(); + + QWidget::mousePressEvent( event ); +} + +void Summary::mouseMoveEvent( QMouseEvent *event ) +{ + if ( (event->state() & LeftButton) && + (event->pos() - mDragStartPoint).manhattanLength() > 4 ) { + + QDragObject *drag = new QTextDrag( "", this, "SummaryWidgetDrag" ); + + QPixmap pm = QPixmap::grabWidget( this ); + if ( pm.width() > 300 ) + pm = pm.convertToImage().smoothScale( 300, 300, QImage::ScaleMin ); + + QPainter painter; + painter.begin( &pm ); + painter.setPen( Qt::gray ); + painter.drawRect( 0, 0, pm.width(), pm.height() ); + painter.end(); + drag->setPixmap( pm ); + drag->dragMove(); + } else + QWidget::mouseMoveEvent( event ); +} + +void Summary::dragEnterEvent( QDragEnterEvent *event ) +{ + event->accept( QTextDrag::canDecode( event ) ); +} + +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/kontact/interfaces/summary.h b/kontact/interfaces/summary.h new file mode 100644 index 000000000..8ef96ef2c --- /dev/null +++ b/kontact/interfaces/summary.h @@ -0,0 +1,94 @@ +/* + This file is part of KDE Kontact. + + Copyright (c) 2003 Cornelius Schumacher <schumacher@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. +*/ +#ifndef KONTACT_SUMMARY_H +#define KONTACT_SUMMARY_H + +#include <qwidget.h> +#include <qpixmap.h> +#include <kdepimmacros.h> + +class KStatusBar; + +namespace Kontact +{ + +/** + Summary widget for display in the Summary View plugin. + */ +class KDE_EXPORT Summary : public QWidget +{ + Q_OBJECT + + public: + Summary( QWidget *parent, const char *name = 0 ); + + virtual ~Summary(); + + /** + Return logical height of summary widget. This is used to calculate how + much vertical space relative to other summary widgets this widget will use + in the summary view. + */ + virtual int summaryHeight() const { return 1; } + + /** + Creates a heading for a typical summary view with an icon and a heading. + */ + QWidget *createHeader( QWidget* parent, const QPixmap &icon, + const QString& heading ); + + /** + Return list of strings identifying configuration modules for this summary + part. The string has to be suitable for being passed to + KCMultiDialog::addModule(). + */ + virtual QStringList configModules() const { return QStringList(); } + + public slots: + virtual void configChanged() {} + + /** + This is called if the displayed information should be updated. + @param force true if the update was requested by the user + */ + virtual void updateSummary( bool force = false ) { Q_UNUSED( force ); } + + signals: + void message( const QString &message ); + void summaryWidgetDropped( QWidget *target, QWidget *widget, int alignment ); + + protected: + virtual void mousePressEvent( QMouseEvent* ); + virtual void mouseMoveEvent( QMouseEvent* ); + virtual void dragEnterEvent( QDragEnterEvent* ); + virtual void dropEvent( QDropEvent* ); + + private: + KStatusBar *mStatusBar; + QPoint mDragStartPoint; + + class Private; + Private *d; +}; + +} + +#endif diff --git a/kontact/interfaces/uniqueapphandler.cpp b/kontact/interfaces/uniqueapphandler.cpp new file mode 100644 index 000000000..de77df7d5 --- /dev/null +++ b/kontact/interfaces/uniqueapphandler.cpp @@ -0,0 +1,201 @@ +/* + This file is part of KDE Kontact. + + Copyright (c) 2003 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 <kstartupinfo.h> +#include <kapplication.h> +#include <kcmdlineargs.h> +#include "core.h" +#include <kwin.h> +#include <dcopclient.h> +#include <kdebug.h> +#include <klocale.h> +#include <kuniqueapplication.h> + +/* + 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 + 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 "dcop kmail kmail 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; + +int UniqueAppHandler::newInstance() +{ + // This bit is duplicated from KUniqueApplication::newInstance() + if ( kapp->mainWidget() ) { + kapp->mainWidget()->show(); + KWin::forceActiveWindow( kapp->mainWidget()->winId() ); + KStartupInfo::appStarted(); + } + + // Then ensure the part appears in kontact + mPlugin->core()->selectPlugin( mPlugin ); + return 0; +} + +bool UniqueAppHandler::process( const QCString &fun, const QByteArray &data, + QCString& replyType, QByteArray &replyData ) +{ + if ( fun == "newInstance()" ) { + replyType = "int"; + + KCmdLineArgs::reset(); // forget options defined by other "applications" + loadCommandLineOptions(); // implemented by plugin + + // This bit is duplicated from KUniqueApplication::processDelayed() + QDataStream ds( data, IO_ReadOnly ); + KCmdLineArgs::loadAppArgs( ds ); + if ( !ds.atEnd() ) { // backwards compatibility + QCString asn_id; + ds >> asn_id; + kapp->setStartupId( asn_id ); + } + + QDataStream _replyStream( replyData, IO_WriteOnly ); + _replyStream << newInstance(); + + // OK, we're done, reload the initial kontact command line options, + // so that "kontact --module foo" keeps working (#103775). + + KCmdLineArgs::reset(); // forget options defined above + loadKontactCommandLineOptions(); + + } else if ( fun == "load()" ) { + replyType = "bool"; + (void)mPlugin->part(); // load the part without bringing it to front + + QDataStream _replyStream( replyData, IO_WriteOnly ); + _replyStream << true; + } else { + return DCOPObject::process( fun, data, replyType, replyData ); + } + return true; +} + +QCStringList UniqueAppHandler::interfaces() +{ + QCStringList ifaces = DCOPObject::interfaces(); + ifaces += "Kontact::UniqueAppHandler"; + return ifaces; +} + +QCStringList UniqueAppHandler::functions() +{ + QCStringList funcs = DCOPObject::functions(); + funcs << "int newInstance()"; + funcs << "bool load()"; + return funcs; +} + +UniqueAppWatcher::UniqueAppWatcher( UniqueAppHandlerFactoryBase* factory, Plugin* plugin ) + : QObject( plugin ), mFactory( factory ), mPlugin( plugin ) +{ + // The app is running standalone if 1) that name is known to DCOP + mRunningStandalone = kapp->dcopClient()->isApplicationRegistered( plugin->name() ); + + // and 2) it's not registered by kontact (e.g. in another plugin) + if ( mRunningStandalone && kapp->dcopClient()->findLocalClient( plugin->name() ) ) + mRunningStandalone = false; + + if ( mRunningStandalone ) { + kapp->dcopClient()->setNotifications( true ); + connect( kapp->dcopClient(), SIGNAL( applicationRemoved( const QCString& ) ), + this, SLOT( unregisteredFromDCOP( const QCString& ) ) ); + } else { + mFactory->createHandler( mPlugin ); + } +} + +UniqueAppWatcher::~UniqueAppWatcher() +{ + if ( mRunningStandalone ) + kapp->dcopClient()->setNotifications( false ); + + delete mFactory; +} + +void UniqueAppWatcher::unregisteredFromDCOP( const QCString& appId ) +{ + if ( appId == mPlugin->name() && mRunningStandalone ) { + disconnect( kapp->dcopClient(), SIGNAL( applicationRemoved( const QCString& ) ), + this, SLOT( unregisteredFromDCOP( const QCString& ) ) ); + kdDebug(5601) << k_funcinfo << appId << endl; + mFactory->createHandler( mPlugin ); + kapp->dcopClient()->setNotifications( false ); + mRunningStandalone = false; + } +} + +static KCmdLineOptions options[] = +{ + { "module <module>", I18N_NOOP( "Start with a specific Kontact module" ), 0 }, + { "iconify", I18N_NOOP( "Start in iconified (minimized) mode" ), 0 }, + { "list", I18N_NOOP( "List all possible modules and exit" ), 0 }, + KCmdLineLastOption +}; + +void Kontact::UniqueAppHandler::loadKontactCommandLineOptions() +{ + KCmdLineArgs::addCmdLineOptions( options ); + KUniqueApplication::addCmdLineOptions(); + KApplication::addCmdLineOptions(); +} + +#include "uniqueapphandler.moc" diff --git a/kontact/interfaces/uniqueapphandler.h b/kontact/interfaces/uniqueapphandler.h new file mode 100644 index 000000000..23a593af6 --- /dev/null +++ b/kontact/interfaces/uniqueapphandler.h @@ -0,0 +1,123 @@ +/* + This file is part of KDE Kontact. + + Copyright (c) 2003 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. +*/ + +#ifndef KONTACT_UNIQUEAPPHANDLER_H +#define KONTACT_UNIQUEAPPHANDLER_H + +#include <dcopobject.h> +#include <plugin.h> +#include <kdepimmacros.h> + +namespace Kontact +{ + +/** + * DCOP Object that has the name of the standalone application (e.g. "kmail") + * and implements newInstance() so that running the separate application does + * the right thing when kontact is running. + * By default this means simply bringing the main window to the front, + * but newInstance can be reimplemented. + */ +class KDE_EXPORT UniqueAppHandler : public DCOPObject +{ + K_DCOP + + public: + UniqueAppHandler( Plugin* plugin ) : DCOPObject( plugin->name() ), mPlugin( plugin ) {} + + /// This must be reimplemented so that app-specific command line options can be parsed + virtual void loadCommandLineOptions() = 0; + + /// We can't use k_dcop and dcopidl here, because the data passed + /// to newInstance can't be expressed in terms of normal data types. + virtual int newInstance(); + + Plugin* plugin() const { return mPlugin; } + + /// Load the kontact command line options. + static void loadKontactCommandLineOptions(); + + private: + Plugin* mPlugin; +}; + +/// Base class for UniqueAppHandler +class UniqueAppHandlerFactoryBase +{ + public: + virtual UniqueAppHandler* createHandler( Plugin* ) = 0; +}; + +/** + * Used by UniqueAppWatcher below, to create the above UniqueAppHandler object + * when necessary. + * The template argument is the UniqueAppHandler-derived class. + * This allows to remove the need to subclass UniqueAppWatcher. + */ +template <class T> class UniqueAppHandlerFactory : public UniqueAppHandlerFactoryBase +{ + public: + virtual UniqueAppHandler* createHandler( Plugin* plugin ) { + (void)plugin->dcopClient(); // ensure that we take over the DCOP name + return new T( plugin ); + } +}; + + +/** + * If the standalone application is running by itself, we need to watch + * for when the user closes it, and activate the uniqueapphandler then. + * This prevents, on purpose, that the standalone app can be restarted. + * Kontact takes over from there. + * + */ +class KDE_EXPORT UniqueAppWatcher : public QObject +{ + Q_OBJECT + + public: + /** + * Create an instance of UniqueAppWatcher, which does everything necessary + * for the "unique application" behavior: create the UniqueAppHandler as soon + * as possible, i.e. either right now or when the standalone app is closed. + * + * @param factory templatized factory to create the handler. Example: + * ... Note that the watcher takes ownership of the factory. + * @param plugin is the plugin application + */ + UniqueAppWatcher( UniqueAppHandlerFactoryBase* factory, Plugin* plugin ); + + virtual ~UniqueAppWatcher(); + + bool isRunningStandalone() const { return mRunningStandalone; } + + protected slots: + void unregisteredFromDCOP( const QCString& appId ); + + private: + bool mRunningStandalone; + UniqueAppHandlerFactoryBase* mFactory; + Plugin* mPlugin; +}; + +} // namespace + +#endif /* KONTACT_UNIQUEAPPHANDLER_H */ |