|author||toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>||2009-11-25 17:56:58 +0000|
|committer||toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>||2009-11-25 17:56:58 +0000|
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdepim@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kontact/DESIGN.dcopinteraction')
1 files changed, 84 insertions, 0 deletions
diff --git a/kontact/DESIGN.dcopinteraction b/kontact/DESIGN.dcopinteraction
new file mode 100644
@@ -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
+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":
+ m_foo_stub = 0L;
+ kapp->dcopClient()->setNotifications( true );
+ connect( kapp->dcopClient(), SIGNAL( applicationRemoved( const QCString&)),
+ this, SLOT( unregisteredFromDCOP( const QCString& )) );
+ 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
+ if ( !connectToFoo() )
+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,
+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.