Development/Tutorials/Services/Introduction: Difference between revisions

From KDE TechBase
No edit summary
m (→‎KService: add code snipplet to note)
 
(16 intermediate revisions by 9 users not shown)
Line 1: Line 1:
{{TutorialBrowser|
{{TutorialBrowser|


Line 5: Line 7:
name=Introduction to the Services Framework|
name=Introduction to the Services Framework|


next=[[../Traders|Traders: Querying the System]]|
next=[[../Traders|Finding Services Using Trader Queries]]|


reading=[http://www.freedesktop.org/wiki/Specifications/desktop-entry-spec freedesktop.org Desktop File Specification]<br>[http://www.freedesktop.org/wiki/Specifications/menu-spec freedesktop.org Menu Specification]<br>[http://www.freedesktop.org/wiki/Specifications/shared-mime-info-spec freedesktop.org MimeType specification]
reading=[http://www.freedesktop.org/wiki/Specifications/desktop-entry-spec freedesktop.org Desktop File Specification]<br>[http://www.freedesktop.org/wiki/Specifications/menu-spec freedesktop.org Menu Specification]<br>[http://www.freedesktop.org/wiki/Specifications/shared-mime-info-spec freedesktop.org MimeType specification]
Line 12: Line 14:
== Abstract ==
== Abstract ==


== Three Categories of Entries ==
Services represent applications, plugins and other add-ons available on the system. They make it easy to find, launch and load the items they represent without having to hardcode any specific component or even know ahead of time what services will be available. This tutorial covers what the services system provides and where the information is stored.
 
== Advantages of Using Services ==
 
There are three main advantages to using services:
* it's simple
* it's future proof
* it's flexible
 
Whenever your application needs to launch another desktop application, find available applications, load plugins or find application add-ons it's as simple as a few lines of code to do so and the code is quite similar regardless of what you are looking for.
 
Since most of the details involved in looking up services are hidden away from your application, if things change either due to time and new standards or platform specific features your code will continue to work. For instance, when KDE implemented the freedesktop.org specification for describing application launcher menu structures, application code that had been functioning previous to this continued to function without any changes or even a recompile.
 
Best of all, the services system provides a flexible system under the hood for users and administrators to be able to customize, add new entries, remove existing items and even lock down access without putting any burden of complexity on application developers.
 
== Classes At A Glance ==
 
The main services related classes that applications are likely to use are generally limited to the following two:
 
*{{class|KService}}: represents one application, plugin or add on
*{{class|KServiceTypeTrader}}: allows discovery of available services through a simple query language; this class and the query language is covered in detail in the [[../Traders|next tutorial]]
 
Other classes that are available but less often used by applications include:
*{{class|KServiceOffer}}: provides information on user preference for a given service; primarly used for mimetypes
*{{class|KServiceType}}: provides access to information about a given type of service
*{{class|KServiceTypeProfile}}: represents the user's preferences between multiple services of the same type; this is used internally by KServiceTypeTrader
 
== KService ==
 
The {{class|KService}} class is at the center of the services system. It serves both an informational and a functional role. {{class|KService}} provides access to details on a given service such as whether it is an application, the name of the service, the associated icon (if any), etc. But it can also be used to launch applications and load plugins from disk.
 
A {{class|KService}} object can be obtained in one of three ways:
*creating one manually
*requesting one by name
*querying
The first approach is the most straightforward and often looks something like this:
 
<syntaxhighlight lang="cpp-qt">
QString pathToDesktopFile = KStandardDirs::locate("services", "konqueror.desktop");
KService service(pathToDesktopFile);
</syntaxhighlight>
 
KService also provides ways to load services by name directly with the <tt>serviceBy*</tt> set of methods, of which the safest and most recommended is <tt>serviceByStorageId</tt>:
 
<syntaxhighlight lang="cpp-qt">
KService::Ptr service = KService::serviceByStorageId("konqueror");
</syntaxhighlight>
 
Note that it passed back a <tt>KService::Ptr</tt> rather than just a {{class|KService}}. A <tt>{{class|KService}}::Ptr</tt> looks, acts and behaves just like a regular pointer (<tt>{{class|KService}}*</tt>) but it is automatically memory managed. It is not necessary to manually delete <tt>KService::Ptr</tt>s, because they are reference counted.
 
A list of all services can be retrieved using the <tt>{{class|KService}}::allServices</tt> method. Of course, one often wants finer grained control over locating services, which is the role of the {{class|KServiceTypeTrader}} and is the topic of the next tutorial in this series.
 
At this point we now have access to all sorts of information on the service, which in this case is an application called <tt>konqueror</tt>. We can even launch the app using this service:
 
{{Note|With KF5 the following code will change. E.g. KUrl is replaced by QUrl. Basic call: `KRun::run(*service, QList<QUrl>(), nullptr);`
}}
 
<syntaxhighlight lang="cpp-qt">
if (service.isApplication()) {
    KUrl::List urls;
    urls << "http://www.kde.org";
    KRun::run(service, urls, 0);
}
</syntaxhighlight>
 
This would launch <tt>konqueror</tt> and cause it to open the KDE homepage.
 
== Registering Services ==


== The Files ==
Services are represented on disk as individual <tt>.desktop</tt> files. This makes it easy to add, remove, and customize services on the system. The <tt>.desktop</tt> files are organized by their type of service. Applications, plugins, protocols, and mimetypes are each kept in their own directories. The location of these directories is documented in the [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Filesystem Hierarchy]] page. Installation is usually automated through the build system, such as CMake in KDE4.
 
Services may also have one or more "service types" that are used to categorize and search for them. While applications and mimetypes don't utilize this, plugins and other services do. These service types are registered by placing a <tt>.desktop</tt> file describing the service type in the correct location in the filesystem, usually {{path|share/kde4/servicetypes}}. See the [[KDE System Administration/KDE_Filesystem_Hierarchy|KDE Filesystem Hierarchy]] page for more information.
 
The content and form of these .desktop files is covered in detail in the [[../Plugins|Creating and Loading Plugins Using KService]] tutorial.


== SyCoCa: The System Configuration Cache ==
== SyCoCa: The System Configuration Cache ==


== Building The SyCoCa ==
While the <tt>.desktop</tt> (file) method is very handy for users (and adding new entries), performance could be an issue because it is common to have thousands of these files describing various mimetypes, applications, plugins, screensavers, etc. Thus, the entries are put into a binary cache which is accessed via shared memory by all applications. The cache is known as the '''Sy'''stem '''Co'''nfiguration '''Ca'''che, or SyCoCa for short. Loading and locating {{class|KService}}s is done via this cache, transparently to the application.
 
Whenever a new <tt>.desktop</tt> file is added, removed or altered, the cache is automatically updated by the {{path|kbuildsycoca4}} application. You can force an update of the cache by running {{path|kbuildsycoca4}} manually, though usually it is launched by {{path|kded4}} automatically when needed. A full rebuild of the cache (versus a simple update) can be triggered by passing <tt>--noincremental</tt> to {{path|kbuildsycoca4}}.
 
== Searching For Services ==


== Searching The SyCoCa ==
The next tutorial is [[../Traders|Finding Services Using Trader Queries]]. We will look at how to find services using the KTrader query language and {{class|KServiceTypeTrader}} .

Latest revision as of 15:32, 17 December 2014


Introduction to the Services Framework

Abstract

Services represent applications, plugins and other add-ons available on the system. They make it easy to find, launch and load the items they represent without having to hardcode any specific component or even know ahead of time what services will be available. This tutorial covers what the services system provides and where the information is stored.

Advantages of Using Services

There are three main advantages to using services:

  • it's simple
  • it's future proof
  • it's flexible

Whenever your application needs to launch another desktop application, find available applications, load plugins or find application add-ons it's as simple as a few lines of code to do so and the code is quite similar regardless of what you are looking for.

Since most of the details involved in looking up services are hidden away from your application, if things change either due to time and new standards or platform specific features your code will continue to work. For instance, when KDE implemented the freedesktop.org specification for describing application launcher menu structures, application code that had been functioning previous to this continued to function without any changes or even a recompile.

Best of all, the services system provides a flexible system under the hood for users and administrators to be able to customize, add new entries, remove existing items and even lock down access without putting any burden of complexity on application developers.

Classes At A Glance

The main services related classes that applications are likely to use are generally limited to the following two:

  • KService: represents one application, plugin or add on
  • KServiceTypeTrader: allows discovery of available services through a simple query language; this class and the query language is covered in detail in the next tutorial

Other classes that are available but less often used by applications include:

  • KServiceOffer: provides information on user preference for a given service; primarly used for mimetypes
  • KServiceType: provides access to information about a given type of service
  • KServiceTypeProfile: represents the user's preferences between multiple services of the same type; this is used internally by KServiceTypeTrader

KService

The KService class is at the center of the services system. It serves both an informational and a functional role. KService provides access to details on a given service such as whether it is an application, the name of the service, the associated icon (if any), etc. But it can also be used to launch applications and load plugins from disk.

A KService object can be obtained in one of three ways:

  • creating one manually
  • requesting one by name
  • querying

The first approach is the most straightforward and often looks something like this:

QString pathToDesktopFile = KStandardDirs::locate("services", "konqueror.desktop");
KService service(pathToDesktopFile);

KService also provides ways to load services by name directly with the serviceBy* set of methods, of which the safest and most recommended is serviceByStorageId:

KService::Ptr service = KService::serviceByStorageId("konqueror");

Note that it passed back a KService::Ptr rather than just a KService. A KService::Ptr looks, acts and behaves just like a regular pointer (KService*) but it is automatically memory managed. It is not necessary to manually delete KService::Ptrs, because they are reference counted.

A list of all services can be retrieved using the KService::allServices method. Of course, one often wants finer grained control over locating services, which is the role of the KServiceTypeTrader and is the topic of the next tutorial in this series.

At this point we now have access to all sorts of information on the service, which in this case is an application called konqueror. We can even launch the app using this service:

Note
With KF5 the following code will change. E.g. KUrl is replaced by QUrl. Basic call: `KRun::run(*service, QList<QUrl>(), nullptr);`


if (service.isApplication()) {
    KUrl::List urls;
    urls << "http://www.kde.org";
    KRun::run(service, urls, 0);
}

This would launch konqueror and cause it to open the KDE homepage.

Registering Services

Services are represented on disk as individual .desktop files. This makes it easy to add, remove, and customize services on the system. The .desktop files are organized by their type of service. Applications, plugins, protocols, and mimetypes are each kept in their own directories. The location of these directories is documented in the KDE Filesystem Hierarchy page. Installation is usually automated through the build system, such as CMake in KDE4.

Services may also have one or more "service types" that are used to categorize and search for them. While applications and mimetypes don't utilize this, plugins and other services do. These service types are registered by placing a .desktop file describing the service type in the correct location in the filesystem, usually share/kde4/servicetypes. See the KDE Filesystem Hierarchy page for more information.

The content and form of these .desktop files is covered in detail in the Creating and Loading Plugins Using KService tutorial.

SyCoCa: The System Configuration Cache

While the .desktop (file) method is very handy for users (and adding new entries), performance could be an issue because it is common to have thousands of these files describing various mimetypes, applications, plugins, screensavers, etc. Thus, the entries are put into a binary cache which is accessed via shared memory by all applications. The cache is known as the System Configuration Cache, or SyCoCa for short. Loading and locating KServices is done via this cache, transparently to the application.

Whenever a new .desktop file is added, removed or altered, the cache is automatically updated by the kbuildsycoca4 application. You can force an update of the cache by running kbuildsycoca4 manually, though usually it is launched by kded4 automatically when needed. A full rebuild of the cache (versus a simple update) can be triggered by passing --noincremental to kbuildsycoca4.

Searching For Services

The next tutorial is Finding Services Using Trader Queries. We will look at how to find services using the KTrader query language and KServiceTypeTrader .