Tutorial Series | Services |
Previous | Introduction to the Services Framework |
What's Next | Creating and Loading Plugins Using KService |
Further Reading | n/a |
It is often desirable to be able to find specific types of services or services with specific features or designations. KDE provides a simple yet powerful query language to accomplish this called the KTrader Query Language.
KDE provides two classes that act as "traders". A trader takes a query and returns a set of services that match those constraints. There is one trader for plugins and other add-ons, KServiceTypeTrader, and one for mimetypes, KMimetypeTrader. Both use the same syntax for querying, offer a singleton pattern accessor and return KService::Ptrs, among other similarities. So while this tutorial concentrates primarily on the KServiceTypeTrader, much of the content is applicable to the mimetype trader as well.
KServiceTypeTrader is used to locate individual components such as application plugins, screensavers and control panels that are registered with the system. The primary concept used is that of the "service type". Each set of services has a unique service type, which makes it very easy to locate exactly the sort of component needed.
This means that each kind of application plugin is uniquely namespaced within the set of all services so it is trivial to locate plugins for a given application without having to worry about also getting another application's plugins in the list.
Examples of service types include:
There is no limit to the number of service types that a given application may use or register. Creating new service types is covered in the next tutorial in the series, Services/Creating and Loading Plugins Using KService. Of course, service types are not limited to plugins and may be used for any sort of data component.
The service trader is always accessed via the self() singleton accessor. With the KServiceTypeTrader in hand, we can then do one of three things:
The code to do this is very straight forward:
KService::List services;
KServiceTypeTrader* trader = KServiceTypeTrader::self();
services = trader->query("KParts/ReadWritePart"); foreach (KService::Ptr service, services) {
kDebug() << "read write part " << service->name() << endl;
}
services = trader->defaultOffers("ThumbCreator"); if (services.isEmpty()) {
kDebug() << "no services found for ThumbCreator!" << endl;
}
KService::Ptr service = trader->preferredService("KDevelop/Plugin"); if (!service) {
kDebug() << "no preferred service found for KDevelop/Plugin" << endl;
}
In each case zero or more services are returned that are now usable for locating, describing and loading the item it represents.
The above examples are quite simplistic and are not detailed enough for many application needs. For instance, one may want to list only plugins with a certain category, that are associated with a particular mimetype or that have a specific plugin name. This is where the query language comes in.
The query language itself is designed to be human readable and flexible. KServiceTypeTrader::query optional takes a query in addition to the service type and uses that to provide more fine-grained searches. So example, we may modify the earlier example in this way:
KService::List services ;
KServiceTypeTrader* trader = KServiceTypeTrader::self();
QString constraint = "'text/plain' in MimeTypes and "
"('KOfficePart' in ServiceTypes or " " 'oasis' ~ [X-KDE-ExtraNativeMimeTypes])";
services = trader->query("KParts/ReadWritePart", constraint);
foreach (KService::Ptr service, services) {
kDebug() << "read write part " << service->name() << endl;
}
This would look for a KPart capable of both reading and writing plain text files that is also a KOffice component or which can read ODF document formats.
Errors in queries are reported via debug output to console at runtime.
Three types of literals are supported by the KTrader Query Language:
Identifiers in query string are mapped to entries listed in the service's .desktop file. For example, "Name" is the name of the service, "ServiceTypes" is a list of the service types it supports.
Identifiers may contain only alphanumeric characters and the '-' character. Identifiers that do not start with an alphabetical character or contain non-alphanumeric characters must be enclosed in brackets, e.g. [X-KDE-Init].
There are also three special identifiers:
The following comparison operators may be used to compare values of any of the supported data types:
The following mathematical operators can be used with numerical types:
The following boolean operators are supported:
String matching can be accomplished using the following matching operators: