The K Desktop Environment

Next Previous Table of Contents

6. The KDE Daemon

Simon Hausmann <hausmann@kde.org>

v1.0 26, June 1999

This documentation describes the KDE Daemon, the services it provides and how to use it. So if you're dealing with CORBA servers in the KDE or if you're interested in a smart way of accessing KService data in your application then you might want to read this and use kded

6.1 Introduction

The KDE Daemon, herein simply named kded, is a central daemon in the KDE Desktop Environment. It provides three services:

6.2 Using The KDE Daemon In Your Application

Before we can use any of kded's services, we have to know something about it's "position" in the KDE and the way it itself and the services can be accessed.

As kded uses CORBA to communicate with it's clients, your application (as client), has to

The first two points are fixed for all clients, the third one depends on the specific client. In general you have to choices:

Although kded uses CORBA extensively, the API is kept simple and free from complicated CORBA stuff. In fact when talking about kded and it's API not the kded server is meant but the KDE Daemon library. This library contains the interface to the server (for the clients) as well as the whole server functionality. The reason for this is based on the idea that an application using kded should not be forced to rely on an existing kded server binary nor a running server at all. The following three situations may exist when a client app gets started:

To sum it up: libkded will always make sure that the services of kded are available for your client application, no matter in what alien environment the app is running :-) . And, although you don't have to care about this, you can optionally control this behaviour of libkded by adding one of the following three commandline arguments to your app:

Your actual interface to kded and it's services is the KdedInstance class, defined in kded_instance.h . So if you want to use kded (I guess that's why you're reading this shit ;) ) then make sure to create one single instance of it, preferably by adding the following line somewhere in the beginning of your main() :

KdedInstance( argc, argv, _a_reference_to_the_orb_here_ );
If you're using KOMApplication as application object (make sure to create the instance before this line) , then you're fine by specifying komapp_orb as reference to the ORB.

As there is always only one single instance of this class, you can simply access it by the static self() method of the class from anywhere you want. No need to pass KdedInstance arguments all around in your program ;-) .

For further information about KdedInstance you might want to read kded_instance.h , it's pretty good documented.

6.3 KTrader

As already mentioned in the introduction, KTrader gives you access to the registry. "Now what the hell is the registry?" you might ask. As this is just a documentation about kded/libkded, I can only respond: "Please consult the documentation of/in libkio for more information" :-} . Just one thing about it here: KTrader loads the whole and bloaty registry for you. Thanks to the magic of libkio the loaded registry will always be in sync with the "real" registry, the .desktop files in the following standard directories (both types, the system wide and the user ones) :

Now over to KTrader and it's API. Similar to KdedInstance there can be only one single instance. The difference is that you don't have to care about allocating it, just simply get a reference to the KTrader by calling the ktrader() method of KdedInstance . And: don't even think about deleting the returned reference! Just simply use it and be happy with it :-) . (hey, kded is designed to be easy to use, no need for difficult stuff...)

The KTrader API is even so simple that it contains only two methods ;-) . But before I describe these methods you have to know something about the kind of data KTrader returns. In simple words: You will always get a list of KService objects. More detailed: The returned list is a QValueList and the entries are KSharedPtr's (FIXME: will soon be renamed to QSharedPtr, as it will become part of Qt.... AFAIK) to KService objects. Please read the corresponding Qt documentation about these two classes. The big advantage of using these two template classes is that everything becomes easy for you and that the memory consumption is kept at a minimum . You don't have to care about pointers, freeing them and cleaning up the list, as long as you use KTrader::ServicePtr variables to hold the KService objects and as long as you use KTrader::OfferList to pass the list around in your program. So: Remember to always use these two types when dealing with KTrader!

Now over to the two methods.

KTrader::listServices() returns your a list of all available services in the whole KDE. (no need for further explanations I think...)

KTrader::query() is the key method of this beast. It performs a lookup in the registry database, given your information about what you want to have. The first argument is the name of the servicetype which all returned services must implement. If you're unsure about the word "servicetype" , then you can replace it with "mimetype" , for most, but not all, cases.

The second argument is an additional constraint expression, which has to be fulfilled by a service.

The third argument is a preference expression after which the returned services will be sorted. The value of the expression has to be numeric.

The syntax of these two expressions is equal with the language of the standard CORBA Trader (this is due to the fact that the parsing code is from the COS Trader of MICO) . The language is not very difficult and I don't want to bloat this documentation with further explanations about it. Please consult your CORBA literature for more information. Just one thing you have to know: Comparisons are always done with the properties of the KService object, which are the standard entries (Name, ServiceType, RepoIds, ...) plus the ones specified in the servicetype declaration and read by KService.

Well, after so much theoretical explanations it's time for some practical example code:

  ...
  //get a reference to the KTrader
  KTrader *trader = KdedInstance::self()->ktrader();

  ...
  //will return a list of all services which implement the servicetype
  //named "text/plain"
  KTrader::OfferList offers = trader->query( "text/plain" );


  ...
  //will return a list of all services which implement the servicetype
  //named "image/gif" and which have the AllowAsDefault property set true
  KTrader::OfferList offers = trader->query( "image/gif", "AllowAsDefault == TRUE" );

  ...
  //will return KSpread ;-)
  KTrader::OfferList offers = trader->query( "KOfficeDocument", "(Exec == 'kspread') and (Path != '/opt/gnome/bin')" );

  ...
  //will return a list of all services which implement the servicetype
  //named "BlahFoo" and which will be sorted (from lowest to highest) by
  //the value of the property "Price" , declared in the servicetype
  //declaration of BlahFoo.
  KTrader::OfferList offers = trader->query( "BlahFoo", QString::null, "min Price" );

Please note that KTrader, since it queries libkio for services, will always return services sorted by the user's preferences for the specific servicetype. These preferences can be specified in the file "profilerc" .

KTraderServiceProvider

This section requires to be familiar with libkio and it is meant for everybody who wants to use KRun in his application.

KRun requires a fully loaded registry in order to resolve mimetype <-> application bindings. A fully loaded registry means that you need a KServiceTypeFactory and a KServiceFactory, which both load the appropriate KServiceTypeKService objects. Now the KServiceType information doesn't need that much memory, but the KService object really eat loooots of it. And isn't it kind of stupid to load this information if this is already done by kded? Yes, it is ;-) .

What we would need is to make KRun query KTrader for KService data, instead of directly using KServiceTypeProfile. Fortunately KRun is flexible enough for this, we just need a re-implementation of the KServiceProvider, defined in krun.h and used by KRun. Guess what, but KTrader provides you this re-implementation :-) . Just have a look at the end of ktrader.h.

To sum it up: The following line makes KRun query kded, in your application:

  ...
  //place this somewhere BEFORE the first usage of KRun, preferable somewhere
  //in main()
  KTraderServiceProvider serviceProvider;
  ...
That's all, except that you must have a KdedInstance in order to be able to use it.

6.4 KActivator

One often mentioned problem, when talking about applications which provide their services via CORBA, is how to start and access these services. Solutions like making apps write the IOR of an object somewhere into a file in the filesystem or similar approaches are just hacks ;-) . Better use KActivator, since it can automatically, on demand, start servers for you or use already running ones. This is accomplished with the help of the mediators for BOA/POA and the IMR (Implementation Repository), both provided by MICO. Fortunately you don't have to deal with IMR entries and the mediators.

Before you can use KActivator to start a server for you, you have to register the server's service. There are two possible ways, the last one is highly recommended though:

For the second point it's important that the .desktop file is available for KRegistry, by placing it in a directory which gets scanned by the registry. If your application has already a .desktop file in the applnk tree for example, then you're fine with adding the necessary fields in there. Otherwise the directory named "services" (either system-wide or user-local) is the best place for it. If you provide the CORBA service information this way, then KActivator will automatically detect it and register it automatically at the IMR. This means that it is immediately available for KActivator and thus to your client app. And since KRegistry is such a cool thing :-) , you can do all this even at run-time, when kded is running. Just place the .desktop file in one of the right directories for it and KActivator will update the IMR on-the-fly. The same applies obviously for just deleted or modified .desktop files, which will make KActivator adjust the IMR. Now you might get the idea why this is the preferred way :-)) .

Now that you know how to register CORBA services you will want to know how to "access" it. activateService() is your friend here. Simply pass it the name of the service, the repository id of the server object and the object's tag and it will return you a functional object reference. That's all :-)

Depending on the service's activation mode, KActivator will either return a reference to an already running server or it will start a new instance.

One note about the returned object reference: This is a virtual reference, which means that that server object is started when the first call is invoked on this reference, thus making your server get started "lazy", only on-demand. But that's just additional information, you don't have to deal and know about it at all. Just be happy with your functional object reference :-) .

Want some examples? Here we go:

This is how a .desktop file could look like, assuming that the commandline "--server" starts the app in CORBA server mode:

Name=MyApp
Exec=fooblah
CORBAExec=fooblah --server
X-KDE-RepoIds=IDL:Foo/Blah:1.0#MyFoo
X-KDE-ActivationMode=shared

If KActivator "gets" this file, it will register the service and then you're able to do something like this:

  ...
  KActivator *activator = KdedInstance::self()->kactivator();
  ...
  CORBA::Object_var obj = activator->activateServer( "MyApp", "IDL:Foo/Blah:1.0", "MyFoo );
  ...

The above example will either start a new fooblah instance or connect to a running one.

For further information please have a look at the examples in kdelibs/corba/tutorials/kded . The example application there registers the server manually via registerService .

Please note: The server has to be started by kded in order to make KActivator return a reference to a running one. Executing "fooblah" from somewhere else will not make KActivator use it. This is a problem for persistent servers like KDesktop for example. But there's a solution available, just read the next chapter about the KDE Naming Service :-) .

6.5 KNaming

The KDE Naming Service, KNaming, is also a very simple service, but it's pretty useful and in some cases a very nice solution to make a CORBA client connect to a persistent CORBA server.

With KNaming you can bind a freely chooseable name to a CORBA object. And since kded is system (session) wide available, your object becomes available for any client which is able to connect to kded.

There's not much to explain here :-} , so I suggest having a look at the KNaming API, in knaming.h.

Example code can be, again, found in kdelibs/corba/tutorials/kded . Here's just a short real example situation:

Just think of KDesktop, that nice app providing your background desktop icons. It provides some functionality via CORBA, just have a look at kdesktop.idl to see what I'm talking about. Now the problem for KDesktop is: How can it provide this service to other apps in the system? Writing an IOR into some file is no clean solution IMHO, and using KActivator doesn't work because KDesktop does not get started by kded but by the startkde script on KDE startup. So we find a better way and make KDesktop register it's object at KNaming. This is done by the following lines:

  ...
  KNaming *knaming = KdedInstance::self()->knaming();
  naming->bind( "KDesktop", kdesktop_object_here );
  ...
Well, I told you a lie ;) : KNaming does not really bind to "KDesktop" but instead to "IDL:KDesktopIf:1.0" , but since there's no naming convention for the naming I have choosen a more readable name, IMHO of course :-) (don't mind me David :] ) . I personally prefer human readable names ;) , in contrary to repository ids with tags.

Back to KNaming and KDesktop: Now any client application, kfmclient for example, can "connect" to KDesktop. Just like this:

  ..
  KNaming *knaming = KdedInstance::self()->knaming();
  ...
  CORBA::Object_var obj = knaming->resolve( "KDesktop" );
  KDesktopIf_var kdesky = KDesktopIf::_narrow( obj );
  kdesky->selectAll(); //let's confuse the user by selecting all icons ;-)
  ...

Next Previous Table of Contents