Tips for KDE App Programmers

unleashing the power of the KDE libraries


(image: kde)

Table of Contents

  1. Loading and saving configuration settings
  2. Docking widgets onto the panel
  3. Prefer to create widgets on the heap
  4. Internationalizing your Application
  5. From Qt to KDE: it's easy!
  6. Displaying help with KDEHelp
  7. Multiple windows
  8. Dealing with network resources

Loading and saving configuration settings

The KApplication class opens and reads (or creates if it doesn't exist), a configuration file and creates a KConfig object for the application to modify it. This can be accessed via the KApplication::getConfig() method.

top


Docking widgets onto the panel

You can have toplevel (parentless) widgets swallowed, a la kscd, by kpanel if your users are using the KWM window manager. To do this, you just need to call the static KWM::setDockWindow() method declared in kwm.h, with the window id of your widget:

#include<kwm.h>

	...

	// Create a top level widget
	QWidget *myNewWidget = new QWidget( 0 );
	...
	
	// Dock it
	KWM::setDockWindow( myNewWidget->winId() );

The panel will swallow the window as soon as it is shown and will resize it to a small square that will fit in the panel, the exact size depending on the user's panel size setting.

top


Prefer to create widgets on the heap

It is usually better to allocate objects derived from QWidget on the heap with new(), rather than creating them on the stack. This can prevent problems if QWidget::close(TRUE) is called.

top


Internationalizing your Application

You may have noticed that KDE is amongst the forerunners of internationalization (i18n) in the free software world. Thousands of people are using KDE in languages other than English today, even though English has so far been the primary language used by developers during communication and programming.

This has been achieved with a tool known as gettext, an LGPL i18n library. To use this facility in your application, you must use the i18n() macro with every literal string in your code that requires translation. This macro resides in the kapp.h header file, and requires that a valid, preconfigured KApplication object is available. So don't use i18n() unless you have created kapp. You have been warned. Here is an example of the macro's usage:

#include<kapp.h>

...

	KMsgBox::message( i18n( "The pizza is your friend" ) );

This string will be parsed out from the file by the xgettext program, which will create a template file (.pot extension) of strings in your application. This template will be used by the i18n teams to create translation catalogs (.po extension) for each language. These catalogs will be automatically used to translate the strings at runtime.

For more information on i18n and translation, see the official KDE i18n Page.

top


From Qt to KDE: it's easy!

To automatically gain basic features like automatic colour schemes, GUI style, automatic configuration etc to your existing Qt application, all you need to do is

  1. Create a KApplication instead of a QApplication as your central Application object. Since KApplication is a subclass of QApplication, everything should work as it did before.
  2. Remove all explicit calls to QApplication::setGUIStyle, since your application's GUI style and colour scheme will now be automatically setup using your users' desktop-wide preferences.
  3. Update your Makefile(s). It is highly recommended that you use the distribution framework template that is provided with the kexample package. It is distributed in the KDE SDK package. This will allow a quick way to convert your app into one that fits nicely into the KDE framework, providing portable building and Makefile generation.

top


Displaying help with KDEHelp

KDEHelp is the KDE's standard help viewer and is to KDE apps what Winhelp is to M* W******, but streets ahead. To view your manual page(s) with KDEHelp, assuming the KDEHelp executable is in your path, use the KApplication::invokeHTMLHelp() method.

If your application is named kmyapp and its help is a single file with the path $KDEDIR/doc/HTML/kmyapp.html , all you need to do is

KApplication::getKApplication()->invokeHTMLHelp("","");

If, however, it is located in a directory called kmyapp and is called kmyapp.html (that is, its pathname is $KDEDIR/doc/HTML/kmyapp/kmyapp.html), and you would like to jump to the section named "#setup", you can invoke it with

KApplication::getKApplication()->invokeHTMLHelp(
    				"kmyapp/kmyappl.html","setup");

top


Multiple windows

Where possible, you should allow users to open multiple windows of your application without loading another copy of the app. In simple cases, this can be done by adding a static list of widgets to your main application window widget.

    static QList<KMyMainWidget> windowList;

Then in your widget definition source:
    QList<KMyMainWidget> KMyMainWidget::windowList;
Now you want each new window to register itself in this list, so in the constructor:
    // so that windows can delete themselves
    windowList.setAutoDelete(FALSE);

    // now add the window
    windowList.append(this);

To make sure widgets remove themselves from the list properly, make sure they contain

    windowList.removeRef(this);

in their destructor.

Now you can create a new window by just creating a new widget with new and show()-ing it. No need to track references.

Something to watch out for: Since logically, all application widgets are at par with each other, no widget should be set to be the main widget with QApplication::setMainWidget(). Instead, use something like this to close your window:

    void KMyMainWidget::closeWindow()
    {
    // quit app if closing last window
        if( windowlist.countRef() > 1 )
            close(TRUE); // no need to quit app
        else
            qApp->quit();
    }

top


Dealing with network resources

Kfm, the KDE file manager, also offers an interface for applications to retrieve and perform operations on Internet resources. This means you can use Kfm to read and write files that are accessible via a URL, be they local files, FTP resources or WWW documents.

With Kfm, you application doesn't block while it is performing network IO; your users can continue to interact with the application while the job continues in the background.

To fetch a file via network IO with Kfm in a widget, here is a simple way to do it:

  • Include a pointer to an object of type KFM in your widget class. This will be used to communicate with Kfm.
        #include<kfm.h>
        ...
        public:
            enum transferDirection {GET, PUT};
        private:
            // direction of file transfer
            transferDirection ioDir;
    
            // the KFM connection
            KFM *kfmConn;
    then, in your widget constructor, initialize your KFM object:
        // if kfmConn is null, there is no
        // current IO job.
        kfmConn = 0;
  • Create a slot, for your widget, that is called on completion of the KFM job (more on this later).
         public slots:
              void slotKFMJobDone();
  • To perform, say a read operation from a URL and transfer the remote file...
        //create a new KFM connection
         kfmConn = new KFM;
    
         // ... (check kfmConn==0 or kfmConn->isOk()
         // to check that we connected ok <not shown for brevity>)
    
         // call your slot on KFM completion
         connect( kfmConn, SIGNAL( finished() ), 
              this, SLOT( slotKFMJobDone() ) );
    
         // start the KFM job
         kfmConn->copy(remoteFile, localFile);
    
          // remember the direction of the transfer
            ioDir = MyWidgetType::GET; 
  • Now, when Kfm finishes the IO job, your slotKFMJobDone() slot will be called. Here you can
    • Use the fetched file (load, print, whatever). Remember to unlink() it if you just wanted to read the file once and don't want it to stay on the user's local filesystem.
    • delete your kfmConn object and set it to NULL, so that you can easily check if you're in the middle of a transfer or not. This is recommended.

top


back

Written and maintained by: Sirtaj S. Kang (taj@kde.org)
Last modified: Mon Jan 24 15:00:47 EST 2000