User:Claus chr/Search

From KDE TechBase
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

There are 9120 pages A-J:

KDE used to produce monolithic collections of software, called either "KDE" or "The KDE Source Collection". You can find archived information at the historic build instructions page.

Building KDE3 From Source
Tutorial Series   Getting Started
Previous   None
What's Next   n/a
Further Reading   The KDE From Subversion Build Tool

Status

This page is accurate as of 2008-07-19 for building KDE stable 3.5.9 (please report problems to kde-devel if they do not work for the latest stable 3.5.x). Other pages containing similar information are being consolidated to here. Similar pages include:

KDE Stable

The old stable version of KDE stable is 3.5.10 (current stable version is a 3.4 branch as of 2009/11/20). You will want to build KDE stable if you are a maintainer for an OS distribution. Otherwise, you may want to install KDE stable using the tools provided by your OS distribution or vendor.

The recommended way to install KDE stable used to be Konstruct, a build system which helped you to install KDE releases and applications on your system. It downloads defined source tarballs, checks their integrity, decompresses, patches, configures, builds and installs them. A complete KDE installation should be as easy as "cd meta/kde;make install".

By default Konstruct installs to your home directory, which means you don't have to possess root privileges or risk to damage your system or affect another KDE.

Currently it does not work and is not maintained any more.

Compiling Yourself

The following instructions describe how to build KDE 3.5.x yourself, i.e. without using Konstruct or kdesvn-build.

Requirements

To compile KDE you need:

  • Qt 3.3.2 or newer
  • a C++ compiler which supports exceptions, preferably a recent gcc 3.x release. gcc 2.95.x is still working.
  • bunzip2 to decompress .bz2 files. You can find it here. Get libbz2 while you're at it, it enables reading of .tar.bz2 files in konqueror, and one day, will give access to .bz2 files to all KDE applications.
  • If you want SSL support (for instance for secure web sites in konqueror), make sure you install openssl, version 0.9.6 or later (versions 0.9.5x are not supported).
  • For a better regular-expressions support in Javascript, install libpcre.
  • For the KDE help system, you'll need to install libxml2, version 2.3.13 or newer.
  • pkg-config, to help find installed software.
  • There are additional modules that are compiled if the required library is present, but they aren't critical to run KDE. For instance, libldap for the LDAP kioslave, and cdparanoia for the audiocd kioslave. A more detailed list of requirements is available in the KDE 3.5 Requirements List

Download

In order to run KDE applications, you need the Qt, arts, and kdelibs packages. For a simple desktop (with a window manager, panel, etc), you will also need kdebase. The other packages contain many other applications by topic: networking, graphics, multimedia, games, utilities, toys, software development, etc.

You can find the Qt library (qt-x11-free-3.3.8) from ftp://ftp.trolltech.com/qt/source/

KDE 3.5.x is available from ftp://download.kde.org/pub/kde/stable/

Installation

Unlike most compiled software, Qt is compiled in the place where it will stay instead of using a make install. Please read the INSTALL instructions in the Qt package. You need to set the environment variables $QTDIR and $KDEDIR to the locations where Qt and KDE will be installed, respectively. Also, append $QTDIR/bin and $KDEDIR/bin to your $PATH and $QTDIR/lib and $KDEDIR/lib to $LD_LIBRARY_PATH. Alternatively, instead of using $LD_LIBRARY_PATH, you may add your Qt and KDE library paths to /etc/ld.so.conf, but don't forget to run ldconfig as root after installing Qt and kdelibs, otherwise configure scripts will fail to find the newly installed libraries!

If your distribution sets $XDG_DATA_DIRS and/or $XDG_CONFIG_DIRS you will want to update them to include the correct $KDEDIR/share/ resp. $KDEDIR/etc/xdg/

bunzip2 qt-x11-3.3.8.tar.bz2
tar xvf qt-x11-3.3.8.tar
cd qt-x11-3.3.8
less INSTALL
# Set up QTDIR, KDEDIR, PATH, LD_LIBRARY_PATH,
# XDG_DATA_DIRS and XDG_CONFIG_DIRS
cd $QTDIR
./configure -system-zlib -qt-gif -system-libpng \
    -system-libjpeg -plugin-imgfmt-mng -thread -no-stl \
    -no-xinerama -no-g++-exceptions
make

Note that -thread is required (KDE will not run or even compile if you omit it), that -no-xinerama is only if you're not using xinerama, and -no-g++-exceptions is strongly recommended if you're using gcc.

Make sure to compile and install arts first, and afterwards kdelibs and then kdebase before any other packages. Also, if you want to use kdeaddons, it should be compiled last as it requires kdebase, kdemultimedia, etc.

For each KDE package:

bunzip2 <package>.tar.bz2
tar xvf <package>.tar
cd <package>
./configure
make
make install

TroubleShooting

  • If you get an error like
uic: File generated with too old version of Qt Designer

try

which uic

and

uic -v

to find out with which version of the UI compiler you are working. For KDE 3.5 and koffice 1.6 you will need a 3.x version.

Notes

  • If compiling on a system where GNU make is not the default make (that is, most systems other than Linux), please run gmake && gmake install instead of make && make install.
  • All packages mentioned here have to be compiled with the same compiler!
  • See the KDE 3.5.9 Info Page for some common encountered problems when running KDE 3.5.9.
  • Development/Tutorials/Programming Tutorial KDE 4
Warning
The tutorial series linked to from this page has been moved to the main page.
Tip
Note: This page is about KDE 4. It isn't applicable for KDE 3 development.

Overview

Basics

KDE heavily depends on Qt. Many KDE classes inherit from Qt classes. KDE 4 is based on Qt 4, KDE 3 is based on Qt 3. When this tutorial introduces a new Qt class, you're also learning KDE programming.

Your lessons

Hello World

If you read the above, you will be taken into a world where every line of code is friendly and good to beginners.

Using KXmlGuiWindow

This tutorial shows you the magic of an application's most important thing: The main window.

Using KActions and XmlGui

Maybe you want to guide your users through your own menues, then this is right for you.

Using KConfig XT to store and retrieve settings

You always wanted to store configuration options ? Then eat this!

How to write an XML parser

Yes, even XML parsers are explained here.

Using QTableWidget

A QTableWidget is an easy way to present an editable table to the user.

Using QTreeWidget

A QTreeWidget is like a QTableWidget with hierarchical display.

Using KDirWatch

With KDirWatch, your application gets notified if a given file changes.

Getting Help

Finding documentation

Whenever you have a KDE class and want the API documentation for it (KApplication, for example), point a konqueror window to

kde:KApplication

Be aware that the kde: konqueror shortcut only works for classes in kdelibs. If you ask for a class outside of kdelibs or a class that the API search software doesn't know about, you'll be redirected to the main API documentation page. You will need to navigate from there to find the class you're looking for.

If you need to look up the Qt API documentation for a class, you can point a Konqueror window to

qt:QApplication

This can be done in addition to browsing the Qt documentation locally, or using Qt Assistant.

Finding other developers

Mailing lists

There are two main development mailing lists:

Many other mailing lists for certain applications also existing. Before posting a question, it's always best to make sure you direct it to the right list. Emailing your question to the right list can help you get an answer faster. You can get an overview of the various available mailing lists at http://www.kde.org/mailinglists

IRC

If you're looking for something a bit more in the instant gratification department, then feel free to ask your question on IRC. KDE uses the Freenode network and the easiest way to get on IRC is to point your favorite IRC client to irc.kde.org. There are several IRC clients available for KDE such as konversation and ksirc. There are two main channels for KDE development:

  • The #kde-devel channel for general KDE development questions
  • The #kde4-devel channel for questions specific to KDE 4 development

Additionally, there are channels for discussing the sub-frameworks of KDE 4:

  • The #plasma channel for development on Plasma. The new KDE 4 desktop framework.
  • The #solid channel for development on Solid. The hardware detection/management framework for KDE 4.
  • The #phonon channel for development on Phonon. The new KDE 4 multimedia framework.

As with mailing lists, many applications have their own IRC channel. However, there currently is not a list of common IRC channels available. If you need to ask a question about a specific application, check that application's home page to see if there's an IRC channel available specifically for that application. If a channel is not listed, it's best to ask your question on one of the above two general development discussion channels.

In order to get the most out of your IRC experience, it's best to follow these guidelines when asking questions:

  • If you have a question, just ask it. There's no need to ask if you can ask a question.
  • Be prepared to wait for an answer. Even though IRC is more real-time mode of communication, there may not be anyone available to answer your question immediately after you ask it. In general, if you don't receive a response on IRC in about an hour, it's best to send an email.
  • Don't ask the question more than once. Even though the channel is active, the right person may not be available to provide an answer. If you are told to wait for a certain person to come online, be sure to ask again when you see them come online. Again, if you don't receive a response to your question in about an hour, it's best to send an email.

Suggested reading

Before you start to add or change content, please read:

Wiki Syntax

To get started with the MediaWiki syntax, read:

Tips

Syntax highlighting
Wrap your C++ Qt/KDE code snippets in <syntaxhighlight lang="cpp">, <syntaxhighlight lang="cpp" line="">, <syntaxhighlight lang="cpp-qt"> and </syntaxhighlight> to get syntax highlighting (cpp for C++, cpp-qt for Qt) and numbered lines (line=""). Replace cpp with the language used, e.g. ruby for Ruby and python for Python (soon). Use ini for .desktop files, xml for XML files.

New Templates

To get a list of pages using a template, go to corresponding template page (e.g. Template:movepage) and click "What links here" in the toolbox.

{{movepage|url}}
Use this template to mark a page as not finished.
{{improve|explanation}}
Pages which need cleanups or contain empty sections and/or todos are marked with this template. Add an explanation if you want (optional)
{{tip|text}}
Use this template to add a tip for the reader.
{{note|text}}
Use this template to add an explanatory note.
{{warning|text}}
Use this template to add a warning.
{{qt|class-name}} and {{qt3|class-name}}
Use this template to generate a link to a Qt class, e.g. QWidget. For Qt3 classes use {{qt3|class-name}}
{{class|class-name}}
Use this template to generate a link to a KDE class, e.g. KDialog.
{{path|path-or-filename}}
Use this template for paths and filenames, this way all of them have a consistent style.
{{bug|123456}}
Use this template to automatically create a link to KDE's bugzilla.
{{KDE3}}
Use this template to mark the content of a page as applicable for either KDE 3. Don't tag technology agnostic pages. For KDE4 content, use [[Category:KDE4]].
{{TutorialBrowser|series|name|pre|next|reading}}
A template for tutorial navigation
{{Box|caption|text|width|float}} - Deprecated, please use Box1
Use this template to create a box with a caption and a text. The width parameter is optional and can be specified absolute (400px) or relative (50%). The last parameter is the float value, which is also optional and defaults to center.
{{Box1|text|caption|icon image|color code}}
Use this template to create a box with a caption and a text. The color code parameter is optional. Normally you would use one of the partial instantiations of Box1, such as Template:Info, Template:Note, Template:Tip, Template:Warning, or Template:Remember; each of these take a title as an optional second argument.
 
Proposed for Deletion
This page has been proposed for deletion.

A parser is used to distinguish between formal language and bulk data of a given grammar. See http://en.wikipedia.org/wiki/Parser for more information. There are two ways to write a parser: to split up the content of a file into an object as known from object-oriented programming (the DOM approach) or to trigger a function everytime a reader occurs a given syntax tag (the QXML approach).

The QXML approach

parser.h:

/*
 parser.h - demonstration of a parser in C++
*/

#ifndef PARSER_H
#define PARSER_H

#include <qstring.h>
#include <QtXml/QXmlDefaultHandler>
#include <QtXml/QXmlAttributes>

class Parser : public QXmlDefaultHandler
{
public:

  Parser();

  /** given by the framework from qxml. Called when parsing the xml-document starts.          */
  bool startDocument();

  /** given by the framework from qxml. Called when the reader occurs an open tag (e.g. \<b\> ) */
  bool startElement( const QString&, const QString&, const QString& qName, const QXmlAttributes& att );

};


#endif

parser.cpp:

/*
 parser.cpp - demonstration of a parser in C++
*/

#include "parser.h"
#include <kdebug.h>

  Parser::Parser()
  {
  }
  
  bool Parser::startDocument()
  {
    kDebug() << "Searching document for tags";
    return true;
  }
  
  bool Parser::startElement( const QString&, const QString&, const QString& qName, const QXmlAttributes& att )
  {
    kDebug() << "Found Element" << qName;
    return true;
 }

hello.cpp:

/*
hello.cpp
compile it with
g++ -I. -I/home/kde-devel/kde/include -I/home/kde-devel/qt-unstable/include/Qt -I/home/kde-devel/qt-unstable/include /home/kde-devel/qt-unstable/include/QtXml parser.h parser.cpp hello.cpp -L/home/kde-devel/kde/lib -L/home/kde-devel/qt-unstable/lib -lQtCore_debug -lQtXml_debug -lkdeui
*/


#include <qstring.h>
#include <QXmlInputSource>
#include <qfile.h>
#include <parser.h>

int main()
{  
  Parser* handler=new Parser();
  QXmlInputSource* source=new QXmlInputSource(new QFile("hello.htm"));
  QXmlSimpleReader reader;
  reader.setContentHandler( handler );
  reader.parse( source );
}

The DOM approach

/*
   dom.cpp
   A demonstration how to use the dom parsing framework.
   Prints the first subnode of an HTML file, i.e. typically 
   "head" or "body".
   compile it like this:
   g++ -I. -I/opt/kde3/include -I/usr/lib/qt3/include dom.cpp \
   -L/opt/kde3/lib -L/usr/lib/qt3/lib -lqt-mt -lkdeui   
*/
#include <qdom.h>
#include <qfile.h>
#include <kdebug.h>

int main()
{
  QDomDocument doc( "myDocument" );
  QFile qf("hello.htm");
  doc.setContent( &qf );
  QDomElement docElement = doc.documentElement(); 
  QDomNode node;
  node = docElement.firstChild();
  kdDebug() << node.nodeName() << endl;
}

Drawbacks

HTML parsing only works for "legal" html documents. For example, look at this code:

<html>
  <body>
      <a href="http://www.kde.org/"></a>
      <a href="/index.php?title=Special:User&returnto=Main_Page">Log in</a>
      <a href="http://www.gmx.de"></a>
  </body>
</html>

This code contains a & and will bring your parser to an error.

See here:

<html>
  <body>
      <a href="http://www.kde.org/"></a>
      <a href="/index.php" nowrap>Log in</a>
      <a href="http://www.gmx.de"></a>
  </body>
</html>

This code will throw an error because of the nowrap that is not xml-conform.

The KDE Community produces libraries and tools for software development but, aside from Qt and CMake, doesn't prescribe which one to use. Here is just a sample of the various tools you can use when developing software that uses KDE APIs or contributing to KDE applications themselves.

Core Tools

These are the tools that are absolutely required to build and develop KDE software. On Linux, they will typically be provided by your distribution. On other platforms, packages should normally be available, often for download directly from the home page for the tool. Of course, the standard development tools, such as a C/C++ compiler and some sort of text editor, are also required.

CMake
CMake is KDE's build system of choice. Once you have this, you can use it to configure a software project for building, and that process will tell you of any other requirements you are missing. NOTE: KDE Frameworks can also be used in QMake-based projects.
Git
Most KDE projects are developed in Git, and so you will need it to get the latest development version of the source code. KDE also provides source code tarballs for the most recent releases. You can find the relevant Git URLs at the KDE Git repository browser.
Subversion
Some KDE projects still use Subversion for some things, notably translations. Third-party developers mostly don't need to bother with this but contributors should take note of it.

Development Environments and Editors

Qt Creator
Qt application developers are most likely already using Qt Creator as their IDE. The good news is that they don't need to switch away from it just to use KDE Frameworks. Simply add the appropriate module to the QMake project file as indicated by each one's API documentation and you're good to go.
KDevelop
KDevelop is a powerful IDE for developing KDE and Qt C++ applications. Unlike Qt Creator, however, it isn't limited to just that use case and supports other languages, libraries, and tools as well.
Kate
Although not exactly an IDE, KDE's premiere Advanced Text Editor has features and plugins that simplify the software development workflow, from syntax highlighting and code folding to project management to an embedded terminal emulator.

Debugging and Analysis

There is a wide variety of tools available, especially on Linux that analyze code and profile applications. Here are some of the more popular ones.

Valgrind
Valgrind helps to find memory leaks and uninitialized memory blocks. Additional features are a profiler and more. Valgrind is one of the most important development tools!
The GNU Project Debugger (GDB)
GDB helps in debugging source code. A graphical frontend, like the two below, might be a preferable way to use this tool.
KDbg and DDD
KDbg and DDD are graphical user interfaces to GDB, which are able to set breakpoints, step through the code, etc.

For some tips on KDE software analysis and profiling, please visit the Debugging page of the KDE Community Wiki.

Translation

Most Qt projects use the framework's built-in translation system. For KDE projects, please see the Community Internationalization Guide.

Helper Tools

Here are some command-line tools that can assist developers in some of their day-to-day tasks.

kf5-config
Provides information related to the installation of KDE libraries and applications, particularly paths and prefixes.
kioclient5
Performs network-transparent operations (via the KIO framework) on the command line, like copying or even downloading files.
kconf_update
Automates updating config files.
kapidox
Generates API documentation for Doxygen-marked code.

Quality Assurance

KDE contributors and third-party developers interested in monitoring the community's software development activities can take a peek via the sites and tools below.

Project Management
KDE currently uses Phabricator for project management but is also moving to a Gitlab instance.
Continuous Building
To ensure high-quality, KDE software operates a continuous integration system powered by Jenkins.
Static Analysis
KDE's continuous integration tooling performs static code analysis, see community::Infrastructure/GitLab/CI/Static Code Analysis
 
Proposed for Deletion
This page has been proposed for deletion for the following reason:

techbase is about developers that want to create non KDE apps.

Guidelines used internally, related to UI design and consistency. The section about policies also contains standards-like documents that relate to developer activity.

Human Interface Guidelines

Accessibility and Usability Checklists
Test your application for accessibility/usability along these checklists
Community Identity Guidelines (CIG)
Definitions and recommendations which help the KDE Project to establish a unique, characteristic, and appealing design.
Plasma Interface Guidelines (PIG)
This document is a place to collect all the "do"s, "don't"s and "how to"s for interface elements in Plasma, particularly applets and plasmoids.
KDE Human Interface Guidelines (HIG)
Guidelines for designing user interfaces.

Note: this page should be moved to the Template namespaceThis page is a template, editing it will affect all the pages that make use of it, so users should be especially careful when editing it.

You can include this content in another page by using the wiki markup {{User:Claus chr/Search}}. For more details on how to use templates see "A Quick Guide to Templates".

Provide the bug number as the first argument to this template, and it will automatically create a link to the bug in the KDE bugzilla.

Included content begins


bug #{{{1}}}


Included content ends

In this Userspace:

User talk:

TODO

  • Beautify Subpage titles


Bugs

sorry for reporting a bug here; but this seems like as good a place as any :) When using <code cpp> tags I noted a bug. Specifically when you use the colon (or other means) to indent it. Zander 20:39, 9 April 2007 (CEST) Example code:

  1. include <iostream>
  2. include <QtCore/QDate>
  3. include <zlib.h>

Rights Request

I have been asked on a couple of occasions to help remove some techbase content, usually personal pages of the person requesting it. I can, of course, do this on userbase. I'd like the same ability on techbase, if possible. Thanks. --Annewilson 13:19, 12 January 2010 (UTC)

The {{Class}} template creates a link to the API Documentation for a member Class of the KDE Frameworks.

Variables

{{Class|1=<className>|2=<library/module>|3=<frameworksVersion>|text=<linkText>}}

The numbered variables may be used without names as positional parameters, and the text= variable may be used with any quantity of other variables. Such as:

  • {{Class|<className>|<library/module>|<frameworksVersion>|text=<linkText>}}, or
  • {{Class|<className>||<frameworksVersion>|text=<link text>}}, or
  • {{Class|<className>|text=<linkText>}}

Usage Examples

  • {{Class|KColorDialog}} looks for the docs of the KColorDialog Class in the KDE Frameworks.
  • {{Class|KProcessList::KProcessInfo|kcoreaddons}} shows the docs for the KProcessList::KProcessInfo Class in the KCoreAddons library.
  • {{Class|KColorDialog|kdelibs|3.5}} shows the docs for the specified class in version 3.5 of the KDE Frameworks.
  • {{Class|KColorDialog|kdelibs|3.5|text=Color Dialog}} shows the docs for a different version and defines the link text.
  • Installing third party softwares in terminal/Build/KDE4==== This article is fat ====

When I first wrote this article, it was lean and mean and simple to understand. And it was good for all distributions. Now I have the impression of a fat pig when I read this article. I pledge for removing the usual sources of error, e.g. the many subdirectories. Why do we need a directory KDE, for example ? If a tutorial is not simple, it is not done.

--Tstaerk 14:23, 9 September 2007 (CEST)

+1. A cleanup would be nice, especially before the official 4.0.0 release! Volunteers needed who do this. --Dhaumann 22:52, 9 September 2007 (CEST)
This tutorial is fine by me. Okay, that's not for newbies, but someone who wants to compile KDE4 RC1 needs to know how to follow this tutorial at least. --Chackal_sjc 06:56, 27 November 2007 (CEST)

This article is full of errors

For example it *is* nessecary to install qt-copy, even if you keep it in the source directory (which leads to 394583069845 error messages on the console during the install). And kdelibs won't build unless something unknown is done with strigi - if it is installed into KDEDIR, it isn't just found.


the heading says pre-requirments are to read "Anonymous SVN Quickstart Guide" first. but the things it does are mostly done in this guide(but a little differently). for example the "Anonymous SVN Quickstart Guide" has you just svn a bunch of stuff.... but that all ended up in the wrong place cause in this guide the svn'd stuff needed to go to "kde-devl"-user's dir not the normal user dir..

This tutorial clearly states: "The rest of this tutorial assumes you are running as the kde-devel user." -TMG 14:16, 25 June 2007 (CEST)

This article is complicated

when I wrote this article, it was lean and simple. It has been improved somewhere, but on most places worsened. An example is the directory structure (to get to qt-copy: cd && cd qt-copy; to get to kdelibs: cs && cd kdelibs; to get to kdepim: cs && cd KDE && cd kdepim - no one understands this!!!). Another example is cs and cb which is quite unnecessary as my initial article shows. But of course, with the complexity as the article has NOW, it IS necessary.

Why do you spoil a simple article so that even I no longer find my own subdirs ? --­­­­Tstaerk 10:25, 28 May 2007 (CEST)

Where do you see "cs && cd KDE && cd kdepim"? Because I don't see that anywhere. In any case it would just be "cs kdepim". Perhaps that's the bit need explaining a bit better? --Aseigo 02:48, 29 May 2007 (CEST)
To whom are you talking to? ;) There are many contributors and as it's a wiki an article probably "degenerates" automatically if noone has an eye on it. The article certainly has valuable information and simply needs a cleanup. In other words: Fix it! :) --Dhaumann 12:20, 28 May 2007 (CEST)
IMHO all of this cs/cb/cmakekde and such is only confusing, users just do copy&paste with no really knowledge of what's going on when they type those commands. This way troubleshooting is quite difficult, and they learn nothing about the real compiling way. The concept of source/build dirs is barely noted. The old http://developer.kde.org/build/trunk.html has some more commands to type, but it was quite more understandable and clear about the real steps to do. --pino 12:54, 28 May 2007 (CEST)
Yes, this article could go back to being more verbose. I suppose what is missing is an explanation of why the shortcuts are used. They are there for a reason. I also don't get the differentiation between real and not real steps; unless we now consider using the shell for what it was designed for as not real. --Aseigo 02:48, 29 May 2007 (CEST)
What's wrong in explicitely telling:
svn co .../kdelibs
mkdir build-kdelibs
cd build-kdelibs
cmake <options> ../kdelibs
make install
After all, we did that with the ./configure && make && make install sequence in KDE 3 times, and that worked quite fine. I still fail why we have to make our things more complicated. Moreover, these macros force fixed paths -- pino 23:43, 29 May 2007 (CEST)
I am also for removing cb and cs, somebody should just do it. They are indeed confusing and sometimes don't work as expected (that is why cd $KDE_SRC is needed in one place). cmakekde on the other hand could stay IMHO. -TMG 14:16, 25 June 2007 (CEST)
I find this article too confusing, more-so than it needs to be

This should be simplified, it should be made much easier to understand, with more technical on info later on. I find it hard to just follow it along. Remember, you guys are trying to help out would-be developers, so there can be more of them (good). With guides like this, and guides that don't exist, the new developers will be overly confused (like me) and will probably turn the other way (bad). I don't know, maybe it's just me that finds it too complex to understand....

Q: What is cs and cb?

A: This is not a typo. Read the article about setting up your .bashrc. Both cs and cb are bash functions, used to change to the KDE source directory and KDE build directory respectively.

Q: Are there build instructions for other OS?

A: Actually yes, for Mac OS X. There also is kdelibs.com (see also here) which will be merged into this wiki in the future.

Q: Isn't the install prefix, make and make install missing for modules like kdelibs and kdebase?

A: No. The shell function cmakekde handles this, have a look at the file .bashrc.


Notes: ~/install

When installing KDE4, I strongly recommend installing all tools (like dbus and cmake) and kde packages into the same place, e.g. ~/install. Qt is the only exception.

The reason for this is because if you install some packages to ~/kde and some to /usr/local and maybe one in /usr then cmake will generate errors like:

-- It is impossible to order the include directories.

This is not a fatal error, so you will still be able to compile, but you will possibly be using the wrong versions of libraries and this will product problems that are very hard to diagnose.

You may not experience any problems when installed like I advise not to, however I have and you might too in some typical situations.

Install CMake modules local

The CMake modules should be installed local into ~/install/cmake/modules or similar. When following the current instructions 6.1: Install additional CMake modules, it's impossible to do a non-root installation, because "kdelibs/cmake/modules/cmake_install.cmake" wants to install the modules to "/cmake/modules". (I didn't install CMake local, because my system already provided CMake > 2.4.3).

I've already tried to do this, fiddling around with CMAKE_MODULE_PATH and DATA_INSTALL_DIR but couldn't get it working.

Does anybody know how to do this properly?

--Eliasp 15:44, 4 January 2007 (CET)


Fixes needed

  • qt-copy: Should we pass the -debug flag? Doesn't Qt install debug information separately by default anyways? Or is that just in the snapshot? --Mpyne
according to ./configure --help, the default is -release in snapshot. --Aseigo 04:33, 14 March 2007 (CET)
  • In the part of the tutorial that describes how to create a new users, shoudn't to have an edit /etc/sudoers to add permitions for kde-devel call sudo? --SilveiraNeto 03:01, 14 March 2007 (CET)
no. why would you want them to have sudo access?

libungif/giflib

Since the patents expired, why not use giflib?

Old gcc and -pch flag

In Qt part I had problems with error like this: QtForum thread. I had GCC 3.3.X installed. Using -pch flag (as in recipe) get me errors. Someone friendly gave me tip on #kde-devel not to use this flag, although I didn't test it. Instead I've just updated gcc and g++ from debian repositories. Newer version works fine as "Precompiled headers are supported in GCC (3.4 and newer)" Wikipedia pch.

Build status

You might want to include the dashboard link to show which modules currently build and which don't. --141.35.8.106 13:28, 20 March 2007 (CET)

Extra optional software

- openldap - cyrus

If there was a line at the top like:

sudo apt-get install libaaa-dev libbbb-dev ...-dev ...

This would be very useful and save hours. Is this something we should do?

su - kde4 didn't set the variables

after running 'su - kde4' and 'export' i saw that no variables in .bashrc were set, instead the old one (of the system) where set. I tried 'su kde4' and it worked fine. Why is that?

I'm running gentoo 2006.1 amd64

Qt Flags

Are "-pch" and "-qdbus" really needed? The configure script shows that they're enabled by default. --McEnroe 16:49, 19 April 2007 (CEST)

Fixed. Also got rid of openssl for the same reason Logixoul 18:03, 5 July 2007 (CEST)

Amount of space needed?

It would be nice to know how much space (roughly, in GB) you need for a setup to build and run the basic things and packages. --Liquidat 03:08, 7 June 2007 (CEST)

4.5 GB --Logixoul 18:12, 5 July 2007 (CEST)

Install error?

With the kdesupport package I have an install error: CMake Error: Error in cmake code at /media/local/kde-devel/kde/build/kdesupport/qca/plugins/qca-logger/cmake_install .cmake:35: FILE cannot create directory: /usr/lib/qt4/plugins/crypto. Maybe need administrative privileges. Current CMake stack: /media/local/kde-devel/kde/build/kdesupport/cmake_install.c make;/media/local/kde-devel/kde/build/kdesupport/qca/cmake_install.cmake;/media/ local/kde-devel/kde/build/kdesupport/qca/plugins/cmake_install.cmake;/media/loca l/kde-devel/kde/build/kdesupport/qca/plugins/qca-logger/cmake_install.cmake make: *** [install] Error 255

Why is it trying to install that system wide?


Have you installed local copy of qt4 as described in this tutorial? I had the same error while trying to skip installation of local qt4 copy and use system-wide installed one. The error is gone with local copy of qt4.
I checked back, and the problem is that the script tries to install "libqca-logger.so" to $QTDIR - any idea how to change that?
Did you set $QTDIR to the correct value? Make sure you use the .bashrc so that all environment variables are correct. -TMG 14:25, 25 June 2007 (CEST)
The entire point is that $QTDIR has to be set to /usr/lib/qt4/ - because I use the system wide installed copy of Qt 4.3!
So the problem is not that $QTDIR is set wrong but that the script tries to install something to $QTDIR. --141.35.185.149 23:38, 3 July 2007 (CEST)
Well, then you probably need to install with sudo to get the file installed. I guess it needs to be in the Qt directory because otherwise, Qt doesn't find the files. -TMG 17:31, 4 July 2007 (CEST)

Wrong line numbers (and explanation) in the "What's Happening" section for Qt part.

Line numbers:


Once the patches have been applied, we then set up the build using the configure script (line 5-7). Finally, we build the minimal requirements for KDE (line 8)...


It should be 5-6 for configure and 7 for make.

Explanation is wrong because there is no make install command. And this directory will be used directly. But in the article: "...we build the minimal requirements for KDE (line 8) and install (line 9-10) Qt". But in lines 9-10:


  1. if we don't install, we'll just clear obj files to
  2. save disk space

Best regards, powerfox.

Wrong directories?

Why does the recipe for kdesupport only say "cs" before getting the source and building while the "cmakekdeall" function in the example .bashrc says "cs KDE/kdesupport && svn up && cmakekde"?

It should either use the KDE subfolder or it shouldn't but now I'm confused as to which of the two is right.

Problem with required soprano version (Kubuntu Gutsy Gibbon)

(sorry for grammar errors if they occur) So,

I,m using Kubuntu Gutsy Gibbon and I had problems with soprano library at installing kdelibs.

cmakekde requires to install kdelibs the version of soprano library, which does not exist in ubuntu repositories. The needed version you can find e.g. here: http://ubuntu2.cica.es/ubuntu/ubuntu/pool/universe/s/soprano/

From this website you have to download libsoprano-dev and libsoprano4 having the same suffix (e.g. ubuntu1~gutsy1_all.deb if you are using Kubuntu Gutsy Gibbon).

Go to directory where you downloaded packages and install each package using dpkg ( I have forgotten the order, so try and when something goes wrong, dpkg shows an information and proposes a solution).

After this remove ~/kde/build/KDE/kdelibs/CMakeCache.txt and try again to install kdelibs.

Good luck :)

  • It was damned hard to find, but libsoprano-dev in Gutsy is 1.96.0, and kdelibs requires >=1.97.1. The article says "in this case you need to download and build the relevant part of kdesupport", but as long as the package is installed, cmakekde prefers the files in /usr/include to those under ~/kde/include. Only after removing the package, I was able to move forward.
  • I think the real fix should be to make cmakekde prefer the local versions of include files and libraries, but until then, we should at least fix the procedure for Gutsy - please remove libsoprano-dev from the list of packages to install.
  • Thanks, Shai. 19:53, 28 November 2007 (CET)
  • kdelibs requires Soprano >=1.99 --> Build kdesupport and remove package libsoprano-dev and libsoprano4 : make all folks - chatmoa - 11Dec2007

Following the article I get directly into "no objdir found. Tried /home/kde4/kde/build/qt-copy"

Following the article I get to (in order):

-modify the .bashrc file with the one provided (which has a wrong "export QTDIR=$HOME/qt-copy") when everything else in the article uses "~/kde/src/qt-copy" or "~/kde/build/qt-copy" (I don't really understand which, but sure not "~/qt-copy"

-go to the console and do:

cs

svn checkout svn://anonsvn.kde.org/home/kde/trunk/qt-copy

cd qt-copy

./apply_patches

cb

../../src/qt-copy/configure -largefile -phonon -qt-gif -openssl -opengl -glib -prefix $QTDIR

make -j2

At this point the make says: "no objdir found. Tried /home/kde4/kde/build/qt-copy", which I have no idea what means, but anyway is not an usual message of the "make" command.

Try to follow the article to convince yourself. Also these smart command like cs, cb and the like don't work if they are called from inside a script, and too mysterious, so I would really like the thing a little more verbose and less high level smart shell tricks. Alex

Getting Started on TechBase

The KDE community is perhaps best known for its Plasma desktop workspace as well as its rich collection of applications but the community has also produced libraries and tools to make software development more enjoyable or, at the very least, less painful. Whether you're looking to write you first KDE application, make your existing Qt project more awesome, or get involved with one or more of the great KDE projects, this is a great place to get your journey started!


Note
To contribute to KDE, see the Get Involved page on the Community Wiki. If you are looking for build instructions, up-to-date build instructions are available on the Community Wiki, and we also have historic ones.


Setting Up

Getting started can be as simple or as involved as you need it to be. As much as possible, use your distro's packages to simply and speed up development unless you really need to get the latest source code version. And no, you don't need to "compile all of KDE" just to use a single framework. Not convinced? Check out our Setting Up Guide to see how easy it can be.

KDE Frameworks

KDE Frameworks 5 is built on top of the excellent Qt application framework to provide more functionality and power to your next big project. KDE software developers will also find classes that help them better integrate their applications into the Plasma workspace and with other KDE products.

Kirigami

Named after the Japanese art of cutting and folding paper to create beautiful objects, the Kirigami framework offers components to let your piece together a beautiful and responsive application. Expanding the Qt Quick framework, Kirigami empowers developers to create apps that look and behave well on desktop, mobile, and more.

Tutorials

Get your feet wet or dive head first into coding with KDE's collection of Tutorials. From writing your first application using the KDE Frameworks to developing applets for the Plasma workspace, these bite-sized guides will get you up and running in no time.

Plasma

KDE's world-famous workspace for desktops and mobile, Plasma provides a rich set of building blocks to help developers create rich, beautiful, and productive user experiences on different devices, form-factors, and use cases. KWin is one of the most powerful and most flexible window managers around, providing advanced functionality and control on both X11 and Wayland systems.

It's just the beginning

These are just the large tips of the KDE iceberg. The community has developed many libraries for more specific needs and use cases that developers can also use to simplify their projects.

  • Need an easy and cross-platform way to handle audio and video? Phonon's API will be very familiar to Qt developers and supports multiple backends, including GStreamer, VLC, and anything else you might want to develop.
  • If you need a privacy-respecting way to display maps and even the whole world, Marble provides data models and widgets to make that a walk in the park.
  • If you need libraries for handling email, events, and more, the KDE PIM libraries have withstood not only the test of time but also the test of enterprise customers.


Check out the other KDE Projects that provide libraries and APIs that you can use to boost your own projects. The KDE Community is also welcoming not just new contributors but also new projects that want to be part of one of the biggest free software communities on the planet.

noframe
noframe

Welcome to the KDE TechBase Development Hub. This page contains links to Tutorials, Tools, and other Resources you might need to add KDE libraries to your project. If you're looking for a guide on starting your journey, head on over to the Getting Started page. If you're looking for tutorials on how to build KDE software and contribute to projects, hop over to the KDE Community Wiki.

Programming Tutorials
A collection of step-by-step guides and references for developers who want to use the KDE Frameworks and other APIs. The list covers a broad range of topics from introductory tutorials to advanced topics like plugins and scripting.
Development Tools
KDE software can be created using a wide variety of tools available to developers from IDEs to text editors to debuggers.
Other Resources
KDE API Documentation website
KDE Community Wiki
KDE Mailing Lists
Proposed for moving to community.kde.org
It has been proposed that this page should be moved to the community.kde.org wiki for the following reason:

Archive under https://community.kde.org/Promo/Guidance/Branding

The KDE Interface Guidelines provide a complementary set of reference manuals to ensure a consistent high quality user interface in respect to these topics:

  • Human Interface Guidelines (HIG) - Usability Manual
  • Community Identity Guidelines (CIG) - Branding Manual
  • Accessibility Guidelines (AG)

The CIG gives definitions and recommendations which help the KDE Project to establish a unique, characteristic and appealing design and to promote KDE on all kinds of media. It's the ultimate reference manual for all people who are involved in designing the KDE user interface as well as promotional material.


Content

Warning
This page needs to be migrated. You can find the original page and its subpages at {{{1}}}. Please make use of subpages to structure the wiki, e.g. Policies/Packaging Policy. Read Help:Contents for further details. If in doubt, join #kde-www on irc.kde.org.
Proposed for moving to community.kde.org
It has been proposed that this page should be moved to the community.kde.org wiki for the following reason:

Archive under https://community.kde.org/Promo/Guidance/Branding


Names

The names in this guide are the only ones that may be used for publications and other materials, either in print or electronic form.

Acceptable

  • K Desktop Environment — This is our formal name; it is especially used on all communications intended for external groups which might not be familiar with KDE yet.
  • KDE — This is our informal name and abbreviation; it is our preferred casual name.

Not Acceptable

Do not use different capitalization and hybrid forms, such as: kde, K desktop environment, KDE Desktop Environment (used upper case and stand-alone — note that there are no restrictions for the (lower case) descriptive usage of "the KDE desktop environment" in continous text)

Claims

Proposed for moving to community.kde.org
It has been proposed that this page should be moved to the community.kde.org wiki for the following reason:

Archive under https://community.kde.org/Promo/Guidance/Branding

Color

The plain KDE Logo displays the white trademarked K-Gear shape on a blue square with mitered corners. The exact official color of the blue background color is Pantone 300 C (which is equivalent to CIE L*a*b 40,-13,-63). Various approximate device dependent color space representations include:

purpose color space value
screen design RGB #0068C6
printed matter CMYK 100 43 0 0

Other approximate media dependent color matching system representations include:

purpose color matching system
offset printing Pantone 300(U/C), HKS 44, Euroscale 100%C 43%M
serigraphy Marabu 1526
lacquering RAL 5017

Shape

Detailed Logo (Lineart)

  • screen design: to be used in large appearances (> 128x128 pixel),watermarks, patterns etc.
  • print design: for use in corporate context in printed matters (letter heads, business cards, etc.)

Simple Logo (Lineart)

  • screen design: to be used for small patterns.
  • print design: for use in printed matters where the KDE Logo measures less than 10x10 mm

Logo in Crystal Design

  • screen design: to be used for desktop artwork (e.g.icons, splashscreens) and webdesign.
  • print design: for use in home user context
 
Proposed for Deletion
This page has been proposed for deletion for the following reason:

This wiki page does not have a parent wiki page.

Use Okular / Amarok's passive popup class to display things like "13 replacements done" or "Document successfully loaded". The needed class is PageViewMessage in the files pageviewutils.cpp and pageview.h. Maybe it is a good idea to alter the function slightly from

void display( const QString & message, const QString & details = QString(), Icon icon = Info, int durationMs = 4000 );

to

void display( const QString & message, const QString & details = QString(), Icon icon = Info, Qt::Corner corner = Qt::TopLeft, durationMs = 4000 );

Maybe KPassivePopup works, too. It can show arbitrary widgets as content. But it's more ugly.

Kate Cleanups

KateDocManager derives from QStandardItemModel. Since the view is a plugin now, this should be converted back to a simple list.

TODO

attic

Setup a KDE4 development environment

Compiling KDE SC 4
Instructions for installing KDE SC 4.x from source code.
Installing KDE4 on Windows
Instructions for installing KDE SC 4.x on Windows from pre-built packages.
Using Konstruct
Instructions for using the Konstruct script to build KDE3 from source code.
Compiling KDE 3.5.x
Instructions for installing KDE 3.5.x from source code.
Compiling KDE 3.4.x
Instructions for installing KDE 3.4.x from source code.
Compiling KDE 3.3.x
Instructions for installing KDE 3.3.x from source code.
Compiling KDE 3.2.x
Instructions for installing KDE 3.2.x from source code.
Compiling KDE 3.1.x
Instructions for installing KDE 3.1.x from source code.
Compiling KDE 3.0.x
Instructions for installing KDE 3.0.x from source code.
Compiling KDE 2.2.2
Instructions for installing KDE 2.2.2 from source code.

Requirements

To compile KDE you need:

  • Qt 3.3.0 or newer
  • a C++ compiler which supports exceptions, preferably a recent gcc 3.x release. gcc 2.95.x is still working.
  • bunzip2 to decompress .bz2 files. You can find it here. Get libbz2 while you're at it, it enables reading of .tar.bz2 files in konqueror, and one day, will give access to .bz2 files to all KDE applications.
  • If you want SSL support (for instance for secure web sites in konqueror), make sure you install openssl, version 0.9.6 or later (versions 0.9.5x are not supported).
  • For a better regular-expressions support in Javascript, install libpcre.
  • For the KDE help system, you'll need to install libxml2, version 2.3.13 or newer.
  • There are additional modules that are compiled if the required library is present, but they aren't critical to run KDE. For instance, libldap for the LDAP kioslave, and cdparanoia for the audiocd kioslave. A more detailed list of requirements is available in the KDE 3.4 Requirements List

Download

In order to run KDE applications, you need the Qt, arts, and kdelibs packages. For a simple desktop (with a window manager, panel, etc), you will also need kdebase. The other packages contain many other applications by topic: networking, graphics, multimedia, games, utilities, toys, software development, etc.

You can find the Qt library (version 3.3.4) at ftp://ftp.trolltech.com/qt/source/

KDE 3.4.x is available from http://download.kde.org/stable/

Installation

Unlike most compiled software, Qt is compiled in the place where it will stay instead of using a 'make install'. Please read the INSTALL instructions in the Qt package. You need to set the QTDIR and KDEDIR to the locations where Qt and KDE will be installed, respectively. Also, append $QTDIR/bin and $KDEDIR/bin to your $PATH and $LD_LIBRARY_PATH. Alternatively, instead of using $LD_LIBRARY_PATH, you may add your Qt and KDE library paths to /etc/ld.so.conf, but don't forget to run ldconfig as root after installing Qt and kdelibs, otherwise configure scripts will fail to find the newly installed libraries!

If your distribution sets $XDG_DATA_DIRS and/or $XDG_CONFIG_DIRS you will want to update them to include the correct $KDEDIR/share/ resp. $KDEDIR/etc/xdg/

bunzip2 qt-x11-3.3.4.tar.bz2
tar xvf qt-x11-3.3.4.tar
cd qt-x11-3.3.4
less INSTALL
# Set up QTDIR, KDEDIR, PATH, LD_LIBRARY_PATH, XDG_DATA_DIRS and XDG_CONFIG_DIRS
cd $QTDIR
./configure -system-zlib -qt-gif -system-libpng \
-system-libjpeg -plugin-imgfmt-mng -thread -no-stl \
-no-xinerama -no-g++-exceptions
make

Note that -thread is required (KDE will not run or even compile if you omit it), that -no-xinerama is only if you're not using xinerama, and -no-g++-exceptions is strongly recommended if you're using gcc.

Make sure to compile and install first arts, and afterwards kdelibs before any other packages. Also, if you want to use kdeaddons, it should be compiled last as it requires kdebase, kdemultimedia, etc.

For each KDE package:

bunzip2 <package>.tar.bz2
tar xvf <package>.tar
cd <package>
./configure
make
make install
Note
  • If compiling on a system where GNU make is not the default make (that is, most systems other than Linux), please run gmake && gmake install instead of make && make install.
  • All packages mentioned here have to be compiled with the same compiler!

See the KDE 3.4 Info Page for some common encountered problems when running KDE 3.4.

Requirements

To compile KDE you need:

  • Qt 3.3.0 or newer
  • Automake 1.5 and Autoconf 2.5
  • a C++ compiler which supports exceptions, preferably gcc-2.95.x or gcc-3.2
  • bunzip2 to decompress .bz2 files. You can find it here. Get libbz2 while you're at it, it enables reading of .tar.bz2 files in konqueror, and one day, will give access to .bz2 files to all KDE applications.
  • If you want SSL support (for instance for secure web sites in konqueror), make sure you install openssl, version 0.9.6 or later (versions 0.9.5x are not supported).
  • For Netscape-plugins support in konqueror, make sure to install lesstif.
  • For a better regular-expressions support in Javascript, install libpcre.
  • For the KDE help system, you'll need to install libxml2, version 2.3.13 or newer.
  • There are additional modules that are compiled if the required library is present, but they aren't critical to run KDE. For instance, libldap for the LDAP kioslave, and cdparanoia for the audiocd kioslave. A more detailed list of requirements is available in the KDE 3.3 Requirements List

Download

In order to run KDE applications, you need the Qt, arts, and kdelibs packages. For a simple desktop (with a window manager, panel, etc), you will also need kdebase. The other packages contain many other applications by topic: networking, graphics, multimedia, games, utilities, toys, software development, etc.

You can find the Qt library (version 3.3.3) at ftp://ftp.trolltech.com/qt/source/

KDE 3.3.x is available from http://download.kde.org/stable/

Installation

Unlike most compiled software, Qt is compiled in the place where it will stay instead of using a make install. Please read the INSTALL instructions in the Qt package. You need to set the QTDIR and KDEDIR to the locations where Qt and KDE will be installed, respectively. Also, append $QTDIR/bin and $KDEDIR/bin to your $PATH and $LD_LIBRARY_PATH. Alternatively, instead of using $LD_LIBRARY_PATH, you may add your Qt and KDE library paths to /etc/ld.so.conf, but don't forget to run ldconfig as root after installing Qt and kdelibs, otherwise configure scripts will fail to find the newly installed libraries!

If your distribution sets $XDG_DATA_DIRS and/or $XDG_CONFIG_DIRS you will want to update them to include the correct $KDEDIR/share/ resp. $KDEDIR/etc/xdg/

bunzip2 qt-x11-3.3.3.tar.bz2
tar xvf qt-x11-3.3.3.tar
cd qt-x11-3.3.3
less INSTALL
# Set up QTDIR, KDEDIR, PATH, LD_LIBRARY_PATH, XDG_DATA_DIRS and XDG_CONFIG_DIRS
cd $QTDIR
./configure -system-zlib -qt-gif -system-libpng \
-system-libjpeg -plugin-imgfmt-mng -thread -no-stl \
-no-xinerama -no-g++-exceptions
make

Note that -thread is required (KDE will not run or even compile if you omit it), that -no-xinerama is only if you're not using xinerama, and -no-g++-exceptions is strongly recommended if you're using gcc.

Make sure to compile and install first arts, and afterwards kdelibs before any other packages. Also, if you want to use kdeaddons, it should be compiled last as it requires kdebase, kdemultimedia, etc.

For each KDE package:

bunzip2 <package>.tar.bz2
tar xvf <package>.tar
cd <package>
./configure
make
make install
Note
  • If compiling on a system where GNU make is not the default make (that is, most systems other than Linux), please run gmake && gmake install instead of make && make install.
  • All packages mentioned here have to be compiled with the same compiler!

See the KDE 3.3 Info Page for some common encountered problems when running KDE 3.3.

Requirements

To compile KDE you need:

  • Qt 3.2.x - doesn't compile with Qt 3.1.x
  • Automake 1.5 and Autoconf 2.5
  • a C++ compiler which supports exceptions, preferably gcc-2.95.x or gcc-3.2
  • bunzip2 to decompress .bz2 files. You can find it here. Get libbz2 while you're at it, it enables reading of .tar.bz2 files in konqueror, and one day, will give access to .bz2 files to all KDE applications.
  • If you want SSL support (for instance for secure web sites in konqueror), make sure you install openssl, version 0.9.6 or later (versions 0.9.5x are not supported).
  • For Netscape-plugins support in konqueror, make sure to install lesstif.
  • For a better regular-expressions support in Javascript, install libpcre.
  • For the KDE help system, you'll need to install libxml2, version 2.3.13 or newer.
  • There are additional modules that are compiled if the required library is present, but they aren't critical to run KDE. For instance, libldap for the LDAP kioslave, and cdparanoia for the audiocd kioslave. A more detailed list of requirements is available in the KDE 3.2 Requirements List

Download

In order to run KDE applications, you need the Qt, arts, and kdelibs packages. For a simple desktop (with a window manager, panel, etc), you will also need kdebase. The other packages contain many other applications by topic: networking, graphics, multimedia, games, utilities, toys, software development, etc.

You can find the Qt library (version 3.2.x) at ftp://ftp.trolltech.com/qt/source/

KDE 3.2.x is available from http://download.kde.org/stable/

Installation

Unlike most compiled software, Qt is compiled in the place where it will stay instead of using a 'make install'. Please read the INSTALL instructions in the Qt package. You need to set the QTDIR and KDEDIR to the locations where Qt and KDE will be installed, respectively. Also, append $QTDIR/bin and $KDEDIR/bin to your $PATH and $LD_LIBRARY_PATH. Alternatively, instead of using $LD_LIBRARY_PATH, you may add your Qt and KDE library paths to /etc/ld.so.conf, but don't forget to run ldconfig as root after installing Qt and kdelibs, otherwise configure scripts will fail to find the newly installed libraries!

If your distribution sets $XDG_DATA_DIRS and/or $XDG_CONFIG_DIRS you will want to update them to include the correct $KDEDIR/share/ resp. $KDEDIR/etc/xdg/

bunzip2 qt-x11-3.2.1.tar.bz2
tar xvf qt-x11-3.2.1.tar
cd qt-x11-3.2.1
less INSTALL
# Set up QTDIR, KDEDIR, PATH, LD_LIBRARY_PATH, XDG_DATA_DIRS and XDG_CONFIG_DIRS
cd $QTDIR
./configure -system-zlib -qt-gif -system-libpng \
-system-libjpeg -plugin-imgfmt-mng -thread -no-stl \
-no-xinerama -no-g++-exceptions
make

Note that -thread is required (KDE will not run or even compile if you omit it), that -no-xinerama is only if you're not using xinerama, and -no-g++-exceptions is strongly recommended if you're using gcc.

Make sure to compile and install first arts, and afterwards kdelibs before any other packages. Also, if you want to use kdeaddons, it should be compiled last as it requires kdebase, kdemultimedia, etc.

For each KDE package:

bunzip2 &lt;package&gt;.tar.bz2
tar xvf &lt;package&gt;.tar
cd &lt;package&gt;
./configure
make
make install
Note
  • If compiling on a system where GNU make is not the default make (that is, most systems other than Linux), please run gmake && gmake install instead of 'make && make install'.
  • All packages mentioned here have to be compiled with the same compiler!

See the KDE 3.2 Info Page for some common encountered problems when running KDE 3.2.

Requirements

To compile KDE you need:

  • Qt 3.1.x - doesn't compile with Qt 3.0.x
  • Automake 1.5 and Autoconf 2.5
  • a C++ compiler which supports exceptions, preferably gcc-2.95.x or gcc-3.2
  • bunzip2 to decompress .bz2 files. You can find it here. Get libbz2 while you're at it, it enables reading of .tar.bz2 files in konqueror, and one day, will give access to .bz2 files to all KDE applications.
  • If you want SSL support (for instance for secure web sites in konqueror), make sure you install openssl, version 0.9.6 or later (versions 0.9.5x are not supported).
  • For Netscape-plugins support in konqueror, make sure to install lesstif.
  • For a better regular-expressions support in Javascript, install libpcre.
  • For the KDE help system, you'll need to install libxml2, version 2.3.13 or newer.
  • There are additional modules that are compiled if the required library is present, but they aren't critical to run KDE. For instance, libldap for the LDAP kioslave, and cdparanoia for the audiocd kioslave. A more detailed list of requirements is available in the KDE 3.1 Release Announcement

Download

In order to run KDE applications, you need the Qt, arts, and kdelibs packages. For a simple desktop (with a window manager, panel, etc), you will also need kdebase. The other packages contain many other applications by topic: networking, graphics, multimedia, games, utilities, toys, software development, etc.

You can find the Qt library (version 3.1.x) at ftp://ftp.trolltech.com/qt/source/

KDE 3.1.x is available from http://download.kde.org/stable/

Installation

Unlike most compiled software, Qt is compiled in the place where it will stay instead of using a 'make install'. Please read the INSTALL instructions in the Qt package. You need to set the QTDIR and KDEDIR to the locations where Qt and KDE will be installed, respectively. Also, append $QTDIR/bin and $KDEDIR/bin to your $PATH and $LD_LIBRARY_PATH. Alternatively, instead of using $LD_LIBRARY_PATH, you may add your Qt and KDE library paths to /etc/ld.so.conf, but don't forget to run ldconfig as root after installing Qt and kdelibs, otherwise configure scripts will fail to find the newly installed libraries!

bunzip2 qt-x11-3.1.1.tar.bz2

tar xvf qt-x11-3.1.1.tar
cd qt-x11-3.1.1
less INSTALL
# Set up QTDIR, KDEDIR, PATH, and LD_LIBRARY_PATH
cd $QTDIR
./configure -system-zlib -qt-gif -system-libpng \
-system-libjpeg -plugin-imgfmt-mng -thread -no-stl \
-no-xinerama -no-g++-exceptions
make

Note that -thread is required (KDE will not run or even compile if you omit it), that -no-xinerama is only if you're not using xinerama, and -no-g++-exceptions is strongly recommended if you're using gcc.

Make sure to compile and install first arts, and afterwards kdelibs before any other packages. Also, if you want to use kdeaddons, it should be compiled last as it requires kdebase, kdemultimedia, etc.

For each KDE package:

bunzip2 <package>.tar.bz2
tar xvf <package>.tar
cd <package>
./configure
make
make install
Note
  • If compiling on a system where GNU make is not the default make (that is, most systems other than Linux), please run gmake && gmake install instead of 'make && make install'.
  • All packages mentioned here have to be compiled with the same compiler!

See the KDE 3.1 Info Page for some common encountered problems when running KDE 3.1.

Requirements

To compile KDE you need:

  • Qt 3.0.4 up to 3.0.6, doesn't compile with Qt 3.1.x
  • Automake 1.5 and Autoconf 2.5
  • a C++ compiler which supports exceptions, preferably gcc-2.95.x or gcc-3.2
  • bunzip2 to decompress .bz2 files. You can find it here. Get libbz2 while you're at it, it enables reading of .tar.bz2 files in konqueror, and one day, will give access to .bz2 files to all KDE applications.
  • If you want SSL support (for instance for secure web sites in konqueror), make sure you install openssl, version 0.9.6 or later (versions 0.9.5x are not supported).
  • For Netscape-plugins support in konqueror, make sure to install lesstif.
  • For a better regular-expressions support in Javascript, install libpcre.
  • For the KDE help system, you'll need to install libxml2, version 2.3.13 or newer.
  • There are additional modules that are compiled if the required library is present, but they aren't critical to run KDE. For instance, libldap for the LDAP kioslave, and cdparanoia for the audiocd kioslave. A more detailed list of requirements is available in the KDE 3.0 Release Announcement

Download

In order to run KDE applications, you need the Qt, arts, and kdelibs packages. For a simple desktop (with a window manager, panel, etc), you will also need kdebase. The other packages contain many other applications by topic: networking, graphics, multimedia, games, utilities, toys, software development, etc.

You can find the Qt library (version 3.0.4) at ftp://ftp.trolltech.com/qt/source/

KDE 3.0.x is available from http://download.kde.org/stable/

Installation

Unlike most compiled software, Qt is compiled in the place where it will stay instead of using a 'make install'. Please read the INSTALL instructions in the Qt package. You need to set the QTDIR and KDEDIR to the locations where Qt and KDE will be installed, respectively. Also, append $QTDIR/bin and $KDEDIR/bin to your $PATH and $LD_LIBRARY_PATH. Alternatively, instead of using $LD_LIBRARY_PATH, you may add your Qt and KDE library paths to /etc/ld.so.conf, but don't forget to run ldconfig as root after installing Qt and kdelibs, otherwise configure scripts will fail to find the newly installed libraries!

bunzip2 qt-x11-3.0.4.tar.bz2
tar xvf qt-x11-3.0.4.tar
cd qt-x11-3.0.4
less INSTALL
# Set up QTDIR, KDEDIR, PATH, and LD_LIBRARY_PATH
cd $QTDIR
./configure -system-zlib -qt-gif -system-libpng \
-system-libjpeg -plugin-imgfmt-mng -thread -no-stl \
-no-xinerama -no-g++-exceptions
make

Note that -thread is required (KDE will not run or even compile if you omit it), that -no-xinerama is only if you're not using xinerama, and -no-g++-exceptions is strongly recommended if you're using gcc.

Make sure to compile and install first arts, and afterwards kdelibs before any other packages. Also, if you want to use kdeaddons, it should be compiled last as it requires kdebase, kdemultimedia, etc.

For each KDE package:

bunzip2 <package>.tar.bz2
tar xvf <package>.tar
cd <package>
./configure
make
make install
Note
  • If compiling on a system where GNU make is not the default make (that is, most systems other than Linux), please run gmake && gmake install instead of make && make install.
  • All packages mentioned here have to be compiled with the same compiler!

See the KDE 3.0 Info Page for some common encountered problems when running KDE 3.0.

Requirements

To compile KDE you need:

  • Qt 2.3.1
  • Automake 1.5 and Autoconf 2.5
  • a C++ compiler which supports exceptions, preferably gcc-2.95.x.
  • bunzip2 to decompress .bz2 files. You can find it here. Get libbz2 while you're at it, it enables reading of .tar.bz2 files in konqueror, and one day, will give access to .bz2 files to all KDE applications.
  • If you want SSL support (for instance for secure web sites in konqueror), make sure you install openssl, version 0.9.6 or later (versions 0.9.5x are not supported).
  • For Netscape-plugins support in konqueror, make sure to install lesstif.
  • For a better regular-expressions support in Javascript, install libpcre.
  • For the KDE help system, you'll need to install libxml2, version 2.3.13 or newer.
  • There are additional modules that are compiled if the required library is present, but they aren't critical to run KDE. For instance, libldap for the LDAP kioslave, and cdparanoia for the audiocd kioslave.

Download

In order to run KDE applications, you need the Qt and kdelibs packages. For a simple desktop (with a window manager, panel, etc), you will also need kdebase. The other packages contain many other applications by topic: networking, graphics, multimedia, games, utilities, toys, software development, etc.

You can find the Qt library (version 2.3.1) at https://download.qt.io/archive/qt/

KDE 2.2.2 is available from ftp://ftp.kde.org/pub/kde/Attic/2.2.2/src/

Installation

Unlike most compiled software, Qt is compiled in the place where it will stay instead of using a 'make install'. Please read the INSTALL instructions in the Qt package. You need to set the QTDIR and KDEDIR to the locations where Qt and KDE will be installed, respectively. Also, append $QTDIR/bin and $KDEDIR/bin to your $PATH and $LD_LIBRARY_PATH. Alternatively, instead of using $LD_LIBRARY_PATH, you may add your Qt and KDE library paths to /etc/ld.so.conf, but don't forget to run ldconfig as root after installing Qt and kdelibs, otherwise configure scripts will fail to find the newly installed libraries!

bunzip2 qt-x11-2.3.1.tar.bz2
tar xvf qt-x11-2.3.1.tar
cd qt-2.3.1
less INSTALL
# Set up QTDIR, KDEDIR, PATH, and LD_LIBRARY_PATH
cd $QTDIR
./configure -sm -gif -system-jpeg -no-opengl
make

Make sure to compile and install kdelibs before any other packages. Also, if you want to use kdeaddons, it should be compiled last as it requires kdebase, kdemultimedia, etc.

For each KDE package:

bunzip2 <package>.tar.bz2
tar xvf <package>.tar
cd <package>
./configure
make
make install
Note
  • If compiling on a system where GNU make is not the default make (that is, most systems other than Linux), please run gmake && gmake install instead of make && make instally.
  • All packages mentioned here have to be compiled with the same compiler!

See the KDE 2.2.2 Info Page for some common encountered problems when running KDE 2.2.2.

 
Proposed for Deletion
This page has been proposed for deletion for the following reason:

Instead, use https://community.kde.org/Get_Involved

Proposed for moving to community.kde.org
It has been proposed that this page should be moved to the community.kde.org wiki for the following reason:

Archive, Internal project documentation.


This document gives an overview of the different modules within KDE's repository.

Overview

See also list of module coordinators.

Module Name Description Release Example
qt-copy Qt Qt Qt Designer
kdelibs Basic libraries KDE Plasma
KDE Base Apps Basic programs and utilities KDE Konqueror
kdesupport Support libraries KDE Oxygen
kdenetwork Network KDE Kopete
kdepim Personal Information Management KDE KMail
kdegraphics Image viewing and manipulation KDE KolourPaint
kdeutils Utilities KDE Okteta
kdeedu Education KDE KStars
kdegames Games KDE KMahjongg
kdeartwork Additional artwork for KDE KDE Screensavers
kdemultimedia Multimedia KDE JuK
kdeaccessibility Tools for disabled people KDE KMouth
kdebindings Bindings to programming languages KDE Kross
kdesdk Development Tools KDE Lokalize
kdetoys Toys KDE kteatime
kdeadmin System Administration KDE KSystemLog
l10n-kde4 Translations L10N British English (en_GB)
kwebdev Web development KDE KFileReplace
extragear-accessibility Extra accessibility programs Extra Simon
extragear-base Extra base programs Extra BlueDevil
extragear-games Extra games Extra Knights
extragear-graphics Extra graphic programs Extra digiKam
extragear-kdevelop Developing Environment Extra KDevelop
extragear-multimedia Extra mutlimedia programs Extra K3B
extragear-network Extra network programs Extra Konversation
extragear-office Extra office programs Extra Kile
extragear-pim Extra PIM programs Extra KSig
extragear-sdk Extra development tools Extra Massif Visualizer
extragear-sysadmin Extra system administration programs Extra kiosktool
extragear-utils Extra utility programs Extra Krusader
extragear-libs Extra libraries Extra libkgapi
calligra Calligra Calligra Krita
koffice KOffice KOffice KWord
www Web Sites Web KDE Web Site
kdereview New applications Never -
playground-artwork Artwork sandbox Never Dekorator
playground-base Basic application sandbox Sometimes Public Transport applet
playground-edu Education sandbox Sometimes KVerbos
playground-games Game sandbox Sometimes KBackgammon
playground-graphics Graphics sandbox Sometimes Cirkuit
playground-ioslaves KIO slave sandbox Sometimes kio_locate
playground-multimedia Multimedia sandbox Sometimes Audex
playground-network Network sandbox Sometimes Smb4K
playground-office Office sandbox Sometimes Kraft
playground-pim PIM sandbox Sometimes Zanshin
playground-sdk Development sandbox Sometimes Cocoon
playground-sysadmin System administration sandbox Sometimes Shaman
playground-utils Utility sandbox Sometimes GwenRename
kde-common Administrative stuff Never Accounts

Release rhythms:

  • Qt: Qt Project has its own release cycles for Qt.
  • KDE: released with KDE (2 per year).
  • Calligra: released with Calligra (2 per year).
  • KOffice: released with KOffice.
  • Extra: Each program has its own release cycle.
  • L10N: the translations are released with the corresponding programs.
  • Web: web sites are normally synchronized every half-an-hour.
  • Sometimes: these modules are relesed at the developer's wish.
  • Never: these modules are never released.

Most Basic System

TODO (In short: the most basic system is made of Qt, arts, kdelibs, kdebase). ???Recommended minimal: add kdegraphics and kdepim???

Qt

Qt-copy is a convenience to avoid to have to patch the official Qt release. (Note: it is not a fork.) Nevertheless KDE works with official Qt versions and also with Qt snapshots (except major bugs of course). Using snapshots is not recommended for using a stable KDE.

KIOSK

TODO (in short: the KIOSK mode allows to forbid users to change certain settings in KDE.) Further information: KDE System Administration Kiosk Introduction

Playground

TODO (in short: these modules are the sandboxes for developers. Programs here might not work.)

kdereview

See Application Lifecycle

Extragear

The kdeextragear modules contains stable applications that are not released with KDE but that have their own release schedule.

See extragear.kde.org.

www

TODO: (in short: write protect by default.)

Warning
This section needs improvements: Please help us to

cleanup confusing sections and fix sections which contain a todo


DCOP: Desktop COmmunications Protocol

Preston Brown <[email protected]> October 14, 1999

Revised and extended by Matthias Ettrich <[email protected]> Mar 29, 2000

HTMLized by Hans Meine Hans Meine <[email protected]> May 25, 2000

Added a DCOPRef example: Tim Jansen May 12, 2003

Demotivation and Background

Note that new features may not be developed for DCOP. The successor for DCOP is D-Bus

The motivation behind building a protocol like DCOP is simple. For the past year, we have been attempting to enable interprocess communication between KDE applications. KDE already has an extremely simple IPC mechanism called KWMcom, which is (was!) used for communicating between the panel and the window manager for instance. It is about as simple as it gets, passing messages via X Atoms. For this reason it is limited in the size and complexity of the data that can be passed (X atoms must be small to remain efficient) and it also makes it so that X is required. CORBA was thought to be a more effective IPC/RPC solution. However, after a year of attempting to make heavy use of CORBA in KDE, we have realized that it is a bit slow and memory intensive for simple use. It also has no authentication available.

What we really needed was an extremely simple protocol with basic authorization, along the lines of MIT-MAGIC-COOKIE, as used by X. It would not be able to do NEARLY what CORBA was able to do, but for the simple tasks required it would be sufficient. Some examples of such tasks might be an application sending a message to the panel saying, "I have started, stop displaying the 'application starting' wait state," or having a new application that starts query to see if any other applications of the same name are running. If they are, simply call a function on the remote application to create a new window, rather than starting a new process.

Implementation

DCOP is a simple IPC/RPC mechanism built to operate over sockets. Either unix domain sockets or tcp/ip sockets are supported. DCOP is built on top of the Inter Client Exchange (ICE) protocol, which comes standard as a part of X11R6 and later. It also depends on Qt, but beyond that it does not require any other libraries. Because of this, it is extremely lightweight, enabling it to be linked into all KDE applications with low overhead.

Model

The model is simple. Each application using DCOP is a client. They communicate to each other through a DCOP server, which functions like a traffic director, dispatching messages/calls to the proper destinations. All clients are peers of each other.

Two types of actions are possible with DCOP: "send and forget" messages, which do not block, and "calls," which block waiting for some data to be returned.

Any data that will be sent is serialized (marshalled, for you CORBA fellows) using the built-in QDataStream operators available in all of the Qt classes. This is fast and easy. In fact it's so little work that you can easily write the marshalling code by hand. In addition, there's a simple IDL-like compiler available (dcopidl and dcopidl2cpp) that generates stubs and skeletons for you. Using the dcopidl compiler has the additional benefit of type safety.

This HOWTO describes the manual method first and covers the dcopidl compiler later.

Managing DCOP Connections Manually

Establishing the Connection

KApplication has gained a method called "KApplication::dcopClient()" which returns a pointer to a DCOPClient instance. The first time this method is called, the client class will be created. DCOPClients have unique identifiers attached to them which are based on what KApplication::name() returns. In fact, if there is only a single instance of the program running, the appId will be equal to KApplication::name().

To actually enable DCOP communication to begin, you must use DCOPClient::attach(). This will attempt to attach to the DCOP server. If no server is found or there is any other type of error, attach() will return false. KApplication will catch a dcop signal and display an appropriate error message box in that case.

After connecting with the server via DCOPClient::attach(), you need to register this appId with the server so it knows about you. Otherwise, you are communicating anonymously. Use the DCOPClient::registerAs(const QCString &name) to do so. In the simple case:


/*
 * returns the appId that is actually registered, which _may_ be
 * different from what you passed
 */
appId = client -> registerAs (kApp -> name());

If you never retrieve the DCOPClient pointer from KApplication, the object will not be created and thus there will be no memory overhead.

You may also detach from the server by calling DCOPClient::detach(). If you wish to attach again you will need to re-register as well. If you only wish to change the ID under which you are registered, simply call DCOPClient::registerAs() with the new name.

KUniqueApplication automatically registers itself to DCOP. If you are using KUniqueApplication you should not attach or register yourself, this is already done. The appId is by definition equal to kapp->name(). You can retrieve the registered DCOP client by calling kapp->dcopClient().

Sending Data to a Remote Application

To actually communicate, you have one of two choices. You may either call the "send" or the "call" method. Both methods require three identification parameters: an application identifier, a remote object, a remote function. Sending is asynchronous (i.e. it returns immediately) and may or may not result in your own application being sent a message at some point in the future. Then "send" requires one and "call" requires two data parameters.

The remote object must be specified as an object hierarchy. That is, if the toplevel object is called "fooObject" and has the child "barObject", you would reference this object as "fooObject/barObject". Functions must be described by a full function signature. If the remote function is called "doIt", and it takes an int, it would be described as "doIt(int)". Please note that the return type is not specified here, as it is not part of the function signature (or at least the C++ understanding of a function signature). You will get the return type of a function back as an extra parameter to DCOPClient::call(). See the section on call() for more details.

In order to actually get the data to the remote client, it must be "serialized" via a QDataStream operating on a QByteArray. This is how the data parameter is "built". A few examples will make clear how this works.

Say you want to call "doIt" as described above, and not block (or wait for a response). You will not receive the return value of the remotely called function, but you will not hang while the RPC is processed either. The return value of send() indicates whether DCOP communication succeeded or not.

QByteArray data;
QDataStream arg(data, IO_WriteOnly);
arg << 5;
if (!client -> send ("someAppId", "fooObject/barObject", "doIt(int)",
                     data))
    qDebug ("there was some error using DCOP.");

OK, now let's say we wanted to get the data back from the remotely called function. You have to execute a call() instead of a send(). The returned value will then be available in the data parameter "reply". The actual return value of call() is still whether or not DCOP communication was successful.

QByteArray data, replyData;
QCString replyType;
QDataStream arg (data, IO_WriteOnly);
arg << 5;
if (!client -> call ("someAppId", "fooObject/barObject", "doIt(int)",
                     data, replyType, replyData))
    qDebug("there was some error using DCOP.");
else {
    QDataStream reply (replyData, IO_ReadOnly);
    if (replyType == "QString") {
        QString result;
        reply >> result;
        print ("the result is: %s", result. latin1());
    } else
        qDebug ("doIt returned an unexpected type of reply!");
}

N.B.: You cannot call() a method belonging to an application which has registered with an unique numeric id appended to its textual name (see dcopclient.h for more info). In this case, DCOP would not know which application it should connect with to call the method. This is not an issue with send(), as you can broadcast to all applications that have registered with appname-<numeric_id> by using a wildcard (e.g. 'konsole-*'), which will send your signal to all applications called 'konsole'.

Since KDE 3.1 there is an even easier way to make a DCOP call: DCOPRef. Then you only need to create a DCOPRef to the object and as long as the function does not use unusual argument types, calling the function is as easy as this:

DCOPRef barObject ("someAppId", "fooObject/barObject");
DCOPReply reply = barObject. call ("doIt", 5);
if (!reply. isValid())
    qDebug("there was some error using DCOP.");
else {
    print("the result is: %s", ((QString)reply). latin1());
}

Receiving Data via DCOP

Currently the only real way to receive data from DCOP is to multiply inherit from the normal class that you are inheriting (usually some sort of QWidget subclass or QObject) as well as the DCOPObject class. DCOPObject provides one very important method: DCOPObject::process(). This is a pure virtual method that you must implement in order to process DCOP messages that you receive. It takes a function signature, QByteArray of parameters, and a reference to a QByteArray for the reply data that you must fill in.

Think of DCOPObject::process() as a sort of dispatch agent. In the future, there will probably be a precompiler for your sources to write this method for you. However, until that point you need to examine the incoming function signature and take action accordingly. Here is an example implementation.

bool BarObject:: process (const QCString &fun, const QByteArray &data,
                        QCString &replyType, QByteArray &replyData)
{
    if (fun == "doIt(int)") {
        QDataStream arg (data, IO_ReadOnly);
        int i; // parameter
        arg >> i;
        QString result = self -> doIt (i);
        QDataStream reply (replyData, IO_WriteOnly);
        reply << result;
        replyType = "QString";
        return true;
    } else {
        qDebug ("unknown function call to BarObject::process()");
        return false;
    }
}

Processing Received Calls with Transactions

If your applications is able to process incoming function calls right away the above code is all you need. When your application needs to do more complex tasks you might want to do the processing out of 'process' function call and send the result back later when it becomes available.

For this you can ask your DCOPClient for a transactionId. You can then return from the 'process' function and when the result is available finish the transaction. In the mean time your application can receive incoming DCOP function calls from other clients.

Such code could like this:

bool BarObject::process(const QCString &fun, const QByteArray &data,
                        QCString &, QByteArray &)
{
    if (fun == "doIt(int)") {
        QDataStream arg (data, IO_ReadOnly);
        int i; // parameter
        arg >> i;
        QString result = self -> doIt(i);

        DCOPClientTransaction *myTransaction;
        myTransaction = kapp -> dcopClient() -> beginTransaction();

        // start processing...
        // Calls slotProcessingDone when finished.
        startProcessing (myTransaction, i);

        return true;
    } else {
        qDebug("unknown function call to BarObject::process()");
        return false;
    }
}
 
slotProcessingDone(DCOPClientTransaction *myTransaction, const QString &result)
{
    QCString replyType = "QString";
    QByteArray replyData;
    QDataStream reply(replyData, IO_WriteOnly);
    reply << result;
    kapp 
-> dcopClient() -> endTransaction(myTransaction, replyType, replyData);
}

DCOP Signals

Sometimes a component wants to send notifications via DCOP to other components but does not know which components will be interested in these notifications. One could use a broadcast in such a case but this is a very crude method. For a more sophisticated method DCOP signals have been invented.

DCOP signals are very similair to Qt signals, there are some differences though. A DCOP signal can be connected to a DCOP function. Whenever the DCOP signal gets emitted, the DCOP functions to which the signal is connected are being called. DCOP signals are, just like Qt signals, one way. They do not provide a return value.

A DCOP signal originates from a DCOP Object/DCOP Client combination (sender). It can be connected to a function of another DCOP Object/DCOP Client combination (receiver).

There are two major differences between connections of Qt signals and connections of DCOP signals. In DCOP, unlike Qt, a signal connections can have an anonymous sender and, unlike Qt, a DCOP signal connection can be non-volatile.

With DCOP one can connect a signal without specifying the sending DCOP Object or DCOP Client. In that case signals from any DCOP Object and/or DCOP Client will be delivered. This allows the specification of certain events without tying oneself to a certain object that implementes the events.

Another DCOP feature are so called non-volatile connections. With Qt signal connections, the connection gets deleted when either sender or receiver of the signal gets deleted. A volatile DCOP signal connection will behave the same. However, a non-volatile DCOP signal connection will not get deleted when the sending object gets deleted. Once a new object gets created with the same name as the original sending object, the connection will be restored. There is no difference between the two when the receiving object gets deleted, in that case the signal connection will always be deleted.

A receiver can create a non-volatile connection while the sender doesn't (yet) exist. An anonymous DCOP connection should always be non-volatile.

The following example shows how KLauncher emits a signal whenever it notices that an application that was started via KLauncher terminates.

Example
QByteArray params;
QDataStream stream (params, IO_WriteOnly);
stream << pid;
kapp -> dcopClient() -> emitDCOPSignal ("clientDied(pid_t)", params);

The task manager of the KDE panel connects to this signal. It uses an anonymous connection (it doesn't require that the signal is being emitted by KLauncher) that is non-volatile:

Example
connectDCOPSignal (0, 0, "clientDied(pid_t)", "clientDied(pid_t)", false);

It connects the clientDied(pid_t) signal to its own clientDied(pid_t) DCOP function. In this case the signal and the function to call have the same name. This isn't needed as long as the arguments of both signal and receiving function match. The receiving function may ignore one or more of the trailing arguments of the signal. E.g. it is allowed to connect the clientDied(pid_t) signal to a clientDied(void) DCOP function.

Using the dcopidl compiler

dcopidl makes setting up a DCOP server easy. Instead of having to implement the process() method and unmarshalling (retrieving from QByteArray) parameters manually, you can let dcopidl create the necessary code on your behalf.

This also allows you to describe the interface for your class in a single, separate header file.

Writing an IDL file is very similar to writing a normal C++ header. An exception is the keyword 'ASYNC'. It indicates that a call to this function shall be processed asynchronously. For the C++ compiler, it expands to 'void'.

Example
#ifndef MY_INTERFACE_H
#define MY_INTERFACE_H

#include <dcopobject.h>

class MyInterface : virtual public DCOPObject
{
    K_DCOP

    k_dcop:

        virtual ASYNC myAsynchronousMethod (QString someParameter) = 0;
        virtual QRect mySynchronousMethod() = 0;
};

#endif

As you can see, you're essentially declaring an abstract base class, which virtually inherits from DCOPObject.

If you're using the standard KDE build scripts, then you can simply add this file (which you would call MyInterface.h) to your sources directory. Then you edit your Makefile.am, adding 'MyInterface.skel' to your SOURCES list and MyInterface.h to include_HEADERS.

The build scripts will use dcopidl to parse MyInterface.h, converting it to an XML description in MyInterface.kidl. Next, a file called MyInterface_skel.cpp will automatically be created, compiled and linked with your binary.

The next thing you have to do is to choose which of your classes will implement the interface described in MyInterface.h. Alter the inheritance of this class such that it virtually inherits from MyInterface. Then add declarations to your class interface similar to those on MyInterface.h, but virtual, not pure virtual.

Example
class MyClass: public QObject, virtual public MyInterface
{
    Q_OBJECT

    public:
        MyClass();
        ~MyClass();

        ASYNC myAsynchronousMethod(QString someParameter);
        QRect mySynchronousMethod();
};

Note: (Qt issue) Remember that if you are inheriting from QObject, you must place it first in the list of inherited classes.

In the implementation of your class' ctor, you must explicitly initialize those classes from which you are inheriting from. This is, of course, good practise, but it is essential here as you need to tell DCOPObject the name of the interface which your are implementing.

Example
MyClass::MyClass()
  : QObject(),
    DCOPObject("MyInterface")
{
    // whatever...
}

Now you can simply implement the methods you have declared in your interface, exactly the same as you would normally.

Example
void MyClass::myAsynchronousMethod(QString someParameter)
{
    qDebug("myAsyncMethod called with param `" + someParameter + "'");
}

It is not necessary (though very clean) to define an interface as an abstract class of its own, like we did in the example above. We could just as well have defined a k_dcop section directly within MyClass:

class MyClass: public QObject, virtual public DCOPObject
{
    Q_OBJECT
    K_DCOP

    public:
        MyClass();
        ~MyClass();

    k_dcop:
        ASYNC myAsynchronousMethod(QString someParameter);
        QRect mySynchronousMethod();
};

In addition to skeletons, dcopidl2cpp also generate stubs. Those make it easy to call a DCOP interface without doing the marshalling manually. To use a stub, add MyInterface.stub to the SOURCES list of your Makefile.am. The stub class will then be called MyInterface_stub.

Inter-user communication

Sometimes it might be interesting to use DCOP between processes belonging to different users, e.g. a frontend process running with the user's id, and a backend process running as root.

To do this, two steps have to be taken:

  • both processes need to talk to the same DCOP server
  • proper authentication must be ensured

For the first step, you simply pass the server address (as found in .DCOPserver) to the second process. For the authentication, you can use the ICEAUTHORITY environment variable to tell the second process where to find the authentication information. (Note that this implies that the second process is able to read the authentication file, so it will probably only work if the second process runs as root. If it should run as another user, a similar approach to what kdesu does with xauth must be taken. In fact, it would be a very good idea to add DCOP support to kdesu!)

For example

ICEAUTHORITY=~user/.ICEauthority kdesu root -c kcmroot -dcopserver `cat ~user/.DCOPserver`

will, after kdesu got the root password, execute kcmroot as root, talking to the user's dcop server.

NOTE: DCOP communication is not encrypted, so please do not pass important information around this way.


Performance Tests

A few back-of-the-napkin tests folks:

Code:

#include <kapp.h>

int main (int argc, char **argv)
{
    KApplication *app;

    app = new KApplication (argc, argv, "testit");
    return app -> exec();
}

Compiled with:

g++ -O2 -o testit testit.cpp -I$QTDIR/include -L$QTDIR/lib -lkdecore

on Linux yields the following memory use statistics:

VmSize:     8076 kB
VmLck:         0 kB
VmRSS:      4532 kB
VmData:      208 kB
VmStk:        20 kB
VmExe:         4 kB
VmLib:      6588 kB

If I create the KApplication's DCOPClient, and call attach() and registerAs(), it changes to this:

VmSize:     8080 kB
VmLck:         0 kB
VmRSS:      4624 kB
VmData:      208 kB
VmStk:        20 kB
VmExe:         4 kB
VmLib:      6588 kB

Basically it appears that using DCOP causes 100k more memory to be resident, but no more data or stack. So this will be shared between all processes, right? 100k to enable DCOP in all apps doesn't seem bad at all. :)

OK now for some timings. Just creating a KApplication and then exiting (i.e. removing the call to KApplication::exec) takes this much time:

0.28user 0.02system 0:00.32elapsed 92%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (1084major+62minor)pagefaults 0swaps

I.e. about 1/3 of a second on my PII-233. Now, if we create our DCOP object and attach to the server, it takes this long:

0.27user 0.03system 0:00.34elapsed 87%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (1107major+65minor)pagefaults 0swaps

I.e. about 1/3 of a second. Basically DCOPClient creation and attaching gets lost in the statistical variation ("noise"). I was getting times between .32 and .48 over several runs for both of the example programs, so obviously system load is more relevant than the extra two calls to DCOPClient::attach and DCOPClient::registerAs, as well as the actual DCOPClient constructor time.

Conclusion

Hopefully this document will get you well on your way into the world of inter-process communication with KDE! Please direct all comments and/or suggestions to Preston Brown <[email protected]> and Matthias Ettrich <[email protected]>.

Warning
This page needs a review and probably holds information that needs to be fixed.

Parts to be reviewed:

Port to KF5

The mission

Print Hello World on your printer. There will be no more dialog to confirm how many pages you want or the like.

The files

main.cpp

#include <qpainter.h>
#include <qprinter.h>
#include <kapplication.h>
#include <kaboutdata.h>
#include <kmessagebox.h>
#include <kcmdlineargs.h>

/*
This prints Hello World on your printer
*/

int main(int argc, char *argv[])
{
    KAboutData aboutData(
                         // The program name used internally.
                         "tutorial-printing",
                         // The message catalog name
                         // If null, program name is used instead.
                         0,
                         // A displayable program name string.
                         ki18n("Printing Tutorial"),
                         // The program version string.
                         "1.0",
                         // Short description of what the app does.
                         ki18n("Displays a KMessageBox popup"),
                         // The license this code is released under
                         KAboutData::License_GPL,
                         // Copyright Statement
                         ki18n("(c) 2006-2011"),
                         // Optional text shown in the About box.
                         // Can contain any information desired.
                         ki18n("Some text..."),
                         // The program homepage string.
                         "http://example.com/",
                         // The bug report email address
                         "[email protected]");
    KCmdLineArgs::init( argc, argv, &aboutData );
    KApplication app;

    QPrinter printer;
    printer.setFullPage(true);
    QPainter painter;
    painter.begin(&printer);
    painter.drawText(100,100,"Hello World");
    painter.end(); 
    // this makes the print job start
}

CMakeLists.txt

find_package(KDE4 REQUIRED)
include_directories( ${KDE4_INCLUDES} )
kde4_add_executable(printhelloworld main.cpp)
target_link_libraries(printhelloworld ${KDE4_KDEUI_LIBS} ${QT_QTGUI_LIBRARY})

Make and Run

To build and run it, make sure you have your build environment set up correctly as described here, then do:

cmake .
make
./printhelloworld

Next

Next: How to use the KDE print dialog in your programs


Below is the old version of this wiki page.




Here is a list of currently available tutorials for developing KDE Applications or KDE Plasma, or using KDE Frameworks to develop a 3rd-party application.

Basics of how to develop with KDE Frameworks

These tutorials were moved to Getting Started with KXmlGui. Not yet moved pages:

Common Programming Mistakes
Various common mistakes made while developing Qt and KDE applications and how to avoid them.

Integrating with Workspaces

These tutorials were moved to Features. Not yet moved pages:

Icons
Deliver your application with icons that are automatically installed to the right places. Based on the Kaction Tutorial.

Managing Configuration Data With KConfig

These tutorials were moved to Configuration. Not yet moved pages:

Updating KConfig Files
Tutorial on how to write an update script to keep changes in your application's config file format in sync with the user's already existing config file

Services : Applications and Plugins

Introduction to the Services Framework
An overview of the services framework in KDE and what it provides the application developer. Covers the system configuration cache (SyCoCa), the source data files and what the indexed information can be used for.
Finding Services Using Trader Queries
How to find services, such as plugins or mimetypes, that are indexed in the SyCoCa using Trader Query Syntax
Creating and Loading Plugins Using KService
Learn how to define custom plugin types, find installed plugins (including 3rd party plugins) and load them in an easy and portable fashion using KService.

Localization

See also Localization portal.

Introduction To Unicode
An introduction to what Unicode is as well as how to handle Unicode data in KDE applications.
Writing Applications With Localization In Mind
This tutorial covers what localization is, why it's important and how to ensure your application is ready to be localized. A must read for all application developers.
Avoiding Common Localization Pitfalls
There are several common mistakes that prevent applications from being properly localized. Find out what they are and how to easily avoid them in this tutorial.
Building KDE's Localization Module
Building and installing language support from KDE's localization (l10n) module is a good idea for those working on applications in the main KDE repository. Doing so will allow you to test your application in another language and spot problem areas. Learn how to do just that in this tutorial.
Incorporating i18n Into the Build System
Once your application is ready to be localized, the next step is to ensure that translation files are built automatically and kept up to date. This tutorial covers the necessary CMakeFiles.txt additions as well the process of distributing the resulting message catalogs with your application.
Common i18n Challenges and Solutions
This tutorial covers challenges that you may eventually run into such as translating handbooks and other data that exists outside of the source code, merging and handling obsolete .po files, dealing with freezes, coding in languages other than English and creating independent releases of or moving applications between KDE modules.
Semantic Markup of Messages
To ensure consistent presentation and more meaningful representations of messages in applications, semantic markup can be applied to messages marked for translation using the KUIT system. This tutorial describes how this system works.
Automated i18n Code Checking
The Krazy code checker scans KDE's code and reports common i18n mistakes.
Dealing with Language Changes
This tutorial covers dealing with changing languages: How to add the function to change the language and then dynamically update the user interface when language has been changed.
Understanding How Messages Appear to Translators
An introduction to what context information is extracted (and what isn't) from source code for translators to see.

Application Automation and Scripting

D-Bus

These tutorials were moved to D-Bus. Not yet moved pages:

Intermediate D-Bus
Tips to make use of QtDBus when faced with problematic real-world interfaces.
Creating D-Bus Interfaces
Learn how to expose functionality in your application by creating and using custom D-Bus interfaces. Covers generating the XML descriptions, instantiating interfaces at run time and setting up the build system with CMake.
Using Custom Types with D-Bus
Learn how to use your own types in classes exported on D-Bus. Covers marshaling and unmarshaling of objects, the integration of custom types into XML descriptions and registering the custom types with the Qt Meta Object system.
D-Bus Autostart Services
Turn your application into a D-Bus autostart service with this tutorial. This D-Bus feature, also known as "D-Bus service activation", will ensure that even when your application isn't running that D-Bus calls made to it will work by relying on the D-Bus daemon itself to start your app if and when needed.


Dolphin

These tutorials were moved to Dolphin.

Kross

Introduction to Kross
An introduction to the Kross Scripting Framework.
Hello World
A first application with working kross code.
Calling Functions in Kross
Simple demonstration of calling scripting functions
Connecting Signals and Slots in Kross
Simple demonstration of connecting object signals with script slots
Scripts as Plugins with Kross
This tutorial provides a step-by-step introduction how to integrate scripts as plugins into a KDE application.
Placing script actions in your application menus
Simple demonstration on how to extend you application menus to execute script files.
How to use an ActionCollection
A small Tutorial on How to use Kross::ActionCollections.

Calligra Plugin Tutorials

Calligra Overview
This document shows an overview of the different Calligra plugin types and tells you what each of their purpose and strengths are. If you are new with Calligra plugins, this is the place to start.
Calligra Plugin Creation
This gives a technical overview of what it means to write a Calligra plugin.
Creating Calligra Flake Plugins
This tutorial shows you how you can build a plugin for Calligra applications to allow you embed content in ODF documents using Flake.
Calligra Words Scripting
This tutorial shows how to script Calligra Words with Python, or JavaScript using Kross.
Calligra Sheets Scripting
This tutorial shows how to script Calligra Sheets with Python, or JavaScript using Kross.

System Activity

Writing script actions for the process's context menu
This tutorial shows how to add a context menu action to show custom information about a process.

KWin

These tutorials were moved to KWin Scripting Tutorial. Not yet moved pages:

QML Window Switcher Layouts
This tutorial documents the new QML layouts for the KWin Window Switcher

Plugins and KParts

Using KParts
A kPart is a plugin that you can just load into your application. For example, it is easy to integrate an editor (the katePart) or a console (the konsolePart) into your application's window.
Writing kontact plugins
Kontact plugins are KParts. This tutorial describes how you can write one.
Writing Qt Designer Plugins
Add your widgets to Qt Designer and thus make them usable in UI files.
KCM HowTo
KCM are plugins which are loaded by System Settings to display configuration elements. They can also be used within an application.

Hardware Awareness (Solid)

Introduction to Solid
An introduction to the Solid effort in general and it library in particular.
Listing Devices
How to use the Solid core library to discover the hardware and interact with the system.
Accessing Network Information
How to use the Solid system to get information about the network
Creating a Device Action
When your application is interested in registering actions with the system for removable hardware

Authorization and Privilege escalation (KAuth)

These tutorials were moved to KAuth. Not yet moved pages:

Creating a KAuth helper to perform a privileged action
You will learn how to use KAuth's helpers and escalation facilities, and how to seamlessly make a privileged and non privileged portion of your application interact
Creating a KCM requiring authorization upon saving
Learn how to use the high level KCModule API to create KCModules handling authorization, and its UI integration, on their own

Multimedia (Phonon)

Phonon
Introduction to Phonon tells how to compile and run the code. If you like to work in Python, try this version of the same tutorial
Writing Backends
How to start creating a new backend for the multimedia API
Resources
Please have a look at the online documentation for information on the Phonon API. If you prefer using Qt Assistant or Qt Creator you can also use our offline documentation.

Plasma 5

See Plasma tutorials.

Personal Information Management (Akonadi)

Using Akonadi in Applications
Displaying and modifying data provided by Akonadi
Developing Akonadi Resources
Akonadi Resources are agent programs which transport PIM data between Akonadi and a backend (files, servers, etc)
Using custom data types with Akonadi
Akonadi can handle arbitrary data as item payloads through the use of a plugin based serialization framework

Kate / KWrite

Getting started with KTextEditor plugins
Creating your first KTextEditor plugin
Developing a plugin with configuration dialog
Adding a configuration dialog to the Time & Date example
A small Editor
Create a small application using KTextEditor

KDevelop

Creating a class template
Instructions for creating a class template, which can be used to quickly generate classes from KDevelop.
Creating a project template
Instructions for creating a project template, which can be used for starting new project with KDevelop.
KDevelop-PG-Qt Introduction
Information on the KDevelop parser generator, useful for language plugins.

Printing

KDE mostly uses the Qt Printing infrastructure.

Hello World
Introduction to the KDE printing system

kioslaves

Collaboration

Open Collaboration Services (libattica)

Introduction to Attica
In this tutorial a simple widget showing information about a Person on the server is created.

Get Hot New Stuff

Get Hot New Stuff 3 - Download
How to use KHotNewStuff3 in your application.
Get Hot New Stuff 3 - Checking for Updates
How to check whether updates for installed stuff are available without showing the dialog/widget.
Get Hot New Stuff 3 - Upload
How to add an upload dialog to your application.

Other programming languages

Python (PyQt4)

Note
The tutorials below apply to an older version of Qt only. While there are stable Python bindings available for Qt 5, bindings for KDE Frameworks 5 are still under development.
An Introduction to PyQt
Starting off with an introduction to PyQt4
Using PyKDE4
Introduction to PyKDE4
PyKDE WebKit Tutorial
A simple web browser application in PyKDE
101 Introduction to signals and slots
A simple introduction to Qt's signal and slot architecture.
PyKDE DBus Tutorial
An introduction to DBus communication using PyKDE
PyKDE KNotify Tutorial
An introduction to Knotify (Notifications and KJobs) using PyKDE

Ruby

Note
The tutorials below apply to an older version of Qt only. There are currently no Ruby bindings for Qt 5 and KDE Frameworks 5 available.
KDE Ruby Korundum tutorial
A ruby version of Antonio Larrosa Jiménez's KDE tutorial by Richard Dale. See the Ruby Developers Corner for Qt tutorials and other info.
Qt4 Ruby Tutorial
Nokia's fabulous introductory tutorial to Qt, translated to Ruby.
Creating a Plasma Widget in Ruby
Tutorial that shows how to create your first Plasma Applet using the Ruby language.
Developing Qt4 Applications using Qt Designer and Ruby on Kubuntu
Tutorial that shows how to design a simple User Interface in Qt Designer and then use the resulting widget in a Qt Ruby application we build from scratch.
Ruby-Qt/KDE Book
There is also an approach to create an Ruby-Qt/KDE Book under a free license. The content will be created in this wiki.

Shell

This tutorial was moved to Shell Scripting with KDE Dialogs.

Graphics Programming

QPainter Perfomance
Hints on avoiding common mistakes leading to poor performance when using QPainter
HiDPI Support
How to render sharp GUI for HiDPI display
Migrate Qt Quick Controls 1
Qt Quick Controls 1 is not supported so please follow the guide to upgrade to Qt Quick Controls 2

Using the KDE Games Libraries

KStandardGameAction
Using libkdegames to make your game fit the kdegames standard
Highscores
Implementing a simple highscore table into your game
Theme Selector
Using the libkdegames theme selection dialog
Palapeli Slicers
Creating a slicer plugin for Palapeli

Other tutorials

2D Plotting (KPlotWidget)

Using the KDE data-plotting widget
This tutorial introduces KPlotWidget, which is used for 2-D data plotting. It includes information on simple usage of the widget (including adding and modifying data sets, and customizing the plot axes and labels), and advanced customization (including extending the widget through sub-classing).
Physical Simulation
How to perform a physical simulation: animation and diagram

Spelling and Grammar Checking (Sonnet)

Adding spell-checking or grammar-checking to KDE applications
This tutorial introduces Sonnet and how one may use it to add language correction to your KDE application. Sonnet's auxiliary features shall be described in a separate tutorial.

Using the KDE Wallet API for safe storage

KWallet
"Brief introduction to the KWallet API which can be used for storing all kinds of sensitive information."

Deprecated Material

Warning
Tutorials in this section are outdated and are no longer relevant to the current state of KDE software. They are being retained here for historical purposes only. Please do not use them.


Porting Your Application to KDE4
Help Porting Applications from Qt3/KDE3 to Qt4/KDE4


Accessibility

Accessibility Overview
A list of accessibility tutorials and general information.
Accessibility Checklist
What to look for in your application to make it accessible for as many people as possible.
Screen Reader
This tutorial will explain some details about using screen readers with KDE applications.
Text-To-Speech
How to utilize Jovie text-to-speech service in your application.

D-Bus

Porting from DCOP to D-Bus
Port your applications from DCOP to D-Bus with this handy guide.

Personal Information Management (Akonadi)

Porting Applications which use KResource API
Applications using KDE's now deprecated KResource APIs, e.g. KABC or KCal, need to be ported to use their Akonadi equivalents

Get Hot New Stuff

Old links for KNS2 and KNS1 content:

Introduction to Get Hot New Stuff 2
A short tutorial about how to use KHotNewStuff2 in your application. Deprecated, use version 3
Introduction to Get Hot New Stuff
An introduction to the developer-friendly network update system that allows KDE applications to fetch new application data at runtime in a user friendly manner.
KNewStuff Secure (Original Link)
Tutorial showing how to share resources in a secured way (KDE 3.4 and later). By András Mantia <[email protected]>.

Goya

Introduction to Goya usage
An introduction for the Goya subsystem usage, which allows you to easily add widgets to your itemviews and connect their signals to your code, as they were real widgets.
Introduction to Goya usage (part 2)
The second part of the tutorial, with a slightly more complex example than the first part.

Using the KDE PIM Libraries

iCalendar functionality
Using kcal to manage iCalendar files

Pixmap cache (KPixmapCache)

Using the KDE pixmap cache
This tutorial shows how to use KPixmapCache to cache e.g. pixmaps generated from SVGs or some data.

Porting an application from KSystemTrayIcon to KStatusNotifierItem

Porting from KSystemTrayIcon to KStatusNotifierItem
This tutorials shows how to port an application using KSystemTrayIcon to KStatusNotifierItem

How to edit a wiki with Libmediawiki

Libmediawiki
This tutorial present how to edit a wiki with Libmediawiki.

KDE2 and KDE3 Materials

KDE3 Tutorials
These tutorials cover topics related to KDE3.
KDE2 Tutorials
These tutorials cover topics related to KDE2.

Content moved to this TODO list. Please add your stuff there, now a whole section is reserved for the kde.org stuff.

Obviously, QXML and QDOM need XML-compliant HTML pages, and the least HTML pages are XML-compliant. Perl is not the scope of this site. This tutorial chooses the XHTML approach.

First step

As we remember from http://developernew.kde.org/Development/Tutorials/Programming_Tutorial_KDE_4/How_to_write_an_HTML_parser, biggest thing is to be able to parse non-XML-conform syntax. It works with the following program.

tags.cpp

#include <kapplication.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <dom/html_document.h>

int main (int argc, char *argv[])
{
        KAboutData aboutData( "test", "test",
        "1.0", "test", KAboutData::License_GPL,
        "(c) 2006" );
        KCmdLineArgs::init( argc, argv, &aboutData );
        KApplication khello;

        DOM::HTMLDocument doc;
        DOM::DOMString tag("*");
        DOM::DOMString uri("<html><body><a href=\"http://www.kde.org/\"></a><a href=\"/index.php\" nowrap>Log in</a><a href=\"http://www.gmx.de\"></a></body></html>");

        doc.loadXML(uri);
        kdDebug() << "Does this doc have child elements ? " << doc.hasChildNodes() << endl;
        for (int i=0; i<doc.getElementsByTagName(tag).length(); i++) kdDebug() << doc.getElementsByTagName(tag).item(i).nodeName().string() << endl;
        kdDebug() << "Size of your doc " << sizeof(doc.firstChild()) << endl;
        kdDebug() << doc.isHTMLDocument() << endl;
        kdDebug() << doc.toString().string() << endl;
}


Compile it like this:

gcc -I/usr/lib/qt3/include -I/opt/kde3/include \
-L/opt/kde3/lib -lkdeui -lkhtml -o tags tags.cpp

Second

#include <kapplication.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <dom/html_document.h>
#include <dom/html_element.h>
#include <dom/dom_node.h>

int main (int argc, char *argv[])
{
        KAboutData aboutData( "test", "test",
        "1.0", "test", KAboutData::License_GPL,
        "(c) 2006" );
        KCmdLineArgs::init( argc, argv, &aboutData );
        KApplication khello;

        DOM::HTMLDocument doc;
        DOM::DOMString tag("*");
        DOM::DOMString uri("<html><body><a href=\"http://www.kde.org/\"><b>fat</b></a><a href=\"/index.php\" nowrap>Log in</a><a href=\"http://www.gmx.de\"></a></body></html>");

        doc.loadXML(uri);
        kdDebug() << "Here's a list of the document elements" << endl;
        for (int i=0; i<doc.getElementsByTagName(tag).length(); i++) kdDebug() << doc.getElementsByTagName(tag).item(i).nodeName().string() << endl;
       
        DOM::HTMLDocument doc2;
        DOM::DOMString uri2("<html><body>this is html<b>fat</b></body></html>");
        doc2.loadXML(uri2);
        kdDebug() << "This is the in-memory html:" << endl;
        kdDebug() << doc.toString().string() << endl;
        doc.body().insertBefore(doc.body().firstChild().firstChild(),doc.body().firstChild());
        kdDebug() << "Moving around nodes" << endl;
        kdDebug() << doc.toString().string() << endl;
}

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This icon is part of Oxygen.

Note: The Oxygen icons are copyrighted to the KDE Artist team. This implies that you are not allowed to distribute them without prior written permission.

This tutorial has been taken from http://developer.kde.org/documentation/tutorials/writingunittests/

This tutorial was originally licensed under the GFDL. It can also be used under the terms of the Creative Commons Share-alike license.

Placement

Does this tutorial really belong under "Getting started" on the Tutorial page? It doesn't really seem like a beginner tutorial. At least not something that beginners to KDE4 programming would need to know. Maybe place it under Debugging (though maybe that's a bit stretched :S ) --milliams 14:49, 5 January 2007 (CET)

It doesn't appear under "Getting started", so I think that this might be out of date? --bhards 17:04, 23 March 2007 (UTC+11)

Problems

Did someone try the tutorial? I noted that there is an include of tutorial1.moc but we use qmake in that example. I was under the impression that foo.moc was a cmake standard; qmake doesn't generate that file (its something like moc_foo.h) . You typically don't need to include anything in qmake. Zander 22:08, 21 March 2007 (CET)

|-

|

noframe
noframe

||

Getting Started
Read how to get and build KDE.
Related: Join the Team | Our Policies

|-

|

noframe
noframe

||

Develop KDE
API Documentation, HOWTOs, FAQs and more.
Related:Release Schedules and Feature Plans | Developer Events

|-

|

noframe
noframe

||

ISV Information
Developer information for Independent Software Vendors.

|-

|

noframe
noframe

||

KDE Projects
Information about KDE Projects.

|}

This page has been archived
The information on this page is outdated or no longer in use but is kept for historical purposes. Please see the Category:Archives for similar pages.

Tutorials are the fastest way of finding out what KDE will do for you, and how to do it. Here is a list of currently available tutorials for KDE3 development.

Tip
If you are working with a newer version of KDE software, visit the main tutorials page


Getting Started

Qt Designer and KDevelop 3.0 for Beginners (Original Link)
Qt is the toolkit used by the KDE project for developing graphical applications. Currently, translations are available through the original link. This paper, written by Anne-Marie Mahfouf, shows a beginner how to create a simple application using Qt Designer 3 and KDevelop 3. This tutorial is based on an application written by Jono Bacon and has been reviewed by Daniel Molkentin (for the KDevelop 2 version) and Thomas Nagy. Translations to German, Russian, French, Italian, and Romanian available at the original site. Brought to you by KDE-Women.
KDE 3.0 Tutorial
An excellent tutorial by KDE developer Antonio Larrosa Jiménez leading you from nothing to a fairly full featured web browser. Highly recommended for KDE 3.0 developers.
Programming Tutorial for KDE 3
Makefile.am HOWTO
Make the KDE 3 build system work for you. This HOWTO shows you how to do most anything you would need to do to get your application to compile and install

Components and Plugins

KDE User Interface Tutorial (XML GUI)
Tutorial by KDE developer Kurt Granroth showing how to convert an existing KDE application to use the new XML based user interface builder.
Creating KParts Component
Tutorial on IBM DeveloperWorks, by David Faure shows developers how to create KParts components, under KDE 2 and KDE 3.
Developing a Plugin Structure for a KDE Application
This tutorial will take you through all the steps needed to write a plugin structure, plus plugins for your KDE application.
Providing file meta-data support with KFile plugins
Tutorial by Brad Hards that describes how to write a meta-data plugin for your favourite file format. It is presented as an example based tutorial.
Embedded Components Tutorial
Tutorial by KDE developer Kurt Granroth showing how to convert an existing KDE application into a component suitable for embedding in Konqueror.
How to write Kontact plugins
Kontact plugins
KConfig Module HOWTO
A small tutorial about writing a module for the KDE Control Center.
Using the KDE dock widget
Tutorial for creating widgets that dock to other widgets.
Introduction to Get Hot New Stuff
An introduction to the developer-friendly network update system that allows KDE applications to fetch new application data at runtime in a user friendly manner.

Components and Plugins

KWin

KWin decoration styles
Tutorial on creating decoration plugins for the KWin window manager (KDE 3.2 and later).

Scripting and Application Automation

Konqueror

Creating Konqueror Service Menus
This tutorial shows you how to create mimetype-specific actions in Konqueror's context menu (aka "servicemenus").
This page has been archived
The information on this page is outdated or no longer in use but is kept for historical purposes. Please see the Category:Archives for similar pages.

Tutorials are the fastest way of finding out what KDE will do for you, and how to do it. Here is a list of currently available tutorials for KDE2 development.

Tip
If you are working with a newer version of KDE software, visit the main tutorials page


Getting Started

A KDE tutorial, KHello
A KDE 2 programming tutorial by Daniel Marjamäki. This tutorial introduces the KDE APIs using a graphical version of the world famous 'hello world' program. This document is also available in single download as a gzipped tar file.

General

KDE 2.0 Development
A KDE 2.0 development "book"

Components and Plugins

Kicker

Extending the KDE Panel
This tutorial teaches you how to implement a simple panel applet using the panel applet API. It is a suitable task for an introduction to KDE programming.
Code

{{{text}}}

Parameters

Parameter Function
title A label for the code
args Highlighting type and line-numbering settings
text The code
  • Codesnippet
    {{{1}}}
  • CodeTest{| style="background: #F5F5FF;border: 1px solid #0B198C;" width=90% cellpadding=3 cellspacing=1

| style="background: #334D80;color: #FFFFFF;font: bold 13px tahoma, verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif; padding: 1 5px 3 5px; " align="center" | Code |- | style="font-family:Courier New, Courier, Monospace;font-size: 100%; padding: 0 5px 0 5px;background: #F5F5FF;color: #000000;" | |- |{{{1}}} |- |}

{{{2}}}
{{{1}}}

Use this template for content that needs to be specially emphasized. Syntax:

{{Box1|2=Title|3=Image|4=color|1=text}}

The template takes four arguments:

  1. The text of the main body of the box
  2. The title of the box
  3. An image file to be displayed in the top left of the box - the image size should be 40 x 40 (optional)
  4. The background color (optional): possible values
    • default 'alert-warning' is yellow
    • alert-info gives blue - use with care; it doesn't work well with links
    • alert-success gives green
    • alert-error gives red

Example:

{{Box|2=Example|3=[[Image:Dialog-information.png|left|40px|link=]]|1=This is an example box}}
Example
This is an example box


Please avoid using this template directly in pages. If you need something that doesn't already exist, consider making a new template based on this template. That way it will be much easier to maintain TechBase, and the risk of introducing unintended effects on your page is reduced considerably.

Existing templates based on this template: Template:Info, Template:Note, Template:Tip, Template:Warning, Template:Remember.

 
Proposed for Deletion
This page has been proposed for deletion for the following reason:

This wiki page does not have a parent wiki page.

This page has been archived
The information on this page is outdated or no longer in use but is kept for historical purposes. Please see the Category:Archives for similar pages.
Warning
This tutorial uses Qt4 Ruby bindings that no longer work on Qt 5 and KDE Frameworks 5.



Author: Darshan Ishaya, [email protected]

Original link:http://www.darshancomputing.com/qt4-qtruby-tutorial/

Qt®4 Tutorial for Ruby

This tutorial gives an introduction to GUI programming using the Qt toolkit, Ruby, and qt4-qtruby. It is simply a port of Nokia's fine Qt Tutorial. Therefore, most of the text after this paragraph comes straight from their tutorial. I have modified it as necessary to make it make sense with the Ruby bindings, and have rearranged or rewritten a few parts to make them (I hope) a bit clearer.

This tutorial doesn't cover everything; the emphasis is on teaching the programming philosophy of GUI programming, and Qt's features are introduced as needed. Some commonly used features are never used in this tutorial.

Chapter one starts with a minimal "Hello world" program and the following chapters introduce new concepts. By Chapter 14, the "Hello world" program from Chapter 1 will have turned into a 448-line game.

If you're completely new to Qt, you might want to read How to Learn Qt if you haven't already done so. Keep in mind that like most documents about Qt, it is very C++ oriented.

Table of Contents

  1. Hello World!
  2. Calling it Quits
  3. Family Values
  4. Let There Be Widgets
  5. Building Blocks
  6. Building Blocks Galore!
  7. One Thing Leads to Another
  8. Preparing for Battle
  9. With Cannon You Can
  10. Smooth as Silk
  11. Giving It a Shot
  12. Hanging in the Air the Way Bricks Don't
  13. Game Over
  14. Facing the Wall

This little game doesn't look much like a modern GUI application. It uses some GUI techniques, but after you've worked through it, I recommend checking out the Application example, which presents a small GUI application with menus, tool bars, a status bar, and so on. There are quite a few very educational Examples. They are all written in C++, but are easy enough to follow since the point of them is to demonstrate usage of the Qt library, not C++ features.

Creative Commons License
This work is licensed under a Creative Commons Attribution-Noncommercial 2.5 License.

Hello World!
Tutorial Series   Qt4 Ruby Tutorial
Previous   Ruby
What's Next   Tutorial 2 - Calling it Quits
Further Reading   n/a

Hello World!

Files:

Overview

This first program is a simple "Hello world" example. It contains only the bare minimum you need to get a Qt application up and running. The picture above is a screenshot of this program.

Here's the complete source code for the application:

require 'Qt4'

app = Qt::Application.new(ARGV)

hello = Qt::PushButton.new('Hello World!')
hello.resize(100, 30)
hello.show()

app.exec()

Intro

The top level in a QtRuby application usually only needs to perform some kind of initialization and then pass control to the Qt library, which then tells the program about the user's actions via events.

There has to be exactly one Qt::Application object in every GUI application that uses Qt. Qt::Application manages various application-wide resources, such as the default font and cursor.

Qt::PushButton is a GUI push button that the user can press and release. It manages its own look and feel, like every other Qt::Widget. A widget is a user interface object that can process user input and draw graphics. The programmer can change both the overall look and feel and many minor properties of it (such as color), as well as the widget's content. A Qt::PushButton can show either text or a Qt::Icon.

Line by Line Walkthrough

require 'Qt4'

This line loads the QtRuby extension.

app = Qt::Application.new(ARGV)

app is this program's Qt::Application instance. It is created here. We pass ARGV to the Qt::Application constructor so that it can process certain standard command-line arguments (such as -display under X11). All command-line arguments recognized by Qt are removed from ARGV.

Note: It is essential that the Qt::Application object be created before any window-system parts of Qt are used.

hello = Qt::PushButton.new('Hello World!')

Here, after the Qt::Application, comes the first window-system code: A push button is created.

The button is set up to display the text "Hello world!". Because we don't specify a parent window (as second argument to the Qt::PushButton constructor), the button will be a window of its own, with its own window frame and title bar.

hello.resize(100, 30)

The button is set up to be 100 pixels wide and 30 pixels high (excluding the window frame, which is provided by the windowing system). We could call Qt::Widget::move() to assign a specific screen position to the widget, but instead we let the windowing system choose a position.

hello.show()

A widget is never visible when you create it. You must call Qt::Widget::show() to make it visible.

app.exec()

This is where our program passes control to Qt. Qt::CoreApplication::exec() will return when the application exits. (Qt::CoreApplication is Qt::Application's base class. It implements Qt::Application's core, non-GUI functionality and can be used when developing non-GUI applications.)

In Qt::CoreApplication::exec(), Qt receives and processes user and system events and passes these on to the appropriate widgets.

You should now try to run this program.

Running the Application

When you run the application, you will see a small window filled with a single button, and on it you can read the famous words: "Hello world!"

Exercises

Try to resize the window. Click the button. If you're running X11, try running the program with the -geometry option (for example, -geometry 100x200+10+20).

Calling it Quits
Tutorial Series   Qt4 Ruby Tutorial
Previous   Tutorial 1 - Hello World!
What's Next   Tutorial 3 - Family Values
Further Reading   n/a

Calling it Quits

Files:

Overview

Having created a window in Chapter 1, we will now go on to make the application quit properly when the user tells it to.

We will also use a font that is more exciting than the default one.

require 'Qt4'

app = Qt::Application.new(ARGV)

quit = Qt::PushButton.new('Quit')
quit.resize(75, 30)
quit.setFont(Qt::Font.new('Times', 18, Qt::Font::Bold))

Qt::Object.connect(quit, SIGNAL('clicked()'), app, SLOT('quit()'))

quit.show()
app.exec()

Line by Line Walkthrough

quit = Qt::PushButton.new('Quit')

This time, the button says Quit and that's exactly what the program will do when the user clicks the button.

quit.resize(75, 30)

We've chosen another size for the button since the text is a bit shorter than "Hello world!". We could also have used Qt::FontMetrics to set right size, or let Qt::PushButton choose a reasonable default.

quit.setFont(Qt::Font.new('Times', 18, Qt::Font::Bold))

Here we choose a new font for the button, an 18-point bold font from the Times family. It is also possible to change the default font for the entire application, using Qt::Application::setFont().

Qt::Object.connect(quit, SIGNAL('clicked()'), app, SLOT('quit()'))

Qt::Object::connect() is perhaps the most central feature of Qt. Note that connect() in this context is a static function in Qt::Object. Do not confuse it with the connect() function in the Berkeley socket library.

This connect() call establishes a one-way connection between two Qt objects (objects that inherit Qt::Object, directly or indirectly). Every Qt object can have both signals (to send messages) and slots (to receive messages). All widgets are Qt objects, since they inherit Qt::Widget, which in turn inherits Qt::Object.

Here, the clicked() signal of quit is connected to the quit() slot of app, so that when the button is clicked, the application quits.

The Signals and Slots documentation describes this topic in detail.

Running the Application

When you run this program, you will see an even smaller window than in Chapter 1, filled with an even smaller button.

Exercises

Try to resize the window. Click the button to close the application.

Are there any other signals in Qt::PushButton you can connect to quit? [Hint: The Qt::PushButton inherits most of its functionality from Qt::AbstractButton.]

require 'Qt'

instead of

require 'Qt4'

Why is that? Has the ackage name been changed? --Danimo 12:41, 19 December 2006 (CET)


Looks like it's the same for me on Ubuntu Gusty. --anonymouse 5:37 PM, 18 December 2007 (EDT)

Warning
This section needs improvements: Please help us to

cleanup confusing sections and fix sections which contain a todo


Tip
Note: This page deals with content related to KDE 3. If you are developing for KDE 4, this information might not be valid anymore.


Introduction

To get us started doing something useful with Qt Designer, we are going to build a simple program that will show you the power of Qt Designer and KDevelop. I hope that this will help you to create your first "real" KDE application.

KDevelop will help you to build a complete KDE application. The KDE project uses the autoconf and automake tools for KDE 3.x, and KDevelop will provide you with all the necessary files (admin directory, Makefile.cvs, Makefile.am,...).

Requirements

How to Get Qt Designer

From your Distribution

Qt Designer is part of the qt-3.2.x package and above. If you have an older Qt on your system, you should get at least this version. At the time of writing, Qt latest version is 3.3.2.

Please remember to check if you have all the qt-related packages installed. You need the qt headers in order to compile this tutorial application. These headers usually come in the devel package. You also need to be sure you have designer. In some distributions, it comes in a separate package.

To check if you have everything, do a: locate qstring.h

If you get something like /usr/lib/qt3/include/qstring.h then you can set your QTDIR variable to /usr/lib/qt3/. In bash environment, this is done by typing:

export QTDIR= /usr/lib/qt3

Tarball or Anonymous Subversion

You can download the tarball from the Trolltech website, or get the qt-copy module from SVN. Please note that Qt for Linux is GPL.

For an explanation for how to use anonymous SVN, get the qt-copy and kde modules and compile them, please see a great documentation at Using Subversion with KDE.

You must then set the QTDIR environment variable. This should point to the directory into which you installed Qt. In bash, for example, you would type export QTDIR= /usr/local/qt provided that /usr/local/qt is the directory into which you installed Qt. Please read the INSTALL file for more details.

You then compile by issuing the following commands, here is the recommended compile line:

./configure -system-zlib -qt-gif -system-libpng -system-libjpeg \
-plugin-imgfmt-mng -thread -no-exceptions -debug -fast
make

The command make install is not needed.

Qt Designer is located in the bin directory of your Qt installation directory. You can run it by typing: /usr/local/qt/bin/designer in a console.

To compile Qt from source, please see Trolltech's Qt/X11 Open Source Edition page.

How to get KDevelop 3

From your Distribution

KDevelop 3 should be part of your distribution. Pre 3 versions of KDevelop were nicknamed Gideon, but they are obsolete now.

From Tarball

KDevelop can be downloaded from the KDevelop website, under the Quick download heading.

To compile KDevelop 3, you need qt-3.1.0 or higher and kdelibs-3.1.0 or higher. The environment variables QTDIR and KDEDIR should point to those directories.

Don't forget to set up the KDE and Qt paths. The most common errors while using KDevelop come from the environment variables not set up properly. Check in a console by issuing the command set to see all your environment variables. You should set your PATH variable as follow as well as your LD_LIBRARY_PATH:

export PATH=$QTDIR/bin:$KDEDIR/bin:$PATH
export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH

If you have any problem getting KDevelop running, please refer to the KDevelop Forum to find the answer to your problem.

If you never used KDevelop before, try to create a new project and to compile it to get used to the interface and the icons.

KDevelop 3.4

Please refer to Downloading KDevelop 3.4 and Compiling KDevelop 3.4.

Lexicon

  • Widget: a widget is an element of an graphical interface such as a container window, a button or a field for entering text.
  • Layout management: this term describes the way in which widgets are arranged in a window. In its simplest form, an element may be placed at a specific position and given a specific height and width. But when the user resizes the window, the widgets should stay in their position and change their size accordingly. Linux allows to do that by using layouts to place the widgets in.
  • Signal and Slots: Signals and slots are used for communication between objects. The signal/slot mechanism is a central feature of Qt. Signals are emitted by objects when they change their state in a way that may be interesting to the outside world. Slots can be used for receiving signals, but they are normal member functions. You can connect as many signals as you want to a single slot, and a signal can be connected to as many slots as you desire. Please see the TrollTech documentation on signals and slots for more details. In the excellent online documentation that comes with Qt, you'll find the signals and the public slots that go with each class. You can then implement your own slots.

Creating the Application

Starting the project

Creating the framework with KDevelop

The framework in which our program will sit in (i.e. the main window) can be done easily and quickly by using KDevelop. Start KDevelop and select New Project in the Project menu. The Application Wizard appears then. Choose a C++ -> KDE -> Simple KDE Application. Fill in the blank lines with the project name SigCreate, your name as author, and your email. Refer to the following screenshot as a reference:

Click on Next. Have a look to the CVS option and the header templates. Then click on Finish on the last screen. KDevelop creates all the files that you need to compile your project. You can use the file selector to view the code of the 3 files, which are main.cpp, sigcreate.cpp and sigcreate.h, as shown here:

.

Once the Application Wizard has created your application, compile it to ensure that everything is fine. To do that, select Build -> Run automake & friends then Build -> Run configure. The Messages output window should say

Good - your configure finished. Start make now
*
* *** Success ***

so you can run make with Build -> Build Project (or using the F8 shortcut). Then Build -> Install. Then Build -> Execute program (or F9). The result is shown here:

.

{{Note|1=If KDevelop does not recognize your QTDIR and KDEDIR variables, you can set them in Configure Optiona... -> Project -> Project Options..., as shown:

.

Using Qt Designer

Qt Designer is a tool for designing and implementing user interfaces. It helps you arranging your widgets on a form and adding a proper layout so your interface can be resized properly. I recommend that you read the Qt Designer manual to know everything about Qt Designer. Qt Designer includes a code editor but we'll use KDevelop to edit and modify all code.

We will now create the interface of our application using Qt Designer. A form from Qt Designer is saved with a .ui extension because it is then processed by the uic program to generate a .h and .cpp files. KDevelop takes care of that, the only thing we need to do is to create the form.

Note
Each time you add or remove a file (now we will add a .ui file) in your KDevelop project, the Makefile.am will be changed. KDevelop does that itself but you will need to Run automake & friends after such changes.


In KDevelop, click on File -> New and fill the dialog window that appears. First write the file name: sigcreatedlg and select what new file you want in the combobox: here we want a Widget (.ui). Please be sure that Add to project is checked, as this ensures that the Makefile.am is updated. Refer to this screen shot:

Click the OK button. The Automake manager dialog then pops up.

Click the OK button for this dialog as well.

If the new file sigcreatedlg.ui is not open in Qt Designer, open the Automake Manager, right-click on the file and select Open With -> Qt Designer. Qt Designer will open.

Tip
About the names: it is a good idea to finish a dialog name or a form name by dlg to ensure a nice visibility for people who want to have a look at the code. sigcreatedlg says that it is a dialog, i.e an interface class, only.


The Qt Designer interface]] is essentially split into three areas.

On the left is the toolbox, where you can select your widgets. On the right, several dialogs can be selected. I'll keep only the Property Editor dialog (I close the 2 others). Your widgets can be fine tuned to behave how you want them to. You can choose the size of the widget, its background color (palette), and so on. Between those 2 windows is the Form, your program window, within which you will design your user interface.

Note
After adding the sigcreatedlg.ui file, you will have to run Automake & friends and Run configure before building the program. This ensures that the updated Makefile.am is now read.


Designing the Program

Each time you want to use Qt Designer, you should have a precise visual idea of the design of your interface. You can see in the following picture what the program will be like.

It is a window with a number of different items (or widgets) on it, designed so that the user puts the right information in the right boxes. You should always design your program from the user's point of view, as it must be easy to use.

This application creates an email signature, which is then displayed on the screen. The user should enter her/his name, email address, and then select one of three comments. When you click the Create! button, the generated signature is shown in a MultiLineEdit. When you click Cancel, the program quits.

Note
Note that this project is meant as a tutorial, so this is somewhat far away from practical use.


Go back to the Qt Designer window with the new dialog open. You will see that the property editor has been filled with details about the form you have created. The first line in the Property Editor shows the name of the form which is Form1.

Click on the field with this name to change it and type SigCreateDlg. This will form the class name of the dialog so you should name it something useful.

To change properties, select the property you wish to change, then alter its setting on the right. Change the Caption property to "SigCreateDlg v.01". We will now begin to add widgets on our dialog.

Adding Widgets

To start, we will insert the text at the top of the program window, which can be seen here:

This text tells the user how to operate the program. This type of widget is called a Label and you can put one on your program like this:

  1. Select the dialog in ToolBox called Common Widgets -> TextLabel, or from the menubar Tools -> Display -> TextLabel
  2. The cursor will become a crosshair over the form. Draw a box for the label, just as you would in a paint program, and you will see that the label is created with some dummy text in it.
  3. To change this text, double click on the label and type in the text, instead of TextLabel1. The text you should type is
    This program will create an email signature for you. Just fill in the boxes and hit the Create! button.
    Select Align Center to have the text positioned nicely. Refer to this screenshot:
    .
  4. Finally, resize the widget using the handles so it is the correct size and at the top of the box. Try to center the label by moving it with the mouse. This is just a temporary measure. Later on we will look at a more elegant layout management technique. You may refer to this screenshot:

.

You follow pretty much the same procedure for embedding any type of widget that is supported by Qt Designer; select it, drag it, and finally, change its properties and size.

An interesting concept in Qt Designer is that widgets can act as containers for other widgets. This will be demonstrated in our next task, which is to create the input fields inside the frame. You can see that in Picture 8 we have a bunch of labels and text boxes inside a frame. This frame is called a Group Box and acts as a container for the labels and text boxes inside it. Let's first create the frame by selecting the GroupBox in the Toolbox dialog -> Containers or Tools -> Containers -> GroupBox from the menubar. You can drag the mouse to create the box just below the Label you created before. In the Property Editor you can change the title property to alter the text in the frame. Put Details in the title text field. You may notice a + symbol in this entry in the Property Editor. This indicates that the property has subproperties that can also be changed.

Once you have created the frame (i.e the GroupBox), create three more labels as before but when you draw them, draw them inside the GroupBox frame. You can then see in the Object Explorer box (Windows menu -> Views -> Object Explorer) to the right that the labels have become children of the GroupBox frame. See this image:

.

Change the text of labels by double-clicking on it.

Once you have done this you can then create the text boxes. They will allow the user to type in text like his(her) name and email address. We use the simplest type of text boxes: a widget called QLineEdit which allows the user to enter one line of text only. You have to create two QLineEdit widgets for the name and the email address. You choose the menu Tools -> Input -> LineEdit and you draw it beside the 'Your Name' Label. Do the same below for the address.

The witty comment will be selected by the user. We use a ComboBox which will present the user with three comments. Click on the ComboBox icon or select it via the Tools -> Input-> ComboBox menu. Draw it beside the Witty Comment label. Then double-click on it. You will be presented with a box into which you can add the contents of the combo box. Click on the New Item button and type in your comment in the text box at the right. Then click again on New Item for the second and third comments. Click on OK when you have finished.

Adjust the size of the different widgets so they are nicely placed.

Up to now, we have not named any of the widgets that are being placed in our program. It is useful to set an internal name for widgets so we can call them after in the program. Labels don't perform any action so they don't need to be named but other widgets do. It is the case now for our text boxes. We'll need to manipulate the data from the three input widgets (i.e. read the text) so we should give them a name. Names should be easily recognized later and they should make sense. The names are assigned via the name property on the top of the Property Editor. We name the top LineEdit nameBox and the second one mailBox. We name the ComboBox commBox. This will allow us to access the comments. So click on each LineEdit and then besides Name in the Property Editor write nameBox and mailBox. Then click on the ComboBox and name it commBox.

We finish the graphical design by adding a label with Generated Signature as text. Below it, we put a TextEdit (Tools -> Input -> TextEdit) where the generated signature will be displayed. We name it sigBox. And then we add two PushButtons at the bottom ('Create!' and 'Cancel'). They don't need names but you can give them some if you want.

Save your form. You can now have a quick preview by selecting the menu Preview -> Preview Form. This is the form before layout management.

Getting Spaced Out

This section describes the layout management. If you resize the preview window you will then notice that the widgets do not adjust appropriately. They are not resized. To improve things, we need to use a feature in Qt called spacers. Spacers are like virtual springs that push the widgets on each side apart. {{Note|1= Having a good layout is essential for your application, as when the strings are translated, they might be longer than the English ones and they need to fit on your widgets. The geometry of the widgets has to be nice if the user can resize your window application. Layouts are done by trial and error so use Preview -> Preview Form to see the result of your layout management and to achieve the best layout.

The use of spacers and layout management is a skill that is developed through trial and error. The main thing to remember when dealing with spacers is that you work horizontally first and then vertically.

We will first use spacers to center the text in the top box. Resize your label so that it is only the size of the text. Then we add two spacers, one at each side. Choose the spring icon or menu Layout -> Add Spacer. You adjust each of the spacers horizontally. Click the space to the left of the text and the blue spacer will appear . Repeat the same procedure for the right. Then add a spacer on the right of the "Generated Signature" label, and a last one on the left of the the "Create!" pushbutton. Please use this image as a reference.

Now that we have spacers to fill blank space, we need a proper layout management. This will allow the widgets to be nicely resized whenever the main window is resized. It is really compulsory to have good layout management. Again, try to resize several times to see if everything is in place. We can use Vertical or horizontal layout or grid management. The top row of widget is horizontal (spacer + label + spacer) so we need Horizontal management. We need to select the three widgets alltogether: click on the first spring, then click on the label while holding down Shift, then on the second spring while holding down Shift. Then click on the Horizontal Layout icon or menu Layout -> Lay Out Horizontally. You will then see a resizable red line around the three objects to indicate that their layout is being managed. Resize the red box if it needs it.

We can now repeat this procedure for the three labels inside the GroupBox, this time using vertical layout management. The same vertical management is used for the two LineEdit and the ComboBox. It is better to use vertical management to keep the objects aligned. If we use horizontal management for each label + text box then they will not stay aligned and equally sized. Horizontal management is needed for the label with the spacer and another one for the two pushbuttons and the spacer.

To finish the layout, we need to let the form look after the laid-out boxes. We put everything in a grid. This is done by right clicking the form and selecting Lay Out in a Grid from the menu. The final design with layout lines should resemble something similar to this image:

Signals and Slots

Signals and Slots are used for communication between Qt objects. The signal/slot mechanism is a central feature of Qt and probably the part that differs most from other toolkits which often use callbacks. In Qt, a signal is emitted by a widget when a particular event occurs, very often triggered by the user like for example pressing a button or writing something in a LineEdit. A slot is simply a function that is called in reponse to a particular signal.

Now the widgets are implemented and the layout is arranged the final thing we need to do in the design stage of the form is to create the signal/slot connections. To do this manually requires a connect() function but Qt Designer provides a simple yet effective solution. To create the signal/slot connections we need to use the connecting tool. To do this either select the icon (it looks like a red arrow going into a green square) or select Tools -> Connect Signals/Slots from the menu (or use the F3 shortcut key). To create a connection, click on the form on the widget that is going to be dealing with the slot, drag the line off the form and release the mouse button.

.

Let's deal first with the Create! button. Click first on the Connect Signal/Slot icon or select it from the Tools menu or use the F3 key. Then click on the Create! button with the crosshair and drag the line off the form completely. When you have released the mouse button you will see the connections tool shown in the image.

What we want to do is to create a slot that will create our signature when the user clicks on the Create! button. The signal will be clicked() (you may choose among five signals for a QPushButton) and we need to create the slot then make the connection.

To create the slot we need to click on the Edit Slots button. The slot creation box then appears. Now click on the New Function button and a slot will appear in the box. Instead of new_slot() rename it to slotCreateSig() and leave the access specifier as public. When you click on OK you will be returned to the connections box and you will see your new slot in the Slots section of the box.

To make a connection you simply select the appropriate signal (which is clicked() in our case) and then select the slot (which is our new slot slotCreateSig()). When you have selected both signal and slot you will see the connection made at the bottom of the screen. After you are finished click OK.

Repeat the procedure for the Cancel button by using the clicked() signal and the close() slot. You are now done with the signals and slots.

Warning
Don't forget to save your form!


Generating the Source

In this tutorial, we use KDevelop subclassing tool in Automake Manager. If you have KDevelop version which has not that capability, then please go to Chapter 7 where I explain this step without the subclass tool.

Here we start with the KDE simple project named SigCreate and the sigcreatedlg.ui that we have added in our project. In the Automake Manager, in the section sigcreate (Program in bin) you must have three files: sigcreatedlg.ui, sigcreate.cpp and main.cpp. The project must compile and give the main window as in picture 3 (creating.html).

As the sigcreate class is no use for us, we will remove it and use it for subclassing the sigcreatedlg.ui file. In the Automake Manager, right click on sigcreate.cpp and select Remove and a dialog pops up. Please check Also Remove it from disk. Then do the same with sigcreate.h. This is the way to remove obsolete files from your project and the Makefile.am will be updated. Remember to run Automake & friends and configure before compiling your project again. We will not do it right now because we will make other changes. We will now use the class name SigCreate for the subclass.

In the Automake Manager -> sigcreate (program in bin), right click on sigcreatedlg.ui and choose Subclass Widget... from the context menu that appears. Then fill in the subclass name which is SigCreate. Check the box: Reformat source and click on OK. Say No then about adding these files in cvs as we did not enable this in our project.

Note
You can see that the slot we created in designer is listed here and checked, the method will be implemented in the generated files. If you uncheck it, the code will not be generated in your class.


(The subclass dialog Image)

We have to suppress some lines in main.cpp as the KDE simple project template refers to a KMainWindow which is usually the base class used. But here, SigCreate is based on QWidget. You have to remove all the lines between KApplication app; and return app.exec(); except the ones I keep here:

SigCreate *mainWin = 0;

mainWin = new SigCreate();
app.setMainWidget( mainWin );
mainWin->show();

Implementing the Slot

Then open the sigcreate.cpp source file and then you implement the slot by adding the following lines in the parenthesis of:

void SigCreate::slotCreateSig()
{}

to implement the slot:

	sigBox->append("\n--");
 	sigBox->append(nameBox->text());
 	sigBox->append(mailBox->text());
 	sigBox->append(commBox->currentText());

</

Also, the corresponding headers of course:

 #include <qlineedit.h>
 #include <qcombobox.h>
 #include <qmultilineedit.h>

Run Build -> Run automake & friends, Build-> Run Configure, Build -> Build Project, Build -> Install (or Build->Install as root user), Build -> Execute Program. That's it! The program is working!

(Picture 20)

A few more words about signals and slots. The signals and slots mechanism is type safe: the signature of a signal must match the signature of the receiving slot (for example, you will connect valueChanged(int) with a slot having an int as argument). And another thing to keep in mind is that all classes that inherit from QObject or one of its subclasses (e.g. QWidget) can contain signals and slots.

All the strings used in KDE program must be wrapped in the i18n() function (klocale.h as header) because all KDE projects are translated. Please see the KDE Translation HowTo to learn more about i18n to make translations for an application.

In Short

This is a short resume on how to work with KDevelop and QtDesigner.

  • In the KDevelop menu File->New, select a Widget (.ui) file and give it a name (kprojectdlg for that example), check add to Project. Click OK.
  • Qt Designer starts. Work on your form in Qt Designer then save your file and close designer. The designer file appears then in KDevelop under User Interface (kprojectdlg.ui).
  • Create a new class (KProject as name for example) (Project menu then New class...) that inherits from your dialog file (kprojectdlg) and is a QWidget-childclass.
  • Add your slots and others signals or member functions in the inherited class KProject.

Make the Translations for a Simple KDE Project

When your own project is finished, you may like to have one or several translations for the GUI. Here is how you can do that.

Install gettext Patched for KDE

Install a patched gettext that you can find on developer.kde.org and install it in your home directory. The patched gettext can be found there : http://public.kde.planetmirror.com/pub/kde/devel/gettext-kde/

   $ tar xvzf gettext-0.10.35-kde.tar.gz
 $ cd gettext-0.10.35-kde
 $ ./configure
 $ make
 $ mkdir -p ~/bin
 $ cp src/gettext src/xgettext ~/bin # copy gettext and xgettext into your HOME/bin directory
 $ export PATH=~/bin:$PATH

Prepare the Translations

Then, go into your project directory :

$ cd /path/to/myproject

Set KDEDIR to match your kde installation - on my Mandrake it is /usr This path can also be found by doing kde-config --prefix

$ export KDEDIR=`kde-config --prefix` # or export KDEDIR=/usr

Then create the translations files :

$ make -f admin/Makefile.common package-messages

Make the Translations

Translate the .po files using kbabel These files are in the po directory of your project.

Warning
Do not touch the .pot file!


Compile and Install the Translations Files

 $ make package-messages
 $ sudo make install

General Tips

General Hints

Your Application Name

KDE application names generally start with the letter K followed by a name suggesting what the program does. For example, KMail is very simple and tells the user that this is indeed a KDE application and about email. A good practice is to choose an english name for the name that follows the K. Of course, this is just an indication and you are free to do what you want. But a good name can help to get your program known quicker.

Note
Run a search in Google (in Konqueror, write gg:your_app_name) to see if the name you want to use is not the name of a copyrighted program. If this is the case or if in doubt, change it.


Coding Practice

Comments should be in English as it is really easier if someone else has a look at your code.

Class names usually are also in English and the names must indicate what the class does. Good examples: TopLevel, CursorInterface, TaskManager. Note the upper case letters and remember that C++ is case-sensitive.

Function names usually begin with a lower case letter and here are examples of good names:

void activateRaiseOrIconify();
void toDesktop(int);
void windowAdded(WId);

Code indentation can be whatever you like as long as the code is visible for other developers. Always keep in mind that other people will have a look in your code and try to make it easy to read.

Importing your project in KDE CVS

Your program interests people, you feel you have time to really work on it, you need more feedback and help for improving it. You also agree to release it under the GPL license or equivalent. You can ask for a cvs account to import it in kdenonbeta. The kdenonbeta module is quite big and is not distributed with the official KDE. It is not packaged nor translated and feature freeze does not apply to kdenonbeta. Its purpose is to allow other developers to work on your application and to test it. Of course, you will need qt-copy, arts and kdelibs from cvs HEAD at least. Please see a tutorial here on how to get started for compiling KDE from cvs HEAD.

Note
When your application has the most important features, when it's totally KDE compatible (i18n, xml GUI, ect.), you will be able to ask for moving it in a KDE official package.


In order to get a cvs account, please follow theses instructions. Send a mail to sysadmin (at) office (dot) kde (dot) org to justify why you need cvs access. Tell that you want to import your application (app_name) in the kdenonbeta module. Make sure to specify your full name and e-mail address, if the From field in your mails doesn't specify them. You can also choose a nickname for your user login. You can currently choose between the standard non-encrypted CVS protocol (pserver) and the encrypted CVS-over-ssh. If you choose pserver, send also an encrypted password (for instance using useradd dummy ; passwd dummy ; grep dummy /etc/passwd /etc/shadow). If you choose CVS-over-ssh, send a public ssh key (e.g. ~/.ssh/id_dsa.pub).

Wait for the answer from a KDE sysadmin.

Once you have compiled at least qt-copy, arts and kdelibs, you need to check out kdenonbeta files. Log in the cvs server with your login user and password.

    $ cvs co -l kdenonbeta
    $ cd kdenonbeta
    $ cvs co admin  (or ln -s ../kde-common/admin .admin)

You copy your project main dir with everything in kdenonbeta and then, in your project main dir, you issue $ make disclean

All the .o files must be gone. You can also remove by hand all Makefile, Makefile.in (not Makefile.am) and all kdevelop related files. Remove the admin, autom4te.cache, debug, doc, po and templates folders. You must just keep some files and the src subdir. Then, you cd .. to go back in kdenonbeta and you type:

    $ make -f Makefile.cvs
    $ ./configure --prefix=$KDEDIR
    $ cd your_project_name
    $ make
    $ su -c 'make install'

All these steps must go well. If there are errors, you should be able to correct them by carefully reading the error message. If you are really stuck, please go to IRC and ask on #kde or #kde-devel, someone will help you.

then, in kdenonbeta dir:

    $ cvs add your_project_name
    $ cvs add your_project_name/*
    $ cvs add your_project_name/src
    $ cvs add your_project_name/src/*
    $ cvs commit

You get the window (vi editor as default) where you can log your message. It's a good practice to note what your commit is about. In your case, you will say (type i first if you are in vi to get in edit mode):

First import of your_app_name which does this and that.

Check if all the files are added correctly. If not, cvs add filename and cvs commit.

Each time you want to work on your project, don't forget to log in the kde server with your user login and password and, to be sure you have the latest version, do a:

    $ cvs up

Finished!

Development

Warning
This section needs improvements: Please help us to

cleanup confusing sections and fix sections which contain a todo


Development Framework

  1. Library Structure
  2. Accessing System Resources
    1. Standard Resources
    2. Icon Loading
    3. System Configuration Cache (KSycoca)
  3. Graphics
    1. Low-level graphics with QPainter
    2. Structured graphics with QCanvas
    3. 3D graphics with OpenGL
  4. User Interface
    1. Action Pattern
    2. Defining menus and toolbars in XML
    3. Providing online help
  5. Complex Widgets
    1. HTML renderer with JavaScript
    2. File dialog
    3. Displaying large amounts of data - Using QListView, QListBox and QIconView
  6. Components and Services
    1. KDE services
    2. MIME types
    3. Network transparency
  7. Inter Client Communication
    1. Desktop Communication Protocol (DCOP)
  8. Starting Other Programs
  9. il8n and l10n

Desktop Framework

  1. Panel Applets
  2. Control Center Modules

Multimedia Framework

  1. aRts - the current state
  2. Imaging and Animation

Component Architecture

  1. KParts
  2. Docking Into the Panel's System Tray
  3. Java Integration

KOffice Architecture

  1. Document and View Introduction
  2. File Format Filters

Protocols

  1. Window Management
  2. Session Management
  3. System Tray Docking
  4. Drag-And-Drop
  5. Printing

Development Tools

  1. Interface Documentation Tool (Doxygen)
  2. Integrated Development Environment (KDevelop)
  3. Graphical Debugger (kdbg)
  4. VCS Frontend (Subversion)
  5. Advanced Developer Text Editor (Kate)
  6. Icon Editor (KIconEdit)
  7. Hex Editor

Development HOWTOs

  1. Binary Compatibility Issues With C++
  • Development/ArchitectureWho gave the SIMPLINUX presentation? "I" on a wiki doesn't work well, being collaborative and all.... so I edited what was copied from developer.kde.org - CuCullin 22:27, 21 December 2006 (CET)
I believe it was Richard Moore. Imo we should avoid using "I", even the term "Author" on the top of some articles is irritating, as it to some degree implies "This is my article, don't touch it". How do others feel about this? Maybe a simple "Maintainer" or "Initial Author" would be better? Dhaumann 14:32, 22 December 2006 (CET)

Konstruct is a build system which helps you to install KDE releases and applications on your system. It downloads defined source tarballs, checks their integrity, decompresses, patches, configures, builds and installs them. A complete KDE installation should be as easy as "cd meta/kde;make install".

By default Konstruct installs to your home directory which means you don't have to possess root privileges or risk to damage your system or affect another KDE.

Getting Konstruct

You must have the Subversion client installed, then run in a shell:

 svn co svn://anonsvn.kde.org/home/kde/trunk/konstruct/

If you have no own old gar.conf.mk, copy gar.conf.mk.in over to gar.conf.mk.

To update your Konstruct checkout or the released Konstruct tarballs, change to the konstruct directory and run:

 svn up

There will be an official snapshot of the 3.5.8 release of Konstruct soon. The latest version in subversion will build 3.5.8 now, so give it a try and report all bugs you find in KDE's bugzilla under the Konstruct product.

Konstruct seems far away from beeing continued! This is miserable!

Preconditions

A working GNU tool chain (gcc, GNU make, flex, BSD yacc, gettext etc.) and additional GNU tools like tar, gzip, bzip2, md5sum, patch and wget.

Some basic libraries and some other libraries enabling additional functionality are not included in "Konstruct", http://www.kde.org/info/requirements/3.5.php lists them. Note that you may have to install the header files within separate "-dev" or "-devel" packages too.

  • NOTE: If you use a recent SUSE or Mandrake 9.2 distribution you might be interested in "Detektive", a simple script which checks and tells which required rpm packages of your distribution you have not installed: Just run "cd misc/detektive;make".

Configuration

Copy gar.conf.mk.in to gar.conf.mk and change it to your liking. Common options:

  • GARCHIVEDIR - If you have already downloaded source tarballs, set the path here.
  • prefix - Where to install your KDE desktop. Default is ~/kde3.5.7/ . Moving KDE installation elsewhere afterwards calls for troubles!
  • HAVE_64BIT_TARGET - Set this if you want to compile KDE for a 64bit target (x86_64)
  • OWN_CFLAGS - Allows you to specify compiler flags specific to your CPU.
  • HAVE_QT_3_3_INSTALLED - Set this if you have at least Qt 3.3 (including moc, uic and headers) installed and want to skip Qt installation.
  • BUILD_CLEAN - Set this if you're low on available file system space.

If the download fails because of a proxy, then please consult the wget man page for necessary options in your ~/.wgetrc. If download.kde.org redirects you to a broken or incomplete mirror, you may fix your problem by changing kde.conf.mk.

Targets

Konstruct installs the current stable development releases of KDE and applications. Currently it gives a complete KDE 3.5.7 installation. Optionally you can install additional applications like KOffice 1.6.3 or KDevelop 3.4.1.

The following table shows how many MBytes source tarballs will be downloaded:

MBytes of Source Tarballs
Directory/Target Size Description
kde/kdebase 56MB Desktop with browser, editor and terminal
meta/kdepim-crypto 68MB Above plus kdepim and crypto libraries
meta/kde 172MB All "KDE 3.5.7" packages & dependencies
meta/everything 248MB Most stable known targets, see next table


The following (unstable) targets are not included in the meta/everything target:

Unstable Targets Not Included
Directory/Target Reason
apps-unstable/ Unstable development versions and/or undelivered dependencies, maybe conflict with apps/ entries
i18n/ Nobody needs everything, just pick your language
kde/kdebindings Only needed for developing with non-C++ language


If you have at least Qt 3.3 installed, define variable HAVE_QT_3_3_INSTALLED (see Configuration) and subtract 14 MB from the numbers in every column.

If you want to have KDE localized into your native language, look into the i18n/ directory, change to your language directory and start make install. To localize KOffice, install an i18n/koffice-l10n-<language-code> package.

Usage

Be sure that you have a live internet connection. Choose a target, and change to the directory which holds its definition, e.g. cd kde/kdebase. Now run make with one of the following targets, usually you only need make install.

The GAR system provides seven basic targets for each package:

  • fetch - This target downloads all files and patches needed to compile the package. Typically this is a single tarball, accompanied by occasional patch files.
  • checksum - Uses md5sum to ensure that the downloaded files match those with which the package maintainer worked.
  • extract - Makes sure that all of the necessary source files are available in a working directory. In some cases (such as when downloading a single C++ source file) this will simply copy files over.
  • patch - If the package has to be patched (either via third-party patches or package maintainer patches), this target will perform that step.
  • configure - Configures the package as specified in the Makefile. It will typically run the package's underlying configuration system (such as autoconf or Imake).
  • build - Performs the actual step of compilation after installing the dependencies.
  • install - Puts files in the proper locations and performs any necessary mop-up work.

These targets are named after their counterparts in the BSD Ports system, and behave in the same manner. If you want to install a package, you have to enter the package's or target's directory and run make install or make patch (just two examples). A later target includes all the previously listed ones.

Some additional useful targets which you usually don't require are:

  • buildclean - Clean up the working directory but don't delete downloaded packages. Run this if you installed missing dependencies and want to re-configure the package.
  • clean - Clean up the working directory. This also deletes downloaded packages! Either use buildclean instead or call garchive before to prevent new downloads.
  • garchive - Call checksum target and save downloaded files to GARCHIVEDIR directory.
  • showdeps - Print a tree with the recursive dependencies of current package.

For every target exists a deep-foo variant, which will also call it recursively for all its dependencies. E.g. with make deep-checksum you can download all required source tarballs and build it later (when you have no net connection).

After installation

After installation you have to set some variables allowing your system to find KDE binaries and libraries and KDE to allow to find its own files, for Bash:

export QTDIR=~/kde3.5.9
export KDEDIR=~/kde3.5.9
export KDEDIRS=~/kde3.5.9

export LD_LIBRARY_PATH=~/kde3.5.9/lib
export PATH=~/kde3.5.9/bin:$PATH

Setting KDEHOME too, e.g. "export KDEHOME=~/.kdetest", will tell KDE to save your settings to this directory and leave default ~/.kde directory unaffected.

On shadow password systems you have to set $(prefix)/bin/kcheckpass SUID root or SGID shadow - otherwise you will not be able to unlock a locked desktop.

The complete KDE desktop is started with "startkde", most distributions start it if you set it to the WINDOWMANAGER variable in your shell initializations.

About Konstruct

Konstruct was originally maintained by Stephan Binner (binner at kde dot org) and based on GAR ports system by Nick Moffitt from the now defunct LnxBBC project and is inspired by the GARNOME distribution of the GNOME desktop started by Jeff Waugh (http://cipherfunk.org/garnome/). Recently, the maintenance of Konstruct has been taken on by Gary Greene (greeneg at tolharadys dot net).

License

Redistribution and/or use, with or without modification, is permitted. This software is without warranty of any kind. The author(s) shall not be liable in the event that use of the software causes damage.

  • CuCullinI'm Joseph Gaffney from New Jersey. You can call me CuCullin, a misspelling of an ancient Irish hero named Cúchullain. Done purposefully when IRC limited me to 8 characters :)

I'm an Audiovisual and Telecommunications Consultant for Shen, Milsom, & Wilke, Inc., and you can reach me via email at cucullin AT wtfisthat DOT net.

Warning
This section needs improvements: Please help us to

cleanup confusing sections and fix sections which contain a todo


What is Solid

Solid is the new hardware device framework for KDE 4 that features, among other things, a hardware discovery layer which allows you to detect and use devices regardless of operating system or architecture. You can learn more about the Solid project at solid.kde.org.

For a more detailed (still not complete!) description, read here.

The API documentation can be found at api.kde.org

Who are those tutorials for?

This tutorial is written for developers looking to use the Solid hardware discovery layer within their applications. It can also serve as a good starting point for developers looking to start working on the Solid framework.

Solid core library tutorials

Listing Devices
How to use the Solid core library to discover the hardware and interact with the system.
Accessing Network Information
How to use the Solid system to get information about the network
Creating a Device Action
When your application is interested in registering actions with the system for removable hardware

File analyzers extract data from files to display in the file dialogs and file managers. The data gathered this way is also used to search for files. KDE4 allows the use of multiple analyzers per file type. Analyzers can extract text which is used for indexing, but they can also retrieve other data such as song title, album title, recipient, md5 sum, the mimetype of a file, and much more.

This tutorial describes how you can write new analyzers.

Primer

What are file analyzers?

A file analyzer is a class that extracts metadata from a file or data stream. You can have file analyzers that are specific for certain file types such as an analyzer that extracts the information from an ogg vorbis file. There are also more general file analyzers that calculate for example the md5 or sha1 of a file.

File analyzers in KDE4

KDE4 uses stream based file analyzers for retrieving text and metadata from files. This has a number of advantages over file based methods. Stream based access

  • is faster for 90% of the file types,
  • allows easy analysis of embedded files such as email attachments or entries from zip files, rpms and many other container file formats.

Writing stream-based analyzers requires a different approach than the usual file-based methods and in the tutorial we will explain how to go about it.

The current state of porting the KDE3 kfile plugins to KDE4 stream analyzers can be seen at http://wiki.kde.org/tiki-index.php?page=Porting+KFilePlugin+Progress.

Look for existing code

If you want to see some code examples, take a look at the already implemented file analyzers at /kdesupport/strigi/src/streamanalyzer/.

Some examples of meta-data extraction from files can also be found in the Hachoir project in the online parser sourcecode.

Choosing the type of analyzer

There are two main types of analyzers: StreamThroughAnalyzer and StreamEndAnalyzer. The latter is more powerful and a bit easier to program, but has a limitation: only one StreamEndAnalyzer can analyze a particular resource, while you can use as many StreamThroughAnalyzers as you like. Most analyzers can be written as StreamThroughAnalyzers. The most important exception is for analyzers that extract embedded resources from a stream. Examples of this are the ZipEndAnalyzer, the MailEndAnalyzer and the RpmEndAnalyzer.

In this tutorial we focus on a simple example file type: BMP images. The information we will get from this file is located at the start of the file. It turns out that in this case, it is just as easy to implement the analyzer as a StreamEndAnalyzer as a StreamThroughAnalyzer. We will implement it as a StreamEndAnalyzer and point out how to do the same as a StreamThroughAnalyzer.

Two other types of stream analyzers have been added to Strigi. StreamLineAnalyzer, for file format based on lines of plan text, StreamSaxAnalyzer, for XML based file such as SVG.

StreamEndAnalyzer

Three functions need to be implemented in a StreamEndAnalyzer:

  • name()
  • checkHeader()
  • analyze()

Here is what a class used to process BMP images might look like:

#include <strigi/streamendanalyzer.h>

class BmpEndAnalyzerFactory;

class BmpEndAnalyzer : public Strigi::StreamEndAnalyzer 
{
public:
    BmpEndAnalyzer(const BmpEndAnalyzerFactory* f) :factory(f) {}
    const char* name() const { return "BmpEndAnalyzer"; }
    bool checkHeader(const char* header, int32_t headersize) const;
    char analyze(Strigi::AnalysisResult& idx,
                 Strigi::InputStream* in);
private:
    const BmpEndAnalyzerFactory* factory;
};

The factory object is used to load the analyzer at runtime and will be covered in detail later in this tutorial.

name() returns a unique name used to internally identify the indexer. As such the name does not need to be translated or suitable for display in a user interface.

Since only one StreamEndAnalyzer can be used per resource, it is important to quickly select the right one. For this, we do not rely on the mimetype, but on the actual contents of the resource. As a first sifting, the initial bytes of a file are checked. This is usually just as fast as comparing a mimetype identifier, but has the advantage of being more direct and thus often more accurate.

It is by no means necessary for checkHeader to be 100% correct. The most important thing is that it should allow one to quickly determine if an analyzer can not handle a resource. Should it by accident return true and thus indicate that a resource can be handled, then it can always handle this in the analyze() method.

bool BmpEndAnalyzer::checkHeader( const char* header,
                                  int32_t headersize) const
{
    bool ok = false;
    if (headersize > 2) {
        ok = ok || (strncmp(header, "BM", 2) == 0);
        ok = ok || (strncmp(header, "BA", 2) == 0);
        ok = ok || (strncmp(header, "CI", 2) == 0);
        ok = ok || (strncmp(header, "CP", 2) == 0);
        ok = ok || (strncmp(header, "IC", 2) == 0);
        ok = ok || (strncmp(header, "PT", 2) == 0);
    }
    return ok;
}

A BMP file can start with six different initial bytes. If the header matches any of them, we return true.

If a resource passes this test, the analyze() function will be called. The real work occurs in this function. In this tutorial, we will not do a complete analysis, but we only look at the way the pixels are stored in the BMP file. This information is stored in the bytes 30-33 that encode a number.

using namespace Strigi;
char BmpEndAnalyzer::analyze(AnalysisResult& idx, InputStream* in)
{
    // read compression type (bytes #30-33)
    const char* h;
    int32_t n = in->read(h, 34, 34); // read exactly 34 bytes
    in->reset(0);   // rewind to the start of the stream
    if (n < 34) {
        return Error;
    }

    uint32_t bmpi_compression = (unsigned char)h[33] +
                                ((unsigned char)h[32]<<8) +
                                ((unsigned char)h[31]<<16) +
                                ((unsigned char)h[30]<<24);

    switch (bmpi_compression) {
    case 0 :
        idx.addValue(factory->compressionField, "None");
        break;
    case 1 :
        idx.addValue(factory->compressionField, "RLE 8bit/pixel");
        break;
    case 2 :
        idx.addValue(factory->compressionField, "RLE 4bit/pixel");
        break;
    case 3 :
        idx.addValue(factory->compressionField, "Bitfields");
        break;
    default :
        idx.addValue(factory->compressionField, "Unknown");
    }
    return Ok;
}

First we read exactly 34 bytes from the stream. We do not need to allocate a buffer; this is handled by the stream. The stream returns a pointer to its internal buffer, which avoids data copying and buffer allocation. If the resource has less than 34 bytes or if an error occurred during reading, we return with an error code.

The bytes 30-33 contain the information we need and we write this into the AnalysisResult object. This object collects all metadata and passes it to the code that initiated the analysis. The data may get written into an index or get passed to for example a file dialog. To indicate the type of metadata, we pass a pointer to a registered field.

StreamThroughAnalyzer

We will now look at how to implement a StreamThroughAnalyzer. For this, we need to implement three functions.

class BmpThroughAnalyzer : public Strigi::StreamThroughAnalyzer {
private:
    Strigi::AnalysisResult* analysisResult;
    const BmpThroughAnalyzerFactory* factory;
public:
    BmpThroughAnalyzer(const BmpThroughAnalyzerFactory* f) :factory(f) {}
    ~BmpThroughAnalyzer() {}
    void setIndexable(Strigi::AnalysisResult* i) { analysisResult = i; }
    Strigi::InputStream *connectInputStream(Strigi::InputStream *in);
    bool isReadyWithStream() { return true; }
};

For simple file formats where all information is in the initial part of the file, all of the work gets done in connectInputStream(). For more complicated cases look at other examples, such as DigestThroughAnalyzer. In connectInputStream(), we perform the same analysis as we did in the StreamEndAnalyzer:

Strigi::InputStream
BmpThroughAnalyzer::connectInputStream(Strigi::InputStream* in) {    // read compression type (bytes #30-33)
    const char* h;
    int32_t n = in->read(h, 34, 34); // read exactly 34 bytes
    in->reset(0);   // rewind to the start of the stream
    if (n < 34) return in;
 
    uint32_t bmpi_compression = (unsigned char)h[33] + ((unsigned char)h[32]<<8)
         + ((unsigned char)h[31]<<16) + ((unsigned char)h[30]<<24);
 
    switch (bmpi_compression) {
    case 0 :
        analysisResult->addValue(factory->compressionField, "None");
        break;
    case 1 :
        analysisResult->addValue(factory->compressionField, "RLE 8bit/pixel");
        break;
    case 2 :
        analysisResult->addValue(factory->compressionField, "RLE 4bit/pixel");
        break;
    case 3 :
        analysisResult->addValue(factory->compressionField, "Bitfields");
        break;
    default :
        analysisResult->addValue(factory->compressionField, "Unknown");
    }
    return in;
}

The difference with StreamEndAnalyzer is that we must make sure we only return a stream that has the current position at the start of the stream. We can ensure this by calling reset(0) after each call to read(). This will not affect the pointer to the character data that was set in the call to read().

In addition, we do not return any status message, but an InputStream. In this case this is the same stream. For more complicated cases, we can subclass the InputStream and analyze the data that passes through it. This is where the StreamThroughAnalyzer gets its name.

Since we have finished with the stream after the call to connectInputStream, we implement isReadyWithStream() to return true. This function is used by StreamIndexer to stop reading as soon as possible to speed up the analysis.

Registering the analyzer

KDE4 keeps a register of the capabilities of each analyzer. This allows it to speed up determining which analyzers to use. In addition, when it knows what data type an analyzer provides under what name, it can use this information to optimize the storage of the data or search queries. For this, each loadable analyzer must define two factories. An AnalyzerFactoryFactory and either a StreamThroughAnalyzerFactory or a StreamEndAnalyzerFactory.

AnalyzerFactoryFactory

The AnalyzerFactoryFactory is used only in the loadable plugins. It is not needed for analyzers that are part of the Strigi core. To initialize the StreamThroughAnalyzerFactories and StreamEndAnalyzerFactories in plugins, we need to implement an AnalyzerFactoryFactory. We do so by implementing one or two functions: streamThroughAnalyzerFactories() and streamEndAnalyzerFactories(). This function returns instances of all the factories available in a plugin. Here is for example the AnalyzerFactoryFactory for the KDE trash file analyzer (we cannot use the BMP analyzer here, because it is in Strigi core):

class Factory : public AnalyzerFactoryFactory {
public:
    list<StreamAnalyzerFactory*>
    streamThroughAnalyzerFactories() const {
        list<StreamThroughAnalyzerFactory*> af;
        af.push_back(new TrashThroughAnalyzerFactory());
        return af;
    }
};

// macro that initializes the Factory when the plugin is loaded
STRIGI_ANALYZER_FACTORY(Factory)

StreamEndAnalyzerFactory

StreamEndAnalyzerFactories and StreamThroughAnalyzerFactories are very similar. They provide information about analyzers and the create instances of the analyzers. Each analyzer must have a factory. StreamThroughAnalyzers have StreamThroughAnalyzerFactories and StreamEndAnalyzers have StreamEndAnalyzerFactories. Here, we look at the factory for the BmpEndAnalyzer.

The class BmpEndAnalyzerFactory looks like this:

class BmpEndAnalyzerFactory : public Strigi::StreamEndAnalyzerFactory {
friend class BmpEndAnalyzer;
private:
    static const cnstr typeFieldName;
    static const cnstr compressionFieldName;
    const Strigi::RegisteredField* typeField;
    const Strigi::RegisteredField* compressionField;
    const char* name() const {
        return "BmpEndAnalyzer";
    }
    Strigi::StreamEndAnalyzer* newInstance() const {
        return new BmpEndAnalyzer(this);
    }
    void registerFields(Strigi::FieldRegister&);
};

All members are private, which is ok, because the important functions are virtual and thus accessible anyway. The functions name() and newInstance() are selfexplanatory. The other important function is registerFields(Strigi::FieldRegister&). To speed up the extraction of fields, we dont use strings to identify fields, but we use pointers to registered fields. These RegisteredField instances are stored in a global register. When you extract a piece of metadata, you pass the pointer to the registered field to identify the metadata.

But first we need to register the fields:

#include <strigi/fieldtypes.h>
#include <strigi/analysisresult.h>

void BmpEndAnalyzerFactory::registerFields(Strigi::FieldRegister& reg) {
    typeField = reg.registerField(typeFieldName,
                                  Strigi::FieldRegister::stringType,
                                  1, 0);
    compressionField = reg.registerField(compressionFieldName,
                                         Strigi::FieldRegister::stringType,
                                         1, 0);
}

We pass the key of the field to the register, along with it's type, the maximum number of times the field occurs per resource and the parent of the field. The parent of a song tile, for example, could be a more general title field. The datatype of this field should be the same or a subset of the fieldtype of the parent.

The pointers to the registered fields are used during the analysis to identify the type of data we have analyzed:

   idx.addValue(factory->typeField, "OS/2 Color Icon");

Building the analyzer

Building your analyzer is easy. There are three things you must take into account:

  • Link the analyzer as a module,
  • Let the name of the analyzer start with 'strigita_' for a StreamThroughAnalyzer and 'strigiea_' for a StreamEndAnalyzer,
  • Install the plugin in the lib/strigi directory.

Here is the CMakeLists.txt code to do this:

add_library(trash MODULE trashthroughanalyzer.cpp trashimpl.cpp)
target_link_libraries(trash ${STRIGI_STREAMANALYZER_LIBRARY})
set_target_properties(trash PROPERTIES
    PREFIX strigita_)
install(TARGETS trash LIBRARY DESTINATION ${LIB_INSTALL_DIR}/strigi)

Testing your code

Strigi comes with a simple command line tool to check if your plugins work. This tool is called xmlindexer. It extracts data from files and outputs it as simple xml. To use it call it like this:

xmlindexer [FILE]

or

xmlindexer [DIR]

This is very fast and I recommend using it with valgrind. This hardly slows down your workflow but helps to keep memory management in good shape:

valgrind xmlindexer [DIR]

ta['n-portal'] = new Array('z','About the project, what you can do, where to find things');

ta['n-portal'] = new Array('z','About the project, what you can do, where to find things');

 
Proposed for Deletion
This page has been proposed for deletion for the following reason:

Empty page.

 
Proposed for Deletion
This page has been proposed for deletion for the following reason:

Content is now at https://community.kde.org/KDE/FAQs/General_FAQ and this page may no longer be up-to-date. Translations are still available for this page, however.


I want to start this new application. What do you advise?

We all agree that there are plenty of KDE applications that need to be written. But there are also a lot of existing kde applications that need your help.

To see the areas where help is needed, check this page.

Before starting a new application, it's always a good idea to check KDE-Apps.org and other open source software hosting services like GitHub, Google Code, and SourceForge for existing applications and to ask on the kde-devel mailing-list whether someone is already working on a similar project.

I am a developer, how can I contribute to KDE software?

Calligra and KDevelop, despite being very praised, have very few developers, so you might check there. There is no need to be a developer of the KDE workspaces or KDE platform libraries to help. The whole range of KDE software is very modular so you can perfectly improve one area without knowing how others work.

You can also ask on kde-devel if someone needs help on an application. Use the latest version of your favourite KDE software and spot things that are needed. A theme generator? A konsole schema editor? Improve a game? There is always a small feature missing. Go and implement it!

Are you familiar or attracted with a specific field? See if there is a related application that could use your help. Or write one. KDE especially welcomes more non-geek oriented applications.

I am not a developer, how can I help?

There are plenty of tasks that don't require development skills. Write reviews of applications for the promoting of KDE (see the kde-promo mailing-list), help the documentation team (see i18n.kde.org/doc), help the translations (see i18n.kde.org), help to filter the incoming bugs (see bugs.kde.org).

Where can I find images of Konqi the dragon?

The Konqi for some people SDK is at ftp.kde.org/pub/kde/devel/konqi_sdk.tar.bz2
It was posted to artist.kde.org before that site ceased to be updated.

Further images are on KDE merchandise. Also you can find some unofficial Konqi images and models from Create Konqi with Krita Contest and SuperTuxKart game.

What is the level required to contribute to KDE? What should I learn? What should I read?

You need to know C++. Read the Qt tutorials and browse the Qt docs to get familiar with what's available with Qt. Then read the KDE tutorials and browse architecture and documentation. You can also read the KDE Book, it can not harm. But you don't have to be familiar with the whole KDE architecture to become a KDE developer. Using KDE's technologies is quite easy, so concentrate on what you really need, you can learn the other bits later on. KDE TechBase and doc.qt.digia.com (also in your $QTDIR/doc/html) are invaluable resources, take advantage of them. Then, browse the source, look for the examples directories, see how the other did code their applications. Reading and writing code is the best way to learn.

How do I get KDE software from the KDE git or SVN repositories?

See the Building and Running KDE Software From Source section on the Getting Started page.

Can I access KDE source code online?

Yes. There are many ways to do this:

What should I put in my .subversion/config?

You need to add the ignore list to the [miscellany] group in your ~/.subversion/config:

[miscellany]
global-ignores = *.moc *.moc.cc *.moc.cpp config.log config.status \
config.cache *.gmo .deps .libs SunWS_cache *.lo *.la *.rpo *.la.closure \
*_la_closure.cpp *_la_closure.cc *_la_closure.cxx *.all_cc.cc *.all_cpp.cpp \
*.all_C.C *.all_cxx.cxx *_meta_unload.cc *_meta_unload.h *_meta_unload.cpp \
*_meta_unload.C *_meta_unload.cxx index.cache.bz2 .memdump Makefile.rules.in \
Makefile.calls.in Makefile.rules Makefile.calls autom4te.cache *.kidl \
*.o *.lo *.la #*# .*.rej *.rej *.pyc

And to make svn diff ignore whitespace, and print function names:

[helpers]
diff-cmd = /usr/local/bin/_svndiff

with the following in /usr/local/bin/_svndiff:

#!/bin/sh
exec /usr/bin/diff -b -u -p "$@"

Don't forget to make /usr/local/bin/_svndiff executable.

I want to put my app in KDE

There are three requirements:

  • Your app must compile with the latest version of KDE (git master or SVN trunk).
  • Your app must be stable.
  • Your app must be maintained. You will probably get a good deal of bug reports and wishes. People expect you to fix the bugs and implement the wishes that make sense.

See also the next question.

Is it better to develop inside or outside KDE?

As core developer Waldo Bastian explains in a copyrighted mail:

Being part of KDE means that you have to work together with others. Such cooperation brings along advantages but it also brings along responsibilities.

Some of those advantages are: your code ends up on all distro's, people might fix your bugs, you get free translations and documentation, you get tons of bugreports.

On the other side there are disadvantages and responsibilities: you will have to communicate with other developers about your work, other people might make changes to your code, you will have to respect release freezes, you get tons of bugreports and people actually expect that you fix them as well (what are they smoking?), people expect you to maintain your code.

You can't chose for the advantages and ignore the responsibilities that come with it, it's a complete package, it's both or nothing.

In general it should be the author of a piece of software that chooses to put his application in KDE's repositories. We usually don't put software in KDE's repositories unless the author wishes to do so. The other way around, if the author prefers to work on his application elsewhere then that's his right as well. Unless there is a split in the actual group of people working on the application it makes no sense to fork the development of an application because of that.

BUT... by putting your code under and open source license and putting it in a KDE repository you give the world at large, as well as KDE in particular, the irrevocable right to use your code. And KDE will use that right at its discretion to protect the interests of KDE, even if that goes against the wishes of the author at that point in time.

It is important to know that but don't be afraid. Usually, things work very well. In 5 years, it has only happened once that a developer had his work put kept in KDE while he wanted to remove it.

How do I get write access to KDE repositories?

See full article at Get a KDE Contributor Account.

Go to KDE Identity, fill out the form and describe why you need write access. Make sure to specify your full name and e-mail address.

Please also include the name of your bugs.kde.org account, if non-existent please create one so that it can be given usual developer rights. Closing bugs.kde.org reports with keywords in commit comments only works if the email address of your KDE Identity and bugs.kde.org accounts match. You can change your bugs.kde.org address in the Bugzilla user settings.

Git requires use of an ssh key, and new accounts for SVN must also choose the svn+ssh protocol. Send a public ssh key (e.g. ~/.ssh/id_dsa.pub)

See also #How do I create a SSH key?

If you are contributing to an application that is not yours, it is a good idea to first submitting your coding as patches to the author and let him apply them. If the author is not maintaining his application, you might become the new maintainer...

Although there are few restrictions on repository commit rights, we expect you not to disrupt other developers' code without their consent. You must also respect the feature freezes of the release schedule (published on Schedules page)

A detailed list of rules you should follow when committing to KDE repositories are listed in the KDE Commit Policy.

My app is not stable but I would like to have it in KDE

As a first step, we can put it in playground, which is essentially "kde-alpha". Develop it there and when it is ready, request that your app to be moved to the appropriate KDE package or the extragear module.

I don't want to lose my SVN history.

This is no longer possible with Subversion. Maybe in the future, if the server is upgraded and allows that. Note that for git this is not an issue.

What is kdebindings?

It contains Qt bindings for Ruby, PHP, C# to use Qt classes with those langages, KDE bindings for Ruby, C#, python to use KDE classes with those langages, and XParts to embed non-KDE apps as a KPart. Check the binding page of TechBase.

Does the feature freeze apply to playground?

No, playground are not a released packages. The same is true for kdereview and extragear: they are not frozen and released. But if you want your app to move to a package, ask for it before the beta-release.

Can I have a stable and an unstable KDE on the same computer?

Yes, check Building KDE Software from git.kde.org video series:

How do I know which version of Qt/KDE I am using?

kde-config and all KDE programs accept --version as argument.

Qt-copy or Qt from qt.digia.com: if one were doing a clean build of trunk, which would be preferable?

You can use either. They are binary compatible (forward and backward). There can be, however, a few bugfixes in qt-copy over the most recent Qt release. Especially if building from qt-copy, pay attention to the apply-patches script.

How can I checkout a single directory from a SVN module?

Checkout the top-level dir with 'svn co -N /modulename', 'cd modulename', 'svn up admin' to get the admin/ dir and then finally checkout the dir you want with 'svn up subdir'

For instance, to get only reaktivate from playground/utils: svn co -N /playground/utils; svn up reaktivate Then compile as usual.

The same answer applies to the question "How do I get a single language out of kde-i18n?".

If you don't know the name of the directory you want to check out, you can browse websvn.kde.org to find it.

How can I get one of the KDE application as a standalone tarball?

kdesdk/scripts/svn2dist is a script to extract an application from the KDE source tree and package it as a standalone application.

How do I close my own bug reports?

If you reported a bug that is fixed in a new release of KDE but is still reported as open, you can close it. It might happen because your bug is the same as another one, or simply because the developer fixed something without noticing that it would correct your bug.

You can do that from your Subversion commit. To do so, append to your commit message a line like this:

BUG: XXXXX where XXXXX is the bug report you want to close. If the report you're closing is adding a new feature, you can use FEATURE instead of BUG.

Managing a bug list is a huge task for the developers and they usually have a lot of bugs listed, some being fixed already without their knowledge, some being unreproducible, some without enough information to be corrected, etc. If you can help by managing and updating the list of outstanding bugs, you will be gladly welcome. And you will receive an even happier welcome if you provide a patch.

How do I create a SSH key?

SSH makes use of two keys: a private key and a public key. You should keep the private key secret at all times and only place it on machines over which you have direct control. Public, shared, and community machines are not suitable environments to store SSH private keys. Take action to help prevent theft of your SSH private key data. Setting a password on your SSH private key will help reduce the risks involved with private key theft.

Generate a key pair for each major location you work from. This helps to reduce the impact when your key gets stolen. When someone obtains access to your private key, your key can be abused in attempts to compromise KDE servers. Well known open source projects have been compromised this way in the past, YOU must help us to make sure that this doesn't happen with KDE servers as well. For that reason it is important to notify sysadmin (at) kde (dot) org immediately when you notice that someone may have had access to your private key for example when a computer on which it was stored has been hacked or infected with a virus, worm or trojan.

If you choose to make a backup of your SSH private key data, please ensure that any such backup is stored in a secure manner as well.

For the practical part, the following command can be used to generate a SSH private/public key pair with ssh-keygen -t dsa This will create a private key as ~/.ssh/id_dsa and a public key as ~/.ssh/id_dsa.pub.

There are times when you may want to use a key of a different name to the default, perhaps to use separate keys for different projects. To let SSH know which key you want to use for KDE.org, you can keep a list of servers and their corresponding keys in ~/.ssh/config. For example,

Host svn.kde.org 
IdentityFile ~/.ssh/id_dsa_kde

In order to use SSH to access KDE servers you need to send your public key to sysadmin (at) kde (dot) org.

How can I monitor changes made by others?

The kde-commits mailinglist carries automatic notifications for all changes made in the KDE repositories. The KDE-Commits mailinglist is very high traffic. An alternative is CommitFilter which allows you to get notification for only those areas that interest you.

 
Proposed for Deletion
This page has been proposed for deletion for the following reason:

Not relevant to external devs, content now at https://community.kde.org/KDE/FAQs/Technical_FAQ


Warning
This section needs improvements: Please help us to

cleanup confusing sections and fix sections which contain a todo


The build system has changed in KDE4.

How do I start a new application?

The easiest way is to use kdesdk/kapptemplate to generate the CMakeLists.txt. Or you can just copy a CMakeLists.txt from another app and install it in a new toplevel directory of existing KDE sources. Or you can start the old way, from scratch.

What is plasma, kpart, kio, kdeinit, ...

Check TechBase, especially the architecture documents. Check also the kde book.

Do I really need to use kpart?

Well, you are not forced to but it is a lot better. KPart allows powerful code reuse. Given how simple it is to use the technology and how widely it is deployed, it is a shame not to use it if you can.

How do I write a CMakeLists.txt?

Please follow this CMake tutorial.

What targets are available to make?

  • all: the default target (the one you get when typing "make").
  • clean: removes all the generated files
  • distclean: also removes the files generated by Makefile.cvs Not very useful within KDE (see dist for the "dist" concept and svn-clean for a better way to make really clean).
  • dist: supposedly for making a tarball out of SVN sources, but not very well supported within KDE. Better use kdesdk/scripts/cvs2pack for that.
  • force-reedit: re-run automake and am_edit on the Makefile.am
  • install: well, install everything :)
  • install-strip: install everything and strips binaries (removes debugging symbols).
  • install-exec: only install the binaries and libraries
  • install-data: only install the data files
  • check: compiles the test programs (i.e. those defined with check_PROGRAMS). It is even possible to actually run some tests during "make check", see kdelibs/arts/tests/Makefile.am

I have a checkout of SVN, there is no configure and no Makefile?

Use make -f Makefile.cvs It will run all the Makefile generation steps

How can I temporarily exclude certain directories from build?

While hacking a program it might be useful to exclude certain directories from build that would otherwise be recompiled, but don't actually need to be. Also, if you checked out source code that didn't compile and you don't have the time or knowledge to fix the error you might want to turn off compilation of the directory alltogether. There are two cases. Toplevel directories, and subdirectories. For toplevel directories you can simply erase them (or not check them out).

If for some reason you don't want to do that, you can also set DO_NOT_COMPILE="someapp" before calling configure, which will make configure skip "someapp". To only compile very few toplevel dirs, instead of using DO_NOT_COMPILE to exclude most of them, you can list in a file named inst-apps, at the toplevel, the toplevel subdirs you want to compile.

To turn off compilation of any directory, including subdirectories, you have to modify the Makefile or Makefile.am files. Makefile.am is not recommended because that file is in KDE Subversion and you could accidentally commit your changes. So we'll modify the Makefile instead here:

Open the Makefile in the directory immediately above the directory you want to exclude in a text editor and look for a variable SUBDIRS. It will often look somewhat like

SUBDIRS = share core ui . proxy taskmanager taskbar applets extensions data

Just remove the directory that you want to exclude and save your file. A new make will skip the directory you just removed.

Sometimes you'll have to look harder because the SUBDIRS variable consists of a number of other variables:

SUBDIRS = $(COMPILE_FIRST) $(TOPSUBDIRS) $(COMPILE_LAST)

Here you have to find the COMPILE_FIRST, TOPSUBDIRS and COMPILE_LAST variables. One of those contains the dir you want to exclude. Remove the directory where you find it and save the Makefile again. To undo your changes you can either regenerate the Makefile from scratch or revert to an older backup (you did make one, did you? :-). To regenerate a Makefile, just make force-reedit.

You can also copy the original line in the file when editing and make it a comment by prefixing a '#' in front of it. Then undoing the change is as easy as making the modified line a comment and removing the comment in the original line.

What are the various compilation options?

--enable-debug

Add debug symbols, disable optimisations and turns logging of kdDebug() on.

--disable-debug

The opposite of the previous one: enable optimisations and turns kdDebug() logging off.

--enable-final

Concatenates all .cpp files into one big .all_cpp.cpp file, and compiles it in one go, instead of compiling each .cpp file on its own. This makes the whole compilation much faster, and often leads to better optimised code, but it also requires much more memory. And it often results in compilation errors when headers included by different source files clash one with the other, or when using c static functions with the same name in different source files.

This is a good thing to do at packaging time, but of course not for developers, since a change in one file means recompiling everything.

--disable-fast-perl

By default KDE uses perl instead of sh and sed to convert Makefile.in into Makefile. This is an addition to autoconf done by Michael Matz. You can use this option to disable this but it is a lot slower.

Which compile option do you recommend?

If you are a developer, you should definitely compile Qt and KDE with --enable-debug. You will then be able to debug your program even inside Qt and KDE function calls. If you are just a user, you can still use --enable-debug. KDE will occupy more space on your hard disk but it won't slow down your desktop. The advantage is that you get stack trace when an application crashes. If you can reproduce a crashing behaviour, go to bugs.kde.org, check that your bug doesn't exist yet and submit it. It will help us improve kde. For Qt, the compilation options are explained in qt-copy/README.qt-copy.

Tips to increase compilation speed?

See --enable-final above :) . make final uses the all-in-one-file trick in the current directory even if --enable-final wasn't used, and make no-final does a normal compilation in the current directory even if --enable-final was used. Include your moc files! Header files declaring a QObject descendant have to be run through moc to produce a .moc file. This .moc file has to be compiled, for which two possibilities exists: compile it separately, or #include it in the C++ file implementing that above mentioned class. The latter is more efficient in term of compilation speed. BTW, kdesdk/scripts/includemocs does this automatically. Buy more ram, a faster machine and another processor. On a bi-PIII 866 MHz with 1GB of RAM, kde compiles at a decent speed :-)))

There is a STRIP variable set in the Makefile but it doesn't seem to be used?

The strip is done at install. To use it, use "make install-strip" instead of "make install".

What indentation should I use?

If you are working on an existing application, respect the author's indentation. Else, you can use whatever indentation you like.

What is the difference between i18n and I18N_NOOP?

If you do QString translatedStuff = i18n("foobar"); translatedStuff will contain the translation of "foobar", while for const char *markedStuff = I18N_NOOP("foobar"); markedStuff will still contain literal "foobar", but translators will know you want "foobar" translated so you can later on do QString translatedStuff = i18n(markedStuff); and get the translation of "foobar", which wouldn't work without that I18N_NOOP. So, normally you want to just use i18n(), but in cases where you absolutely need to pass something untranslated, but still need to translate it later or in the case that you have something to be translated before the KInstance exists, use I18N_NOOP().

I get "virtual tables error"?

This often comes from the moc files not being in sync with the sources, or not linked at all. Check that you are running the right moc. 'which moc' will tell it. Regenerate your moc files (make force-reedit; make clean; make).

I have added Q_OBJECT to myClassHeader.h but no moc files is generated?

You need am_edit to reparse your Makefile.am to generate the correct Makefile. If it's the first Q_OBJECT you're using in this directory, you'll need to re-run Makefile.cvs or create_makefile from kdesdk/scripts. Otherwise, you can simply run "make force-reedit".

To go quicker, I have coded my whole class in a cpp file, how do I get the moc files generated?

Hmm, don't do that, if some of the classes use the Q_OBJECT macro. Maybe METASOURCES=file.cpp might work for moc files though.

I have developed a kpart (or a plugin). I don't want to install it yet because it is not finished but I need that KDE finds it when I request it using KTrader or KLibLoader. How do I do that?

KDE searches its libraries in $KDEDIR/lib and in the lib directory of all the components of $KDEDIRS (note the additional 'S', this different from $KDEDIR). So, while you are still developing your library and don't want to install it, you can use this trick:

cd to your development directory, the one where your library is built.
Set up KDEDIRS so that it include your development directory: export KDEDIRS=`pwd`:$KDEDIR
Create a pseudo lib directory where KDE should find your component: ln -s .libs lib (all the objects and libraries are built in the .libs directory).
Run kbuildsycoca to inform KDE that it KDEDIRS has changed.

Now, KDE should find your library when using KTrader or KLibLoader.

How can I install additional KDE stuff when I am not root?

If want to install your application privately, configure it with another prefix: for $HOME/kdeprefix, use configure --prefix=$HOME/kdeprefix. Then let KDE know about this prefix: set KDEDIRS to $HOME/kdeprefix:$KDEDIR. To make KDE aware of new prefixes, one can also edit /etc/kderc and add

[Directories]
prefixes=/the/new/prefix

but this doesn't answer this specific question ;-) Make sure to run "kbuildsycoca" after setting the new KDEDIRS.

My kpart lib is not listed when I request it with KTrader

The mimetype database must be rebuilt when you install new services (such as applications or parts). In theory this happens by itself (kded is watching those directories), but in doubt, run "kbuildsycoca". The best way to debug trader-related problems is to use ktradertest: cd kdelibs/kio/tests; make ktradertest, then run ./ktradertest to see how to use it.

I changed something in kdelibs, installed the new lib, but new KDE apps don't seem to use it?

The solution is simple: start new apps from a command line, then they will use the new lib.

The reason is that applications started by other KDE applications (kicker, minicli, konqueror, etc.) are started via kdeinit, which loads the libs when KDE starts. So the "old" version of the libs keep being used. But if you want kdeinit to start using the new libs, simply restart it. This is done by typing kdeinit in a terminal.

This is necessary if you can't start things from the command line - e.g. for a kioslave. If you change something in kio, you need to restart kdeinit and kill the running kioslave, so that a new one is started.

I'm developing both a KPart and a standalone application, how do I avoid duplicated code?

Apps are often tempted to link to their part because they of course have much functionality in common. However this is wrong for the reasons below.

A lib is something you link to, a module is something you dlopen. You can't dlopen a lib ; you can't link to a module.

A lib has a version number and is installed in $libdir (e.g. $KDEDIR/lib) a module doesn't have a version number (in its name), it's more like a binary (we don't have konqueror-1.14.23 either :), and is installed into kde_moduledir (e.g. $KDEDIR/lib/kde3) (which means it's not in the search path for ld.so, so this breaks on systems without -rpath).

If you didn't understand the above, don't worry. The point is: you should NOT make your application link to your (or any other) KPart, nor any other kind of dlopened module.

The solutions:

Let the app dlopen the part. This is what KOffice does. However this limits the app to the very limited ReadOnlyPart/ReadWritePart API. Keep in mind that you can't call a non-virtual method whose implementation you don't link to. The solution is to define a ReadWritePart-derived class (like we have in koffice: KoDocument), with new virtual methods. Either this derived class has code (and you need a lib shared by the app and the part, see point 2 below), or an abstract interface (header file only) is enough. You can also use known interfaces to child objects of the part instead of changing the base class of the part itself - this is the solution used by e.g. KParts::BrowserExtension.

Define a common library with the common classes and let both the part and the app use it. That library can be noinst_ or lib_, both work. In the first case the compiled object code is duplicated, in the second case a real versioned lib will be installed. The idea here is that the part itself is not available to the app, but instead the part is a very thin wrapper around the same classes as the app uses. Only KParts-specific stuff remains in the part.

What is the best way to launch another app?

In KDE there are several ways to start other programs from within your application. Here is a short summary of your options with reasons why you should or should not use them.

fork + exec

You never want to use this unless you have a very good reason why it is impossible to use KProcess.

KProcess

You want to use this if you need to start a new process which needs to be a child of your process, e.g. because you want to catch stdout/stderr or need to send it data via stdin. You should never use this to start other KDE applications unless your application is called kgdb :-)

startServiceByDesktopPath

Preferred way to launch desktop (KDE/Gnome/X) applications or KDE services. The application/service must have a .desktop file. It will make use of KDEinit for increased startup performance and lower memory usage. These benefits only apply to applications available as KDEinit loadable module (KLM)

KRun

Generic way to open documents/applications/shell commands. Uses startServiceBy.... where applicable. Offers the additional benefit of startup-notification.
KRun can start any application, from the binary or the desktop file, it will determine the mimetype of a file before running the preferred handler for it, and it can also start shell commands. This makes KRun the recommended way to run another program in KDE.

KToolInvocation::invokeBrowser

KToolInvocation::invokeBrowser launches a web browser. The difference with using the more generic KRun on the webpage URL is that KRun has to determine the mimetype of the URL first (which, for HTTP, involves starting a download to read the headers), so if you know that the URL is an HTML webpage, use invokeBrowser, it will be faster.

More details: the problem with KRun for webpages is that it delays the appearance of the browser window, and if the user's preferred browser is a non-kde application like firefox then it has to start a second download while konqueror which can reuse the kioslave started by KRun. On the other hand if the URL might be an image or anything else than html, then KRun is the right solution, so that the right application is started.

How do I create and submit a patch to KDE?

You have spotted a bug and you want to write the code to fix it. Or you want to code a specific feature. Sending a patch is very appreciated by developers. A tutorial is available but here is a description of how you should proceed:

  • Get the latest KDE using SVN to check that the code you want to write has not been added yet.
  • Check the bug database to see if your bug is not worked on.
  • Get in contact with the author. His/her name is in the about box or in the source header. If the project has a mailing-list, browse the archives to see if your bug/feature has not been the subject of any discussion. If you can't find any mailing lists or author, simply write to kde-devel.
  • Post a message explaining your intentions. It is important to inform the author(s) about what you are planning because somebody might already be working on your feature, or a better design could be proposed by the author, or he could give you some good advice.
  • Next step is to code your feature. It is usually a good idea to keep an original at hand and to work on a copy. This allow to check the behaviour of both versions of the code. Respect the author's indentation and naming scheme, code carefully, think about side-effects and test everything many times.
  • Using the latest KDE code, make a diff using either svn diff or a diff -uNp original-dir new-dir. Don't send reversed patch. The first argument of diff should be the old directory and the second the new directory.
  • Send a mail to the author/mailing-list with your patch as attachment (don't forget to attach it :-) ).
  • People usually have some remarks on your work and you must work further on your patch to improve it. It is common to see three or four submission before acceptation.

Ok, you have done it, your code has been included in KDE. You are now fully part of the KDE project. Thanx a lot.

How do I make my application Xinerama and multi-head safe?

Never make assumptions about the geometry of the "desktop" or the arrangement of the screens. Make use of the following functions from kglobalsettings.h:

 static QRect KGlobalSettings::splashScreenDesktopGeometry(); 
 static QRect KGlobalSettings::desktopGeometry(const QPoint& point); 
 static QRect KGlobalSettings::desktopGeometry(QWidget *w);

Use splashScreenDesktopGeometry() to determine the geometry of the desktop when you want to display an application splash screen. Use desktopGeometry() to determine the geometry of the desktop with respect to a given point on the desktop, or with respect to a given widget. Do not use the Qt class QDesktopWidget to determine these values yourself. The KDE functions take the user's settings into account, something the Qt functions cannot do.

It is ideal to try to avoid using the desktop geometry altogether. Your application will be much more standards compliant if you let the window manager place your windows for you. When this is not possible, you have the aforementioned functions available. Please beware that the geometry that is returned from these functions may not start at (0,0)! Do your math correctly!

One other caution: Both KWin and the NETWM specification have severe difficulties handling struts with Xinerama or "merged" displays. This can result in dead areas on the screen, for instance if kicker does not span a whole edge. There is not much that can be done about this, and you should try to avoid hacks to circumvent this at this time. We hope to find a proper solution for this soon.

I get an error about KDE not finding UIC plugins, but I know they're installed. What's wrong?

This is almost certainly an installation problem, not a KDE code problem. A number of problems can lead to this, but most likely you have more than one version of Qt laying around and the configure script is calling a different one than KDE is using.

Another thing that may help is to rebuild and reinstall your kdewidgets.so file, which is located in the kdelibs/kdewidgets directory. Note that if you *do* have multiple versions of Qt, this may compile against the wrong one.

This problem creeps up on various mailing lists occasionally, so looking at the archives on lists.kde.org may be helpful.

I put some functions in anonymous namespace and someone reverted it and made those functions static, why?

Symbols defined in a C++ anonymous namespace do NOT have internal linkage. Anonymous namespaces only give an unique name for that translation unit and that is it; they don't change the linkage of the symbol at all.

Linkage isn't changed on those because the second phase of two-phase name lookup ignores functions with internal linkages. Also, entities with internal linkage cannot be used as template arguments.

Can I delete a NULL pointer?

Yes. Calling delete on a null pointer is a noop in C++. Having "if (ptr) delete ptr;" is redundant. Doing ptr = 0; after a delete is a good idea, especially if the delete can be called on it from a different code path.

My locally installed application doesn't run, but KDEDIRS is set correctly, what's going on?

If you're running a 64 bits system, your libraries might have been compiled with the -DLIB_SUFFIX=64 option given to cmake. If your application wasn't compiled with that option, it'll get its modules installed into $prefix/lib/kde4, not $prefix/lib64/kde4 -- and then it will not be found. Easy solutions: a symlink to lib64 or compile your code with -DLIB_SUFFIX=64, too.

 
Proposed for Deletion
This page has been proposed for deletion for the following reason:

Not relevant to external devs

This page is now on the community wiki.

Getting Help/Contact belongs to the Contact / Contribute pages, not into this tutorial itself (it only bloats up the page) - what do you think? Dhaumann 17:05, 23 December 2006 (CET)

Fully agree, but I didn't see a good place to put this when I was writing it. So I just tacked it on here. Suggestions on a specific page it should go to? Mattr 18:36, 23 December 2006 (CET)
Maybe add it somewhere to Contribute or even put it into the Help: namespace? I'm yet undecided :) Dhaumann 16:54, 26 December 2006 (CET)
personally i think the "finding other developers" belongs in the Getting Started area, as it's something that anyone working on a kde application would want or even need to do. the finding documentation section could perhaps be broken out into it's own little tutorial? that tutorial could cover: developer[new].kde.org, accessing api documentation online as well as locally via konqueror or kdeveloper (qt assistant?), lxr.kde.org ...?
While this is being decided, I'll move the "Your lessons" section near the top. Since, to be honest, if someone clicked on the "KDE 4 Programming Tutorial" link on the Tutorials page then they're going to be expecting tutorials, not a page full of non-tutorial txt. --milliams 00:29, 4 January 2007 (CET)
Okay, coming back to this again. This information needs to be in a easier to find place. At the moment it's the best source of information on the KDE IRC channels I can find anywhere and it needs to be more prominent. On kde.org, this sort of info is under "Getting Started" but I'm not sure where it belongs on TechBase (if at all). Perhaps some sort of Contact page or maybe it should all simply be put on kde.org? --milliams 01:10, 11 March 2007 (CET)

Breaking this out into separate tutorials?

I have to say that this seems to be duplicating much of intent of the Tutorials section in general. The topics are pretty eclectic (nearly random?) and would each make nice top-level tutorials where they would be more visible and likely gain more editing love as well as readership. thoughts?

I feel that this page should just be introductory tutorials about the basics of KDE4 programming. The others (like printing and sound) should be moved to the main Tutorials page. -- milliams
I decided that instead of just saying 'should', I've gone ahead and written some tutorials which are aimed at developers complely new to KDE (but who know C++ (and maybe Qt)). I've also reformatted the 'First Program' tutorial to fit in with mine (to make a series of it). --milliams 22:55, 3 January 2007 (CET)
the tutorials look great. but i'm once again struck by the thought that these simply don't belong here but on the main tutorials page. tutorial #4 is about kconfigxt. we already have a tutorial on kconfigxt on the main tutorials page, and i'd suggest that is where this one belongs as well. if it's meant to be a more introductory piece than the existing one (e.g. introduces KConfig and friends, etc), then it can be placed before it (and perhaps even numbered appropriately?). if someone comes to the site asking "what does kde provide for configuration?" will they really find it all if that information is in the "beginner's tutorial" and some of that information is on the main tutorials page? and will people working on kconfig (to keep picking on that example ;) remember to update all the kconfig related tutorials spread around the tutorials area? i'm willing to help move things around on friday, but i don't want to do that without the blessings of those involved in authoring this set of rather nice tutorials... aseigo
OK, agreed. My KConfig tutorial should be on the main tutorial page along with the main KConfig intro. I see two possible ways to sort out what to do with the rest: (1) This page should be renamed to something like "Introduction to KDE Programming" The three (tutorial 1-3) tutorials I wrote should stay here since they are really aimed at completely new KDE developers but all the rest should be moved to appropriate places on the main Tutorial page. (2) All the tutorials should be moved to the main tutorial page and put in sensible places but that the three (tutorial 1-3) tutorials that I wrote should be put under a new heading and names with the 101, 110 etc. naming scheme. --milliams 14:06, 4 January 2007 (CET)
What I really think would work well is something like what the Qt documentation has at Qt 4.2: Qt Examples. Here they've written a series of tutorials (the one that build up an application, introducing one concept at a time) and then, after that, have got a largish number of 'examples' where they show you how to use a specific technology/widget/concept. The latter, I feel, is covered by the tutorials on the main tutorial page (i18n/solid/dbus etc.) but I do think we need a simple introductory tutorial which walks the new developer through KDE programming which is what I feel this page should aim for. --milliams 14:06, 4 January 2007 (CET)
i agree that we need a basic "getting started" tutorial; i also think your efforts here are doing a great job providing exactly that. i also agree that the tutorials on the main page should serve a similar purpose to Qt's examples (though hopefully we can structure it a bit better even). perhaps instead of covering kconfigxt in tutorial 4, you could cover "just" kconfig itself? that seems like a basic introductory concept. and then point from there to the article on kconfig xt (which adds all the xml stuff to the mix). kapplication, mainwindow, actions, config .. those are pretty universal concepts. most everything else varies from app to app based on needs/scope/audience of the app imho. so ... sounds like we're at an agreement point here? --Aseigo 22:02, 4 January 2007 (CET)
Just a quick sidenote: I think it's bad to have 10 tutorials of the same thing (a bit exaggerated =). Let's try to have only one. And if we need more advanced tutorials, we still can have only one -- with subpages. --Dhaumann 17:41, 4 January 2007 (CET)
this is a breadth-versus-depth organization issue, isn't it? i see no problem with having 5 or 6 tutorials covering a given topic as long as they each cover a separate, distinct part of that topic. that distinction can come in many forms: introductory vs advanced, commonly used vs niche aspects, topics that each fill a good sized article. one thing i'd really suggest we avoid is having tutorials that try and cover every aspect of a technology resulting in huuuuge documents that are onerous to read and which make it more difficult to find exactly the bit you want. the xmlgui tutorials for kde2/3 were great examples of this latter problem imho. you'd get stuff that was too advanced for the new developer and the nuggets of gold that the advanced dev needs from time to time hidden quite effectively amongst the intro stuff. =/
that said, i can certainly see the possibility of needing to eventually move all the tutorials for a given topic to a subpage of their own, much as this tutorial (the kde4 programming tutorial) is doing for "introductory tutorials". i see this becoming an issue once we have, say, >100 tutorials but until then i'm not sure we'll be able to best see how to organize the final content. i think building the library is the most important aspect at the moment. --22:03, 4 January 2007 (CET)

Off topic tutorial stubs don't belong here!

This page is NOT a dumping ground for all the small tips you couldn't find anywhere else for. This is a small series of tutorials for introducing a completely new programmer to the KDE API and build system etc. We don't need a tutorial telling the reader how to implement a QTreeView for example. That's what the Qt docs are for! I'll leave these up for a week incase someone wants to move these somewhere more appropriate after which point I will delete all these stubs. The CMake tutorial should perhaps be slimmed down and included into the CMake tutorial in the Development/Tutorials page. The XML parser tutorial isn't really needed, that's not the sort of thing someone looks up documentation for. That's what we have the Qt XML stuff for. --milliams 15:14, 31 May 2007 (CEST)

Imho, we should add a link in (2) to (1) and cleanup (2) so that it gives a quick introduction and further links to subversion tutorial etc. Thoughts? Dhaumann 12:52, 24 December 2006 (CET)

agreed. i also think it might be worthwhile to promote this whole area to the front page. i just got an email with the too-common lament regarding kde development: "Getting the source is not the problem, figuring out the processes and the steps that follow is the challenge." seems to me the steps are: get set up, develop, contribute... so perhaps this contribute section should have it's own front page section after "developing with kde"? User:aseigo

I understand that this page is for developers, however, I think the "note" was giving mixed messages; i.e. the text is saying there are many ways to get involved and then the note said that (paraphrasing) "if you can't code, go here". I think that the note (and preamble) should be consistent and direct the user to where they can go whether they can code or not (or, even if they don't feel like coding)... User:psych

link to KDE Traffic (http://www.kerneltraffic.org/kde/archives.html) seems to be broken (Alexander Kabakov)

It's still applicable
Mattr 16:02, 24 December 2006 (CET)

I had some problems understanding this tutorial. I propose creating a a page under KDE 4 Architecture Overview where we can describe the configuration architecture in more detail. I found the details in this interview very helpful.

When we put most of the theory and history there we can focus on examples and how to use KConfig XT here.

Grodaas 01:48, 2 January 2007 (CET)

i think it's pretty obvious that we need some more tutorials in the kconfig section. e.g. introducing kconfig itself (which is probably better done after some of the upcoming kconfig refactoring) ... a bit more introduction as to what kconfigxt is in this tutorial wouldn't be bad either. in other words, fleshing it out would be a good idea. an architecture overview document would be good as well i suppose..
User:aseigo
Introduction to Unicode
Tutorial Series   Localization
Previous   None
What's Next   Writing Applications With Localization In Mind
Further Reading   The Unicode website
Unicode article at Wikipedia
Unicode for Unix/Linux FAQ

Abstract

Unicode is a standard that provides a unique number for every character and symbol in various writing systems used around the world which makes it the basis for translatable software and international content creation. This tutorial provides a brief introduction to Unicode and how to work with Unicode data using Qt.

What Is Unicode?

Unicode is hardware, development platform and language independent. As of version 5 there are codepoints assigned up to 0x10FFFF (but not all are used), the first 256 entries being identical to ISO 8859-1 a.k.a. ISO Latin-1. This also means that the first 128 characters are identical to the familiar ASCII mapping. Codepoints were assigned with ease of implementation for legacy character sets in mind, so Unicode is littered with such coincidences to keep translation tables and logic short.

Why use Unicode?

If you use a legacy character set like ISO 8859-15 it is difficult to create documents containing more than only a couple of languages. You can interchange them only with people using the same character set. Even then, many writing systems contain more characters than can be uniquely addressed by an 8-bit number.

Therefore Unicode is the best of the sensible ways to mix different scripts and languages in a document and to interchange documents between people with different locales. Unicode makes it possible to do things such as writing a Russian-Hungarian dictionary.

UTF-8 and UTF-16

UTF stands for "Unicode Transformation Format". The two most commonly used variants, UTF-8 and UTF-16, define how to express a Unicode character's assigned codepoint in bits.

UTF-16 signifies that every character is represented by the 16-bit value of its Unicode number. For example, in UTF-16 b (LATIN SMALL LETTER B) has a hex representation of 0x0062. There are also surrogate pairs used to encode characters with codepoints beyond 0xFFFF.

UTF-8 signifies that the Unicode characters are represented by a stream of bytes in a special encoding scheme described in [1] and [2]. Unlike UTF-16, it is compatible to ASCII. Higher codepoints take two or three bytes to encode, rarely more than that.

Unicode in KDE Applications

Storing Unicode strings in memory and displaying Unicode on screen is very easy with Qt: QString and QChar provide full Unicode support transparently to your application.

QString and QChar both internally represent characters using UTF-16. If you read in text pieces from or write it to an 8-bit source such as QTextStream you must use a QTextCodec to convert the text between representations. Normally you would use the UTF-8 codec to convert a Unicode string between a QByteArray and a QString.

Getting an appropriate Unicode QTextCodec is quite simple:

QTextCodec Utf8Codec  = QTextCodec::codecForName("utf-8");
QTextCodec Utf16Codec = QTextCodec::codecForName("utf-16");

Display

Any widget that uses QString or QChar when painting text will therefore be able to show Unicode characters as long as the user has an appropriate font available.

For flexible text editing and display, consult the Qt documentation on rich text processing. The Scribe system provides a set of classes centered around the QTextDocument class that makes it easy to accurately display and print formated text, including Unicode.

In-Memory Buffers

To read Unicode data from an in-memory buffer, such as a QByteArray, one can use the codecs created earlier in this section:

QByteArray buffer;

// UTF-16
QString string = Utf16Codec->toUnicode(buffer);

// UTF-8
QString string = Utf8Codec->toUnicode(buffer);

Writing to a buffer looks very similar:

QString string; // my Unicode text
QByteArray array; // Buffer to store UTF-16 Unicode
QTextStream textStream(array, IO_WriteOnly);

textStream.setEncoding(QTextStream::Unicode);
textStream << string;

File Handling

For storage and retrieval to and from a file KDE applications should provide the option to store text data in Unicode instead of the locale character set. This way the user of your application can read and save documents with the locale charset as the default while having the option to store it in Unicode. Both UTF-8 and UTF-16 should be supported. European users will generally prefer UTF-8 while Asian users may prefer UTF-16.

Reading Unicode data from a text file is demonstrated in the following example using the QTextCodecs we created earlier for UTF-8 data:

QTextStream textStream;
QString line;

// UTF-16, if the file begins with a Unicode mark
// the default is ok, otherwise:
// textStream.setEncoding(QTextStream::Unicode);
line = textStream.readLine();

// UTF-8
textStream.setCodec(Utf8Codec);
line = textStream.readLine();

Writing is equally straight-forward, also using the QTextCodecs we created earlier:

QTextStream textStream;
QString line;

// UTF-16
textStream.setEncoding(QTextStream::Unicode);
textStream << line;

// UTF-8
textStream.setCodec(Utf8Codec);
textStream << line;

Unicode Character Input

Being able to load, store and display Unicode is only part of the puzzle. One of the final pieces is allowing the user to input Unicode characters. This is generally solved using platform-specific multibyte input methods (IM), such as XIM on X11. KDE provides good support for these input methods via Qt and your application should not need to do anything special to enable such input.

Sample Unicode Files and Fonts

An easy way to get Unicode sample data is to take the kde-i18n package and convert some files from there to Unicode using the recode command line tool:

recode KOI8-R..UTF-8      ru/messages/kdelibs.po
recode ISO-8859-1..UTF-16 de/messages/kdelibs.po
recode ISO-8859-3..UTF-8  eo/messages/kdelibs.po

The majority of operating systems today come packaged with Unicode TrueType fonts, see [3].

TODOs


KDElibs.com and developernew.kde.org coexistence

  • Mind if I copy the build info over from kdelibs.com to here under Getting_Started/Build/Unstable_Version-Windows, and then could you review it for current correctness? Thanks --CuCullin 16:13, 11 January 2007 (CET)
    • I do not recommend making redundant copies of http://www.kdelibs.com. The content there is under heavy development now. I won't be able to maintain another wiki (I already have FOUR :) ). We can make a move (not a copy) to kdelibs once KDE4 buildsystem is stable. Why? Because many steps are common and we want to share them between targets. For now the instructions are even splitted between msvc and mingw compilers, what's not optimal for maintenance.
      According to my vision: eventually, kdelibs.com will be more ISVs-oriented while *.kde.org stays oriented at the community in general. -- jstaniek 17:27, 11 January 2007 (CET)
      • Moving once its settled in sounds good. As long as at some point we have all our information in one place we should be good. The issue of kdelibs.com becoming an ISV portal raises a question with regards to the ISV section on this website. We don't need two of them IMHO, it'll only split resources and give opportunity for confusion to those looking for ISV info. Jaroslaw: i'll see if i can find you on irc to discuss kdelibs.com a bit since that's a bit off-topic here. =) --Aseigo 20:43, 11 January 2007 (CET)
        • In fact, kdelibs.com is planned as a web site about kdelibs technology only (or mostly), as it sounds, and how to use it for developemnt and deployment. Among other plans I think the web site will have a variation of kde.org's look&feel, with some "commercial" touch. Something like trolltech.com is for Qt while there exist various forums devoted Qt, I'd risk such comparison. Companies/organizations having multiple web sites, one per orthogonal topic, are not unusual these days... These are random thoughts for now. ---jstaniek 21:08, 11 January 2007 (CET)
      • I'm not wanting to move all of it - specifically, what I'd like to do is just get basic build information onto this wiki and also a working windows version of the "hello world" for KDE 4 tutorial posted. This is partially to coordinate with something upcoming.... if you're available, I'm on freenode to chat about it further. --CuCullin 21:36, 11 January 2007 (CET)
  • Development/Tutorials/Solid/Network Management
Warning
This page needs a review and probably holds information that needs to be fixed.

Parts to be reviewed:

  • Port to KF5
  • Add more content

Prerequisites

This tutorial assumes that you have read Introduction to Solid and are familiar with the Solid hardware framework. If you want to use any backends other than the fake backends provided in kdelibs, you will need to compile and install kdebase.

Features of the Solid Network Manager

The Solid Network Manager provides many useful features that have, up until now, been missing from KDE. These include:

  • Notification of connection state. This allows applications to know when there is no internet connection, allowing them to not bother the user with "Connection Error" messages
  • Notification of wireless connection state.
  • Access to network devices and interfaces.
  • Device <-> interface cross-referencing.

Note that there is a difference between the devices and the interfaces. The device is a representation of the device itself and all the things that normally are associated with a PCI/USB device such as: bus address, IRQ, etc. The interface is the name of the device e.g. 'eth0' which is used for commands like 'ifconfig.'

Let's begin

Our first program is going to be the most common use of the network manager, checking the network status of the system. This will be useful for programs like KMail which will be able to see if the computer has network connectivity. It would then be able to judge whether or not it should check for mail.

//test to see if networking is enabled on the system
if(Solid::Networking::status() == Solid::Networking::Connected)
{
    kDebug() << "Networking is enabled. Feel free to go online!";
}
else
{
    kDebug() << "Network not available.";
}

To get informed about changes in network connectivity you'll have to connect to the events of Solid::Networking::notifier().

Cross-referencing devices to interfaces

It is no longer required for the user to figure out which device corresponds to a given interface as the NetworkManager has the ability to cross-reference a device to its interface name. This can be done with the following code:

//get a reference to the device manager
Solid::DeviceManager &manager = Solid::DeviceManager::self();
    
//get a network device
Solid::DeviceList netlist = manager.findDevicesFromQuery(Solid::Capability::NetworkHw, QString());
    
//check to see if no network devices were found
if(netlist.empty() )
{
    kDebug() << "No network devices found!";
}
    
Solid::Device device = netlist[0];
Solid::NetworkHw *netdev = device.as<Solid::NetworkHw>();
//keep the program from crashing in the event that there's a bug in solid
if(!netdev)
{
    kDebug() << "Device could not be converted. There is a bug.";
    return 0;
}
    
kDebug() << "The iface of" << device.udi() << "is" << netdev->ifaceName();

Initializing devices

Encryption

Putting it all together

Writing Applications With Localization In Mind
Tutorial Series   Localization
Previous   Introduction to Unicode is recommended, though not required
What's Next   Avoiding Common Localization Pitfalls
Further Reading   n/a

Abstract

Reaching a broad audience of users and developers requires that your software can be translated and otherwise shaped at runtime to be linguistically and culturally relevant to whomever is sitting in front of the computer. This is the realm of localization and this tutorial steps you through what is needed to make your application localizable.

What is Internationalization and Localization?

Internationalization, or i18n ('i', followed by 18 letters, then an 'n'), is the process of writing your application so that it can be run in any locale. This means taking into account such things as:

  • textual messages that are displayed to the user
  • data input from the user, files and other sources
  • format of dates, numbers, currency, etc.

Localization, or l10n ('l', followed by 10 characters, then an 'n'), is the process of taking an internationalized application and adapting it for a specific locale.

Generally speaking, programmers internationalize their applications and translation teams localize them.

Why is This Important?

KDE development happens primarily in English as this allows the broadest reach into the development and translation communities. However, English is not the primary language of most people on the planet. In fact, fewer than 8% of humanity speaks English and less than 5% speak it as their mother tongue. Even on the Internet, only 35% people who are online use English as their primary language and as more and more of the world gets wired this number is only decreasing. Additionally most languages, including 9 out of the 10 most common languages, use non-ASCII characters in their written form. It is easy to see, then, why it has become a necessity to provide localized software.

As an international project that spans the globe, such localization is a core value within the KDE culture. In fact, while many KDE developers write their software in English they use the desktop in their native locale.

Translatable Code Using i18n()

To ensure your application is ready to be localized you have to follow a few simple rules. All user-visible strings in your application should be translated before they are displayed on the user's screen, exceptions to this being debugging messages, configuration keys and similar types of text data.

KDE provides the KLocale class as part of libkdecore to facilitate the technical details of localization. KLocale makes it as easy as possible for developers to make their code i18n aware, but there are some things you need to be aware of so that applications are usable in other languages and countries.

Access to a global KLocale object is provided via KGlobal::locale(). This KLocale object is created automatically by KInstance and takes care of all user i18n related settings. It is deleted automatically on application exit.

Translations are made possible by the QString i18n(const char*) method, defined in klocalizedstring.h, which you must wrap all strings that should be displayed in. The QString returned by i18n() is the translated (if necessary) string. This makes creating translatable widgets as simple as in this example:

#include <klocalizedstring.h>
[...]
QPushButton* myButton = new QPushButton(i18n("Translate this!"));

QString's native Unicode support ensures that all translations are represented correctly. All string handling done by your application should therefore use QString.

Tip
If the string to be translated contains any non-UTF8 characters, use the utf8() method to get a char*.


ki18n

The i18n() method requires that a KInstance (e.g. KApplication) has been created. For any strings that are created prior to this there is another method provided: ki18n(). This allows one to mark strings that should be translated later as such. The ki18n() will return a KLocalizedString, which can be finalized into a QString (i.e. translated for real) after the KInstance has been created, using its toString() method.

ki18n() is typically used for strings given to KAboutData, because it is constructed before the KApplication and you can use i18n() only after the construction of the KApplication. Other than these special cases, it is always safe to use i18n() if you are sure that the code will be executed after construction of KApplication or some other KInstance.

Adding Context with i18nc()

There is an extended method, i18nc() which takes two const char* arguments. The first argument is an additional contextual description of the second string which will be translated. The first string is used to find the proper corresponding translation at run-time and is shown to translators to help them understand the meaning of the string.

Use i18nc() whenever the purpose of the text might be ambiguous without further context. For example, consider a context menu in a file manager with an entry called "View" which opens a viewer for the currently selected file. In this context "View" is a verb. However, the same application also may have a menu called "View" in the menubar. In that context "View" is a noun. In the English version of the application everything looks fine, but in most other languages one of the two "View" strings will be incorrect.

Additionally, translators sometimes need extra help in understanding what the text is actually referring to during the translation process.

In the file manager example above, one might therefore write:

contextMenu->addAction(i18nc("verb, to view something", "View"));
viewMenu->addAction(i18nc("noun, the view", "View"));

Now the two strings will be properly translatable, both by the human translators and at runtime by KLocale.

Use this form of i18n whenever the string to translate is short or the meaning is hard to discern when the context is not exactly known. For example:

QString up = i18nc("Go one directory up in the hierarchy", "Up");
QString relation = i18nc("A person's name and their familial relationship to you.", "%1 is your %2", name, relationship);
Note
There is also a ki18nc("context","text") method for providing context to strings which are constructed before the KInstance. It returns a KLocalizedString, so use the toString() method afterwards to convert it into a QString.


Contexts can also be added when building forms in Qt Designer. Each widget label, including tooltips and whatsthis texts, has a "disambiguation" attribute (named "comment" prior to Qt 4.5), which will serve the same purpose as first argument to i18nc() call.

KDE provides a standard set of strings to identify the semantic context of translatable strings. These are defined in the KUIT Semantic Markup scheme.

Standard Context For Common Phrases

Below is a chart showing some common words and phrases in English and the context that must be used with them to ensure proper translation of them in other languages.

Standard Contexts
Phrase Context i18nc Call Example
Busy Referring to a person i18nc("A person is busy", "Busy")
Busy Referring to a thing i18nc("A thing is busy", "Busy")
Color Color mode, as opposed to Grayscale i18nc("Not Grayscale", "Color")
Creator Referring to a person i18nc("A person who creates", "Creator")
Creator Referring to software i18nc("Software", "Creator")
Display Referring to hardware i18nc("Hardware display", "Display")
Editor Referring to a person i18nc("A person who edits", "Editor")
Editor Referring to software i18nc("Software", "Editor")
Line Referring to drawing i18nc("Draw a line", "Line")
Line Referring to text i18nc("Line of text", "Line")
Name Referring to a name of thing i18nc("A thing's name", "Name") In theme change dialog: i18nc("Theme name", "Name")
Name Referring to first name and last name of person i18nc("Person's first and last name", "Name") In KAddessbook contact edit dialog: i18nc("Person's first and last name", "Name")
New Create something i18nc("Action", "New")
New Status i18nc("New mail message", "New")
No Answer to a question i18nc("Answer to a question", "No")
No Availability of a thing i18nc("Availability", "No")
(Re)load (Re)load a document, medium etc. i18nc("(Re)load a document", "(Re)load")
(Re)load (Re)start a program, daemon etc. i18nc("(Re)start a program", "(Re)load")
Title Referring to a person i18nc("A person's title", "Title")
Title Referring to a thing i18nc("A thing's title", "Title")
Trash Referring to the action of emptying i18nc("The trash is not empty. Empty it", "Empty")
Trash Referring to the state of being empty i18nc("The trash is empty. This is not an action, but a state", "Empty")
Volume Referring to sound i18nc("Sound volume", "Volume")
Volume Referring to a filesystem i18nc("Filesystem volume", "Volume")
Volume Referring to books i18nc("Book volume", "Volume")
Yes Answer to a question i18nc("Answer to a question", "Yes")
Yes Availability of a thing i18nc("Availability", "Yes")

Standard Context for Special Format Strings

  • The context (qtdt-format) should be used for strings that are used as displayFormat in QDateTimeEdit or QTimeEdit.
  • The context (qtundo-format) should be used for strings that are used as text in QUndoCommand. If the application depends on Qt 4.8+, translators can use the "double-form functionality": if you put two strings separated by "\n" in that text, the first line will be used in "Undo History" panel, and the second line will be used in "Edit -> Undo/Redo %1" menu items.

Plurals

Plurals are handled differently from language to language. Many languages have different plurals for 2, 10, 20, 100, etc. When the string you want translated refers to more than one item, you must use the third form of i18n, the i18np(). It takes the singular and plural English forms as its first two arguments, followed by any substitution arguments as usual, but at least one of which should be integer-valued. For example:

msgStr = i18np("1 image in album %2", "%1 images in album %2", numImages, albumName);
msgStr = i18np("Delete Group", "Delete Groups", numGroups);

i18np() gets expanded to as many cases as required by the user's language. In English, this is just two forms while in other languages it may be more, depending on the value of the first integer-valued argument.

Note that this form should be used even if the string always refers to more than one item as some languages use a singular form even when referring to a multiple (typically for 21, 31, etc.). This code:

i18n("%1 files were deleted", numFilesDeleted);

is therefore incorrect and should instead be:

i18np("1 file was deleted", 
     "%1 files were deleted",
     numFilesDeleted);

To provide context as well as pluralization, use i18ncp as in this example:

i18ncp("Personal file", "1 file", "%1 files", numFiles);

In some cases pluralization is needed even if English does not need it. For example:

i18nc("%1 is a comma separated list of platforms the software is available on.",
      "Available on %1", platforms);

One reason for this is that in some languages the preposition "on" needs to be replaced with a descriptive noun in a certain form, which essentially in English means the same as this:

i18nc("%1 is a comma separated list of platforms the software is available on.",
      "Available on platforms %1", platforms);

And that is why the correct way is to use pluralization here as well:

i18ncp("%2 is a comma separated list of platforms the software is available on.",
       "Available on %2", "Available on %2", numberOfPlatforms, platforms);

Formatting Dates and Numbers

When displaying a number to the user, your program must take care of the decimal separator, thousand separator and currency symbol (if any) being used. These symbols differ from region to region. In English speaking countries a dot (.) is used to separate the fractional part of a number, while in some European countries a comma (,) is used instead. Below is a short summary of functions that will help you format the numbers correctly, taking the local conventions into account for you.

Functions to Format Numbers
Formats a.. From a.. Function Prototype
Number String
QString formatNumber( const QString & numStr )
Number Integer, double
formatNumber( double num, 
              int precision = -1 )
Money String
formatMoney( const QString & numStr )
Money Number
formatMoney( double num, 
             const QString & currency,
             int digits = -1 )
Date String
formatDate( const QDate & pDate,
            bool shortFormat=false )
Time QTime
formatTime( const QTime & pTime, 
            bool includeSecs=false)
Date and time QDateTime
formatDateTime( const QDateTime &pDateTime,
                bool shortFormat = true,
                bool includeSecs = false )

Similar functions exist to read information provided by the user at runtime in their localized format, e.g. readNumber() or readMoney().

Calendaring

Developing applications dealing with dates and time, such as calendars, is a very complex area. Not only may the displayed string containing a date or time look different based on locale, but one also has to take care of other aspects such as:

  • what calendar system is being used (e.g. Hebrew, Hijri)
  • which day in the week is the first one (cf int weekStartDay())
  • how many months in a year there are
  • "era"-based calendars
  • whether to use 24-hour time format (cf bool use12Clock())

QDate only implements a hybrid Julian/Gregorian calendar system, if the user's locale has a different calendar system then any direct calls to QDate will result in incorrect dates being read and displayed, and incorrect date maths being performed. All date calculations and formatting must be performed through the KLocale and KCalendarSystem methods which provide a full set of methods matching those available in QDate. The current locale calendar system can be accessed via KGlobal::locale()->calendar(). The KLocale date formatting methods will always point to the current global calendar system.

KLocale provides, among others, these methods:

Calendar Data Functions
Formats a.. From a.. Function Prototype
Date QDate
formatDate( const QDate & pDate,
            bool shortFormat=false )
Time QTime
formatTime( const QTime & pTime,
            bool includeSecs=false )
Date and time QDateTime
formatDateTime( const QDateTime &pDateTime,
                bool shortFormat=true,
                bool includeSecs=false )
Warning
This section needs improvements: Please help us to

cleanup confusing sections and fix sections which contain a todo


provide more info on the different calendar systems

QML

To make QML code translatable, KDeclarative provides the same i18n() calls described above. To enable parsing at runtime, you need to install a KDeclarative object in the QQmlEngine:

KDeclarative kdeclarative;
//view refers to the QQmlView
kdeclarative.setDeclarativeEngine(view.engine());
kdeclarative.initialize();
//binds things like kconfig and icons
kdeclarative.setupBindings();

The application also needs to link to libkdeclarative.

If you don't need the rest of features in KDeclarative, you can use ki18n right away:

    engine.rootContext()->setContextObject(new KLocalizedContext(&engine));

Avoiding Common Traps

There are a number of common problems that may prevent an application being properly localized. See Avoiding Common Localization Pitfalls to learn more about them, and how to avoid them.

Note
Thanks to Lukáš Tinkl, Matthias Kiefer and Gary Cramblitt for writing the original version of this tutorial.
-- gandalf

thanks, i used a few of the interesting stats you collected there

-- aseigo

Concerning the 'Plural' section: Should it not be i18np("%1 file was deleted", "%1 files were deleted", numFilesDeleted); because otherwise the singular form can not be used for values like 21,31,etc?

-- mghansen256

Translators can use %1 (more precisely, the placeholder of the plural-deciding argument) in all msgstr fields, no matter whether the English singular contains it.

Ilic 11:28, 11 January 2010 (UTC)

Avoiding Common Localization Pitfalls
Tutorial Series   Localization
Previous   Writing Applications With Localization in Mind
What's Next   Incorporating i18n Into the Build System
Further Reading   n/a

Abstract

There are a few common pitfalls that prevent applications from being properly translated or otherwise localized. These include using pixel based layouts, "word puzzles" and writing code that does not deal with Unicode characters properly. This tutorial covers each of these issues, explaining what to avoid and how to do it properly.


Pitfall #1: Pixel Based Layouts

English text is often very compact compared to other languages where the translated text is often substantially longer. Therefore the interface must be able to adjust the size to accommodate the length of translations provided at runtime. If it can't do this, then messages will end up misaligned and truncated.

The answer is to use layout managers. Qt provides a number of such layout managers pre-made for you. They include QHBoxLayout, QVBoxLayout, QGridLayout and QStackedLayout, all of which are subclasses of QLayout. You may also create your own QLayout based classes, but this is generally not needed.

These layout classes manage the pixel positioning of widgets for you at runtime, so no matter what the size of the translated strings your interface will adjust properly. For more information look at the documentation for QLayout.

Pitfall #2: Word Puzzles

Another thing to be aware of is to not concatenate pieces of sentences together like this:

QString msg=i18n("Do you want to replace ") + 
                 oldFile+i18n(" with ") + 
                 newFile + "?"

Such "word puzzles" are very hard or even impossible to translate. This is because the structure of the sentence will often be completely different in another language and thus must be controlled by the translator. When the order of words and phrases is hard-coded as in the above example, the translator can not create a proper translation.

Adding to this problem, a translator will only see parts of the sentence while translating and will have to guess at what belongs together.

The solution thankfully is quite simple: use %number placeholder substitution, which lets the translators not only make good translations because they can see the entirety of the sentence during translation, but which also lets them change the order of the arguments freely. The arguments themselves are passed as extra parameters to i18n().

The above example written properly would then look like this:

QString msg = i18n("Do you want to replace %1 with %2?",
                   oldFile, newFile)

It is a good idea to always explain what each %number placeholder means because in some languages the translation depends on what it contains. For example, prepositions might have to be replaced with a specific form of a noun that describes the placeholder's content. Thus it is important to know that %1 refers to a file and not to a folder or something else.

Thus it would be even better, if you wrote the example more explictly:

QString msg = i18n("Do you want to replace file %1 with file %2?",
                   oldFile, newFile)

Or like this:

QString msg = i18nc("%1 and %2 are file names", "Do you want to replace %1 with %2?",
                   oldFile, newFile)

It is also possible to use a comment above the message, but this isn't much used in KDE. Like this:

/* TRANSLATORS: Replacing an old file (%1) with a new one (%2). */
QString msg = i18n("Do you want to replace %1 with %2?",
                   oldFile, newFile)
Note
Avoid inserting anything other than numbers or nouns with this method, since in some languages the translation depends on the inserted words. It is, therefore, best to create strings that are as complete sentences as possible.


A related mistake is not including markup tags in rich text, such as <b></b> or <i></i>, in the translatable string. Not all languages use such markup in an identical fashion to English and so it is necessary for the translator to be able to "translate" the markup accordingly as well.

Similarly, messages that contain a version string or other often changing parts should be inserted by placeholders into the message. This prevents unnecessary changes that cause the translators to have to change the translated messages as well.

Since KDE is translated into more than 65 languages a single string change causes at least 65 people to open the file, find the changed message, look carefully if this is the only thing that has changed, change the translation, save the file again and commit the changed file into the code repository. All in all such a small change might create hours of work which could be easily avoided.

Pitfall #3: Lack of Unicode Support

Whenever there is source code that handles strings using a datatype (such as char) or class (such as std::string) that can not handle Unicode, translations will break.

To avoid this, never call QString::latin1() or QString::ascii() on translated strings. This also applies to information resulting from user input such as passwords, URLs and filenames. If you really need a plain char* representation of a string, it is better to use QString::utf8().

Note
For more information on character sets and Unicode, see the Unicode tutorial.


KIO slaves may also provide paths and file names encoded using UTF-8. It is up to the programmer, however, to take care of passing properly encoded filenames to any KIO method in question. The correct way to do this is not to guess at user's filesystem encoding but to use QFile::encodeName() and QFile::decodeName() instead.

Tip
You can turn KIO's UTF-8 file name support on for testing by exporting the KDE_UTF8_FILENAMES environment variable in your shell's startup file (e.g. ~/.bashrc).


Pitfall #4: Complex Text Flow

When designing an application that needs non-standard text flow, don't assume that the same rules apply to all languages. Given vertical writing, as an example, East-Asian languages using Chinese characters have a long history of vertical writing, even longer than horizontal. Strings are not rotated by 90 degrees but instead, single characters are placed under one another. There might be just a different behavior with different scripts. Expect the need to implement specialized versions.

Success!

If you avoid the four common categories of pitfalls detailed in this tutorial, your application should be fully localizable by the various KDE translation teams around the world and open up your application to the majority of people on the planet.

Building KDE's l10n Module
Tutorial Series   Localization
Previous   Writing Applications With Localization in Mind
What's Next   Dealing with language changes
Further Reading   n/a

Abstract

Now that your application is ready to be localized, we next look at how to incorporate the necessary mechanisms into the CMake build system of your application.

First we'll explain the "theory" of the steps that need to happen from extracting message strings to installing the generated .po files. After that we'll look at how to implement those steps (#Theory: The xgettext toolchain). If your application is developed in KDE's repositories, many of those steps will happen automatically (see #Handling i18n in KDE's repositories). Else you will want to read on in the #Handling i18n outside KDE's repositories section.

Theory: The xgettext toolchain

Making translations work consists of the following steps:

  1. Extract the translatable strings
  2. Merge the new or changed strings with existing translations
  3. Compile the translations into message catalogs
  4. Install the message catalogs
  5. Use the message catalogs in the application

Extracting the strings

In this step, all the strings you marked as i18n()/ki18n()/etc. in your sources need to be collected into a translation template (.pot) file. Some translateable strings are also contained in .ui, .rc, or .kcfg files. Also tips-of-the-day need to be collected into the .pot file.

These steps are handled by xgettext, extractrc, and preparetips programs, respectively. In some cases you may also need extractattr.

Merging translations

Generally, only a few translatable string will change at a time, in an application. Some will be removed, some will be added, some will be changed into different strings, and some will be moved around in the source files. These changes need to be reflected in the translations, but of course it would be a huge effort to redo the entire translation every time a string was changed. Rather the changes should be merged with the existing translations. This is the job of the msgmerge tool.

Compiling the translations

In order to make message lookup fast, the .po files need to be compiled into so-called "message catalogs" (.mo / .gmo). This is done using the msgfmt tool.

Installing the message catalogs

The compiled message catalogs need to be installed alongside the application. In KDE, the standard location for message catalogs is $DATAROOTDIR/locale/xx/LC_MESSAGES/.

Using the message catalogs

Finally, when the application is run, it needs to load the appropriate message catalog in order to be able to look up and show translated strings. In KDE applications, this is the job of the KLocale class, and in the great majority of cases happens automatically.

For some special cases, such as plugins, look at #Runtime Loading Of Catalogs.

Handling i18n in KDE's repositories

If your application is developed inside KDE's repositories, most of the steps outlined above are automated. In this case, generally, all you will need to do is provide a simple script called Messages.sh, which we will look at below.

Of course, for the curious, a more detailed account of what happens behind the scenes is also provided.

Writing a Messages.sh script

Basically, the only thing that is necessary to prepare and install translations for applications in KDE's repositories, is to provide information, which sources, ui-files or tips need to be translated. For this purpose, you write a small script called Messages.sh and place it in your sources. Here is an example with inline comments:

#!/bin/sh

# invoke the extractrc script on all .ui, .rc, and .kcfg files in the sources
# the results are stored in a pseudo .cpp file to be picked up by xgettext.
$EXTRACTRC `find . -name \*.rc -o -name \*.ui -o -name \*.kcfg` >> rc.cpp
# invoke the grantlee extract script for translatable string from Grantlee themes
$EXTRACT_GRANTLEE_TEMPLATE_STRINGS `find . -name \*.html` >> html.cpp
# if your application contains tips-of-the-day, call preparetips as well.
$PREPARETIPS > tips.cpp
# call xgettext on all source files. If your sources have other filename
# extensions besides .cc, .cpp, and .h, just add them in the find call.
$XGETTEXT `find . -name \*.cc -o -name \*.cpp -o -name \*.h -name \*.qml` -o $podir/APPNAME.pot

As you can see, this script contains only four actual lines of code, and not all may even be needed. The $XGETTEXT, $PREPARETIPS, $EXTRACTRC, $EXTRACT_GRANTLEE_TEMPLATE_STRINGS and $podir environment variables are predefined, you do not need to worry about setting these. The only thing that you will need to do is to replace "APPNAME" with the name of your application (but see #Naming .pot Files for exceptions).

  • $XGETTEXT - Extract i18n translatable strings from C++ files
  • $EXTRACT_TR_STRINGS - Extract Qt tr translatable strings from C++ files for Qt5-based projects
  • $EXTRACTRC - Extract translatable strings from xml configuration and ui files.
  • $EXTRACT_GRANTLEE_TEMPLATE_STRINGS - Extract translatable strings from Grantlee template files.

Try to make sure your Messages.sh script collects only those messages that are really needed. If in doubt, look at other Messages.sh files in the KDE repositories for inspiration, or -- of course -- ask.

Testing your Messages.sh script

To test your Messages.sh script, you need a checkout of the l10n scripts. To get one:

   git clone [email protected]:sysadmin/l10n-scripty.git

You can then go to your project dir and run:

   mkdir po
   mkdir enpo # only needed if $EXTRACT_TR_STRINGS is used in any Messages.sh file
   PATH=/path/to/scripts:$PATH bash /path/to/scripts/extract-messages.sh

When it is done, the po/ dir should contain the generated .pot files.

Translating .desktop Files

You don't need to do anything to get the common fields (See #What's happening behind the scenes for a list) of .desktop or .desktop.cmake files translated.

If you have a file with the same syntax than a .desktop file but it has a different extension, you have to create an ExtraDesktop.sh file that outputs the path of those files

#! /bin/sh
find -name *desktop.in -print

Translating .json files

You don't need to do anything to get the common fields (Name, Description, Copyright, ExtraInformation, Authors) for your .json files that belong to a KPlugin.

If you want to have extra fields (inside the KPlugin JSON object) from those .json files translated you can create a file named extraJsonTranslationKeys.txt in the top-level folder of the repository and write the keys of those fields in separate lines.

Translating Mimetype descriptions

Add a file named XmlMessages.sh to the folder with your mimetype XML foo.xml with this content:

function get_files
{
    echo foo.xml
}
function po_for_file
{
    case "$1" in
       foo.xml)
           echo foo_xml_mimetypes.po
       ;;
    esac
}
function tags_for_file
{
    case "$1" in
      foo.xml)
           echo comment
       ;;
    esac
}

What's happening behind the scenes

Tip
If your application is in the KDE code repository, all this happens automatically. If your code is not in the KDE repository, you must perform these steps yourself. See #Handling i18n outside KDE's repositories.


Periodically, the script extract-messages.sh (a.k.a. scripty) runs on the KDE server. This program basically calls all Messages.sh scripts in the repository with the appropriate parameters. The extracted messages are stored in template (.pot) files in the templates folder of the l10n module. See What Is Scripty for more information.

The KDE translation teams translate the messages and commit them into a messages folder corresponding to the language, which is further broken down by module. For example, German translated messages for konqueror are committed to l10n/de/messages/applications/konqueror.po.

When the l10n module is built, the .po files are compiled into a binary format for fast lookup and installed as .mo files to $DATAROOTDIR/locale/xx/LC_MESSAGES/, where xx is the two-letter ISO 639 code for the language. These are called the message catalogs.

At runtime, the i18n(...) function, using the original string you coded, looks up the string in the message catalog of the user's desktop language and returns the translated string. If the message catalog is missing, or the specific string is not found, i18n(...) falls back to the original string in your code.

.desktop files in your project are handled separately. makemessages extracts strings, such as Name and Comment from the .desktop files and places them into a file named desktop_mmmm.pot, where mmmm is the module name, in the templates folder. Once translators have translated this file, makemessages inserts the translated strings back into the .desktop files. The list of strings extracted is in l10n/scripts/apply.cc. Here's the code that checks for them:

if (checkTag("Name", in, argc, argv, newFile))
    continue;
if (checkTag("Comment", in, argc, argv, newFile))
    continue;
if (checkTag("Language", in, argc, argv, newFile))
    continue;
if (checkTag("Keywords", in, argc, argv, newFile))
    continue;
if (checkTag("About", in, argc, argv, newFile))
    continue;
if (checkTag("Description", in, argc, argv, newFile))
    continue;
if (checkTag("GenericName", in, argc, argv, newFile))
    continue;
if (checkTag("Query", in, argc, argv, newFile))
    continue;
if (checkTag("ExtraNames", in, argc, argv, newFile))
    continue;

KI18n

KI18n is the framework most used in applications made by KDE (you can also use the Qt translation system though it's not recommented, see #Qt5-only: Code using Qt translation system

It has a very comprehensive documentation that you can read at https://api.kde.org/frameworks/ki18n/html/prg_guide.html

Special cases (plugins, multiple catalogs, etc.)

Declarative plasmoids

For plasmoids written in pure qml, the .pot file must be named the same as its plugin name (with plasma_applet_ prefix), specified in its desktop file as X-KDE-PluginInfo-Name. For instance if we have X-KDE-PluginInfo-Name=org.kde.active.activityscreen the .pot file will be called plasma_applet_org.kde.active.activityscreen.pot.

If the qml files are developed in the form of package instead of an autonomous plasmoid (for instance a package loaded by a C++ plasmoid) the .pot file will have the prefix plasma_package_ instead.

Akonadi Agents

Akonadi agents get the catalog loaded based on the name of the binary, so your .pot file should be named the same way your binary adding .pot at the end You can check that in AgentBase::parseArguments in kdepimlibs

Qt5-only: Code using Qt translation system

Some Qt5-based applications and libraries use the Qt translation system instead of KI18n. Examples of such code are:

  • Tier 1 KF5 frameworks because they cannot depend on KI18n.
  • Applications which provide a Qt-only version.

To make translators aware of this distinction, your .pot file should follow these naming schemes:

  • *.po: code using gettext with KDE translation extensions. .po files are compiled into .mo files (most common case).
  • *_qt.po: code using Qt translation system. The .po files are compiled into .qm files (some KF5 frameworks, applications providing a Qt-only version).
  • *_qt-mo.po: code using pure gettext. The .po files are compiled into .mo files (legacy).


If you are using the Qt translation system you have to make sure the translations are loaded properly in your application at runtime. For that you can use ECMPoQmTools by adding this to your CMakeLists.txt:

include(ECMPoQmTools)

ecm_create_qm_loader(mybinaryname_QM_LOADER mypotfilename_qt)

set(my_project_SRCS
    ...
    ${mybinaryname_QM_LOADER})

Handbooks

Handbooks, which are written in docbook format, are handled different from applications. The translated Handbooks are committed into the l10n module in the docs folder under each language. In addition, the docs folder is broken down by module and application. For example, the German Kate Handbook is committed to the l10n-kf5/de/docs/applications/kate/ folder. When compiled, the German Kate Handbook is installed to $DATAROOTDIR/doc/HTML/de/kate/index.cache.bz2.

Note that it is up to each translation team to generate the translated Handbook when they feel it is complete.

Handling i18n outside KDE's repositories

There's a whole page dedicated to that in /Outside_KDE_repositories

Common i18n Challenges and Solutions
Tutorial Series   Localization
Previous   Writing Applications With Localization in Mind
Incorporating i18n Into the Build System
What's Next   n/a
Further Reading   n/a

Abstract

The localization process can, at times, be tricky. This tutorial covers challenges that you may eventually run into such as: translating handbooks and other data that exists outside of the source code, merging and handling obsolete .po files, dealing with freezes, coding in languages other than English and creating independent releases, or moving applications between KDE modules.

Note
The references to Makefile.am's needs to be ported to CMake.


Message Freezes

As a release date starts getting close, most software projects (including the KDE project) will freeze all changes to user visible strings. This allows translators a chance to do their work without it being constantly disrupted by changes to strings thereby wasting their efforts. If you change i18n strings in your application during such freezes it creates more work (and confusion) for the teams and could prevent your application from being released with translations.

Note
If your application is part of KDE that is periodically announced and released, you must pay attention to announcements on the mailing lists for message freezes. When a message freeze is in place, you must not change any of the translatable strings in your application or its Handbook.


If you find a GUI string that you feel must be fixed or added during a message freeze, ask your translation teams first. In the KDE project, that would be done by emailing the kde-i18n-doc list. Changing a string or adding a new one will not invalidate the entire translation, but annoys the translation teams who are trying to provide a complete and proper translation for your application.

Fixing Messages During A Freeze

It's message freeze time and you forgot to code with the i18n() function or forgot to include a file in the Makefile.am messages target, or you need to make some changes to existing strings. What should you do?

If you need to change an existing string, ask the translators first for permission first before you make the fixes. In KDE, that would be the kde-i18n-doc mailing list.

If you need to add untranslated strings due to forgotten i18n() or mistakes in the build system, go ahead and make the fixes. When you commit the fixes, write "untranslated strings" in the commit message so that translators will know why you are committing string changes during a message freeze. It is a good idea to email the translation teams to let the translators know that you've added additional strings.

Note
If the translator's don't have time to translate the additional strings, they will display in English at runtime.


It is considered a violation of the message freeze to add a brand new translated string to your code where the string did not exist untranslated before. So changing this:

QMessageBox::warning(0, "Starting KTTSD Failed", error );

to this:

QMessageBox::warning(0, i18n( "Starting KTTSD Failed"), error );

is OK, but adding the call to QMessageBox where it didn't exist before will raise objections from the translators.

In the latter case, ask on the kde-i18n-doc mailing list first. In general, the criteria for modifying or adding strings is a potentially severe misunderstanding of a message, especially if it means a risk of losing data.

Tip
You may see translators refer to "fuzzy" strings. Fuzzy strings come about when a string has already been translated and then is changed a little bit later. xgettext leaves the original translation in the .po file, but marks the string as fuzzy. The translator must look at the translation to determine if a change is needed and remove the fuzzy flag, otherwise the translation will not be used at runtime. In short, if you change strings in your app, they will generate fuzzies for the translators.


Handbooks

Handbooks especially should not be touched during a message freeze. This is because changing a Handbook (even a small change) can prevent the entire translated Handbook from being released. For this reason, you should watch the release cycle plans carefully and try to complete your Handbook at least 3 to 4 weeks before the message freeze.

If you do make a late change to a Handbook, it will be up to the translation team whether to apply the fix to their translation or not. If the team has already generated the translated Handbook, the uncorrected version may end up being released.

Freezes are often announced in two phases. A feature freeze means GUI string changes should not be made without first asking permission on the kde-i18n-doc mailing list. Handbook changes are OK at this time. A hard freeze means you must not make any more changes to code or to the Handbook.

If you find a Handbook string that you feel must be fixed or added during a freeze, ask first on the kde-doc-english mailing list. Changing the Handbook, even a tiny change, can invalidate the entire Handbook. Once a hard freeze is in place, fixes should be sent to kde-doc-english as patch files (svn diff). The fixes will not be translated, but they will be incorporated into the English-only version of the Handbook.

Questions about Handbook translation should be sent to the kde-doc-english mailing list.

Independent Releases

If your application is not part of an official KDE release cycle (e.g. it is in KDE Extra Gear or in an outside repository altogether), it will be up to you to plan releases and coordinate with the translation teams. When you want to do a release, send an email to the kde-i18n-doc mailing list with the following information:

  • The name of your application and its repository location.
  • Your planned message freeze date, the date after which you will not make any more changes that affect i18n strings.
  • Your planned code freeze date, the date after which no more changes except for severe bug fixes will be made.
  • Your planned release date.

You should provide at least 3 weeks between the message freeze date and release date - more if your application is large and complex. If your application has a Handbook, you should provide even more time.

It is a good idea to avoid time periods when KDE or KOffice are in message freeze, since the translators will be very busy at these times.

If you are distributing your code to translators via a source tarball, you should first ask for volunteers. Of course, the message freeze occurs when you send them the tarball. Your tarball must have all the .pot files and prepared po folders.

KDE Extra Gear Releases

Applications in the extragear module have a special procedure for handling translations. When an extragear application becomes stable (mostly at message freeze), the maintainer should copy the application to the appropriate extragear directory in branches/stable/extragear. In addition the whole set of translation template files (.pot) and translation files (.po), including eventual documentation, of the application must be copied to the appropriate places in branches/stable/l10n. This serves as a signal to translators that the application is ready for final translation work in preparation for release.

Translating UI, RC, and KCFG files

User visible strings usually origin not only from code files, but also from three other file types, ui, rc and kcfg files. UI files are the user interface descriptions, which are edited using QtDesigner. Here the text of labels and other ui elements are in need of localized versions. Likewise for the RC files, which are KXmlGui interface descriptions for embedded components. The KCFG files are the configuration data descriptions, which are used to automatically create configuration control code. While that is not related to the user interface, the same KCFG files are also used as the base for the generic runtime editing with KConfigEditor, so the parameter descriptions also need localized versions.

The strings are handled by the translation system by having them extracted by a program called extractrc, which creates a temporary code file that is than simply included by gettext. So extend the messages target in Makefile.am this way:

messages: rc.cpp
    $(EXTRACTRC) */*.kcfg >> rc.cpp
    $(EXTRACTRC) */*.ui >> rc.cpp
    $(EXTRACTRC) */*.rc >> rc.cpp
    $(XGETTEXT) rc.cpp */*.cpp */*.h -o $(podir)/my_program.pot

If there are strings translators need context information for, they can be supplied via context attribute in RC and KCFG files:

<text context="Create new cup of tea">&New...</text>
<label context="Fancy for mixture">Concoction</label>
<whatsthis context="A concoction">Not entirely unlike tea</whatsthis>

and in QtDesigner as the "disambiguation" property to text labels (or "comment" prior to Qt 4.5), which become comment attributes in the UI file itself.

Also, if that is more suitable, a parameter can be added to the call to extractrc by which the same context is provided to all strings extracted from the file. Example:

messages: rc.cpp
    $(EXTRACTRC) --context=my_context my_config.kcfg >> rc.cpp
    $(EXTRACTRC) --context=other_context */*.ui >> rc.cpp
    $(EXTRACTRC) --context=and_some_more */*.rc >> rc.cpp
    $(XGETTEXT) rc.cpp */*.cpp */*.h -o $(podir)/my_program.pot

Translating Data

If your application uses data that you want the translators to translate for you, there are a couple of solutions. If the data is a single string, and you want to use a translation of the string that is different from the user's desktop language setting, you can create a .desktop file and extract the translated string from it. For example, the KDE text-to-speech daemon (KTTSD) has the following kcmkttsd_testmessage.desktop file:

[Desktop Entry]
Encoding=UTF-8
NoDisplay=true
Name=The text-to-speech system seems to be functioning properly.

Notice the NoDisplay=true line. The translators will translate the Name line and scripty will insert the translations back into the .desktop file. At runtime, KTTSD uses the following code to get a test message to speak in the language of the synthesizer's voice, not the user's desktop language:

QString key = "Name[" + languageCode + "]";
QString result;
QString def;
QFile file(locate("data", "kttsd/kcmkttsd_testmessage.desktop"));
if (file.open(IO_ReadOnly))
{
  QTextStream stream(&file);
  stream.setEncoding(QTextStream::UnicodeUTF8);
  while ( !stream.atEnd() ) {
    QString line = stream.readLine(); // line of text excluding '\n'
    QStringList keyAndValue = QStringList::split("=", line);
    if (keyAndValue.count() == 2)
    {
      if (keyAndValue[0] == key)
      {
        result = keyAndValue[1];
        break;
      }
      // Use English default if not found.
      if (keyAndValue[0] == "Name") def = keyAndValue[1];
    }
  }
  file.close();
}
if (result.isEmpty()) {
  result = def;
}
return result;

If your program has larger amounts of data, an XML file is a good way to go. For example, KTTSD maintains a list of Festival synthesizer voices in an XML file called voices. Here's a sample portion from that file:

<?xml version="1.0" encoding="UTF-8"?>
<voices>
<voice>
  <syntaxhighlight lang="text">kal_diphone
 <language>en_US</language>
 <codec>ISO 8859-1</codec>
 <gender>male</gender>
 <name>American Male</name>

</voice> </syntaxhighlight>

Warning
This section needs improvements: Please help us to

cleanup confusing sections and fix sections which contain a todo


The Makefile.am extracts the name strings from this file like this:

messages: rc.cpp
    $(EXTRACTRC) */*.rc */*/*.rc >> rc.cpp
    $(EXTRACTRC) */*.ui */*/*.ui >> rc.cpp
    $(EXTRACTRC) --tag=name --context=FestivalVoiceName plugins/festivalint/voices >> rc.cpp
    $(XGETTEXT) rc.cpp */*.cpp */*.h */*/*.cpp */*/*.h -o $(podir)/kttsd.pot

Notice that the translators are given a context to help them to translate the voice names. At runtime, KTTSD parses the voices file and displays the translated name of each voice (in the user's desktop language) using code like this:

QDomNode childNode = node.namedItem("name");
if (!childNode.isNull())
  QString name = i18n("FestivalVoiceName", childNode.toElement().text().utf8());

Examining .po Files

You can look at the translated .po files to see if a string is present and has been translated. For example, here's a portion of l10n/de/messages/kdebase/konqueror.po:

#: konq_mainwindow.cc:3707 konq_tabs.cc:84
msgid "&New Tab"
msgstr "Neues &Unterfenster"

The string to be translated is given on the msgid line. The translated string is on the msgstr line. Notice that the exact same string to translate came from konq_mainwindow.cc and also from konq_tabs.cc. This saves the translators from having to translate the same identical string twice.

You can also use KBabel to examine .po files. KBabel is part of the kdesdk module.

Coding in a Foreign Language

If you are not comfortable with the English language, you may have coded your application using strings in your native language. You must convert all your code to English before it can be translated by the translation teams.

One solution is to get someone who understands both English and your language to help you with this. You can also ask for a volunteer on the kde-i18n-doc mailing list. You will create your .pot file (see Distributing message catalogs [*]) and send it to them. They will translate it to English and send you back a .po file. Using cut and paste, put the English strings into your code.

If you do this, it is still a good idea to have an English speaker review your code for any mistakes. You can use poreviewtool, a tool which makes the review of the English strings easier (relays also on .po files, but makes the handling much easier if you want to review continuously.)

Merging .po Files

If you made the mistake of creating a single .pot file for all the components in my application and the translators have already created the .po files what should you do so that no work (and translations) are lost ?

Correct your code and the build system. Commit the changes to the repository. Ask one of the KDE admins to merge the existing .po files. She will need to know the exact names of all the .po files, which module they are in, and the name of the desired merged .po file. The admin will have to wait for scripty to generate your new .pot file before doing the merge.

Deleting obsolete .pot files

If you change the build for you application so that it no longer generates a .pot file, or generates a .pot file with a different name, the old .pot file will not automatically disappear from the code repository.

You must delete it yourself from the templates folder in the l10n module. You should also send an email to the kde-i18n-doc mailing list advising translators that they may delete the .po file. If you do not do this, the translators will waste their time working on an obsolete file.

Handbook entity errors

Sometimes, when building Handbooks in the l10n/xx/docs folders, you may get entity errors. First of all, make sure your kdelibs/kdoctools folder is up-to-date and installed. If that doesn't fix the problem, it may be that the translator made an error, leaving an entity in the .docbook file that is defined in English but not in the translated language. In many cases, the translators haven't finished the translation. Contact the translation team.

For example, the English entity eg is defined in the kdelibs/kdoctools/customizations/en/user.entities file but is not defined in the German kdelibs/kdoctools/customizations/de/user.entities. It must be replaced by the translator with the entity zb (Zum Beispiel).

Building KDE's l10n Module
Tutorial Series   Localization
Previous   Using Subversion with KDE
Building KDE From Subversion
Writing Applications With Localization in Mind
What's Next   n/a
Further Reading   n/a


This page was outdated, please see https://community.kde.org/Guidelines_and_HOWTOs/Build_from_source and https://api.kde.org/frameworks/ki18n/html/index.html

Development Framework

  1. Desktop
  2. Hardware
  3. Communication
  4. User Interface
  5. Services

Frameworks in other KDE modules

KOffice 2.0

KParts is the name of the component framework for KDE. An individual component is called a KPart. As an example, Konsole is available as a KPart and is used in applications like Konqueror and Kate. Good examples about how KParts can be used are Konqueror, which (among other things) uses the KWord part to display documents, KMPlayer part to play multimedia, and Kontact, which embeds kdepim applications under one roof.

KParts also provide flexibility in your software selection. For example, the KHTML part which is by default used by Konqueror for HTML rendering can very easily be exchanged by a Webkit KPart.

Further reading

Dhaumann 14:23, 2 January 2007 (CET)

What benefits does ssh -X kde-devel@localhost have over su - kde-devel? The question is directed mainly at tstaerk. ;) Logixoul 00:54, 5 January 2007 (CET)

Using sux

Have you considered using sux instead of "ssh -X" or "su - kde-devel && export DISPLAY=:0 && xhost +localhost:kde-devel" I see it easier and more convient. Kebianizao 18:40, 7 July 2007 (CET)

$KDEDIR

IIRC, $KDEDIR is not used anymore for some weeks now. It's $KDEDIRS now. Right? --Dhaumann 19:35, 27 January 2007 (CET)

Yes, but as used in this tutorial it's just a regular environment variable used to fill in the $PREFIX in other env vars. Perhaps it should be renamed to $KDE_PREFIX or something? --Aseigo 00:55, 30 January 2007 (CET)
How about $KDEBASEDIR? --80.250.128.6 08:43, 30 January 2007 (CET)
Ah ok. Then let's keep KDEDIR, it's short and meaningful. --Dhaumann 09:29, 30 January 2007 (CET)

Xephyr

keyboard layout

Can a note be added on how to change the Xephyr keyboard layout? I tried several options already but always end up with the default qwerty layout :( --tbscope 15:06, 24 February 2007 (CET)

Start Xephyr with the +kb option which enables the xkb extension. Then choose your keyboard layout in KDE as usual (System Settings/Regional&Language/Keyboard Layout) --BenjieMouse 12:35, 19 July 2008 (CEST)


screen size

The default screen size for Xephyr is 640x480 which is not enough for using KDE. I propose adding the parameter -screen 1024x768x16 for example. --Kebianizao 19:45, 10 July 2007 (CET)

kdesdk

Wouldn't it be helpful, to post a hint, that the installation of kdesdk is very useful? --Lucas-r2d2 18:37, 3 May 2007 (CEST)

Well, probably yes (I don't use it myself). Please add it to the page (I'd say same level as KDevelop/KBugBuster/...). Explain how to install it (if that is much different from kdebase) and explain how to use the programs included there and why they are useful. Make sure there is no overlap with this page. TMG 17:16, 5 May 2007 (CEST)

kdevelop

I followed the chapter about kdevelop, nice work. Especially: - you tell the reader what to do - you tell him why to do this - your language is clear, e.g. "Now you should be able to start KDevelop by typing start3app kdevelop. Do that now."

I really like this tutorial and it worked for me. Thanks for the tutorial.

Problems

  • All menu items you name do not exist for me. I am using the latest kdevelop version from 3.5 branch, 3.3.5 (which is too minor according to you).
  • $KDE_SRC/KDE/kdelibs/kdelibs-apidocs/index.html does not exist for me. make apidox is not possible.

--Tstaerk 09:25, 21 December 2007 (CET)

Problem: Kdevelop codecompletetion for KDE libs

Having problems getting the codecompletion to work for kde. Qt4 works just fine.

Tried to tell the importer to import every file in /usr/include/KDE which it does, but codecompletetion won't work.

Do this problem have anything to do with the fact that KDE includes look like this (in this case /usr/include/KDE/KApplication):

#include "../kapplication.h"

Also tried to download the newest KDElibs (4.0.1), but the files in the "includes" dir looks exactly the same as those in /usr/include/KDE

I use a temporary solution: I import every k*.h file from /usr/include which seems to get most of the kde header files.

--90.228.193.140 10:52, 12 February 2008 (CET)

The includes in /usr/include/KDE are just forward includes, which the KDevelop parser does not understand. The real includes are indeed directly in /usr/include. I suggest telling KDevelop to parse the files in the kdelibs source directory, which usually is $KDE_SRC/KDE/kdelibs if you've followed the Techbase guide to build.
If you don't have the source, then I guess the only thing you can do is to import every k*.h file from /usr/include, but that will miss many files. --TMG 19:01, 12 February 2008 (CET)

The following list gives an overview of the library structure.

Libraries by name

kdecore
The kdecore library is the basic application framework for every KDE based program. It provides access to the configuration system, command line handling, icon loading and manipulation, some special kinds inter-process communication, file handling and various other utilities.
kdeui
The kdeui library provides many widgets and standard dialogs which Qt doesn't have or which have more features than their Qt counterparts. It also includes several widgets which are subclassed from Qt ones and are better integrated with the KDE desktop by respecting user preferences.
kio
The kio library contains facilities for asynchronous, network transparent I/O and access to mimetype handling. It also provides the KDE file dialog and its helper classes.
kjs
The kjs library provides an implementation of JavaScript.
khtml
The khtml library contains the KHTML part, a HTML browsing widget, DOM API and parser, including interfaces to Java and JavaScript.

Grouped Classes

Core application skeleton - classes needed by almost every application.* KApplication - initializes and controls a KDE application.


Configuration settings - access to KDE's hierarchical configuration database, global settings and application resources.* KConfig - provides access to KDE's configuration database.


File and URL handling - decoding of URLs, temporary files etc.

  • KURL - represents and parses URLs.* KTempFile - creates unique files for temporary data
  • KSaveFile - allows to save files atomically.


Interprocess communication - DCOP helper classes and subprocess invocation.* KProcess - invokes and controls child processes.

  • KShellProcess - invokes child processes via a shell.* PtyProcess - communication with a child process through a pseudo terminal.
  • KIPC - simple IPC mechanism using X11 ClientMessages.* DCOPClient - DCOP messaging.
  • KDCOPPropertyProxy - a proxy class publishing Qt properties through DCOP.* KDCOPActionProxy - a proxy class publishing a DCOP interface for actions.


Utility classes - memory management, regular expressions, string manipulation, random numbers * KRegExp - POSIX regular expression maching.


Keyboard accelerators - classes helping to establish consistent key bindings throughout the desktop.

  • KAccel - collection of keyboard shortcuts.* KStdAccel - easy access to the common keyboard shortcut keys.
  • KGlobalAccel - collection of system-wide keyboard shortcuts.


Image processing - icon loading and manipulating.

  • KIconLoader - loads icons in a theme-conforming way.* KIconTheme - helper classes for KIconLoader.
  • KPixmap - a pixmap class with extended dithering capabilities.* KPixmapEffect - pixmap effects like gradients and patterns.
  • KPixmapIO - fast QImage to QPixmap conversion.


Drag and Drop - drag objects for colors and URLs.


Auto-Completion


Widgets - widget classes for list views, rules, color selction etc.* KListView - a variant of QListView that honors KDE's system-wide settings.

  • KListBox - a variant of QListBox that honors KDE's system-wide settings.* KIconView - a variant of QIconView that honors KDE's system-wide settings.
  • KLineEdit - a variant of QLineEdit with completion support.* KComboBox - a variant of QComboBox with completion support.
  • KFontCombo - a combo box for selecting fonts.* KColorCombo - a combo box for selecting colors.
  • KColorButton - a button for selecting colors.* KURLCombo - a combo box for selecting file names and URLs.
  • KURLRequester - a line edit for selecting file names and URLs.* KRuler - a ruler widget.
  • KAnimWidget - animations.* KNumInput - a widget for inputting numbers.
  • KPasswordEdit - a widget for inputting passwords.

Dialogs - full-featured dialogs for file, color and font selection.* KFileDialog - a file selection dialog.


Actions and XML GUI

  • KAction - abstraction for an action that can be plugged into menu bars and tool bars.
  • KActionCollection - a set of actions.* KXMLGUIClient - a GUI fragment consisting of an action collection and a DOM tree representing their location in the GUI.
  • KPartManager - manages the activation of XMLGUI clients.


Plugins and Components


Initial Author: Bernd Gehrmann [email protected]

During the KDE 3 lifetime many classes and technologies were added, so that the list of classes may be outdated. Dhaumann 13:46, 3 January 2007 (CET)

KDE Architecture - Accessing Standard Resource Directories

Overview

KDE offers several ways to access the files that your application installed on your user's hard disc while making it transparent to you where the data really are. To allow the user (or adminstrator in most cases) to move files where he sees them fit best, KDE offers a list of different resource types for which a different search path is assigned to. You may have heard of the environment variable PATH to lookup executables or MANPATH for looking up man pages. You wouldn't expect man to lookup man pages in PATH.

Similiar to that concept KDE seperates search paths for different things to make it simpler to add paths for a specific resource without making a lookup for another resource unnecessary slower and without requiring you to put everything into one directory.

The types of resources KDE offers are

  • apps - applications menu (.desktop files)
  • cgi - CGIs to run from khelpcenter* config - configuration files
  • data - where applications store data* exe - executables installed privatly for KDE's use
  • html - HTML documentation* icon - application icons to appear in the window manager or the panel
  • lib - libraries and to be dlopened modules* locale - translation files for KLocale
  • mime - mime types* sound - application sounds
  • toolbar - toolbar pictures
  • wallpaper - wallpapers

For all of them exist also Makefile aliases that configures created by the development tools provided for KDE (e.g. kdevelop) will know about.

KStandardDirs

This is one of the most central classes in kdelibs as it provides a basic service: it knows where the files reside on the user's harddisk. And it's meant to be the only one that knows - to make the real location as transparent as possible to both the user and the applications.

For this it encapsulates all informations from the application and applications always refer to a file with a resource type (e.g. apps) and a filename (e.g. Home.desktop). In an ideal world the application would make no assumption where this file is and leaves it up to KStandardDirs::findResource("apps", "Home.desktop") to apply this knowledge.

The main idea behind KStandardDirs is that there are several toplevel prefixes where files are below. One of this prefixes is the one where the user installed kdelibs into, one where the application has been installed to and one is $HOME/.kde, but there may be even more. Under these prefixes there are several well defined suffixes where specific resource types are to be found. For example for toolbar icons that is share/toolbar and share/apps/<appname>/pics.

So the search algorithm basicly appends to each prefix each registered suffix and tries to locate the file there. To make the thing even more complex, it's also possible to register absolute paths that KStandardDirs looks up after not finding anything in the former steps. They can be useful if the user wants to provide specific directories that aren't in his $HOME/.kde directory as example for icons.

On the usage of locate and locateLocal

locate and locateLocal are both convenient functions that make the use of KStandardDirs as simple as possible. You have however the possibility to use the full power of KStandardDirs without them.

Typical KDE applications use resource files in one out of three ways:

  • A resource file is read but is never written. A system default is supplied but the user can override this default in his local .kde directory:
// Code example
myFile = locate("appdata", "groups.lst")
myData = myReadGroups(myFile);
  • A resource file is read and written. If the user has no local version of the file the system default is used. The resource file is always written to the users local .kde directory.
// Code example
myFile = locate("appdata", "groups.lst")
myData = myReadGroups(myFile);
...
doSomething(myData);
...
myFile = locateLocal("appdata", "groups.lst");
myWriteGroups(myFile, myData);
  • A resource file is read and written. No system default is used if the user has no local version of the file. The resource file is always written to the users local .kde directory.
// Code example
myFile = locateLocal("appdata", "groups.lst");
myData =  myReadGroups(myFile);
...
doSomething(myData);
...
myFile = locateLocal("appdata", "groups.lst");
myWriteGroups(myFile, myData);

Initial Author: Stephan Kulow ([email protected])

Loading and installing icons in KDE

Icons are an important user interface element in any desktop environment. Because of different user preferences and video hardware, one icon may come in different sizes and display depths. In order to make this manageable, a standard way of storing and accessing icons has been developed.

Loading icons

Accessing the iconloader

Icons are loaded using the class KIconLoader. Every KDE appliation has a global iconloader object. You can access this object with:

#include <kglobal.h>
#include <kiconloader.h>
 
KIconLoader *loader = KGlobal::iconLoader();

Loading icons with loadIcon

The iconloader loads icons, transparently caches them and applies effects. To load an icon, use the method loadIcon(), which is defined like this:

QPixmap loadIcon( QString name, int group, int size=0,
                  int state=KIcon::DefaultState, 
                  QString *path_store=0L, bool canReturnNull=false);

As you see, there are a lot of parameters. The first two are most important:

  1. name - The name of the icon to load. You must pass the bare icon name here, without extension.
  2. group - The icon group. This is explained below.

Icon groups

The idea of an icon group is an important concept in the KDE icon scheme. The icon group denotes where on the screen the icon is going to be used. This is relevant because the KDE user can bind icon sizes and visual effects to each group. When passing the icon group to the icon loader, you are in fact telling it which incarnation of the icon to load. And by requiring the group argument, the iconloader provides the means to have a consistent and configurable icon look over the whole KDE desktop.

For example: The user can configure that he wants 32 pixel icons with 0.2 desaturation for the main toolbars.

The available icon groups are given below. All are defined in the KIcon class, so prefix them with KIcon::.

  • Desktop - Icons for use on the desktop, in the filemanager and similar places.
  • Toolbar - Icon for in normal toolbars.
  • MainToolbar - Icons for in the main toolbar. An application can have multiple toolbars, of which one is allways the main toolbar. This typically has entries like "Save" and "Open" and contains larger icons than the other toolbars.
  • Small - Various small icons, like the ones in popup menus, listviews and treelists.
  • User - Special group for loading application specific icons. This is explained in section 3: Installing icons.

So, to load the icon "kfind" for use in the Desktop group, you'd use:

QPixmap icon;
icon = loader->loadIcon("kfind", KIcon::Desktop);

loadIcon continued

Now lets discuss the other parameters of loadIcon.

  1. size - Override the globally configured size for the specified icon group. Effects bound to the group are still applied.
  2. state - The icon state. The icon state is one of KIcon::DefaultState, KIcon::ActiveState or KIcon::DisabledState. The icon state denotes in which state the icon is. Toolbar buttons, for example, are in state active if the mouse pointer is above them, in state disabled when they are not available, and default otherwise. Each icon state can have different effects assigned to it to give the user visual feedback.
  3. path_store - If you want to know where the icon you just loaded is in the filesystem, you can pass a pointer to a QString here and the icon path is stored there.
  4. canReturnNull - If the requested icon is not found, the result of loadIcon depends on this parameter. If canReturnNull is true, a null pixmap will be returned, if not, the "unknown" icon is returned.

Installing icons

Icons may come in different sizes and display depths. I shall refer to these icons as themed icons. Icons that come in just one form are referred to as unthemed icons.

Default icon sizes

Themed icons come in different sizes and display depths. The standard sizes are:

40 Colors
16x16 pixels
22x22 pixels
32x32 pixels
Truecolor
22x22 pixels
32x32 pixels
48x48 pixels

Please refer to the KDE icon factory for information on which icon sizes are mandatory and more. Remember that each of these sizes can be bound to an icon group.

Icon context

Themed icons are stored in a directory hierarchy according to their 1. depth, 2. size and 3. context. The term context is new concept introduced by the KDE icon scheme. The context of an icon is what the icon means. The standard contexts are given below:

  • action - The icon represents an action in a toolbar, for example "Open" or "Save".
  • application - The icon represents an application, for example "kfind".
  • device - The icon represents something related to a device, for example "floppy" or "mount".
  • filesystem - The icon represents something in the filesystem, for example "directory", "socket" or "trashcan".
  • mimetype - The icon represents an mimetype, for example "text/html".

Contexts are important in one case: selecting an icon. When an application wants the user to select an icon for, say, a toolbar, it would be very user unfriendly to show every single icon installed in KDE. Instead, it is much better to let the user select an icon from the "action" icons only. These all represent some action and therefore are suitable for in toolbars.

Directory hierarchy

The directory hierarchy in which themed icons are stored follows. The directory names are self explanatory.

hicolor/
    22x22/
        actions/
        apps/
        devices/
        filesystems/
        mimetypes/
    32x32/
        ...
    48x48/
        ...

locolor/
    16x16/
        ...
    22x22/
        ...
    32x32/
        ...

Directory roots

Themed icons can be installed either globally with respect to KDE, or in application specific place. In the global case, the icon theme hierarchy resides under $KDEDIR/share/icons while in the application specific case, it is under $KDEDIR/share/apps/$APPNAME/icons.

Installing themed icons

The KDE source configuration system (specifically, am_edit) has support for installing themed icons. First, you have to name your icons in a way that it is clear where it must be installed. The naming convention is explained in the table below:

depth size - context - name .png
hi 16 action
lo 22 app
32 device
48 filesys
mime

Examples:

lo22-action-open.png
hi48-app-kfind.png

To install these icons globally, add this line to your Makefile.am.

KDE_ICON = open kfind

and to install them in an application specific directory, use this:

icondir = $(kde_datadir)/myapp/icons
icon_ICON = open kfind

Loading themed icons

Themed icons are loaded with the iconloader, using the standard icon groups. For example:

QPixmap pm;
pm = loader->loadIcon("kfind", KIcon::Desktop);

This will load the "kfind" icon, of depth and size specified for the Desktop group.

Unthemed icons

Unthemed icons are installed in $KDEDIR/share/apps/$APPNAME/pics. To install them, use this in you Makefile.am.

icondir = $(kde_datadir)/myapp/pics
icon_DATA = open kfind

You must not give the icons special names. Also, no further processing is done on them: no effects and size,depth selection is done.

Unthemed icons can be loaded with the iconloader using the User group. This will load a user icon:

QPixmap pm;
pm = loader->loadIcon("myicon", KIcon::User);

Conclusion

There are 3 ways to install icons: global themed, application specific themed and unthemed. All types of icons can be loaded with the iconloader. You should choose a specific installation depending on your needs.


Initial Author: Geert Jansen <[email protected]>

Sycoca - Introduction

Sycoca stands for System Configuration Cache and is nominated to be the successor of kregistry. It is a light weight database optimized for looking up static system configuration information fast and with minimal memory usage.

The database will offer read-only access to many clients at once. The database is read-only which means that looking up can be very fast since no locking or transaction operations need to be performed. The database is created/updated by kbuildsycoca from human readable configuration files. kded monitors these configuration files and will call kbuildsycoca to update the database when a change in any of the configuration files is detected.

Updating the database will mean that the database is replaced as a whole by a more up to date version. This approach allows a very straight forward database implementation. With Sycoca it will not be necessary any more to parse multiple files when looking for static system information. Instead Sycoca can return the requested information with a performance near to O(1). Examples of static system information are mimetype bindings and .desktop information (servicetypes). Application specific configuration information will _NOT_ be stored in Sycoca since this information is usually subject to regular change.

Using Sycoca in your application

Applications never use sycoca directly but always through classes provided by the KDE framework. The following classes use sycoca to obtain their information:

KImageIOFormat
Class that provides information about an image format that is supported by KDE. The correct way to access this information is through the KImageIO class.
KProtocolInfo
Class that provides information about a protocol supported by KDE. These protocols can be used in a URL and will map to an IO-slave that supports the protocol. Examples of protocols supported by KDE are "http", "ftp" and "pop3". The KProtocolInfo class provides information about the capabilities of a protocol. An example of a capability is whether the protocol can provide a list of entries similar to the contents of a directory.
KServiceGroup
Class that provides a (possibly nested) listing of services. Used for things like a hierarchy of applications (K-menu), hierarchy of settings (Control Center) or list of screensavers (screensaver setup in control center)
KService
Class that provides information about a service (or more specific about "applications"). A service is always described by a .desktop file. Such a file contains information like which icon to use for the service, how to start the service, the (translated) name of the service and (translated) comment which describes the service. See the Desktop Entry Standard for a description of .desktop files.
KServiceType
Mostly known due to one of its subclasses KMimeType. KServiceType describes a certain type of service that can be offered by a service. In the case of KMimeType the type of service is the ability to open a file of a specific format. A typical sequence of events, implemented by KRun, is to determine the mimetype of a file and then to search for a service that supports this mimetype. E.g. a file is examined and identified as a HTML file (mimetype text/html) based on this information, one or more services can be found that are able to open this file (for example konqueror, netscape and kwrite)

Sycoca class & responsibilities overview

KSycoca
  • Responsible for building Sycoca database. Factories need to register themselves to KSycoca.
  • Tells factories where to store their information.
  • Builds factory index.
KSycocaEntry
  • Abstract Base Class (ABC) for all information stored in Sycoca.
  • Has an id which is unique in the whole database.
  • Each subclass has a unique type-key which identifies the subclass.
  • Creates itself based on information from human readable config file.
  • Creates itself based on information stored in database.
  • Can find itself in the database based on its id. (because Id == offset)
  • Stores its information content in database.
  • Has static factory lookup-methods which dispatch to the responsible factory.
KSycocaFactory
  • Each factory has a unique type-key which identifies the factory.
  • Finds its own information in the database using the factory index.
  • Maintains a specific number of information types in the Sycoca database.
  • Identifies which human readable configuration files to use for creating which kind of KSycocaEntry's.
  • Builds fast lookup indices inside the database for the KSycocaEntry's managed by it.
  • Stores the KSycocaEntry's it maintains in the database.
  • Looks up information in the Sycoca database and recreates KSycocaEntry's to represent this information.

KSycocaDict

KSycocaDict offers a fast lookup-index based on string keys. Creation of the index is reasonably slow, but once the index has been created information can be found with a small number of steps nearly independent from the data size.

During creation KSycocaDict creates a hash-function and a hash-index which is populated for approximately 20% and which has a typical hash collision chance of 10%.

This means that existing objects can be found at once in 90% of the time. In the other 10% the collision list has to be searched. A collision list typically contains 2 entries.

Not existing objects have a chance of 20% to give a false hit. A hit should therefore always be verified by loading the actual object.

KSycocaDict is used by the KSycocaFactories to be able to create fast lookup functions for the objects it maintains.

Users of the Sycoca database

KServiceTypeFactory (subclass of KSycocaFactory)
  • Offers KServiceType lookup on name.
  • Offers KMimeType lookup on name (name == mimetype).
  • Offers KMimeType lookup on filetype (regexp match).
  • Offers KFolderType lookup (one instance only).
  • Offers KDEDesktopMimeType lookup (one instance only).
  • Offers KExecMimeType lookup (one instance only).
KServiceFactory (subclass of KSycocaFactory)
  • Offers KService lookup on name.
KProtocolInfoFactory (subclass of KSycocaFactory)
  • Offers KProtocolInfo lookup on name (name == protocol).
KImageIOFactory (subclass of KSycocaFactory)
  • Registers image-IO plugins and loads image-IO plugins when needed.
KServiceGroupFactory (subclass of KSycocaFactory)
  • Offers KServiceGroup lookup on path.


KServiceTypeFactory is repsonsible for the following classes:

  • KServiceType (subclass of KSycocaEntry)
  • KMimeType (subclass of KServiceType)
  • KFolderType (subclass of KMimeType)
  • KDEDesktopMimeType (subclass of KMimeType)
  • KExecMimeType (subclass of KMimeType)


KServiceFactory is responsible for the following classes:

  • KService (subclass of KSycocaEntry)


Implementation notes:

  • To speed up the dereferencing of relations between KSycocaEntries of various kinds, the id of the KSycocaEntry should be used to store these references.
  • When e.g. KMimeType creates itself based on the database and its Id it should check that the information labeled with this Id in the database, does indeed belong to a KMimeType type of object. (Watch out with multiple inheritance!)


Initial Author: Waldo Bastian [email protected]

Warning
The subject matter that I was going to cover in this tutorial is already covered in Development/Tutorials/KConfig and so this tutorial will probably be removed.


Abstract

Author: Fabian Korak

Author: Matt Williams(presets)

In this tutorial, we're going to be showing you how to utilise KConfig XT in an application. It is recommended that you read Development/Tutorials/Using KConfig XT before continuing in order to familiarise yourself with the framework.

Prerequisites

KConfig XT

At first we make new File called tutorial4.kcfg within the source directory of your project.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE kcfg SYSTEM "http://www.kde.org/standards/kcfg/1.0/kcfg.xsd">
<kcfg>
	<kcfgfile name="kjotsrc"/>
	<include>kglobalsettings.h</include>
	<group name="kjots">
		<entry name="showAction" type="Bool">
			<label>Whether setupAction is called</label>
			<default>true</default>
		</entry>
	</group>
</kcfg>

This code makes a setting of the type bool, which determines whether we want to do something. Then we set the default value to be true.

Always start the value of <entry name=""> in lower case since KConfig XT sets them to lower case within the generated headers either way. If you don't this could give you some nearly untraceable errors

Now we make a new File called tutorial4.kcfgc.

File=tutorial4.kcfg
ClassName=tutorial4
Singleton=true
Mutators=true

This should set up your configuration for now.

The Code

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <KXmlGuiWindow>
#include <KTextEdit>


class MainWindow : public KXmlGuiWindow
{

	public:
		MainWindow(QWidget *parent=0);
	private:
		KTextEdit* textArea;
		void setupActions();
		void setupConfig();
		void readConfig();
		void saveSettings();
		int m_showAction;

};

#endif

There are some new voids in here, as well as m_showAction witch determines the value stored in KConfig XT. Despite that value being a bool we can actually use an integer here, since the type is converted either way.

mainwindow.cpp

#include "mainwindow.h"
#include "tutorial4.h"

#include <KApplication>
#include <KAction>
#include <KLocale>
#include <KActionCollection>
#include <KStandardAction>
#include <KConfigDialog>

MainWindow::MainWindow(QWidget *parent) : KXmlGuiWindow(parent)
{

	textArea = new KTextEdit;
	setCentralWidget(textArea);
	setupConfig();
}

void MainWindow::setupActions()
{

	QAction* clearAction = actionCollection()->addAction( "clear" );
	
	clearAction->setText(i18n("Clear"));
	clearAction->setIcon(KIcon("filenew"));
	clearAction->setShortcut(Qt::CTRL+ Qt::Key_W);
			
	connect(clearAction, SIGNAL(triggered(bool)), textArea, SLOT(clear()));

	KStandardAction::quit(kapp, SLOT(quit()), actionCollection());
	
	setupGUI();

}

void MainWindow::setupConfig()
{
	readConfig();	
	
	
}

void MainWindow::readConfig() {
	m_showAction    = tutorial4::showAction();
	if(m_showAction = (true)) 
		setupActions();
	
}

void MainWindow::saveSettings() { 
	tutorial4::setShowAction(m_showAction);
	tutorial4::self()->writeConfig();
}

At first we import "tutorial4.h", which should be auto-generated at runtime by KConfig XT every time you compile this. MainWindow and SetupActions are copied from the tutorials before. The only thing new is that we now call a new void called setupConfig. This then calls readConfig. We could also call saveSettings(but only after we called readConfig), but since we don't change any values there this is more of a "proof of concept".

Within readConfig we assign m_showAction the value of the setting showAction. If this returns true setupsActions makes buttons and all that. When false it doesn't.

The setShowActions() in saveSettings() overwrites showAction with a value of your choice, in this case with itself. Then you need to call writeConfig() to apply the changes you made.

main.cpp

#include "mainwindow.h"


#include <KApplication>
#include <KAboutData>
#include <KCmdLineArgs>
 
int main (int argc, char *argv[])
{
	KAboutData aboutData( "tutorial4", "tutorial4",
			      "0.4", "KMessageBox popup",
	 KAboutData::License_GPL, "(c) 2007" );
	KCmdLineArgs::init( argc, argv, &aboutData );
	
	KApplication app;
	
	MainWindow* window = new MainWindow();
	window->show();
	
	return app.exec();

}

No news in here

tutorial4ui.rc

<?xml version="1.0" encoding="UTF-8"?>
<gui name="tutorial4"
     version="1"
     xmlns="http://www.kde.org/standards/kxmlgui/1.0"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://www.kde.org/standards/kxmlgui/1.0
                         http://www.kde.org/standards/kxmlgui/1.0/kxmlgui.xsd" >

  <MenuBar>
    <Menu name="file" >
      <text>&amp;File</text>
      <Action name="clear" />
    </Menu>
  </MenuBar>

  <ToolBar name="mainToolBar" >
    <text>Main Toolbar</text>
    <Action name="clear" />
  </ToolBar>

</gui>

CMake

CMakeLists.txt

PROJECT(tutorial4)

FIND_PACKAGE(KDE4 REQUIRED)
INCLUDE_DIRECTORIES( ${KDE4_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR})

SET(tutorial4_SRCS 
  main.cpp
  mainwindow.cpp
)

KDE4_ADD_KCFG_FILES(tutorial4_SRCS settings.kcfgc)

KDE4_ADD_EXECUTABLE(tutorial4 ${tutorial4_SRCS})

TARGET_LINK_LIBRARIES( tutorial4 ${KDE4_KDEUI_LIBS})

install( TARGETS tutorial4 DESTINATION ${BIN_INSTALL_DIR})
install( FILES tutorial4ui.rc DESTINATION  ${DATA_INSTALL_DIR}/tutorial4)
install( FILES tutorial4.kcfg  DESTINATION  ${KCFG_INSTALL_DIR} )

Moving On

For a better understanding of the XML used in KConfig XT you could try to write an Xml Parser

  • Development/Tutorials/First programAdding authors to wiki pages seems counterintuitive to me. The wiki is editable by everybody. Why does it matter who the author of a tutorial is? IMHO the only thing that matters is that the tutorial is kept up to date. --Mattr 03:31, 4 January 2007 (CET)
I agree with Matt. I usually add a Initial Author: at the bottom for pages from the old developer wiki code, because they wrote it with often no explicit copyright information. See also this page --Dhaumann 17:36, 4 January 2007 (CET)

‘ki18n’ was not declared in this scope

I don't know if this is the place to post this, but I tried to follow this tutorial and get an "error: ‘ki18n’ was not declared in this scope", when trying to compile using the big command gcc main.cpp ...

Well I change a little the code so it now compiles under KDE4, it seems that the constructor of KAboutDate was changed...

Build

Does the g++ command work for you as described? I needed to add -lQtXml, lQtSvg and lQtNetwork.

I'm getting a 'huge' string of error messages in the underlying include/ files, things like

include/KDE/../kmessagebox.h:1128: error: expected constructor, destructor, or type conversion before ‘(’ token but hundreds, possibly thousands of errors apparently affecting nearly every header.

I personally haven't tried the g++ method, that was added by someone else. Does linking against those libraries fix the errors? Does it work for you with the cmake method? --milliams 20:47, 25 January 2008 (CET)
Thanks you, Milliams, it complies with cmake. I copied the g++ instructions, including the additional options, straight from the page and still no joy.

Make and run before explaining the code

As far as I can see,

it presents the code,
explains it, 
shows how to build with g++ (without cmake), 
building with cmake, 
finally running it

Well, I would prefer it to present code and run it (with no explaining), like to a monkey. After showing it works, explaining why it works or how it works. I would find that much more fun this way. Got any ideas why it should not be that way? --Bogdan Bivolaru

The constructor of KAboutData has changed

...or maybe not, I don't know, but in the API doc it is defined with the last two arguments as QByteArray datatype. I was translating this tutorial in italian and, in order to solve this problem, I'd added QByteArray("string...") to the homepage and bugs mail arguments in the main.cpp code (with the right #include of course). Now it build and run like a charm. Maybe it is needed to propagate this little mod over all the tutorial serie? --Fresbeeplayer 12:18, 28 November 2008 (UTC)


How KApplication object has been used

The tutorial creates KApplication object 'app'. But this object has not been used in the program. When I tried compiling after commenting the line 'KApplication app', it gave an error saying I should create a KApplicaion object before I can create other windows. Can some one explain me what is the black magic it is doing there?

This page mentions dcop and I guess it's possible servicemenus will change for Konqueror4. Aaron, I don't know if you want to keep this page intact (as a KDE3 tutorial) and create a separate KDE4 specific one or to rather mention inline what's K3 or K4 specific? --milliams 14:31, 5 January 2007 (CET)

  • JavaTutorials or technology pages that are of relevance to Java programmers
  • JavaScriptTutorials or technology pages that are of relevance to JavaScript (ECMAScript) programmers
  • CSharpTutorials or technology pages that are of relevance to C# programmers
  • FAQsFrequently Asked Questions
  • Build KDEInformation about how to build and run KDE
  • Development== Thumbnail error here ==

Error creating thumbnail: /srv/www/mediawiki/mediawiki_src/bin/ulimit4.sh: line 4: /usr/bin/qsvg-convert: No such file or directory

  • DocumentationPages which are about writing docbook/apidox or are about finding and using apidox. Don't go tagging every page with this category (since obviously the whole wiki is 'documentation' of sorts).

See also

I put this page in Category:Programming rather than Category:C++ because I didn't want to limit its scope too much. It's probably information that all KDE devs should know.

Maybe we should have a internationalisation/localisation type category? Or maybe there aren't enough pages to warrant it?

I'm leaving this page out of the Category:Programming since there's no code here. Any thoughts?

See also: Talk:Development/Tutorials/Localization/Unicode --milliams 18:23, 5 January 2007 (CET)

What about a group 'Localization' or 'Translation' or 'Internationlaization'? --Dhaumann 18:51, 5 January 2007 (CET)

Language bar

It looks like language navigation bar does not work here due to an apostrophe in tile word "KDE's", I think. Is there any way to workaround this problem? --Centerlink 12:10, 30 October 2009 (EET)

How much free disk space is currently needed to set up, build and run a kde4 base environment? Could you please post some rough figures? --62.47.151.217 18:36, 5 January 2007 (CET)

For me, kdelibs sources ~= 100MB, kdebase sources ~= 100MB, qt installed ~= 300MB and my installed kde4 directory ~= 2GB (though I do have every module installed :S) --milliams 18:44, 5 January 2007 (CET)

Can't connect to anonsvn

When I try to do an SVN checkout, I get this error: svn: Can't connect to host 'anonsvn.kde.org': Connection refused any time I try any svn-related work. Anyone understand why? Ben::zen 04:38, 24 September 2007 (CEST)

Never mind, I just didn't read far enough... Ben::zen 04:41, 24 September 2007 (CEST)
Okay, I'm getting a server timeout on websvn.kde.org:443. What am I doing wrong/not doing, or is the server really having problems? Ben::zen 05:16, 24 September 2007 (CEST)
I now find out that Kubuntu has the packages precompiled... oh well. Ben::zen 05:26, 24 September 2007 (CEST)

Interesting places in this wiki

Bhards 04:09, 6 January 2007 (CET)

Yes, I believe it should. I categorised it "KDE4" but I didn't use the {{KDE4}} template because I think it's too obtrusive and so get in the way unless it's at the bottom of the page (where it never gets seen). --milliams 14:13, 6 January 2007 (CET)
  • Development/Architecture/KDE3/Low-level GraphicsQt's low level imaging model is based on the capabilities provided by X11 and other windowing systems for which Qt ports exist. But it also extends these by implementing additional features such as arbitrary affine transformations for text and pixmaps.

Rendering with QPainter

The central graphics class for 2D painting with Qt is QPainter. It can draw on a QPaintDevice. There are three possible paint devices implemented: One is QWidget which represents a widget on the screen. The second is QPrinter which represents a printer and produces Postscript output. The third it the class QPicture which records paint commands and can save them on disk and play them back later. A possible storage format for paint commands is the W3C standard SVG.

So, it is possible to reuse the rendering code you use for displaying a widget for printing, with the same features supported. Of course, in practice, the code is used in a slightly different context. Drawing on a widget is almost exclusively done in the paintEvent() method of a widget class.

void FooWidget::paintEvent()
{
    QPainter p(this);
    // Setup painter
    // Use painter
}

When drawing on a printer, you have to make sure to use QPrinter::newPage() to finish with a page and begin a new one - something that naturally is not relevant for painting widgets. Also, when printing, you may want to use the device metrics in order to compute coordinates.

Transformations

By default, when using the QPainter, it draws in the natural coordinate system of the device used. This means, if you draw a line along the horizontal axis with a length of 10 units, it will be painted as a horizontal line on the screen with a length of 10 pixels. However, QPainter can apply arbitrary affine transformations before actually rendering shapes and curves. An affine transformation maps the x and y coordinates linearly into x' and y' according to


Formula for affine transformation

The 3x3 matrix in this equation can be set with QPainter::setWorldMatrix() and is of type QWMatrix. Normally, this is the identity matrix, i.e. m11 and m22 are one, and the other parameters are zero. There are basically three different groups of transformations:

  • Translations: These move all points of an object by a fixed amount in some direction. A translation matrix can be obtained by calling method m.translate(dx, dy) for a QWMatrix. This corresponds to the matrix


Formula for translating transformation

  • Scaling: These stretch or shrink the coordinates of an object, making it bigger or smaller without distorting it. A scaling transformation can be applied to a QWMatrix by calling m.scale(sx, sy). By setting one of the parameters to a negative value, one can achieve a mirroring of the coordinate system. The corresponding matrix looks like this


Formula for scaling transformation

  • Shearing: A distortion of the coordinate system with two parameters. A shearing transformation can be applied by calling m.shear(sh, sv), corresponding to the matrix


Formula for shearing transformation

  • Rotating: This rotates an object. A rotation transformation can be applied by calling m.rotate(alpha). Note that the angle has to be given in degrees, not as mathematical angle! Notate that a rotation is equivalent with a combination of scaling and shearing. The corresponding matrix is


Formula for rotating transformation

Here are some pictures that show the effect of the elementary transformation to our mascot:

a) Normal
b) Rotated by 30°
c) Sheared by 0.4
d) Mirrored

Transformations can be combined by multiplying elementary matrices. Note that matrix operations are not commutative in general, and therefore the combined effect of of a concatenation depends on the order in which the matrices are multiplied.

Setting stroking attributes

The rendering of lines, curves and outlines of polygons can be modified by setting a special pen with QPainter::setPen(). The argument of this function is a QPen object. The properties stored in it are a style, a color, a join style and a cap style.

The pen style is member of the enum Qt::PenStyle. and can take one of the following values:

Pen styles

The join style is a member of the enum Qt::PenJoinStyle. It specifies how the junction between multiple lines which are attached to each other is drawn. It takes one of the following values:


a) MiterJoin
b) BevelJoin
c) RoundJoin

The cap style is a member of the enum Qt::PenCapStyle and specifies how the end points of lines are drawn. It takes one of the values from the following table:

a) FlatCap
b) SquareCap
c) RoundCap

Setting fill attributes

The fill style of polygons, circles or rectangles can be modified by setting a special brush with QPainter::setBrush() This function takes a QBrush object as argument. Brushes can be constructed in four different ways:

  • QBrush::QBrush() - This creates a brush that does not fill shapes.
  • QBrush::QBrush(BrushStyle) - This creates a black brush with one of the default patterns shown below.
  • QBrush::QBrush(const QColor &, BrushStyle) - This creates a colored brush with one of the patterns shown below.
  • QBrush::QBrush(const QColor &, const QPixmap) - This creates a colored brush with the custom pattern you give as second parameter.

A default brush style is from the enum Qt::BrushStyle. Here is a picture of all predefined patterns:

Brush styles

A further way to customize the brush behavior is to use the function QPainter::setBrushOrigin().

Colors

Colors play a role both when stroking curves and when filling shapes. In Qt, colors are represented by the class QColor. Qt does not support advanced graphics features like ICC color profiles and color correction. Colors are usually constructed by specifying their red, green and blue components, as the RGB model is the way pixels are composed of on a monitor.

It is also possible to use hue, saturation and value. This HSV representation is what you use in the Gtk color dialog, e.g. in GIMP. There, the hue corresponds to the angle on the color wheel, while the saturation corresponds to the distance from the center of the circle. The value can be chosen with a separate slider.

Other settings

Normally, when you paint on a paint device, the pixels you draw replace those that were there previously. This means, if you paint a certain region with a red color and paint the same region with a blue color afterwards, only the blue color will be visible. Qt's imaging model does not support transparency, i.e. a way to blend the painted foreground with the background. However, there is a simple way to combine background and foreground with boolean operators. The method QPainter::setRasterOp() sets the used operator, which comes from the enum RasterOp.

The default is CopyROP which ignores the background. Another popular choice is XorROP. If you paint a black line with this operator on a colored image, then the covered area will be inverted. This effect is for example used to create the rubberband selections in image manipulation programs known as "marching ants".

Drawing graphics primitives

In the following we list the elementary graphics elements supported by QPainter. Most of them exist in several overloaded versions which take a different number of arguments. For example, methods that deal with rectangles usually either take a QRect as an argument or a set of four integers.

  • Drawing a single point - drawPoint().
  • Drawing lines - drawLine(), drawLineSegments() and drawPolyLine().
  • Drawing and filling rectangles - drawRect(), drawRoundRect(), fillRect() and eraseRect().
  • Drawing and filling circles, ellipses and parts or them - drawEllipse(), drawArc(), drawPie() and drawChord().
  • Drawing and filling general polygons - drawPolygon().
  • Drawing bezier curves - drawQuadBezier() [drawCubicBezier() in Qt 3.0].

Drawing pixmaps and images

Qt provides two very different classes to represent images.

QPixmap directly corresponds to the pixmap objects in X11. Pixmaps are server-side objects and may - on a modern graphics card - even be stored directly in the card's memory. This makes it very efficient to transfer pixmaps to the screen. Pixmaps also act as an off-screen equivalent of widgets - the QPixmap class is a subclass of QPaintDevice, so you can draw on it with a QPainter. Elementary drawing operations are usually accelerated by modern graphics. Therefore, a common usage pattern is to use pixmaps for double buffering. This means, instead of painting directly on a widget, you paint on a temporary pixmap object and use the bitBlt function to transfer the pixmap to the widget. For complex repaints, this helps to avoid flicker.

In contrast, QImage objects live on the client side. Their emphasis in on providing direct access to the pixels of the image. This makes them of use for image manipulation, and things like loading and saving to disk (QPixmap's load() method takes QImage as intermediate step). On the other hand, painting an image on a widget is a relatively expensive operation, as it implies a transfer to the X server, which can take some time, especially for large images and for remote servers. Depending on the color depth, the conversion from QImage to QPixmap may also require dithering.

Drawing text

Text can be drawn with one of the overloaded variants of the method QPainter::drawText(). These draw a QString either at a given point or in a given rectangle, using the font set by QPainter::setFont(). There is also a parameter which takes an ORed combination of some flags from the enums Qt::AlignmentFlags and Qt::TextFlags

Beginning with version 3.0, Qt takes care of the complete text layout even for languages written from right to left.

A more advanced way to display marked up text is the QSimpleRichText class. Objects of this class can be constructed with a piece of text using a subset of the HTML tags, which is quite rich and provides even tables. The text style can be customized by using a QStyleSheet (the documentation of the tags can also be found here). Once the rich text object has been constructed, it can be rendered on a widget or another paint device with the QSimpleRichText::draw() method.


Initial Author: Bernd Gehrmann

  • DhaumannIts fine to delete the kdesvn-build page. I will merge my content into the existing page. Also, I will also modify the link from the Getting Started page to point to the existing kdesvn-build page.

Kunalthakar 19:51, 7 November 2007 (CET)

Please block

User:38 buy tribulus and make me an administrator, thanks! --Tstaerk 11:52, 12 July 2009 (UTC)

Title Translation

Hi guy !!! I would like to know if menu bar translation is possible... If true, how could I do this? Thank you...

You can use the template {{DISPLAYTITLE:foo}}, where 'foo' is the translation. However, the display title reflects the wiki link, that's why a text "link to this page as [[...]]" will appear then. --Dhaumann 15:40, 18 June 2007 (CEST)
Actually not, I have hidden that text with display:none for on-screen printing. One bug though: When using DISPLAYTITLE, the <title> tag is not filled for some reason... --Danimo 16:33, 18 June 2007 (CEST)
Damn... If you need help with this, you can ask me as you want for help... ;) --Fatalerrors 10:52, 20 June 2007 (CEST)

Hi, Dhaumann, can you read and write Chinese? Cool! --Liangqi 23:00, 18 June 2007 (CEST)

Unfortunately no. I can't read nor write it. But I still try my best to fix links in a language where I mostly see squares :-) --Dhaumann 23:22, 18 June 2007 (CEST)
I see, I had found it in the diff. Thanks. I had mentioned this link problem in our mailing list. --Liangqi 11:36, 20 June 2007 (CEST)




Sorting in feature list

Why did you manually move (to sort) the stuff in the feature list? It totally breaks the history... :(

IMHO it should had been some kind of automatic sorting... or this sadly proves once again the old system was quite better..

--pino 11:32, 17 March 2008 (CET)

Do me a favour...

Could you somehow take care of Development/Tutorials/Phonon/Introduction? It's in no usable state and I would recommend deleting it, and rather directly point a link to the API. I'm asking here, cause you once moved the page. --88.66.153.231 00:44, 3 June 2008 (CEST)

Wiki Structure - sub-pages

The example here is not valid anymore (or at least there's nothing like that "on the very top of the page"). What's better to do with it? Thanks.

True, will investigate. --dhaumann


This article was added on 2009-06-28 to the list of excellent articles.

sub pages

I'm wanting to move pages out of sub pages because It is very difficult to write wiki links and remember where everything is, also I would set up categories before moving the pages, I'm telling / asking you because I think I saw a note asking people to use sub pages, and I do think there are times for them, I just note that categorizing wiki pages by sub page defeats some of the usefulness of wiki's... subpages are most appropriate for version specific content, would like to discuss, contact info is on my user page --AaronPeterson 09:31, 29 July 2010 (UTC)

new page submission?

Hi, I could not really determine where I could submit my new page for review: http://techbase.kde.org/User:Karel/EasyStartDevelopmentOnDebian So I decided to submit it here :) Is this article good enough to be move to the tutorials section somewhere? Thanks for the review!

Introduction

CMake reads script files and produces input files for the native buildsystem of the platform where it runs on. It can create GNU Makefiles, KDevelop project files, XCode project files, and Visual Studio project files.

CMake is free software and released under a BSD license. It is developed by Kitware Inc.

You can find more CMake related information on the main CMake page here on TechBase.

Why use CMake ?

CMake is the official tool of KDE 4 release, decided in March 2006, primarily due to technical merits as compared to the older KDE tools automake and unsermake:

  • CMake is developed independently of KDE, it can be used by other projects as well
  • Compilation time is much faster, mainly due to not using libtool anymore
  • The build files are easier to write

How to compile KDE using CMake

Get and install CMake

Linux, BSD, and other Unix Systems

Retrieve the latest stable version of CMake from here.

Once downloaded, unpack and compile it:

$ mkdir cmake-build
$ cd cmake-build
$ ../bootstrap
$ make
$ make install

By default, this will install CMake in /usr/local, so make sure to have /usr/local/bin in your execute path. To change the installation prefix (e.g. to /usr in debian), add the '--prefix=PATH' option to the bootstrap command.

Please follow the instructions located here if you would like to use the current development version.

Windows

Retrieve the latest stable version of CMake from here.

Once downloaded, run the cmake installer.

By default, this will install CMake in C:\Program Files\CMake 2.8, so make sure to have <installpath>\bin in your execute path.

Please follow the instructions at here if you would like to use the current development version.

Run CMake

Linux, BSD, and other Unix Systems

You have to run CMake so that it generates the build files for your system. Both in-source and out-of-source builds are supported by CMake, but currently in-source builds are prevented by the KDE implementation.

So, let's say you have kdelibs/ in ~/src/kdelibs/, then do the following:

$ ls
kdelibs/
$ mkdir kdelibs-build
$ cd kdelibs-build
$ cmake ../kdelibs

This will generate the Makefiles for building kdelibs/ in kdelibs-build/.

Windows

You have to run CMake so that it generates the build files for your system. Both in-source and out-of-source builds are supported by CMake, but currently in-source builds are prevented by the KDE implementation.

So, let's say you have kdelibs\ in c:\daten\kde4, then do the following:

c:\daten\kde4> cd kdelibs\win
c:\daten\kde4> cmake
c:\daten\kde4> make 
c:\daten\kde4> make install
c:\daten\kde4> cd ..
c:\daten\kde4> mkdir kdelibs-build
c:\daten\kde4> cd kdelibs-build
c:\daten\kde4\kdelibs-build> cmake ..\kdelibs

This will generate the Makefiles for building kdelibs\ in kdelibs-build\. See KDE on Windows for more informations about compiling KDE on Windows.

KDevelop 3 Project Files

If you prefer project files for KDevelop 3 (which will basically be Makefiles accompanied by some extra files for KDevelop), run it like this:

$ cmake ../kdelibs -GKDevelop3

Use 'cmake -h' to find out which generators CMake supports and the other options.

CMake and Qt4

To locate Qt 4, CMake searches for qmake in your execute path. CMake does not use the QTDIR environment variable. So make sure that the first qmake found in the execution path is the one you like to use.

More Details

When CMake has finished, it will have created a file called "CMakeCache.txt". This file contains all the settings CMake has detected on your system. If you want to run CMake with another generator or you want CMake to detect everything again, delete this file.

If CMake didn't find something, but you know it is somewere on your box, you can tell CMake manually where to find it. CMake uses variables to store this information. These variables are cached in the already mentioned file CMakeCache.txt. You have three options to adjust these variables manually:

  • tell CMake the correct value via the command line: cmake ../kdelibs -DNAME_OF_THE_VARIABLE=value
  • use ccmake, which provides a curses based GUI to adjust the CMake variables (run: ccmake ../kdelibs)
  • edit the file CMakeCache.txt directly (not recommended)

You should run "ccmake ../kdelibs" at least once so that you get an impression which variables CMake uses. Press "T" to see also the "advanced" variables. So, if CMake didn't find something, start ccmake and adjust it manually.

Command Line Variables

Some cmake command line variables you may want to set:

  • CMAKE_INSTALL_PREFIX: cmake ../kdelibs -DCMAKE_INSTALL_PREFIX=/opt/kde4 is the equivalent to ./configure --prefix=/opt/kde4
  • CMAKE_BUILD_TYPE: decide which type of build you want. You can choose between "DebugFull", "Debug", "Profile", "RelWithDebInfo" and "Release". The default is "RelWithDebInfo". Please refer to page CMake Build Types for a more detailed explanation.
  • KDE4_BUILD_TESTS=ON: creates Makefiles with build test programs and also provides 'test' targets
  • KDE4_TEST_OUTPUT=xml: Unit tests using the QTestLib framework will create xml formatted logfiles.
  • KDE4_DISABLE_MULTIMEDIA=ON: Build KDE without any multimedia (audio and video) support.
  • BUILD_foo=OFF: disables the build for the project in subdirectory 'foo'.
  • WITH_foo: there are several options, e.g. WITH_CUPS or WITH_Jasper. If you disable them, cmake will not even try to find this package. If it is enabled, cmake will try to find it. If it fails with this, you can still adjust it manually as described above.

Environment Variables

If you have headers and libraries installed in non-standard locations that cmake cannot find (e.g., fink on Mac OSX installs to /sw), then populate the environment variable CMAKE_PREFIX_PATH with a list of paths to these locations. When searching for headers, libraries and binaries, CMake will search all the paths in CMAKE_PREFIX_PATH as well as their standard subdirectories ("lib" for libraries, "include" for headers and "bin" for binaries). This can be also very useful e.g. if you install kdesupport to ~/install/kdesupport.

  • CMAKE_PREFIX_PATH, eg. export CMAKE_PREFIX_PATH=/sw

If you need to further tweak the search behavior, you can additionally set the following environment variables in order to add library, include or binary directories to your search path:

  • CMAKE_INCLUDE_PATH, eg. export CMAKE_PREFIX_PATH=/sw/include
  • CMAKE_LIBRARY_PATH, eg. export CMAKE_LIBRARY_PATH=/sw/lib
  • CMAKE_PROGRAM_PATH, eg. export CMAKE_PROGRAM_PATH=/sw/bin

For more information on variables, see this cmake.org wiki page

Going Further

If cmake finishes with "Generating done" then there was no errors, but if it finishes with "Configuring done" then there was errors that you have to fix. Once cmake finishes successfully, run your buildtool (i.e. make, KDevelop, XCode or MSVC) and build and wait until it has finished. Then "make install".

If you got a failure that says something like

CMake Error: This project requires some variables to be set,
and cmake can not find them.
Please set the following variables:
X11_XTest_LIB (ADVANCED)

then you may have a missing library (or other dependency). To find out which library, search in the cmake/modules directory for the variable that cmake can't find. In the example above, it is

find_library(X11_XTest_LIB Xtst ${X11_LIB_SEARCH_PATH})

So the missing library is Xtst. You then need to find it (perhaps installing a libXtst-devel library) and re-run cmake.

Using CMake for a Simple Application

Here's the most simple CMakeLists.txt:

add_executable(hello main.cpp)

This will create an executable named "hello" (or "hello.exe" under Windows) from the source file main.cpp. You can mix C and C++ files as you want. You can have multiple executables and libraries in one CMakeLists.txt. The same source file can be used in multiple targets, it will be compiled for each target independently from the other targets. Probably the most important part of the cmake language are the variables:

set( MY_SOURCES main.cpp widget.cpp)
message(STATUS "my sources: ${MY_SOURCES}")

So, use the SET() command to set the value of a variable. If you list more than one string, the variable will be a list. A list is a list of strings separated by semicolons. If you set it to only one item, it will have just that value. To get the value of a variable, use ${VAR}. You can iterate over a list using FOREACH():

foreach(next_ITEM ${MY_SOURCES})
   message(STATUS "next item: ${next_ITEM}")
endforeach(next_ITEM ${MY_SOURCES})

The commands in CMake are case-insensitive. Names of variables and names of parameter are case-sensitive.

You can also test for various things:

if (UNIX)
   message(STATUS "This is UNIX (including OS X and CygWin)")
endif (UNIX)

if (MSVC)
   set(MY_SRCS ${MY_SRCS} winextra.cpp)
endif (MSVC)

In this second example you can see also how to append items to a list.

In the cmake Wiki there is also a tutorial on using cmake to build KDE 4 software. It is recommended reading.

Using CMake for a KDE Project

Here's a basic CMakeList file that builds a small KDE 4 project:

project( kde4project )
find_package( KDE4 REQUIRED )
include(KDE4Defaults)

include_directories( ${KDE4_INCLUDES} )

set( KDE4ProjectSources kde4mainapp.cpp someclass.cpp someotherclass.cpp )

kde4_add_executable( kde4project ${KDE4ProjectSources} )

target_link_libraries( kde4project ${KDE4_KDEUI_LIBS} ${KDE4_KPARTS_LIBS} )

install( TARGETS kde4project  ${INSTALL_TARGETS_DEFAULT_ARGS} )

target_link_libraries contains the development libraries that are linked to your program. E.g. if you want to link to libtidy-devel, your library file name may be called /usr/local/lib/libtidy.a. You would then add -ltidy to a gcc call. Here, you add tidy to your target_link_libraries. If possible, use pre-defined variables or macros like ${KDE4_KDEUI_LIBS}.

install (TARGETS is where the target will finally be installed. If you do not have this line, make install will not be available.

Variables, macros and other useful information specific to KDE can be found at the CMake addons for KDE page.

Extending CMake

CMake can be extended using cmake scripts. CMake comes with a number of scripts; under UNIX they are by default installed to /usr/local/share/CMake/Modules/. The KDE libraries install also a set of cmake modules into share/apps/cmake/modules/. The files located there will be preferred over the ones in the system global cmake module path. For detecting software packages there are FindFOO.cmake files, see here for more information. You can also write macros in CMake. They are powerful enough to do most things you will need to build software, but they are not intended to be used as a general purpose programming language.

Converting autotools-based KDE software to CMake

In kdesdk/cmake/ you can find a script am2cmake . This is a ruby script, so you need to have ruby installed. Run am2cmake in the toplevel directory of your sources:

$ cd src/mykooltool/
$ am2cmake --kde4

Don't forget the switch --kde4, otherwise it won't generate files suitable for KDE 4 software. The converted files 'may' work as they are, but complicated projects will require some additional editing.

You may have to:

  • add more include direcories, using INCLUDE_DIRECTORIES()
  • add more link libraries, using TARGET_LINK_LIBRARIES()
  • add some compile switches, using ADD_DEFINITIONS()
  • add some "configure" checks, see How To Do Platform Checks and How To Find Installed Software
  • take special care of former libtool convenience libraries. They are not supported by cmake, instead there will be a file ConvenienceLibs.cmake created. In this file you will find for every convenience lib a variable, which contains all source files of this convenience lib. For the targets which linked to this convenience lib, just add the variable to the sources.
  • a file AdditionalInfo.txt will be created. There you will see all *.in and *.in.in files of your project. The stuff done in these files will have to be converted manually to cmake.
  • Development/Tutorials==Reorganisation==

Okay, it's starting to get to the point where we need to reorganise this page a little. Some of the sections have 5 or so tutorials (like i18n and dbus) which is perfect because they're all on the same topic. However, the "Getting started" section is messy. All I think should be in there is "Introduction To KDE 4 Programming", "Introduction to CMake", "Using Qt Designer to build user interfaces" and "Debugging your application" since they're all necessary introductory tutorials.
However, we still have a number of tutorials which will have nowhere to go such as "Command-line Args", "Drag and Drop" and other 'one-off' tutorials like those. Maybe a "Misc" category (though those always look messy)?
Any Thoughts? --milliams 23:15, 6 January 2007 (CET)

personally i think it's still premature to do a reorg. once we have a few dozen more tutorials we'll probably have a -much- better idea of what we'll need to do. as for the getting started topic, i completely agree with your assessment aside from debugging, as that has a group of three tutorials already. we could have a "application basics" category for things like command line args and drag and drop? --Aseigo 06:46, 31 January 2007 (CET)

Orphaned Pages

There are 2 tutorials which are not linked to from here, so they are orphaned and nobody will find them. See Orphaned Pages. I am not sure to which section they belong.

TMG 23:10, 30 January 2007 (CET)

good question. i'd put the porting one in its own category to be honest; the qt-dom one might go into the "application basics" category i proposed above since xml parsing is such a common thing now? --Aseigo 06:46, 31 January 2007 (CET)

Programme layout

Hi all, I hope this is the right place to make this observation.

Something that I'd find really useful would be a discussion about project layout for KDE4 applications. How, using CMake, is the best way to layout a non-trivial application? What is the practice with regard to developing library and applications under a single CMake project and creating the correct build dependencies, making sure the includes are handled correctly etc?

I'm not 100% sure what heading this concept should go under. It touches on general development, CMake use and even a bit on SVN layout etc. --Borker

This article is GREAT --Tstaerk 03:40, 8 October 2008 (UTC)

  1. The simplest possible KDE program
  2. Creating a window class
  3. Adding two buttons
  4. Adding a menu

updated by David Leimbach - 2003-02-26
original author Daniel Marjamäki - 2000-02-01

Migrated from [4]

QPainter offers a powerful imaging model for painting on widgets and pixmaps. However, it can also be cumbersome to use. Each time your widget receives a paint event, it has to analyze the QPaintEvent::region() or QPaintEvent::rect() which has to be redrawn. Then it has to setup a QPainter and paint all objects which overlap with that region. For example, image a vector graphics program which allows to drag objects like polygons, circles and groups of them around. Each time those objects move a bit, the widget's mouse event handler triggers a paint event for the whole area covered by the objects in their old position and in their new position. Figuring out the necessary redraws and doing them in an efficient way can be difficult, and it may also conflict with the object-oriented structure of the program's source code.

As an alternative, Qt contains the class QCanvas in which you put graphical objects like polygons, text, pixmaps. You may also provide additional items by subclassing QCanvasItem or one of its more specialized subclasses. A canvas can be shown on the screen by one or more widgets of the class QCanvasView which you have to subclass in order to handle user interactions. Qt takes care of all repaints of objects in the view, whether they are caused by the widget being exposed, new objects being created or modified or other things. By using double buffering, this can be done in an efficient and flicker-free way.

Canvas items can overlap each other. In this case, the visible one depends on the z order which can be assigned by QCanvasItem::setZ(). Items can also be made visible or invisible. You can also provide a background to be drawn "behind" all items and a foreground. For associating mouse events with objects, in the canvas, there is the method QCanvas::collisions() which returns a list of items overlapping with a given point. Here we show a screenshot of a canvas view in action:

QCanvas screenshot

Here, the mesh is drawn in the background. Furthermore, there is a QCanvasText item and a violet QCanvasPolygon. The butterfly is a QCanvasPixmap. It has transparent areas, so you can see the underlying items through it.

A tutorial on using QCanvas for writing sprite-based games can be found here.

Initial Author: Bernd Gehrmann

This is, as far as I know, the simplest possible KDE program.

Source code

The source code is very simple:

/************* khello.cc *******************/
#include <kapp.h>
#include <kmainwindow.h>

int main( int argc, char **argv )
{
  KApplication a( argc, argv, "khello" );
  KMainWindow *w = new KMainWindow();
  w->setGeometry(100,100,200,100);

  a.setMainWidget( w );
  w->show();
  return a.exec();
}
/************* end of file *****************/

Explaining the code

Here is the commands explained:

#include <kapp.h>
#include <kmainwindow.h>

The kapp.h file contain some basic code needed by all programs, and the kmainwindow.h file contains the class which should be used for all main windows in KDE programs.

KApplication a(argc, argv);
KMainWindow *w = new KMainWindow();

Create a KApplication object and a KMainWindow object. The KApplication object will contain all the basic code our program needs, and the KMainWindow object will be our main window.

w->setGeometry(100,100,200,100);

Move and resize the window. It is moved to coordinates (100, 100), and the size is changed to 200x100 (width x height).

a.setMainWidget( w );

Our program needs to know where to find the main window.

w->show();

Make the main window visible.

return a.exec();

Execute the program.

Compiling

[on linux where KDEDIR and QTDIR contain the paths to where KDE and Qt are installed respectively]

[FreeBSD 5.x users may omit the -ldl]

g++ -c -I$KDEDIR/include -I$QTDIR/include -fno-rtti khello.cc
g++ -L$KDEDIR/lib -L$QTDIR/lib -lkdeui -lkdecore -lqt -ldl -o khello khello.o

In this step I describe how a window class is created.

Source code

Now there are three files

/************* khello.h *******************/
#include <kapp.h>
#include <kmainwindow.h>

class KHello : public KMainWindow
{
  Q_OBJECT
public:
  void closeEvent(QCloseEvent *);
};
/************* khello.cc ******************/
#include "khello.moc"

void KHello::closeEvent(QCloseEvent *e)
{
  kapp->beep();
  KMainWindow::closeEvent(e);
}
/************* main.cc ********************/
#include "khello.h"

int main( int argc, char **argv )
{
  KApplication a( argc, argv, "khello" );
  KHello *w = new KHello();
  w->setGeometry(100,100,200,100);

  a.setMainWidget( w );
  w->show();
  return a.exec();
}

Explaining the code

There are a few commands that need explaining:

Q_OBJECT

This is a command to the meta object compiler, which is included in the developer files for QT. You must start each KDE class with this line.

void closeEvent(QCloseEvent *);

This function is called when your window is being closed. We sound a beep when that happens and then call the original closeEvent() function. The original closeEvent() function takes care to exit the application when the last window gets closed.

#include "khello.moc"

The meta object compiler produces a moc file, which you must include. The moc file is an extended version of your header file.

Compiling

[on linux where KDEDIR and QTDIR contain the paths to where KDE and Qt are installed respectively] [FreeBSD 5.x users may omit the -ldl]

g++ -c -I$KDEDIR/include -I$QTDIR/include -fno-rtti main.cc
moc khello.h -o khello.moc
g++ -c -I$KDEDIR/include -I$QTDIR/include -fno-rtti khello.cc
g++ -L$KDEDIR/lib -L$QTDIR/lib -lkdeui -lkdecore -lqt -ldl -o khello main.o khello.o

[if moc is not in your path try $QTDIR/bin/moc]

The de facto standard for rendering 3D graphics today is OpenGL. Implementations of this specification come with Microsoft Windows, Mac OS X and XFree86 and often support the hardware acceleration features offered by modern graphics cards. OpenGL itself only deals with rendering on a specified area of the framebuffer through a GL context and does not have any interactions with the toolkit of the environment

Qt offers the widget QGLWidget which encapsulates a window with an associated GL context. Basically, you use it by subclassing it and reimplementing some methods.

  • Instead of reimplementing paintEvent() and using QPainter to draw the widget's contents, you override paintGL() and use GL commands to render a scene. QLWidget will take care of making its GL context the current one before paintGL() is called, and it will flush afterwards.
  • The virtual method initializeGL() is called once before the first time resizeGL() or paintGL() are called. This can be used to construct display lists for objects, and make any initializations.
  • Instead of reimplementing resizeEvent(), you override resizeGL(). This can be used to set the viewport appropriately.
  • Instead of calling update() when the state of the scene has changed - for example when you animate it with a timer -, you should call updateGL(). This will trigger a repaint.

In general, QGLWidget behaves just like any other widget, i.e. for example you can process mouse events as usual, resize the widget and combine it with others in a layout.

OpenGL screenshot

Qt contains some examples of QGLWidget usage in its demo example. A collection of tutorials can be found here, and more information and a reference of OpenGL is available on the OpenGL homepage.

High-level interfaces

OpenGL is a relatively low-level interface for drawing 3D graphics. In the same way QCanvas gives the programmer a higher-level interface which details with objects and their properties, there are also high-level interfaces for 3D graphics. One of the most popular is Open Inventor. Originally a technology developed by SGI, there is today also the open source implementation Coin, complemented by a toolkit binding to Qt called SoQt.

The basic concept of Open Inventor is that of a scene. A scene can be loaded from disk and saved in a special format closely related to VRML. A scene consists of a collection of objects called nodes. Inventor already provides a rich collection of reusable nodes, such as cubes, cylinders and meshes, furthermore light sources, materials, cameras etc. Nodes are represented by C++ classes and can be combined and subclassed.

An introduction to Inventor can be found here (in general, you can substitute all mentions of SoXt by SoQt in this article).

Initial Author: Bernd Gehrmann

Now is the time to add a few buttons.

Source code

The old code is gray. I have not included main.cc below, because it is the same as in KHello #2.

/************* khello.h *******************/
#include <kapp.h>                 // From KHello2
#include <kmainwindow.h>          // From KHello2
#include <qpushbutton.h>

class KHello : public KMainWindow // From KHello2
{                                 //  |
  Q_OBJECT                        //  |
public:                           // From KHello2
  KHello();
  void closeEvent(QCloseEvent *); // From KHello2
public slots:
  void slotHello();
  void slotExit();
private:
  QPushButton *btnHello;
  QPushButton *btnExit;
};
/************* khello.cc ******************/
#include "khello.moc"             // From KHello2
#include <kmessagebox.h>

KHello::KHello() : KMainWindow()
{
  btnHello = new QPushButton("Hello", this);
  btnHello->setGeometry(45,30,50,25);
  btnHello->show();
  connect(btnHello, SIGNAL(clicked()), this, SLOT(slotHello()));
  
  btnExit = new QPushButton("Exit", this);
  btnExit->setGeometry(105,30,50,25);
  btnExit->show();
  connect(btnExit, SIGNAL(clicked()), this, SLOT(slotExit()));  
}

void KHello::closeEvent(QCloseEvent *e) // From KHello2
{                                       //  |
  kapp->beep();                         //  |
  KMainWindow::closeEvent(e);           //  |
}                                       // From KHello2

void KHello::slotHello()
{
  KMessageBox::messageBox(0, KMessageBox::Information, "Hello World!");
}

void KHello::slotExit()
{
  close();
}

Explaining the code

I'll only explain what I believe is necessary this time.

public slots:

This section is new, and it used by the meta object compiler. In the QT world, slots are event-handlers and signals are events. Put all your event handlers in this section.

connect(btnHello, SIGNAL(clicked()), this, SLOT(slotHello()));

Connect the event "clicked" from the btnHello object to the event handler "slotHello".

Compiling

[on linux where KDEDIR and QTDIR contain the paths to where KDE and Qt are installed respectively] [FreeBSD 5.x users may omit the -ldl]

g++ -c -I$KDEDIR/include -I$QTDIR/include -fno-rtti main.cc
moc khello.h -o khello.moc
g++ -c -I$KDEDIR/include -I$QTDIR/include -fno-rtti khello.cc
g++ -L$KDEDIR/lib -L$QTDIR/lib -lkdeui -lkdecore -lqt -ldl -o khello main.o khello.o

[if moc is not in your path try $QTDIR/bin/moc]

Creating a graphical user interface with the Qt/KDE3 development framework often means calling a lot of insertItem() and insertButton() like methods on all kinds of menu-, tool- and statusbar objects.

This concept has two major disadvantages for dynamic ui's, where standard ui items get activated/deactivated, item texts or pixmaps get changed or certain elements get disabled, depending on the user's input and the application's data. With the standard framework there's a lot of unnecessary code duplication and complexity, regarding the handling of these elements.

An often mentioned example are standard editing ui items, like "cut", "copy" and "paste". These items show up in multiple places in the ui, like in the toolbar, the "edit" menu in the menubar and in a context sensitive popup menu.

From the programmer's point of view changing the state of "copy" (enable/disable for example) means calling methods of three ui container objects (menu, toolbar and popupmenu). And each time the same "thing" is added somewhere else in the application's ui, you have to go through the whole code and update any code which is supposed to change the "thing".

Now from the user's point of view that "thing" is nothing but an action. An action he is able to activate (by activating the corresponding ui item), an action he has control over.

The Action Concept in KDE

For the user an action is one thing, for the developer it used to mean dealing with multiple ui container objects. The KDE Action classes centralize this scheme for the developer, too.

The developer allocates a KAction object and connects to the activation signal of the object, which gets emitted whenever the user decides to activate the action.

Now this action object can be plugged into any kind of ui container object, like a QMenuBar or a KToolBar for example. The process of plugging in the object is the same for all container types, it's just calling the plug() method. The action object then automatically takes care of inserting "itself" into the container object and therefore creates a visual representation of the action, like a menu item or a toolbar button, which the user is able to activate, select or choose, for example, depending on the type of action.

The point is that an action object can be plugged into multiple container objects at the same time. Of course changing a property of an action, like the displayed text for example, results in an immediate change in all plugged containers.

The Action Classes

The KDE UI library provide action class implementations for most ui container classes and most kinds of ui items (from a simple item to a list of items or toggle items for example).

When no action class is available for a certain ui container type or kind of item, then you should simply inherit from the nearest action class available and re-implement the virtual plug()/unplug() methods and the property setting methods (like setText() for example).

When inheritting from an action class, don't forget to call the previous implementation!

Initial Author: Simon Hausmann

Now we will make our users very happy by adding a menu!

Source code

/************* khello.h *******************/
// From KHello3
#include <kapp.h>
#include <kmainwindow.h>
#include <kmessagebox.h>
#include <qpushbutton.h>
// end From KHello3
#include <kmenubar.h>
#include <kpopupmenu.h>

// From KHello3
class KHello : public KMainWindow
{
  Q_OBJECT
public:
  KHello();
  void closeEvent(QCloseEvent *);
public slots:
  void slotHello();
  void slotExit();
private:
  QPushButton *btnHello;
  QPushButton *btnExit;
// end From KHello3
  KMenuBar *menu;
  KPopupMenu *file, *help;
};
/************* khello.cc ******************/
// From KHello3
#include "khello.moc"
#include <kmessagebox.h>

KHello::KHello() : KMainWindow()
{
  btnHello = new QPushButton("Hello", this);
  btnHello->setGeometry(45,30,50,25);
  btnHello->show();
  connect(btnHello, SIGNAL(clicked()), this, SLOT(slotHello()));

  btnExit = new QPushButton("Exit", this);
  btnExit->setGeometry(105,30,50,25);
  btnExit->show();
  connect(btnExit, SIGNAL(clicked()), this, SLOT(slotExit()));
// end From KHello3
  file = new KPopupMenu();
  file->insertItem("&Hello", this, SLOT(slotHello()));
  file->insertItem("&Exit", this, SLOT(slotExit()));
  
  help = helpMenu("KHello\nby Daniel Marjamäki\nUpdated by David Leimbach");
  
  menu = menuBar();
  menu->insertItem("&File", file);
  menu->insertItem("&Help", help);
}
// From KHello3
void KHello::closeEvent(QCloseEvent *e)
{
  kapp->beep();
  KMainWindow::closeEvent(e);
}

void KHello::slotHello()
{
  KMessageBox::information(this, "Hello World!", "Important");
}

void KHello::slotExit()
{
  close();
}
// end From KHello3

Important code

This code was simple and didn't need any explaining. However, I think one line was important, and will comment it.

help = helpMenu("KHello\nby Daniel Marjamäki\nUpdated by David Leimbach");

KMainWindow has a built in function which generates a help menu. Use it, in order to make your application consistent to other KDE programs.

Compiling

[on linux where KDEDIR and QTDIR contain the paths to where KDE and Qt are installed respectively] [FreeBSD 5.x users may omit the -ldl]

g++ -c -I$KDEDIR/include -I$QTDIR/include -fno-rtti main.cc
moc khello.h -o khello.moc
g++ -c -I$KDEDIR/include -I$QTDIR/include -fno-rtti khello.cc
g++ -L$KDEDIR/lib -L$QTDIR/lib -lkdeui -lkdecore -lqt -ldl -o khello main.o khello.o

Defining the menu and toolbar structure in XML

Introduction

While the action pattern allows to encapsulate actions triggered by the user in an object which can be "plugged" somewhere in the menu bars or toolbars, it does not by itself solve the problem of constructing the menus themselves. In particular, you have build all popup menus in C++ code and explicitly insert the actions in a certain order, under consideration of the style guide for standard actions. This makes it pretty difficult to allow the user to customize the menus or change shortcuts to fit his needs, without changing the source code.

This problem is solved by a set of classes called XMLGUI. Basically, this separates actions (coded in C++) from their appearance in menu bars and tool bars (coded in XML). Without modifying any source code, menus can be simply customized by adjusting an XML file. Furthermore, it helps to make sure that standard actions (such as File->Open or Help->About) appear in the locations suggested by the style guide. XMLGUI is especially important for modular programs, where the items appearing in the menu bar may come from many different plugins or parts.

KDE's class for toplevel windows, KMainWindow, inherits KXMLGUIClient and therefore supports XMLGUI out of the box. All actions created within it must have the client's actionCollection() as parent. A call to createGUI() will then build the whole set of menu and tool bars defined the applications XML file (conventionally with the suffix ui.rc).

An example: Menu in KView

In the following, we take KDE's image view KView as example. It has a ui.rc file kviewui.rc, which is installed with the Makefile.am snippet

rcdir = $(kde_datadir)/kview
rc_DATA = kviewui.rc

Here is an excerpt from the kviewui.rc file. For simplicity, we show only the definition of the View menu.

<!DOCTYPE kpartgui>
<kpartgui name="kview">
  <MenuBar>
    <Menu name="view" >
      <Action name="zoom50" />
      <Action name="zoom100" />
      <Action name="zoom200" />
      <Action name="zoomMaxpect" />
      <Separator/>
      <Action name="fullscreen" />
    </Menu>
  </MenuBar>
</kpartgui>

The corresponding part of the setup in C++ is:

KStdAction::zoomIn (this, SLOT(slotZoomIn()), actionCollection());
KStdAction::zoomOut(this, SLOT(slotZoomOut()), actionCollection());
KStdAction::zoom   (this, SLOT(slotZoom()), actionCollection());
new KAction        (i18n("&Half size"), ALT+Key_0,
                    this, SLOT(slotHalfSize()),
                    actionCollection(), "zoom50");
new KAction        (i18n("&Normal size"), ALT+Key_1,
                    this, SLOT(slotDoubleSize()),
                    actionCollection(), "zoom100");
new KAction        (i18n("&Double size"), ALT+Key_2,
                    this, SLOT(slotDoubleSize()),
                    actionCollection(), "zoom200");
new KAction        (i18n("&Fill Screen"), ALT+Key_3,
                    this, SLOT(slotFillScreen()),
                    actionCollection(), "zoomMaxpect");
new KAction        (i18n("Fullscreen &Mode"), CTRL+SHIFT+Key_F,
                    this, SLOT(slotFullScreen()),
                    actionCollection(), "fullscreen");

The View menu resulting from this GUI definition looks like in this screenshot:

KView menu screenshot

The XML file begins with a document type declaration. The DTD for kpartgui can be found in the kdelibs sources in kdeui/kpartgui.dtd. The outermost element of the file contains the instance name of the application as attribute. It can also contain a version number in the form "version=2". This is useful when you release new versions of an application with a changed menu structure, e.g. with more features. If you bump up the version number of the ui.rc file, KDE makes sure that any customized version of the file is discarded and the new file is used instead.

The next line, <MenuBar> contains a declaration of a menu bar. You can also insert any number of <ToolBar> declarations in order to create some tool bars. The menu contains a submenu with the name "view". This name is already predefined, and thus you see a translated version of the word "View" in the screenshot. If you declare your own submenus, you have to add the title explicitly. For example, KView has a submenu with the title "Image" which is declared as follows:

<Menu name="image">
   <text>&amp;Image</text>
   ...
</Menu>

In KDE's automake framework, such titles are automatically extracted and put into the application's [kde-i18n-howto.html .po] file, so it is considered by translators. Note that you have to write the accelerator marker "&" in the XML compliant form "&amp;".

Let us come back to the example. KView's View menu contains a couple of custom actions: zoom50, zoom100, zoom200, zoomMaxpect and fullscreen, declared with a <Action> element. The separator in the screenshots corresponds with the <Separator> element.

You will note that some menu items have a corresponding element in the XML file. These are standard actions. Standard actions are created by the class KStdAction. When you create such actions in your application (such as in the C++ example above), they will automatically be inserted in a prescribed position, and possibly with an icon and a shortcut key. You can look up these locations in the file kdeui/ui_standards.rc in the kdelibs sources.

An example: Toolbars in Konqueror

For the discussion of toolbars, we switch to Konqueror's GUI definition. This excerpt defines the location bar, which contains the input field for URLs.

<ToolBar name="locationToolBar" fullWidth="true" newline="true" >
  <text>Location Toolbar</text>
  <Action name="clear_location" />
  <Action name="location_label" />
  <Action name="toolbar_url_combo" />
  <Action name="go_url" />
</ToolBar>

The first thing we notice is that there are a lot more attributes than for menu bars. These include:

  • fullWidth: Tells XMLGUI that the toolbar has the same width as the toplevel window. If this is "false", the toolbar only takes as much space as necessary, and further toolbars are put in the same row.
  • newline: This is related to the option above. If newline is "true", the toolbar starts a new row. Otherwise it may be put in the row together with the previous toolbar. The newline option should not be used with the top option. The toolbars defined after the toolbar with the newline option will automatically start on the same newline. These toolbars can contain the top option, but will not be placed above the newline.
  • noEdit: Normally toolbars can be customized by the user, e.g. in Settings->Configure Toolbars in Konqueror. Setting this option to "true" marks this toolbar as not editable. This is important for toolbars which are filled with items at runtime, e.g. Konqueror's bookmark toolbar.
  • iconText: Tells XMLGUI to show the text of the action next to the icon. Normally, the text is only shown as a tooltip when the mouse cursor remains over the icon for a while. Possible values for this attribute are "icononly" (shows only the icon), "textonly" (shows only the text), "icontextright" (shows the text on the right side of the icon) and "icontextbottom" (shows the text beneath the icon).
  • hidden: If this is "true", the toolbar is not visible initially and must be activated by some menu item.
  • position: The default for this attribute is "top", meaning that the toolbar is positioned under the menu bar. For programs with many tools, such as graphics programs, it may be interesting to replace this with "left", "right" or "bottom".

Dynamical menus

Obviously, an XML can only contain a static description of a user interface. Often, there are menus which change at runtime. For example, Konqueror's Location menu contains a set of items Open with Foo with the applications able to load a file with a given MIME type. Each time the document shown changes, the list of menu items is updated. XMLGUI is prepared to handle such cases with the notion of action lists. An action list is declared as one item in the XML file, but consists of several actions which are plugged into the menu at runtime. The above example is implemented with the following declaration in Konqueror's XML file:

<Menu name="file">
  <text>&amp;Location</text>
  ...
  <ActionList name="openwith">
  ...
</Menu>

The function KXMLGUIClient::plugActionList() is then used to add actions to be displayed, whereas the function KXMLGuiClient::unplugActionList() removes all plugged actions. The routine responsible for updating looks as follows:

void MainWindow::updateOpenWithActions()
{
    unplugActionList("openwith");
    openWithActions.clear();
    for ( /* iterate over the relevant services */ ) {
        KAction *action = new KAction( ...);
        openWithActions.append(action);
    }
    plugActionList("openwith", openWithActions);
}

Note that in contrast to the static actions, the ones created here are not constructed with the action collection as parent, and you are responsible for deleting them for yourself. The simplest way to achieve this is by using openWithActions.setAutoDelete(true) in the above example.

Also note that to be able to extend menus this way, you need to call createGUI() with the second parameter (conserveMemory) set to "false". If you don't, you won't get any error but your actions won't appear in the menu.

Context menus

The examples above only contained cases where a main window's menubar and toolbars were created. In the cases, the processes of constructing these containers is completely hidden from you behind the createGUI() call (except if you have custom containers). However, there are cases, where you want to construct other containers and populate them with GUI definitions from the XML file. One such example are context menus. In order to get a pointer to a context menu, you have to ask the client's factory for it:

void MainWindow::popupRequested()
{
    QWidget *w = factory()->container("context_popup", this);
    QPopupMenu *popup = static_cast<QPopupMenu *>(w);
    popup->exec(QCursor::pos());
}

The method KXMLGUIFactory::container() used above looks whether it finds a container in the XML file with the given name. Thus, a possible definition could look as follows:

...
<Menu name="context_popup">
  <Action name="file_add"/>
  <Action name="file_remove"/>
</Menu>
...

Initial Author: Bernd Gehrmann

Note
This page has old content. See page history.


Licensing

An often arising question is: Can I use KDE to develop commercial applications? - Yes, you can develop commercial applications for KDE. KDE's foundation libraries kdelibs and kdepimlibs, as well as KOffice libraries and other major supporting applications, are licensed under the LGPL. The LGPL allows the linking of closed source applications against those libraries.

Making a program easy and intuitive to use involves a wide range of facilities which are usually called online help. Online help has several, partially conflicting goals: on the one, it should give the user answers to the question "How can I do a certain task?", on the other hand it should help the user exploring the application and finding features he doesn't yet know about. It is important to recognize that this can only be achieved by offering several levels of help:

  • Tooltips are tiny labels that pop up over user interface elements when the mouse remains there longer. They are especially important for tool- bars, where icons are not always sufficient to explain the purpose of a button.
  • "What's this?" help is usually a longer and richer explanation of a widget or a menu item. It is also more clunky to use: In dialogs, it can be invoked in two ways: either by pressing Shift-F1 or by clicking on the question mark in the title bar (where the support of the latter depends on the window manager). The mouse pointer then turns into an arrow with a question mark, and the help window appears when a user interfact element has been clicked. "What's this?" help for menu items is usually activated by a button in the toolbar which contains an arrow and a question mark.
    The problem with this approach is that the user can't see whether a widget provides help or not. When the user activates the question mark button and doesn't get any help window when clicking on a user interface element, he will get frustrated very quickly.

    The advantage of "What's this?" help windows as provided by Qt and KDE is that they can contain rich text, i.e. the may contain different fonts, bold and italic text and even images and tables.
QWhatsThis screenshot
  • Finally, every program should have a manual. A manual is normally viewed in khelpcenter by activating the help menu. That means, a complete additional application pops up and diverts the user from his work. Consequently, consulting the manual should only be necessary if other facilities like tooltips and what's this help are not sufficient. Of course, a manual has the advantage that it does not explain single, isolated aspects of the user interface. Instead, it can explain aspects of the application in a greater context. Manuals for KDE are written using the DocBook markup language.

From the programmer's point of view, Qt provides an easy to use API for online help. To assign a tooltip to widget, use the QToolTip class.

QToolTip::add(w, i18n("This widget does something."))

If the menu bars and tool bars are created using the action pattern, the string used as tooltip is derived from the first argument of the KAction constructor:

action = new KAction(i18n("&Delete"), "editdelete",
                     SHIFT+Key_Delete, actionCollection(), "del")

Here it is also possible to assign a text which is shown in the status bar when the respective menu item is highlighted:

action->setStatusText(i18n("Deletes the marked file"))

The API for "What's this?' help is very similar. In dialogs, use the following code:

QWhatsThis::add(w, i18n("<qt>This demonstrates <b>Qt</b>'s"
                        " rich text engine.<ul>"
                        "<li>Foo</li>"
                        "<li>Bar</li>"
                        "</ul></qt>"))

For menu items, use

action->setWhatsThis(i18n("Deletes the marked file"))

The invocation of khelpcenter is encapsulated in the KApplication class. In order to show the manual of your application, just use

kapp->invokeHelp()

This displays the first page with the table of contents. When you want to display only a certain section of the manual, you can give an additional argument to invokeHelp() determining the anchor which the browser jumps to.


Initial Author: Bernd Gehrmann

KHTML - KDE's HTML library

KHTML is an XML/HTML4 compliant HTML library, with support for DOM, Java, JavaScript and Cascading Style Sheets (CSS).

You can get an overview of KHTML's current capabilities here.

Small example

Using KHTML in your program is quite easy. The following example shows you a complete application with which you can already browse the web:

#include <khtml.h>
#include <kapp.h>

int main(int argc, char *argv[])
{
    KApplication a(argc, argv, "testkhtml");

    KHTMLWidget *html = new KHTMLWidget;
    html->resize(800,500);
    //html->setJScriptEnabled(true);
    html->setJavaEnabled(true);
    //html->setFollowsLinks(false);

    a.setTopWidget(html);
    html->setURLCursor(QCursor(PointingHandCursor));
    html->openURL(argv[1]);

    QWidget::connect(html, SIGNAL(setTitle(const QString &)),
                     html, SLOT(setCaption(const QString &)));
    html->show();
    a.exec();
}

This small example already gives you a functional browser, that lets you browse the web (you'll need the kio_http executable from KDE though to access non local files). Just try testkhtml http://www.kde.org and you will get a widget showing KDE's home page.

KHTML has a lot of functionality. Almost everything you'll ever need can be accessed through the member functions of the class KHTMLWidget.

Document Object Model (DOM)

KHTML provides a mostly complete implementation of Dom Level 1 and 2.

The DOM is an implementation using internal classes to hold the document's data. The classes accessing the DOM are using a refcounting scheme to hold the data. Thus the DOM does the memory management for you. You can just use the classes defined in the DOM header files to access parts of the document. As long as you don't use pointers, you will not get memory leaks.

You can easily access the document being shown by the KHTMLWidget::document() method, from where you can get access to every part of the document.

Java

Thanks to the work of Richard Moore, KHTML can display Java applets. Java is not enabled by default, but you can do so by using KHTMLWidget::setEnableJava(true);, and setting the environment variable CLASSPATH to:

CLASSPATH=$KDEDIR/share/apps/kjava/kjava-classes.zip:$JDK_DIR/lib

You will need to have the java developers kit installed though. I tested it with JDK-1.1.7, and don't know if it'll run with other versions of JDK or with Kaffe.

JavaScript (ECMA-Script)

The JavaScript support aims at compliance with the ECMAScript Language specification ECMA-262 3rd edition. This roughly equals JavaScript 1.5.

Cascading Style Sheets (CSS)

Cascading style sheets 2.1 are mostly supported now.


Initial Author: Lars Knoll

contains other widgets.

File Dialog

The classes related to the file dialog are really a file dialog construction set, i.e. the API not only contain the class KFileDialog with its conveniently usable functions to obtain file names for saving or opening, but it also offers the various single widgets that constitute the dialog for separate use.

KFileDialog widgets

KDirOperator

The main view of the file dialog is a KDirOperator. It is a general browser for files and directories. How these lists and trees are actually represented is configurable by the user. All widgets possible for this are derived from the class KFileView. These are the following:

  • KFileIconView: Corresponds to selecting "Short view" and "Single view" from the View submenu.
  • KFileDetailView: Corresponds to selecting "Detailed view" and "Single view" from the View submenu.
  • KCombiView: Corresponds to selecting "Separate directories" from the View submenu. This is a splitter widget which displays a KFileIconView (see above) on the left side and either a KFileIconView (if "Short view" is selected) or a KFileDetailView (if "Detailed view" is selected) on the right side.
  • KFilePreview: Corresponds to selecting "Preview" from the View submenu. This is also a splitter, which shows a KFileIconView (if "Short view" is selected) or a KFileDetailView (if "Detailed view" is selected) on the left side and a widget derived from KPreviewWidgetBase on the right side. By default, the widget on the right side is a KImagePreviewWidget, but this can be changed. This should be very rarely necessary, because the KImagePreviewWidget uses a mechanism for obtaining preview images (also known as thumbnails) which can be extended by installing additional ThumbCreator services. In this way, the same preview images can also be used by Konqueror's icon view.

KURLComboBox

This is a combo box for selecting from a number of files and directories. It runs in one of three modes. The KURLComboBox at the top of the file dialog is in "Directories" mode, the one at the bottom in "Files" mode. Items in the popup menu are shown as URLs together with their MIME type icon. Additionally, one can add a number of default items which are shown as clear text. For example:

KURL u(QDir::homeDirPath());
QString text = i18n("Home Directory");
QPixmap pixmap = KMimeType::pixmapForURL(u, 0, KIcon::Small);
combobox->addDefaultURL(u, pixmap, text);

KFileFilter

This is a combo box for selecting from a number of file filters or MIME types. There are two ways to populate it with items:

First, you can give a linebreak-separated list of strings of the following form:

combo->setFilter("*.cpp|Implementation files\n*.h|Header files");

This displays the clear text strings in the popup in order to select the according patterns. The other method is to give a list of MIME types:

QStringList mimeTypes;
mimeTypes << "image/png";
mimeTypes << "text/html";
combo->setMimeFilter(mimeTypes);

Other widgets

Apart from the widgets used in the file dialog, there is a number of related classes (partially contained in the ksycoca library):

KURLCompletion

This is a subclass of KCompletion and specifically designed to provide automatic completions for URLs. It can operate in one of two modes: ExeCompletion completes names of executables by searching them in $PATH (if they are not given as absolute file names). FileCompletion completes generic URLs. This works even for remote addresses.

Completion support can easily be added to line edits (derived from KLineEdit) or combo boxes (derived from KComboBox):

KCompletion *completion =
    new KURLCompletion(KURLCompletion::ExeCompletion);
lineEdit->setCompletionObject(completion);
lineEdit->setAutoDeleteCompletionObject(true);

KURLPixmapProvider

This is a subclass of KPixmapProvider which resolves pixmaps for URLs.

Support for URL icons in combo boxes (derived from KComboBox) can be easily added:

KPixmapProver *pixmapProvider = new KURLPixmapProvider();
comboBox->setPixmapProvider(pixmapProvider);

KURLRequester

This is a lineedit combined with a button that invokes a file dialog. It uses the KURLCompletion class described above.

KURLRequesterDlg

A simple dialog for letting the user input a file name or URL. It is a very thin wrapper around the KURLRequester widget. For example, this is used when you choose "Location->Open Location" in Konqueror.

KOpenWithDlg

The dialog shown by Konqueror when you click on a file with unknown MIME type.

KPropertiesDialog

The properties dialog you get when you choose the "Properties" item from Konqueror's context menu or the context menu in the file dialog. The dialog can be extended with more tabs by inserting additional KPropsDlgPlugin) widgets.

KIconDialog

A dialog for selecting icons.

Furthermore, a number of additional IO jobs:

KDirSize

This computes the sum of the file sizes in a directory.

KDiskFreeSp

A class for finding out the free disk space on a disk.

KIO::PreviewJob

A job for creating thumbnails for a set of files.


Initial Author: Bernd Gehrmann

Note: this page should be moved to the Template namespaceThis page is a template, editing it will affect all the pages that make use of it, so users should be especially careful when editing it.

You can include this content in another page by using the wiki markup {{User:Claus chr/Search}}. For more details on how to use templates see "A Quick Guide to Templates".

Included content begins.


This page is a category. Below the wikitext of this page is an automated listing of all pages in this category. To add a page to this category, add the wiki-style link [[Category:Claus chr/Search]] to that page directly or indirectly (e.g. by template inclusion).


Included content ends.


Introduction

In most of the cases it's quite obvious how to use these three classes and display data in it. But when it comes to displaying larger amount of data it helps a lot if the programmer knows how these classes work internally to be able to use them better, as they offer already some optimations (and also I'm tired of telling the same things again and again :-)

Finally these three classes are quite consistent in Qt 2.1, so most of the things I will tell here apply to all of them. First I'll tell some stuff about the basics and later on some more fency stuff is coming.

NOTE: Never use QTableView to write a widget for displaying large amounts of data. In most cases one of the classes mentioned here should fit your needs. If this is not the case and you need to write your own class, use QScrollView as baseclass. Although in the first impression QTableView often looks like a good choice later on you will find out that this was not the case, and QScrollView fits better.

Inserting and removing items

All classes contain a number of items. To insert such an item it's the easiest way to use the related item class (QListViewItem, etc.). To insert such an item create a new instance and specify the view in the constructor of the item. That's all and nothing special so far. Now when it comes to inserting lots of items at once (e.g. using a loop) I've seen people playing around with timers and other paint optimizations to avoid having the view repaint its contents too often. But the programmers which use these classes don't need to do that at all since the views already perform that type of timer magic. So If you do e.g.

QIconView *view = .... // something
for ( int i = 0; i < 2000; ++i ) {
    (void)new QIconViewItem( view, QString( "Item %1" ).arg( i ) );

the iconview will not do a repaint for each new inserted item, but it will only do a repaint after the loop terminated. So inserting will not flicker or be slow. The same applies for QListBox and QListView. So, don't do any timer magic of your own, the views do that for you! This means the views internally delay the repaint after inserting a new item using a QTimer. Now when a new item is inserted this timer is stopped and restarted. So, if lots of items are inserted, this repaint timer is stopped and restarted all the time and it never comes to a repaint until the last item has been inserted and some milliseconds elapsed.

To remove an item, you don't need to use any methods of the view or so. Just delete the item using the delete operator. The destructors of the items do all the needed work.

Now, in some cases you might still want to disable repainting (updating) the view yourself. This can be done using setEnableUpdates( bool ). But remember, all three classes are derived from QScrollView, so you have do enable/disable updating of the viewport!. So do e.g.

myView->viewport()->setEnableUpdates( FALSE );
// ....
myView->viewport()->setEnableUpdates( TRUE );

Reacting on the correct signals

Finally also all three view classes have a set of consistent signals. This means each class has some specific signals plus some general signals. Most of the time you will use some of the general signals, as these are the signals which are emitted on special mouse and key events.

I leave out here the arguments, as they differ a bit depending on the view. But in most signals you get a pointer to a view item plus some other arguments. Here are the signals with a short description. For further details (e.g. arguments) refer to the documentation of these classes.

  • selectionChanged There are two selectionChanged signals. One with no arguments and one with a pointer to a view item. The first one is always emitted when the selection changes (different item(s) gets the selection). The second signal is only emitted in Single selection mode and the argument points to the newly selected item.
  • currentChanged As all these classes support keyboard navigation, there is always one current item: the item which is surrounded by the focus rectangle (in Single selection mode, the current item is always the same as the selected one). All modifications done by keyboard input are done to this item. This signal is emitted when a new item becomes current with a pointer to the item as argument.
  • clicked This signal is emitted when the user clicks an item or the view with any button. The argument is a pointer to the clicked item or 0 if the user clicked somewhere into the view but not on an item.
  • pressed This signal is emitted when the user presses an item or the view with any button. The argument is a pointer to the pressed item or 0 if the user pressed somewhere into the view but not on an item.
  • doubleClicked This signal is emitted when the user double clicks on an item or the view. The argument is a pointer to the clicked item or 0 if the user clicked somewhere into the view but not on an item.
  • returnPressed This signal is emitted when the user presses return. The argument is a pointer to the current item.
  • rightButtonClicked This signal is emitted when the user clicks an item or the view with the right button. The argument is a pointer to the clicked item or 0 if the user clicked somewhere into the view but not on an item.
  • rightButtonPressed This signal is emitted when the user presses an item or the view with the right button. The argument is a pointer to the pressed item or 0 if the user pressed somewhere into the view but not on an item.

All of the pressed signals are emitted in the mousePressEvent, and all the clicked signals are emitted in the mouseReleaseEvent (click equals press followed by release).

Then there are a number of signals emitted by each view which I will not discuss here, as I think the signals mentioned here are the most important ones.

Single Click / Double Click

TODO

Sorting Items

TODO

Selection Modes

Each of the three classes supports four selection modes. These are following

  • Single When the user selects an item, any already-selected item becomes unselected, and the user cannot unselect the selected item. This means that the user can never clear the selection, even though the selection may be cleared by the application programmer using <TheViewClass>::clearSelection().
  • Multi When the user selects an item in the most ordinary way, the selection status of that item is toggled and the other items are left alone.
  • Extended When the user selects an item in the most ordinary way, the selection is cleared and the new item selected. However, if the user presses the CTRL key when clicking on an item, the clicked item gets toggled and all other items are left untouched. And if the user presses the SHIFT key while clicking on an item, all items between the current item and the clicked item get selected or unselected depending on the state of the clicked item. Also multiple items can be selected by dragging the mouse while the left mouse button stayes pressed.
  • NoSelection Items cannot be selected.

In other words, Single is a real single-selection view, Multi a real multi-selection view, and Extended a view where users can select multiple items but usually want to select either just one or a range of contiguous items, and NoSelection is for a view where the user can look but not touch.

Because of compatibility reasons the enum with the selection modes has not been moved to the Qt namespace. So, each view class contains an enum with the same selection modes, which meas for setting a selection mode you have to use <TheViewClass>::<SelectionMode> (e.g. iconview->setSelectionMode( QIconView::Extended ) ).

Drag'n'Drop

TODO

In-Place renaiming of items

TODO

Special Settings of QListBox

TODO

In most cases listboxes are used to dispay plain lists. But QListBox can also display its items in multiple columns with dynamic or static widths and heights. See following QListBox memeber methods for further details:

  • setRowMode
  • setColumnMode
  • setVariableWidth
  • setVariableHeight

Here is a screenshot of a plain listbox and one of a listbox with multiple columns (with dynamic column widths)


One column listbox screenshot
Multi colum listbox screenshot

Finally, to iterate over all items of a QListBox use following code:

QListBox *lb = .... // something
for ( int i = 0; i < lb->count(); ++i ) {
    lb->item( i )->doSomething();

Special Settings of QListView

TODO

Finally, to iterate over all items of a QListView, use the QListViewItemIterator class:

QListView *view = ... //something
QListViewItemIterator it( view );
for ( ; it.current(); ++it )
    it.current()->doSomething();

Special Settings of QIconView

TODO

Finally, to iterate over all items of a QIconView, use following code:

QIconView *view = ... //something
for (QIconViewItem *item = view->firstItem();
     item; item = item->nextItem()) {
    item->doSomething();
}


Initial Author: Reginald Stadlbauer

What are KDE services?

The notion of a service is a central concept in KDE's modular architecture. There is no strict technical implementation connected with this term - services can be plugins in the form of shared libraries, or they can be programs controlled via DCOP. By claiming to be of a certain service type, a service promises to implement certain APIs or features. In C++ terms, one can think of a service type as an abstract class, and a service as an implementation of that interface.

The advantage of this separation is clear: An application utilizing a service type does not have to know about possible implementations of it. It just uses the APIs associated with the service type. In this way, the used service can be changed without affecting the application. Also, the user can configure which services he prefers for certain features.

Some examples:

  • The HTML rendering engine used in Konqueror is an embedabble component that implements the service types KParts/ReadOnlyPart and Browser/View.
  • In KDevelop HEAD, most functionality is packaged in plugins with the service type KDevelop/Part. At startup, all services with this type are loaded, such that you can extend the IDE in a very flexible way.
  • In the icon view, Konqueror displays - if enabled - thumbnail pictures of images, HTML pages, PDF and text files. This ability can be extended. If you want it to display preview pictures of your own data files with some MIME type, you can implement a service with service type ThumbCreator.

Obviously, a service is not only characterized by the service types it implements, but also by some properties. For example, a ThumbCreator does not only claim to implement the C++ class with the ThumbCreator, it also has a list of MIME types it is responsible for. Similarly, KDevelop parts have the programming language they support as a property. When an application requests a service type, it can also list constraints on the properties of the service. In the above example, when KDevelop loads the plugins for a Java project, it asks only for the plugins which have Java as the programming language property. For this purpose, KDE contains a full-blown CORBA-like trader with a complex query language.

Defining service types

New service types are added by installing a description of them into the directory KDEDIR/share/servicetypes. In an automake framework, this can be done with this Makefile.am snippet:

kde_servicetypesdir_DATA = kdeveloppart.desktop
EXTRA_DIST = $(kde_servicetypesdir_DATA)

The definition kdeveloppart.desktop of a KDevelop part looks as follows:

[Desktop Entry]
Type=ServiceType
X-KDE-ServiceType=KDevelop/Part
Name=KDevelop Part

[PropertyDef::X-KDevelop-Scope]
Type=QString

[PropertyDef::X-KDevelop-ProgrammingLanguages]
Type=QStringList

[PropertyDef::X-KDevelop-Args]
Type=QString

In addition to the usual entries, this example demonstrates how you declare that a service has some properties. Each property definition corresponds to a group [PropertyDef::name] in the configuration file. In this group, the Type entry declares the type of the property. Possible types are everything that can be stored in a QVariant.

Defining shared library services

Service definitions are stored in the directory KDEDIR/share/services:

kde_servicesdir_DATA = kdevdoxygen.desktop
EXTRA_DIST = $(kde_servicesdir_DATA)

The content of the following example file kdevdoxygen.desktop defines the KDevDoxygen plugin with the service type KDevelop/Part:

[Desktop Entry]
Type=Service
Comment=Doxygen
Name=KDevDoxygen
ServiceTypes=KDevelop/Part
X-KDE-Library=libkdevdoxygen
X-KDevelop-ProgrammingLanguages=C,C++,Java
X-KDevelop-Scope=Project

In addition to the usual declarations, an important entry is X-KDE-Library. This contains the name of the libtool library (without the .la extension). It also fixes (with the prefix init_ prepended) the name of the exported symbol in the library which returns an object factory. For the above example, the library must contain the following function:

extern "C" {
  void *init_libkdevdoxygen()
  {
    return new DoxygenFactory;
  }
};

The type of the factory class DoxygenFactory depends on the specific service type the service implements. In our example of a KDevelop plugin, the factory must be a KDevFactory (which inherits KLibFactory). More common examples are KParts::Factory which is supposed to produce KParts::ReadOnlyPart objects or in most cases the generic KLibFactory.

Using shared library services

In order to use a shared library service in an application, you need to obtain a KService object representing it. This is discussed in the section about MIME types (and in a section about the trader to be written :-)

With the KService object at hand, you can very simply load the library and get a pointer to its factory object:

KService *service = ...
QString libName = QFile::encodeName(service->library());
KLibFactory *factory = KLibLoader::self()->factory(libName);
if (!factory) {
  QString name = service->name();
  QString errorMessage = KLibLoader::self()->lastErrorMessage();
  KMessageBox::error(0, i18n("Error while loading service %1.\n"
                             "The diagnostics from libtool is:\n%2")
                        .arg(name).arg(errorMessage);
}

From this point, the further proceeding depends again on the service type. For generic plugins, you create objects with the method KLibFactory::create(). For KParts, you must cast the factory pointer to the more specific KParts::Factory and use its create() method:

if (factory->inherits("KParts::Factory")) {
  KParts::Factory *partFactory = static_cast<KParts::Factory*>(factory);
  QObject *obj = partFactory->createPart(parentWidget, widgetName,
                                         parent, name,
                                         "KParts::ReadOnlyPart");
  // ...
} else {
    cout << "Service does not implement the right factory" << endl;
}

Defining DCOP services

A DCOP service is usually implemented as a program that is started up when it is needed. It then goes into a loop and listens for DCOP connections. The program may be an interactive one, but it may also run completely or for a part of its lifetime as a daemon in the background without the user noticing it. An example for such a daemon is kio_uiserver, which implements user interaction such as progress dialog for the KIO library. The advantage of such a centralized daemon in this context is that e.g. the download progress for several different files can be shown in one window, even if those downloads were initiated from different applications.

A DCOP service is defined differently from a shared library service. Of course, it doesn't specify a library, but instead an executable. Also, DCOP services do not specify a ServiceType line, because usually they are started by their name. As additional properties, it contains two lines:

X-DCOP-ServiceType specifies the way the service is started. The value Unique says that the service must not be started more than once. This means, if you try to start this service (e.g. via KApplication::startServiceByName(), KDE looks whether it is already registered with DCOP and uses the running service. If it is not registered yet, KDE will start it up and wait until is registered. Thus, you can immediately send DCOP calls to the service. In such a case, the service should be implemented as a KUniqueApplication.

The value Multi for X-DCOP-ServiceType says that multiple instances of the service can coexist, so every attempt to start the service will create another process. As a last possibility the value None can be used. In this case, a start of the service will not wait until it is registered with DCOP.

X-KDE-StartupNotify should normally be set to false. Otherwise, when the program is started, the task bar will show a startup notification, or, depending on the user's settings, the cursor will be changed.

Here is the definition of kio_uiserver:

[Desktop Entry]
Type=Service
Name=kio_uiserver
Exec=kio_uiserver
X-DCOP-ServiceType=Unique
X-KDE-StartupNotify=false

Using DCOP services

A DCOP service is started with one of several methods in the KApplication class:

DCOPClient *client = kapp->dcopClient();
client->attach();
if (!client->isApplicationRegistered("kio_uiserver")) {
  QString error;
  if (KApplication::startServiceByName("kio_uiserver",
                                       QStringList(), &error))
    cout << "Starting kioserver failed with message " << error << endl;
}
// ...
QByteArray data, replyData;
QCString replyType;
QDataStream arg(data, IO_WriteOnly);
arg << true;
if (!client->call("kio_uiserver", "UIServer", "setListMode(bool)", 
                  data, replyType, replyData))
  cout << "Call to kio_uiserver failed" << endl;
// ...

Note that the example of a DCOP call given here uses explit marshalling of arguments. Often you will want to use a stub generated by dcopidl2cpp instead, because it is much simpler and less error prone.

In the example given here, the service was started "by name", i.e. the first argument to KApplication::startServiceByName() is the name is appearing in the Name line of the desktop file. An alternative is to use KApplication::startServiceByDesktopName(), which takes the file name of its desktop file as argument, i.e. in this case "kio_uiserver.desktop".

All these calls take a list of URLs as a second argument, which is given to the service on the command line. The third argument is a pointer to a QString. If starting the service fails, this argument is set to a translated error message.


Initial Author: Bernd Gehrmann

What are MIME types?

MIME types are used to describe the content type of files or data chunks. Originally they were introduced in order to allow sending around image or sound files etc. by e-mail (MIME stands for "Multipurpose Internet Mail Extensions"). Later this system was also used by web browsers to determine how to present data sent by a web server to the user. For example, an HTML page has a MIME type "text/html", a postscript file "application/postscript". In KDE, this concept is used at a variety of places:

  • In Konqueror's icon view, files are represented by icons. Each MIME type has a certain associated icon shown here.
  • When you click onto a file icon or a file name in Konqueror, either the file is shown in an embedded view, or an application associated with the file type is opened.
  • When you drag and drop some data from one application to another (or within the same application), the drop target may choose to accept only certain data types. Furthermore, it will handle image data different from textual data.
  • Clipboard data has a MIME type. Traditionally, X programs only handle pixmaps or texts, but with Qt, there are no restrictions on the data type.

From the above examples, it is clear that MIME handling is a complex issue. First, it is necessary to establish a mapping from file names to MIME types. KDE goes one step further in allowing even file contents to be mapped to MIME types, for cases in which the file name is not available. Second, it is necessary to map MIME types to applications or libraries which can view or edit a file with a certain type, or create a thumbnail picture for it.

There is a variety of APIs to figure out the MIME type of data or files. In general, there is a certain speed/reliability trade-off you have to make. You can find out the type of a file by examining only its file name (i.e. in most cases the file name extension). For example, a file foo.jpg is normally "image/jpeg". In cases where the extension is stripped off this is not safe, and you actually have to look at the contents of the file. This is of course slower, in particular for files that have to be downloaded via HTTP first. The content-based method is based on the file KDEDIR/share/mimelnk/magic and therefore difficult to extend. But in general, MIME type information can easily be made available to the system by installing a .desktop file, and it is efficiently and conveniently available through the KDE libraries.

Defining MIME types

Let us define a type "application/vnd.kde.foo" for our new foobar program. To this end, you have to write a file vnd.kde.foo.desktop and install it into KDEDIR/share/mimelnk/application. (This is the usual location, which may differ between distributions). This can be done by adding this to the Makefile.am:

mimedir = $(kde_mimedir)/application
mime_DATA = vnd.kde.foo.desktop
EXTRA_DIST = $(mime_DATA)

The file foo.desktop should look as follows:

[Desktop Entry]
Type=MimeType
MimeType=application/vnd.kde.foo
Icon=fooicon
Patterns=*.foo;
DefaultApp=foobar
Comment=Foo Data File
Comment[de]=Foo Datei

The "Comment" is entry is supposed to be translated. Since the .desktop file specifies an icon, you should also install an icon fooicon.png, which represents the file e.g. in Konqueror.

In the KDE libraries, such a type definition is mapped to an instance of the class KMimeType. Use this like in the following example:

KMimeType::Ptr type = KMimeType::mimeType("application/vnd.kde.foo");
kdDebug() << "Type:    " << type->name() << endl;
kdDebug() << "Icon:    " << type->icon() << endl;
kdDebug() << "Comment: " << type->comment() << endl;
QStringList patterns = type->patterns();
QStringList::ConstIterator it;
for (it = patterns.begin(); it != patterns.end(); ++it)
  kdDebug() << "Pattern: " << (*it) << endl;

Last not least you should register your new MIME type with IANA. Please contact Marc Mutz for help on this.

Finding out the MIME type of data

The fast method for finding out the type of a file is KMimeType::findByURL(). This looks for the url string and in most cases determines the type from the extension. For certain protocols (e.g. http, man, info), this mechanism is not used. For example, CGI scripts on web servers written in Perl often have the extension .pl, which would indicate a "text/x-perl" type. However, we file delivered by the server is the output of this script, which is normally HTML. For such a case, KMimeType::findByURL() returns the MIME type "application/octet-stream" (available through KMimeType::defaultMimeType()), which indicates a failure to find out the type.

KMimeType::Ptr type = KMimeType::findByURL("/home/user/foobar.jpg");
if (type->name() == KMimeType::defaultMimeType())
  kdDebug() << "Could not find out type" << endl;
else
  kdDebug() << "Type: " << type->name() << endl;

(this method has some more arguments, but these are undocumented, so simply forget about them.)

You may want to find out a MIME from the contents of file instead of the file name. This is more reliable, but also slower, as it requires reading a part of the file. This is done with the KMimeMagic class, which has different error handling:

KMimeMagicResult *result =
    KMimeMagic::self()->findFileType("/home/user/foobar.jpg");
if (!result || !result->isValid())
  kdDebug() << "Could not find out type" << endl;
else
  kdDebug() << "Type: " << result->mimeType() << endl;

As a variant of this function, you can also determine the type of a memory chunk. This is e.g. used in KWrite in order to find out the highlighting mode:

QByteArray array;
//...
KMimeMagicResult *res = KMimeMagic::self()->findBufferType(array);
if (!res || !res->isValid())
  kdDebug() << "Could not find out type" << endl;
else
  kdDebug() << "Type: " << res->mimeType() << endl;

Of course, even KMimeMagic is only able to determine a file type from the contents of a local file. For remote files, there is a further possibility:

KURL url("http://developer.kde.org/favicon.ico");
QString type = KIO::NetAccess::mimetype(url);
if (type == KMimeType::defaultMimeType())
  kdDebug() << "Could not find out type" << endl;
else
  kdDebug() << "Type: " << type << endl;

This starts a KIO job to download a part of the file and check this. Note that this function is perhaps quite slow and blocks the program. Normally you will only want to use this if KMimeType::findByURL() has returned "application/octet-stream".

On the other hand, if you do not want to block your application, you can also explicitly start the KIO job and connect to some of its signals:

void FooClass::findType()
{
  KURL url("http://developer.kde.org/favicon.ico");
  KIO::MimetypeJob *job = KIO::mimetype(url);
  connect(job, SIGNAL(result(KIO::Job*)),
          this, SLOT(mimeResult(KIO::Job*)));
}

void FooClass::mimeResult(KIO::Job *job)
{
  if (job->error())
    job->showErrorDialog();
  else
    kdDebug() << "MIME type: "
              << ((KIO::MimetypeJob *)job)->mimetype() << endl;
}

Mapping a MIME type to an application or service

When an application is installed, it installs a .desktop file which contains a list of MIME types this application can load. Similarly, components like KParts make this information available by their service .desktop files. So in general, there are several programs and components which can process a given MIME type. You can obtain such a list from the class KServiceTypeProfile:

KService::OfferList offers =
    KServiceTypeProfile::offers("text/html", "Application");
KService::OfferList::ConstIterator it;
for (it = offers.begin(); it != offers.end(); ++it) {
  KService::Ptr service = (*it);
  kdDebug() << "Name: " << service->name() << endl;
}

The return value of this function is a list of service offers. A KServiceOffer packages a KService::Ptr together with a preference number. The list returned by KServiceTypeProfile::offers() is ordered by the user's preference. The user can change this by calling "keditfiletype text/html" or choosing "Edit File Type" on Konqueror's context menu on a HTML file.

In the above example, an offer list of the applications supporting text/html was requested. This will - among others - contain HTML editors like Quanta Plus. You can also replace the second argument "Application" by "KParts::ReadOnlyPart". In that case, you get a list of embedabble components for presenting HTML content, for example KHTML.

In most cases, you are not interested in the list of all service offers for a combination of MIME type and service type. There is a convenience function which gives you only the service offer with the highest preference:

KService::Ptr offer =
  KServiceTypeProfile::preferredService("text/html", "Application");
if (offer)
  kdDebug() << "Name: " << service->name() << endl;
else
  kdDebug() << "No appropriate service found" << endl;

For even more complex queries, there is a full-blown CORBA-like trader.

In order to run an application service with some urls, use KRun:

KURL::List urlList;
urlList << "http://www.ietf.org/rfc/rfc1341.txt?number=1341";
urlList << "http://www.ietf.org/rfc/rfc2046.txt?number=2046";
KRun::run(offer.service(), urlList);

Miscellaneous

In this section, we want to list some APIs which are loosely related to the previous discussion.

Getting an icon for a URL. This looks for the type of the URL and returns the associated icon.

KURL url("ftp://ftp.kde.org/pub/incoming/wibble.c");
QString icon = KMimeType::iconForURL(url);

Running a URL. This looks for the type of the URL and starts the user's preferred program associated with this type.

KURL url("http://dot.kde.org");
new KRun(url);


Initial Author: Bernd Gehrmann

Introduction

In the age of the world wide web, it is of essential importance that desktop applications can access resources over the internet: they should be able to download files from a web server, write files to an ftp server or read mails from a web server. Often, the ability to access files regardless of their location is called network transparency.

In the past, different approaches to this goals were implemented. The old NFS file system is an attempt to implement network transparency on the level of the POSIX API. While this approach works quite well in local, closely coupled networks, it does not scale for resources to which access is unreliable and possibly slow. Here, asynchronicity is important. While you are waiting for your web browser to download a page, the user interface should not block. Also, the page rendering should not begin when the page is completely available, but should updated regularly as data comes in.

In the KDE libraries, network transparency is implemented in the KIO API. The central concept of this architecture is an IO job. A job may copy, or delete files or similar things. Once a job is started, it works in the background and does not block the application. Any communication from the job back to the application - like delivering data or progress information - is done integrated with the Qt event loop.

Background operation is achieved by starting ioslaves to perform certain tasks. ioslaves are started as separate processes and are communicated with through UNIX domain sockets. In this way, no multi-threading is necessary and unstable slaves can not crash the application that uses them.

File locations are expressed by the widely used URLs. But in KDE, URLs do not only expand the range of addressable files beyond the local file system. It also goes in the opposite direction - e.g. you can browse into tar archives. This is achived by nesting URLs. For example, a file in a tar archive on a http server could have the URL

http://www-com.physik.hu-berlin.de/~bernd/article.tgz#tar:/paper.tex

Using KIO

In most cases, jobs are created by calling functions in the KIO namespace. These functions take one or two URLs as arguments, and possible other necessary parameters. When the job is finished, it emits the signal result(KIO::Job*). After this signal has been emitted, the job deletes itself. Thus, a typical use case will look like this:

void FooClass::makeDirectory()
{
    SimpleJob *job = KIO::mkdir(KURL("file:/home/bernd/kiodir"));
    connect( job, SIGNAL(result(KIO::Job*)), 
             this, SLOT(mkdirResult(KIO::Job*)) );
}

void FooClass::mkdirResult(KIO::Job *job)
{
    if (job->error())
        job->showErrorDialog();
    else
        cout << "mkdir went fine" << endl;
}

Depending on the type of the job, you may connect also to other signals.

Here is an overview over the possible functions:

KIO::mkdir(const KURL &url, int permission)

Creates a directory, optionally with certain permissions.

KIO::rmdir(const KURL &url)

Removes a directory.

KIO::chmod(const KURL &url, int permissions)

Changes the permissions of a file.

KIO::rename(const KURL &src, const KURL &dest, bool overwrite)

Renames a file.

KIO::symlink(const QString &target, const KURL &dest, bool overwrite, bool showProgressInfo)

Creates a symbolic link.

KIO::stat(const KURL &url, bool showProgressInfo)

Finds out certain information about the file, such as size, modification time and permissions. The information can be obtained from KIO::StatJob::statResult() after the job has finished.

KIO::get(const KURL &url, bool reload, bool showProgressInfo)

Transfers data from a URL.

KIO::put(const KURL &url, int permissions, bool overwrite, bool resume, bool showProgressInfo)

Transfers data to a URL.

KIO::http_post(const KURL &url, const QByteArray &data, bool showProgressInfo)

Posts data. Special for HTTP.

KIO::mimetype(const KURL &url, bool showProgressInfo)

Tries to find the MIME type of the URL. The type can be obtained from KIO::MimetypeJob::mimetype() after the job has finished.

KIO::file_copy(const KURL &src, const KURL &dest, int permissions, bool overwrite, bool resume, bool showProgressInfo)

Copies a single file.

KIO::file_move(const KURL &src, const KURL &dest, int permissions, bool overwrite, bool resume, bool showProgressInfo)

Renames or moves a single file.

KIO::file_delete(const KURL &url, bool showProgressInfo)

Deletes a single file.

KIO::listDir(const KURL &url, bool showProgressInfo)

Lists the contents of a directory. Each time some new entries are known, the signal KIO::ListJob::entries() is emitted.

KIO::listRecursive(const KURL &url, bool showProgressInfo)

Similar to the listDir() function, but this one is recursive.

KIO::copy(const KURL &src, const KURL &dest, bool showProgressInfo)

Copies a file or directory. Directories are copied recursively.

KIO::move(const KURL &src, const KURL &dest, bool showProgressInfo)

Moves or renames a file or directory.

KIO::del(const KURL &src, bool shred, bool showProgressInfo)

Deletes a file or directory.

Directory entries

Both the KIO::stat() and KIO::listDir() jobs return their results as a type UDSEntry, UDSEntryList resp. The latter is defined as QValueList<UDSEntry>. The acronym UDS stands for "Universal directory service". The principle behind it is that the a directory entry only carries the information which an ioslave can provide, not more. For example, the http slave does not provide any information about access permissions or file owners. Instead, a UDSEntry is a list of UDSAtoms. Each atom provides a specific piece of information. It consists of a type stored in m_uds and either an integer value in m_long or a string value in m_str, depending on the type.

The following types are currently defined:

  • UDS_SIZE (integer) - Size of the file.
  • UDS_USER (string) - User owning the file.
  • UDS_GROUP (string) - Group owning the file.
  • UDS_NAME (string) - File name.
  • UDS_ACCESS (integer) - Permission rights of the file, as e.g. stored by the libc function stat() in the st_mode field.
  • UDS_FILE_TYPE (integer) - The file type, as e.g. stored by stat() in the st_mode field. Therefore you can use the usual libc macros like S_ISDIR to test this value. Note that the data provided by ioslaves corresponds to stat(), not lstat(), i.e. in case of symbolic links, the file type here is the type of the file pointed to by the link, not the link itself.
  • UDS_LINK_DEST (string) - In case of a symbolic link, the name of the file pointed to.
  • UDS_MODIFICATION_TIME (integer) - The time (as in the type time_t) when the file was last modified, as e.g. stored by stat() in the st_mtime field.
  • UDS_ACCESS_TIME (integer) - The time when the file was last accessed, as e.g. stored by stat() in the st_atime field.
  • UDS_CREATION_TIME (integer) - The time when the file was created, as e.g. stored by stat() in the st_ctime field.
  • UDS_URL (string) - Provides a URL of a file, if it is not simply the the concatenation of directory URL and file name.
  • UDS_MIME_TYPE (string) - MIME type of the file
  • UDS_GUESSED_MIME_TYPE (string) - MIME type of the file as guessed by the slave. The difference to the previous type is that the one provided here should not be taken as reliable (because determining it in a reliable way would be too expensive). For example, the KRun class explicitly checks the MIME type if it does not have reliable information.

Although the way of storing information about files in a UDSEntry is flexible and practical from the ioslave point of view, it is a mess to use for the application programmer. For example, in order to find out the MIME type of the file, you have to iterate over all atoms and test whether m_uds is UDS_MIME_TYPE. Fortunately, there is an API which is a lot easier to use: the class KFileItem.

Synchronous usage

Often, the asynchronous API of KIO is too complex to use and therefore implementing full asynchronicity is not a priority. For example, in a program that can only handle one document file at a time, there is little that can be done while the program is downloading a file anyway. For these simple cases, there is a mucher simpler API in the form of a set of static functions in KIO::NetAccess. For example, in order to copy a file, use

KURL source, target;
source = ...;
target = ...
KIO::NetAccess::copy(source, target);

The function will return after the complete copying process has finished. Still, this method provides a progress dialog, and it makes sure that the application processes repaint events.

A particularly interesting combination of functions is download() in combination with removeTempFile(). The former downloads a file from given URL and stores it in a temporary file with a unique name. The name is stored in the second argument. If the URL is local, the file is not downloaded, and instead the second argument is set to the local file name. The function removeTempFile() deletes the file given by its argument if the file is the result of a former download. If that is not the case, it does nothing. Thus, a very easy to use way of loading files regardless of their location is the following code snippet:

KURL url;
url = ...;
QString tempFile;
if (KIO::NetAccess::download(url, tempFile) {
    // load the file with the name tempFile
    KIO::NetAccess::removeTempFile(tempFile);
}

Meta data

As can be seen above, the interface to IO jobs is quite abstract and does not consider any exchange of information between application and IO slave that is protocol specific. This is not always appropriate. For example, you may give certain parameters to the HTTP slave to control its caching behavior or send a bunch of cookies with the request. For this need, the concept of meta data has been introduced. When a job is created, you can configure it by adding meta data to it. Each item of meta data consists of a key/value pair. For example, in order to prevent the HTTP slave from loading a web page from its cache, you can use:

void FooClass::reloadPage()
{
    KURL url("http://www.kdevelop.org/index.html");
    KIO::TransferJob *job = KIO::get(url, true, false);
    job->addMetaData("cache", "reload");
    ...
}

The same technique is used in the other direction, i.e. for communication from the slave to the application. The method Job::queryMetaData() asks for the value of the certain key delivered by the slave. For the HTTP slave, one such example is the key "modified", which contains a (stringified representation of) the date when the web page was last modified. An example how you can use this is the following:

void FooClass::printModifiedDate()
{
    KURL url("http://www.kde.org");
    KIO::TransferJob *job = KIO::get(url, true, false);
    connect( job, SIGNAL(result(KIO::Job*)),
             this, SLOT(transferResult(KIO::Job*)) );
}

void FooClass::transferResult(KIO::Job *job)
{
    QString mimetype;
    if (job->error())
        job->showErrorDialog();
    else {
        KIO::TransferJob *transferJob = (KIO::TransferJob*) job;
        QString modified = transferJob->queryMetaData("modified");
        cout << "Last modified: " << modified << endl;
}

Scheduling

When using the KIO API, you usually do not have to cope with the details of starting IO slaves and communicating with them. The normal use case is to start a job and with some parameters and handle the signals the jobs emits.

Behind the curtains, the scenario is a lot more complicated. When you create a job, it is put in a queue. When the application goes back to the event loop, KIO allocates slave processes for the jobs in the queue. For the first jobs started, this is trivial: an IO slave for the appropriate protocol is started. However, after the job (like a download from an http server) has finished, it is not immediately killed. Instead, it is put in a pool of idle slaves and killed after a certain time of inactivity (current 3 minutes). If a new request for the same protocol and host arrives, the slave is reused. The obvious advantage is that for a series of jobs for the same host, the cost for creating new processes and possibly going through an authentication handshake is saved.

Of course, reusing is only possible when the existing slave has already finished its previous job. when a new request arrives while an existing slave process is still running, a new process must be started and used. In the API usage in the examples above, there are no limitation for creating new slave processes: if you start a consecutive series of downloads for 20 different files, then KIO will start 20 slave processes. This scheme of assigning slaves to jobs is called direct. It not always the most appropriate scheme, as it may need much memory and put a high load on both the client and server machines.

So there is a different way. You can schedule jobs. If you do this, only a limited number (currently 3) of slave processes for a protocol will be created. If you create more jobs than that, they are put in a queue and are processed when a slave process becomes idle. This is done as follows:

KURL url("http://www.kde.org");
KIO::TransferJob *job = KIO::get(url, true, false);
KIO::Scheduler::scheduleJob(job);

A third possibility is connection oriented. For example, for the IMAP slave, it does not make any sense to start multiple processes for the same server. Only one IMAP connection at a time should be enforced. In this case, the application must explicitly deal with the notion of a slave. It has to allocate a slave for a certain connection and then assign all jobs which should go through the same connection to the same slave. This can again be easily achieved by using the KIO::Scheduler:

KURL baseUrl("imap://[email protected]");
KIO::Slave *slave = KIO::Scheduler::getConnectedSlave(baseUrl);

KIO::TransferJob *job1 = KIO::get(KURL(baseUrl, "/INBOX;UID=79374"));
KIO::Scheduler::assignJobToSlave(slave, job1);

KIO::TransferJob *job2 = KIO::get(KURL(baseUrl, "/INBOX;UID=86793"));
KIO::Scheduler::assignJobToSlave(slave, job2);

...

KIO::Scheduler::disconnectSlave(slave);

You may only disconnect the slave after all jobs assigned to it are guaranted to be finished.

Defining an ioslave

In the following we discuss how you can add a new ioslave to the system. In analogy to services, new ioslaves are advertised to the system by installing a little configuration file. The following Makefile.am snippet installs the ftp protocol:

protocoldir = $(kde_servicesdir)
protocol_DATA = ftp.protocol
EXTRA_DIST = $(mime_DATA)

The contents of the file ftp.protocol is as follows:

[Protocol]
exec=kio_ftp
protocol=ftp
input=none
output=filesystem
listing=Name,Type,Size,Date,Access,Owner,Group,Link,
reading=true
writing=true
makedir=true
deleting=true
Icon=ftp

The "protocol" entry defines for which protocol this slave is responsible. "exec" is (in contrast what you would expect naively) the name of the library that implements the slave. When the slave is supposed to start, the "kdeinit" executable is started which in turn loads this library into its address space. So in practice, you can think of the running slave as a separate process although it is implemented as library. The advantage of this mechanism is that it saves a lot of memory and reduces the time needed by the runtime linker.

The "input" and "output" lines are not used currently.

The remaining lines in the .protocol file define which abilities the slave has. In general, the features a slave must implement are much simpler than the features the KIO API provides for the application. The reason for this is that complex jobs are scheduled to a couple of subjobs. For example, in order to list a directory recursively, one job will be started for the toplevel directory. Then for each subdirectory reported back, new subjobs are started. A scheduler in KIO makes sure that not too many jobs are active at the same time. Similarly, in order to copy a file within a protocol that does not support copying directly (like the ftp: protocol), KIO can read the source file and then write the data to the destination file. For this to work, the .protocol must advertise the actions its slave supports.

Since slaves are loaded as shared libraries, but constitute standalone programs, their code framework looks a bit different from normal shared library plugins. The function which is called to start the slave is called kdemain(). This function does some initializations and then goes into an event loop and waits for requests by the application using it. This looks as follows:

extern "C" { int kdemain(int argc, char **argv); }

int kdemain(int argc, char **argv)
{
    KLocale::setMainCatalogue("kdelibs");
    KInstance instance("kio_ftp");
    (void) KGlobal::locale();

    if (argc != 4) {
        fprintf(stderr, "Usage: kio_ftp protocol "
                        "domain-socket1 domain-socket2\n");
        exit(-1);
    }

    FtpSlave slave(argv[2], argv[3]);
    slave.dispatchLoop();
    return 0;
}

Implementing an ioslave

Slaves are implemented as subclasses of KIO::SlaveBase (FtpSlave in the above example). Thus, the actions listed in the .protocol correspond to certain virtual functions in KIO::SlaveBase the slave implementation must reimplement. Here is a list of possible actions and the corresponding virtual functions:

reading - Reads data from a URL
void get(const KURL &url)
writing - Writes data to a URL and create the file if it does not exist yet.
void put(const KURL &url, int permissions, bool overwrite, bool resume)
moving - Renames a file.
void rename(const KURL &src, const KURL &dest, bool overwrite)
deleting - Deletes a file or directory.
void del(const KURL &url, bool isFile)
listing - Lists the contents of a directory.
void listDir(const KURL &url)
makedir - Creates a directory.;
void mkdir(const KURL &url, int permissions)

Additionally, there are reimplementable functions not listed in the .protocol file. For these operations, KIO automatically determines whether they are supported or not (i.e. the default implementation returns an error).

Delivers information about a file, similar to the C function stat().
void stat(const KURL &url)
Changes the access permissions of a file.
void chmod(const KURL &url, int permissions)
Determines the MIME type of a file.
void mimetype(const KURL &url)
Copies a file.
copy(const KURL &url, const KURL &dest, int permissions, bool overwrite)
Creates a symbolic link.
void symlink(const QString &target, const KURL &dest, bool overwrite)

All these implementation should end with one of two calls: If the operation was successful, they should call finished(). If an error has occured, error() should be called with an error code as first argument and a string in the second. Possible error codes are listed as enum KIO::Error. The second argument is usually the URL in question. It is used e.g. in KIO::Job::showErrorDialog() in order to parametrize the human-readable error message.

For slaves that correspond to network protocols, it might be interesting to reimplement the method SlaveBase::setHost(). This is called to tell the slave process about the host and port, and the user name and password to log in. In general, meta data set by the application can be queried by SlaveBase::metaData(). You can check for the existence of meta data of a certain key with SlaveBase::hasMetaData().

Communicating back to the application

Various actions implemented in a slave need some way to communicate data back to the application using the slave process:

  • get() sends blocks of data. This is done with data(), which takes a QByteArray as argument. Of course, you do not need to send all data at once. If you send a large file, call data() with smaller data blocks, so the application can process them. Call finished() when the transfer is finished.
  • listDir() reports information about the entries of a directory. For this purpose, call listEntries() with a KIO::UDSEntryList as argument. Analogously to data(), you can call this several times. When you are finished, call listEntry() with the second argument set to true. You may also call totalSize() to report the total number of directory entries, if known.
  • stat() reports information about a file like size, MIME type, etc. Such information is packaged in a KIO::UDSEntry, which will be discussed below. Use statEntry() to send such an item to the application.
  • mimetype() calls mimeType() with a string argument.
  • get() and copy() may want to provide progress information. This is done with the methods totalSize(), processedSize(), speed(). The total size and processed size are reported as bytes, the speed as bytes per second.
  • You can send arbitrary key/value pairs of meta data with setMetaData().

Interacting with the user

Sometimes a slave has to interact with the user. Examples include informational messages, authentication dialogs and confirmation dialogs when a file is about to be overwritten.

  • infoMessage() - This is for informational feedback, such as the message "Retrieving data from <host>" from the http slave, which is often displayed in the status bar of the program. On the application side, this method corresponds to the signal KIO::Job::infoMessage().
  • warning() - Displays a warning in a message box with KMessageBox::information(). If a message box is still open from a former call of warning() from the same slave process, nothing happens.
  • messageBox() - This is richer than the previous method. It allows to open a message box with text and caption and some buttons. See the enum SlaveBase::MessageBoxType for reference.
  • openPassDlg() - Opens a dialog for the input of user name and password.


Initial Author: Bernd Gehrmann

Proposed for moving to community.kde.org
It has been proposed that this page should be moved to the community.kde.org wiki for the following reason:

Archive under https://community.kde.org/Promo/Guidance/Branding

The color palette features four kinds of shades:

  • Shadow color: dark color for shadows
  • Base color: usual color of an object
  • Highlight color: light color for highlights
  • Background color: very light color to be used, for example, as a background color for (dark) text

Color Palette

This is the KDE color palette, provided by the Oxygen project.

Color Palette for Gimp and Krita (From SVN at http://websvn.kde.org)

References

KDE Oxygen

Corporate Identity at Wikipedia

Color meanings

Tools

Color scheme generator 2

Other Resources

Colourlovers.com - top colors and color palettes inspirations

Proposed for moving to community.kde.org
It has been proposed that this page should be moved to the community.kde.org wiki for the following reason:

Archive under https://community.kde.org/Promo/Guidance/Branding

Typeface

The KDE Project suggests using Oxygen (preferred - installed by default on leading KDE distros [1]), Lato (www.latofonts.com/) or Cantarell (abattis.org/cantarell/) typefaces for all printed and screen material. These should be used instead of Bitstream Vera Sans Bold (www.bitstream.com/categories/products/fonts/vera/index.html), which was previously recommended. These are free and open fonts with licenses that are appropriate for KDE materials.

Headlines are either: black; or white on a blue or black background. Sublines and lead-ins can be black on white backgrounds. Copy is always black.

[1] Oxygen font download

KDE Logo Font and KDE-EDU

In general the Kabel-Font may only be used uppercase. It may only be used for the term "KDE" itself and related to topics like KDE-EDU, kids and games.

A free look-alike called "Kabel Book" by A. Carr is available at:

http://eksten.net/webgraphix/fonts/k/kabelb.html

Additionally, many Font Companies offer a Kabel font family commercially.

  • Kabel is a trademark of Heidelberger Druckmaschinen AG, which may be registered in certain jurisdictions, exclusively licensed through Linotype Library GmbH, a wholly owned subsidiary of Heidelberger Druckmaschinen AG.
  • Bitstream Inc. announces long-term agreement to bring high quality fonts to free software:
http://www.bitstream.com/corporate/news/press_2003/type_030122_gnome.html
"The donation of these fonts to the free software community is the final piece that will give full functionality to projects like Freetype, XFT2 and X Render extensions in the Xfree86 project, Pango, KDE and Trolltech's QT Rendering,"

Incorrect use of typography

The incorrect use of typography creates confusion and undermines confidence in the brand.