A First Look at KDE Programming

Mr. Sweet teaches us how to write an application for the KDE desktop—for the experienced GUI programmer.

The stated goal of the K Desktop
Environment, KDE, is to provide a free, user-friendly desktop for
Linux/UNIX systems. The project's participants began by providing a
window manager (kwm/kpanel) and a file manager (kfm) and
retrofitting popular X applications (e.g., Ghostview, xcalc,
ezppp), giving them a common look and feel based on the Qt widget
set from Troll Tech. As time has passed, the KDE libraries (which
provide UI elements and file management services) have grown in
functionality so that developing KDE compliant applications is not
only simple, but enticing.

The program presented in this article,
khello, should provide you with a
good foundation for writing your own KDE application, or providing
a K-UI for your favorite UNIX application. To compile the program,
you need to install Qt 1.3 and KDE. For details, see
http://www.kde.org/beta1.html. Although KDE has just been released
in only beta form, it is quite stable and usable. It has, in fact,
been the primary desktop on my home computer since well before the
beta release (alpha releases and frequent development “snapshots”
have been available for some time).

Like so many before me, I have chosen to present a program
which says, “Hello World!” to its user. Nevertheless, the basic
elements of a KDE application are present: a menu bar, a toolbar,
and an “about” box, as well as the functionality provided by
KApplication and KTopLevelWidget. The UI components are provided by
classes in libkdeui; KApplication belongs to libkdecore.

KApplication is the base class from which KDE applications
are derived. It handles simple session management, access to the
application icon, the help file, and configuration and locale
information. The KApplication constructor takes
argc and argv as arguments
and strips away anything used by X11 or by KApplication and updates
argc so that you can go on to process your
program's options. The macro kapp is defined as
KApplication::getApplication().
This returns a pointer to the KApplication object. You can use
kapp anywhere within your program
after you have created a KApplication. So, of course, you can only
create one KApplication object. The GUI is started with
app-exec() and returns when
app->quit() is called. Notice that your
instance of KApplication need not be told about your
KTopLevelWidget. In our case, this means KHelloTW which is derived
from KTopLevelWidget. There can be only one KTopLevelWidget, and it
informs KApplication of itself.

The basis of the user interface is provided by
KTopLevelWidget. It will manage a menu bar, multiple toolbars and a
status bar, you don't need to resize or position these objects;
just create them and fill with the appropriate information. (Some
session management is also handled by KTopLevelWidget, but this
topic won't be discussed in detail here.) You should derive a class
from KTopLevelWidget, as KHelloTW is, and set up the UI (in the
constructor, for example) before calling
show(). This way, your window will
not appear and then “flash” as its child widgets are created
and/or rearranged. You must call show() for your KTopLevelWidget
before calling app->exec(), since it isn't shown
automatically.

Let's look at khellotw.cpp (Listing
1) to get an idea of how to work within KDE and Qt. First
we create the file menu. We've declared “file” as a pointer to an
object of type QPopupMenu and created the object with “new” so
that the file menu will be available for the life of KHelloTW
(which is, in this case, also the life of the program). The method
insertItem places an item on the menu. In this
case, we have only “Quit”. The ampersand in the argument
&Quit tells Qt to underline the letter
Q and, when this menu is visible, to allow the
user to select “Quit” by pressing Q. The last
argument kkeys->quit() says the user can
press the key combination defined in
KStdAccel::quit() (ctrl-Q) at
any time to exit the program (this is called
an “accelerator key”). The class KStdAccel contains various
standard KDE accelerator keys. We use these definitions when
creating menus to be consistent with the KDE look and feel. The
other two arguments tell Qt which method
(slotQuit()) to call when “Quit” is chosen and
within which instance of the class to call that method. This system
for getting messages from the GUI is called “Signals and Slots”.
If we use the Qt precompiler (called
moc for Meta-Object Compiler), we
can use these signals and slots as if they were a natural part of
C++.

Using moc, we get three new C++ keywords:
signal, slot and
emit. In khellowtw.h, several methods are
declared under the heading “public slots:”. These can be called
directly, like normal methods, but they can also be connected to
signals. Signals are emitted whenever any GUI event occurs. All the
slots which were connected to that signal are called at this point,
and may even be called with arguments so that information can be
passed between classes. (For details on how to use signals and
slots, and for a definition of emit, see the Qt
documentation.)

If we look at the toolbar->insertButton
line in khellotw.cpp, which places a QPushButton on the toolbar, we
see

SIGNAL ((released()), this, SLOT (slotHello()))

This tells KToolBar to connect the signal
released(), which is emitted by QPushButton when
the button is released after being pressed down, to the slot
slotHello(), which puts the phrase “Hello
world!” up in our window. Note that we chose the QPushButton
signal released() over
pressed() because the user expects the action to
occur when he releases the button, not while holding it down. You
could try changing this to see the difference in the feel of the
interface.

The moc precompiler generates some C++ code from your header
file and creates a .moc file. This .moc file should be included
once and only once in one of the files that implements that class.
Notice that khellotw.cpp includes khellotw.moc but main.cpp
(Listing 2) includes khellotw.h
(Listing 3).

To give KHello the look of a KDE application, we have added a
KToolBar and used one of the pixmaps supplied by KDE for the
button. To construct the path to the button pixmap, we've used
kapp->kdedir() rather than hard coding the
path, because users may install KDE in different places in their
file systems. For the rest of the path, refer to the KDE File
System Standard (or KFSSTD at http://www.kde.org/fsstnd.html).
There is also a help menu on our menu bar. KApplication provides
you with a base help menu in
kapp->getHelpMenu(). This menu includes
“About KDE...” and, optionally, “About Qt...” entries which
tell the user about the underlying software, and a “Help” entry
which will start the KDE help viewer
(kdehelp) with the argument

kdedir()+ "/share/doc/default/khello"

which refers to the default KDE help file/directory. If you'd
like to see this in action, simply create the directory, place an
HTML file called khello.html in it, and choose “Help” from the
khello Help menu. When invoking help this way, KApplication uses
the string passed to its constructor as your application's name (in
this case, khello). So there is no
need to tell KDE where your help file is; it is determined by the
KFSSTD and is /share/doc/default/appname/appname.html.

Similarly, you can give your application an icon (which will
appear in the task bar next to your application) by placing an
appname.xpm file in /share/icons/. We've added a separator and
“About KHello...” to the bottom of the menu. Your “about” box
should display at least the title, author and contact information
(for bug reports, feature requests and general praise of your
work). KHello's simple “about” box is a KMsgBox. This is a modal
dialog box, meaning that it is the only window of your program
which will respond to user input during the time it is shown. When
the user selects “OK” the box disappears, the function call
returns and the program continues. It is not necessary to create an
instance of KMsgBox for simple dialogs. The method
KMsgBox::message() is static and
can be called directly as is done in
KHelloTW::slotAbout().

Application communication via drag-and-drop is an integral
part of a cohesive desktop. If your application works with data
files, it should accept URLs dragged from kfm (the KDE file
manager) and process them accordingly. This is simple to do and
khello demonstrates this by displaying any URL that is dropped on
it. To accept URL drop events, declare a widget a “drop zone” by
creating a KDNDDropZone object and connecting its
dropAction() signal to a slot which will process
the event. The KDNDDropZone method called
getURLList() will return a
QStrList (a Qt utility class which manages a
list of strings) containing one or more URLs which were dropped in
a single drop event. The function
slotDropped() sets the text of
“label” to the first URL in the list.

There are several ways to shut down an application. The user
could choose “Close” from the system menu (a right-click on the
title bar brings this up) or click on the close button (an “X” on
the title bar), or one's application may be closed by the window
manager when the X session is terminated. All of these call the
closeEvent() member function of
your KTopLevelWidget. So this is where you should ask the
all-important question, “Would you like to save changes to
______?” Then call kapp->quit(), which tells
your KApplication you are done and the
app->exec() call in
main() returns. To keep your
program organized, you should force a closeEvent() call if you
offer the user an alternative way of exiting your program (like
choosing “Exit” from the “File” menu). This way, all
pre-termination code is in that one place (closeEvent()). You can
force a closeEvent() by calling
close(), which is a member of
KTopWidget. (In fact, it is a member of QWidget from which
KTopWidget is derived.) This is done with
KHelloTW::slotExit().

I encourage you to experiment with KHello and alter the code
to learn about other KDE classes. A good place to start is
KConfig. This class allows you to
read and write from an application-specific configuration file
stored in ~/.kde/config/. You should save the default program
options in closeEvent(), then reread and set them upon construction
of your KTopWidget.

KLocale is another important
class for KDE applications. It helps you to translate your
application into other languages by reading string literals (like
“File”, “Help” or “Hello world!”) in from a file. KLocale
will choose the appropriate strings based on the user's locale
settings. You need only provide the text. Since KDE is developed
and used by people all over the world, it is a good idea to
translate your application; the widespread interest makes it easier
to find someone to help with the translation.

For further information on programming for KDE, I recommend
going through the Qt tutorial at
http://www.troll.no/qt/tutorial.html and visiting the KDE
developer's center at http://www.ph.unimelb.edu.au/~ssk/kde/devel/.
Here you'll find helpful tips on KDE programming as well as
documentation for the KDE libraries and ideas for new KDE
applications. It is in the spirit of the KDE project to announce
your intention to create an application on the KDE mailing list so
that effort is not duplicated. You'll also find out how interested
others are in using your proposed application and, most likely,
receive lots of suggestions for program features. Good luck with
your KDE programming.

David Sweet
is a third-year physics graduate
student at the University of Maryland and a participating
programmer in the KDE project. He is currently working on an
interface to Ispell and a plotting package called KPlot
(http://www.glue.umd.edu/~dsweet/KDE). He can be reached via e-mail
at dsweet@chicago.umd.edu.

Trending Topics

Webinar: 8 Signs You’re Beyond Cron

Scheduling Crontabs With an Enterprise Scheduler
11am CDT, April 29th

Join Linux Journal and Pat Cameron, Director of Automation Technology at HelpSystems, as they discuss the eight primary advantages of moving beyond cron job scheduling. In this webinar, you’ll learn about integrating cron with an enterprise scheduler.