Creating Kommander widgets
With Kommander you can create new widgets based on non-Kommander widgets
fairly easily.
The approach is to derive your new Kommander widget class from the
Qt/KDE widget which you wish to integrate with Kommander, and then also from the
KommanderWidget class. Overriding methods from this class gives the Kommander
widget its functionality.

Most of the code of a Kommander widget is just template code.
Therefore, you can use the widgetgenerator.kmdr Kommander dialog to generate 
most the Kommander widget code for you. All you have to do is fill in the
important parts relating to your widget like any state information, widget text
etc.

Let's say we want to create a new line edit widget for Kommander,
based on the KDE widget KLineEdit. Using the Kommander widget generator
dialog, we get something like this in the outputted header file:

--code--
#include <kommanderwidget.h>

class QShowEvent;
class KomLineEdit : public KLineEdit, public KommanderWidget
{
	Q_OBJECT

	Q_PROPERTY(QString populationText READ populationText WRITE setPopulationText DESIGNABLE false)
	Q_PROPERTY(QStringList associations READ associatedText WRITE setAssociatedText DESIGNABLE false)
	Q_PROPERTY(bool KommanderWidget READ isKommanderWidget)
	
public:
	KomLineEdit(QWidget *a_parent, const char *a_name);
	~KomLineEdit();

	virtual QString widgetText() const;

	virtual bool isKommanderWidget() const;
	virtual void setAssociatedText(const QStringList&);
	virtual QStringList associatedText() const;
	virtual QString currentState() const;

	virtual QString populationText() const;
	virtual void setPopulationText(const QString&);
public slots:
	virtual void setWidgetText(const QString &);
	virtual void populate();
protected:
    void showEvent( QShowEvent *e );
signals:
	void widgetOpened();
	void widgetTextChanged(const QString &);
};
--endcode--

Most of this is just template code that you don't need to worry about.
The only two things you need to take notice of are that the kommanderwidget.h
file is included at the top, and that the class is derived first from the 
widget we wish to integrate with Kommander, and secondly from KommanderWidget.

There are a few parts in the cpp file that are important to each particular widget.

--code--
KomLineEdit::KomLineEdit(QWidget *a_parent, const char *a_name)
    : KLineEdit(a_parent, a_name), KommanderWidget(this)
{
    QStringList states;
    states << "default";
    setStates(states);
    setDisplayStates(states);
}
--endcode--

In the constructor, we set the states this widget may have.
Our line edit doesn't have any kind of state, so we just
give it one state 'default'. If you were creating a widget
that had different kinds of states, such as a check box, you might
set three states "unchecked", "semichecked" and "checked" here.

--code--
QString KomLineEdit::currentState() const
{
    return QString("default");
}
--endcode--

We set the states in the constructor above, and this just
returns the current state of the widget. For our widget
it will always be default, but you should put code here
that checks what state your widget is currently in and
return the appropriate string here.

--code--
QString KomLineEdit::widgetText() const
{
    return KLineEdit::text();
}

void KomLineEdit::setWidgetText(const QString &a_text)
{
    KLineEdit::setText(a_text);
    emit widgetTextChanged(a_text);
}
--endcode--

These are the two most important methods, where the bulk of the 
functional code goes.
QString KomLineEdit::widgetText() const method returns the widget text of the 
widget(the text that the @widgetText special is expanded to in text 
associations). For our widget, the widget text is simply the text inside 
the line edit, so we just return that. Similarly when setting the widget text,
we just set the text inside the line edit. We emit the widgetTextChanged()
signal after setting the widget text so other widgets can recognise the fact 
that this widget was updated.

You now have a complete Kommander widget. All that's left
to do is make it available to the Kommander system via plugins.

Kommander plugins
All of the widgets in Kommander are provided by plugins. 
The standard widgets are loaded as widget plugins, but the Kommander editor
is also linked against this library because certain mechanisms in the editor
are tied specifically to the standard widgets.

A plugin in Kommander is simply a shared library that has the symbol
'kommander_plugin'. This symbol is a function returning a pointer
to an instance of a KommanderPlugin class.

Kommander makes it easy to create a plugin for you widgets, so you don't
need to worry about this low level stuff. The basic idea is to derive
a new plugin class for your widgets from the KommanderPlugin base class
and implement a few specific details.

The following code continues on our example of creating a Kommander line edit 
widget.

--code--
#include <kommanderplugin.h>

/* WIDGET INCLUDES */
#include "komlineedit.h"
--endcode-

First thing we do is include kommanderplugin.h. This contains the definition
of the KommanderPlugin class. We also include all header files of the widgets
this plugin provides- only "komlineedit.h" in this case.

--code--
class MyKomPlugin : public KommanderPlugin
{
public:
    MyKomPlugin();
    virtual QWidget *create( const QString &className, QWidget *parent = 0, const char *name = 0 );
};
--endcode--

We then create a KommanderPlugin sub-class called "MyKomPlugin". 
This class simply has a constructor and an overridden create method.

--code--
MyKomPlugin::MyKomPlugin()
{
    addWidget( "KomLineEdit", "My Widget Group", i18n("A Kommander line edit widget") );
    //add my other widgets here
}
--endcode--

In the constructor of the plugin, we call addWidget() for each widget we wish 
to provide in this plugin. addWidget() takes 5 arguments but only the first 3 
are required. In order, the arguments are the widget's class name, group, 
tool tip, what's this information, and a bool indicating whether the widget 
is a container for other widgets or not. This information is used
by the editor when grouping your widget in menus, providing help information
etc.

--code--
QWidget *MyKomPlugin::create( const QString &className, QWidget *parent, const char *name )
{
    if( className == "KomLineEdit" )
	return new KomLineEdit( parent, name );
    //create my other widgets here
    return 0;
}
--endcode--

create() is where instances of our widgets actually get created. 
Whenever Kommander wants an instance of one of the classes provided
by our plugin, it will call create() with the name of the class it wants,
and the parent and name that should be used.
If the className matches any widget we know about, we return a new instance
of that class but otherwise we return 0.

--code--
KOMMANDER_EXPORT_PLUGIN(MyKomPlugin)
--endcode--

Finally, we export our plugin. This just provides an entry point to our
plugin so the Kommander system can get access to it. Without this,
Kommander won't recognise your library as a Kommander plugin.

To compile your new Kommander extension, you should compile all files
as a shared library, linking against the kommanderplugin, kommanderwidget
and any appropriate KDE libraries. 
With the line edit example, if we had komlineedit.h, komlineedit.cpp and
mykomplugin.cpp, compiling and installing your plugin would involve
something similar to the following commands:

libtool --mode=compile g++ -$KDEDIR/include -IQTDIR/include \
   -I. -fPIC -c komlineedit.cpp
libtool --mode=compile g++ -$KDEDIR/include -IQTDIR/include \
   -I. -fPIC -c mykomplugin.cpp

libtool --mode=link g++ -shared -L$KDEDIR/lib -lkdeui -lkommanderwidget \
   -lkommanderplugin komlineedit.cppkomlineedit.o mykomplugin.o 
   -o libmykomplugin.so

If you want to install new plugin system-wide, root, use:

su -c "cp libmykomplugin.so $KDEDIR/lib"

Now that the plugin is installed, run the kmdr-plugins program which is an 
interface to the Kommander config file. The list in this program displays the 
plugins that are currently loaded by Kommander.  Add the new plugin to the 
list by clicking the 'Add' button in the toolbar and choosing your plugin. 
Closing the program saves changes.

If you now start up the Kommander editor, the widgets your new plugin
provides should be available in the menus and toolbars. You can
now use your new widgets in Kommander dialogs.
