KDE Tutorial - p6

p6

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();
}

main.cpp


#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

p6Iface.h


#include "p6Iface.h"
#include <qlistview.h>
 
class MainList : public QListView, virtual public p6Iface
{
 Q_OBJECT
 
public:
 
 MainList();
 
 void add ( const QString s );
 
};

p6.h


#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 ) );
}; 

p6.cpp

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.


Scripting

One of the many benefits of DCOP is the ability to easily allow to script any application using its interface . As an example of this, we will implement a script in Python that adds a url to the bookmark list

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")  

addurl.py

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


© 1999,2000,2001 Antonio Larrosa