summaryrefslogtreecommitdiffstats
path: root/kontact/DESIGN.dcopinteraction
diff options
context:
space:
mode:
Diffstat (limited to 'kontact/DESIGN.dcopinteraction')
-rw-r--r--kontact/DESIGN.dcopinteraction84
1 files changed, 84 insertions, 0 deletions
diff --git a/kontact/DESIGN.dcopinteraction b/kontact/DESIGN.dcopinteraction
new file mode 100644
index 00000000..f3b57598
--- /dev/null
+++ b/kontact/DESIGN.dcopinteraction
@@ -0,0 +1,84 @@
+How to implement DCOP communication between two applications so that
+1) it works when the applications are standalone (separate processes)
+2) it works when the applications are loaded as parts, embedded into kontact
+3) it behaves properly when a separate process exits/crashes.
+
+In the part
+===========
+Let's say that part 'A' wants to use the interface "Foo", via DCOP.
+(where Foo is usually a generic name, e.g. Calendar, Mailer, AlarmDaemon, etc.)
+The services which implement this interface are associated with the service type
+"DCOP/Foo".
+
+One of those services is application 'B', which implements "Foo" - note that
+'B' should make sure that the "Foo" DCOP interface is available both when
+'B' is used as standalone process and when 'B' is only loaded as a part.
+(This means that if the app doesn't use its own part, then both should implement
+"Foo", like kaddressbook does. Of course it's simpler if the app uses its own part :)
+
+Here are some code snippets that must go into the part (A) that wants to use "Foo":
+
+* Constructor:
+ m_foo_stub = 0L;
+ kapp->dcopClient()->setNotifications( true );
+ connect( kapp->dcopClient(), SIGNAL( applicationRemoved( const QCString&)),
+ this, SLOT( unregisteredFromDCOP( const QCString& )) );
+
+* Destructor:
+ kapp->dcopClient()->setNotifications( false );
+ delete m_foo_stub;
+
+[Note that setNotifications() is implemented with a refcount, this is the
+correct way to do it and it won't mess up other parts]
+
+* bool connectToFoo() method, which uses KDCOPServiceStarter::self()->findServiceFor("DCOP/Foo").
+See test part for details (plugins/test/test_part.cpp).
+
+* unregisteredFromDCOP( const QCString& appId ) slot, which will be called when
+the process implementing Foo exits. The method simply does:
+ if ( m_foo_stub && m_foo_stub->app() == appId )
+ {
+ delete m_foo_stub;
+ m_foo_stub = 0;
+ }
+
+* Now you can finally use the foo dcop interface. First you need to connect
+to it:
+ if ( !connectToFoo() )
+ return;
+
+Then you can use m_foo_stub to call the DCOP methods.
+In case of critical methods, where you want to make 100% sure that the DCOP
+call was correctly done (e.g. the remote app didn't crash during the call),
+you can use if ( !m_foo_stub->ok() ).
+
+In the kontact plugin
+=====================
+* Don't use dcopClient() until the part is loaded
+* After loading the part, you might want to create a DCOP stub to use some
+of its methods (do both in a loadPart() method, e.g.).
+* Implement createDCOPInterface( const QString& serviceType ), to
+load the part if the serviceType is one provided by it.
+
+See KAddressbookPlugin (plugins/kaddressbook/*) for a working example.
+
+Don't forget to
+===============
+* Define the service type, using a "Type=ServiceType" .desktop file,
+with "X-KDE-ServiceType=DCOP/Foo".
+See e.g. kdepim/kaddressbook/dcopaddressbook.desktop
+
+* Add DCOP/Foo to the application's ServiceTypes list, in its .desktop file
+See e.g. kdepim/kaddressbook/kaddressbook.desktop
+* Make sure that X-DCOP-ServiceType and X-DCOP-ServiceName are specified too.
+
+Designing DCOP interfaces
+=========================
+Porting the kroupware signals/slots to DCOP requires some changes.
+For instance any non-const reference (such as those used for returning
+values to the caller) has to be changed. If there is more than one
+value to be returned, you need to
+* define a structure containing all the returned values
+* define QDataStream << and >> operators for that structure.
+
+$Id$