Next Previous Table of Contents
p6 is a very simple application that just shows a list with bookmarks.
#include <kapp.h> #include "p6.h" int main( int argc, char **argv ) { KApplication a( argc, argv, "p6" ); MainList *mylist=new MainList; mylist->resize( 300, 200 ); a.setMainWidget( mylist ); mylist->show(); return a.exec(); }
#ifndef __P6IFACE_H__ #define __P6IFACE_H__ #include <dcopobject.h> #include <qstring.h> class p6Iface : virtual public DCOPObject { K_DCOP public: k_dcop: virtual void add( const QString s ) = 0; }; #endif
#include "p6Iface.h" #include <qlistview.h> class MainList : public QListView, virtual public p6Iface { Q_OBJECT public: MainList(); void add ( const QString s ); };
#include "p6.h" #include <klocale.h> #include <kapp.h> #include <dcopclient.h> MainList::MainList() : QListView ( 0L, "Bookmarks" ), DCOPObject ( "bookmarkList" ) { addColumn( i18n("My Bookmarks") ); DCOPClient *client=kapp->dcopClient(); client->attach(); client->registerAs("p6"); }; void MainList::add( const QString s ) { insertItem ( new QListViewItem ( this , s ) ); };
Instead of using a KTMainWindow and to push source clearness over user interface design, we will use directly a QListView item.
With QListView you can create a widget with a list of items (also with different columns to show different properties of each item). It's also possible (and fast) to create a tree of items to better organize things. In this little example, we will just use it as a single column list view with ordering capabilities (that's why we aren't using a QListBox which would fit our needs as well and with a simpler API).
There's a big difference now with previous examples, we have a new file called p6Iface.h, let's see what it is and what it is for.
class p6Iface : virtual public DCOPObject { K_DCOP public: k_dcop: virtual void add( const QString s ) = 0; };
With this file we define the interface that p6 will export for other applications
to use . Using the special k_dcop tag (which will be removed by the preprocessor
before reaching the compiler), we define the object members that others will be
able to remotely call using DCOP , in this case, add
.
Note that we define this function as pure virtual, so it's not implemented in the
p6Iface class . The trick here is to use dcopidl
, a tool which
translates our .h-like interface definition to a common Interface Definition Language. This allows other applications, such as dcopidl2cpp to write for us
the skeleton implementation, which is used internally by the DCOPObject to
know which methods are available in this object.
class MainList : public QListView, virtual public p6Iface
Looking in p6.h, we can see that our main widget inherits QListView (as would be natural to show the list on the X display), but also inherits the p6Iface class that we've just defined. This way, we can implement the remotely accesible methods in usual classes as needed.
MainList::MainList() : QListView ( 0L, "Bookmarks" ), DCOPObject ( "bookmarkList" )
As we haven't implemented any p6Iface constructor, we call here the DCOPObject
one. Note that the parameter to the constructor is the name with which DCOP
will know this object, so that remote calls to one of its methods should
be made using bookmarkList
as object name.
addColumn( i18n("My Bookmarks") );
We add a column (there should be at least one to make the QListView usable).
DCOPClient *client=kapp->dcopClient(); client->attach(); client->registerAs("p6");
Now, this application is attached to the DCOP server, as we did in p5, but in a new way. As in p5 we weren't receiving any call, we just used an anonymous connection. In this case, we want other applications to connect to this one, so we should register with a name, that's what registerAs do.
Of course, that's the name others should use when making a DCOP call.
insertItem ( new QListViewItem ( this , s ) );Finally, the
add
method, takes the QString parameter, constructs
a QListViewItem with it and adds the item to the QListView.
Perhaps you wonder why there isn't a simpler way to insert a QString in a QListView. The reason is simple : A QListView object can hold much more complex cases than simple strings, for example, you can have multiple columns, and multiple columns where some of them are QPixmaps objects ( images ), etc.
To be able to use it, you'll need the xmlrpc library for Python. It's available at http://www.pythonware.com/downloads/xmlrpc-0.9.8--990621.zip , unzip it in the python library dir (usually /usr/lib/python1.5 ) . You also need to run kxmlrpcd , a xmlrpc daemon which works as a bridge between the xmlrpc protocol and the DCOP protocol.
The script we are using is the next one:
#!/usr/bin/python from xmlrpclib import * import os rc = open(os.environ['HOME'] + '/.kxmlrpcd', 'r') config = string.split(rc.read(), ',') port = config[0] auth = config[1] server = Server("http://localhost:" + port +"/p6") server.bookmarkList.add(auth, "http://www.kde.org")
I'd like to thank Kurt Granroth for providing the source code of this script as my knowledge of Python is void .
Anyway, note that we're using a localhost
address when connecting
to the server. Simply changing that line (and having the right authority), we
can connect to servers on remote hosts (even on different CPU types and
operating systems), and control remote applications from a script.
You can even script a KDE application using simply a bash script !
We have now finished examining p6 . Let's see what we can do next.
Next Previous Table of Contents