7.4. Application Resources

Applications often need to internally use data that is stored outside the program source code. You might choose to keep data outside the source code because it is large or subject to change. Such data, called application resources, might include icons, pixmaps, sounds, text strings, and documentation.

7.4.1. Standard Resource Locations

By default, global application resources are stored in the directory trees rooted at $KDEDIR/share and .kde/share (the latter being in the user's home directory). These subdirectories may exist in either place, and applications should make use of both sets of resources. Application-specific resources are stored in the subdirectory apps/kappname (where kappname is an application's name). These default locations can be modified by the user. The user can set the KDEDIRS (note the trailing "S" in this variable name) to contain a colon-separated list of directories under which the share subdirectory could lie. For example, the default setting is functionally equivalent to setting KDEDIRS equal to $KDEDIR:$HOME/.kde (where $HOME refers to the user's home directory).

7.4.2. Application Resources

Applications never need to specify full paths to resources or even be concerned with whether they are using resources from $KDEDIR/share or .kde/share. They can use the class KStandardDirs to locate resources by resource type. Table 7.1 summarizes the resource types that are supported by the KStandardDirs class. The subdirectory may lie in $KDEDIR or in .kde in the user's home directory.

Table 7.1. Resource Types Supported by KStandardDirs Class

IdentifierSubdirectoryResource Type
appdatashare/apps/kappnamercApplication-specific data
appsshare/applnkK-Menu structure
cgicgi-binCGI scripts to run from KHelpcenter
configshare/configConfiguration files (for example, kappnamerc)
datashare/appsDirectory holding all application-specific data subdirectories
exebinKDE executables (binaries) directory
htmlshare/doc/htmlHTML documentation
iconshare/iconsApplication icons and miniicons
liblibKDE libraries directory
localeshare/localTranslation files for the KLocale class
mimeshare/mimelnkMime type description files
servicesshare/servicesDescriptions of the services provided by libraries and programs
servicetypesshare/servicetypesCategories of services
soundshare/soundsApplication sounds
toolbarshare/toolbarPictures for use on toolbars
wallpapershare/wallpapersPictures for use as Idesktop wallpaper

Resources of the types mentioned in the preceding table can be accessed, loaded, and manipulated using standard KDE/Qt classes. Custom data types, stored in the application-specific resources directory, might, of course, need custom classes to manipulate them.

The widget KResourceDemo, given in Listings 7.14 and 7.15, shows how to find and load a picture, a sound, and a custom resource (in this case, a text file).

Example 7.14. kresourcedemo.h: Class Declaration for KResourceDemo, a Widget That Demonstrates Loading and Using Application Resources

   2  1: #ifndef __KRESOURCEDEMO_H__
   3  2: #define __KRESOURCEDEMO_H__
   4  3:
   5  4: #include <qlabel.h>
   6  5:
   7  6: #include <kaudio.h>
   8  7:
   9  8:
  10  9: /**
  11 10:  * KResourceDemo
  12 11:  * Show how to access application resources.
  13 12:  **/
  14 13: class KResourceDemo : public QLabel
  15 14: {
  16 15:  public:
  17 16:   KResourceDemo (QWidget *parent);
  18 17:
  19 18: };
  20 19:
  21 20: #endif

KResourceDemo is derived from the QLabel widget. Its background pixmap is the image Paper01.jpg, a standard KDE global resource. The text displayed in the widget is loaded from the file text.txt, an application-specific resource.

Example 7.15. kresourcedemo.cpp: Class Definition for KResourceDemo

   2  1: #include <qpixmap.h>
   3  2: #include <qfile.h>
   4  3:
   5  4: #include <kglobal.h>
   6  5: #include <kstddirs.h>
   7  6: #include <kimgio.h>
   8  7: #include <klocale.h>
   9  8:
  10  9:
  11 10: #include "kresourcedemo.h"
  12 11:
  13 12: KResourceDemo::KResourceDemo (QWidget *parent) :
  14 13:   QLabel (parent)
  15 14: {
  16 15:   KStandardDirs *dirs = KGlobal::dirs();
  17 16:
  18 17:   //Load picture and set as background.
  19 18:   QString picturepath;
  20 19:   picturepath = dirs->findResource ("wallpaper", "Paper01.jpg");
  21 20:
  22 21:   kimgioRegister();
  23 22:   QPixmap qpixmap;
  24 23:   qpixmap.load (picturepath);
  25 24:   setBackgroundPixmap (qpixmap);
  26 25:
  27 26:
  28 27:   //Draw some text from a resource file.
  29 28:   QFont qfont = font();
  30 29:   qfont.setBold(true);
  31 30:   setFont (qfont);
  32 31:
  33 32:   QString textpath;
  34 33:   textpath = dirs->findResource ("appdata", "text.txt");
  35 34:
  36 35:   char * buffer = new char [1024];
  37 36:   QFile qfile (textpath);
  38 37:   qfile.open (IO_ReadOnly);
  39 38:   qfile.readBlock (buffer, 1024);
  40 39:
  41 40:   QString datatext (buffer);
  42 41:   delete buffer;
  43 42:
  44 43:   datatext.prepend (i18n("Here is some text:\n"));
  45 44:   setText (datatext);
  46 45: }

A global instance of KStandardDirs, a class used to locate resources, is available from the static function KGlobal::dirs(). For readability, assign the return value to the pointer dirs.

In line 19, findResource() returns the full path to the file Paper01.jpg. It searches for this file in the directories that hold resources of type wallpaper.

To manipulate a JPEG file like Paper01.jpg, you need to make use of the kimgio library. Be sure to compile this program by passing the option -lkimgio to g++. This links the kimgio library to the program, giving it access to the functions in the library.

Using the library is quite simple; just call kimgioRegister() (line 21) and you are done with kimgio! (See Chapter 10, "Complex-Function KDE Widgets", for a discussion of KImgIO.) Now you load the picture into the instance of QPixmap called qpixmap with the statement

   2  qpixmap.load (picturepath)

seen on line 23. The pixmap is set as the widget's background in line 24.

Next you find and load an application-specific resource, a text file in this case, and display its contents. In line 33, you search for a resource of type appdata called text.txt. This file, shown in Listing 7.16, contains the text that will be displayed in the label. Figure 7.5 shows a screenshot of KResourceDemo.

Figure 7.5. KResourceDemo places a pixmap in the background and some text in the foreground, both of which are stored as application resources.

Example 7.16. Contents of $KDEDIR/share/appstext.txt, Which is Displayed by kresourcedemo

   2 This text was taken from the file
   3 $KDEDIR/share/apps/kresourcedemo/text.txt

Lines 35–44 of Listing 7.15 contain code to read in and display the text. The code uses QFile, a class that allows you to read and write files. It is not covered in detail; therefore, see the Qt documentation for more information.

The final resource you access is a translation. The function i18n() is defined in klocal.h. (i18n is a commonly used shorthand for internationalization. Internationalization is such a long word that programmers abbreviate it by its first and last letters with a number in between that is equal to the number of letters left out of the word.) All string constants in an application should be enclosed in a call to i18n(). These strings can be translated to other languages, and when your application runs on a foreign desktop, the strings are displayed in the local language.

You create the string translations by extracting all the strings passed to i18n() with xgettext, a GNU utility. Use the call

   2   xgettext --c++ --keyword=i18n kresourcedemo.cpp --output=kresourcedemo.po

to extract the strings from kresourcedemo.cpp and place them in the file kresourcedemo.po. PO stands for Portable Object. This reflects the fact that they are text files that can be easily moved between platforms. The file kresource.po is shown in Listing 7.17.

Example 7.17. kresource.po: The Translation Template File Generated by xgettext

   3  2: # Copyright (C) YEAR Free Software Foundation, Inc.
   5  4: #
   6  5: #, fuzzy
   7  6: msgid ""
   8  7: msgstr ""
   9  8: "Project-Id-Version: PACKAGE VERSION\n"
  10  9: "POT-Creation-Date: 1999-11-20 13:31-0500\n"
  11 10: "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
  12 11: "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
  13 12: "Language-Team: LANGUAGE <LL@li.org>\n"
  14 13: "MIME-Version: 1.0\n"
  15 14: "Content-Type: text/plain; charset=iso-8859-1\n"
  16 15: "Content-Transfer-Encoding: ENCODING\n"
  17 16:
  18 17: #: kresourcedemo.cpp:45
  19 18: msgid "Here is some text:\n"
  20 19: msgstr ""

To test the translation feature, fill in the msgstr entry at the bottom of kresourcedemo.po using any text editor. That is, change the empty string "" to some other string, such as "Look at this text!" or try translating it into another language.

The files used by running KDE programs are machine-object (binary) files. The machine-object file for kresourcedemo is created by msgfmt with

   2   msgfmt kresourcedemo.po -o kresourcedemo.mo

Move this file into $KDEDIR/share/locale/de/LC[lowbar]MESSAGES (create the directory if it does not exist). Now run the KDE control center from the K Menu on the panel. Click Language in the Desktop subtree and choose German as your primary language.

Now, open up a new terminal from the panel and run kresourcedemo. Instead of displaying Here is some text:, it should display the alternative string you entered in kresourcedemo.po.

7.4.3. Creating .desktop Files

KDE 2.0 uses files with the extension .desktop, in a standard Key, Value pair format (discussed shortly) to describe applications. These are called "application .desktop files" because these files are used to describe other objects as well (see Chapter 12, "Creating and Using Components (KParts)"). KDE 1.x used similar files, but with the extension .kdelnk. The extension .kdelnk is still supported, but it is best to use the newer .desktop extension to ensure future compatibility.