Qt API | Qtopia API Qtopia Documentation

Introduction to Qtopia Plugins

Plugins are implemented in Qtopia via a COM-like layer. The basic steps to writing any Qtopia plugin are:

There are also some basic rules to follow when writing a plugin:

Writing the functionality

Consider the following fictious plugin interface:

// {05E0A4AB-DDC5-4449-85A9-828100DE00A9} 
#ifndef IID_WidgetPlugin
#define IID_WidgetPlugin QUuid( 0x05e0a4ab, 0xddc5, 0x4449, 0x85, 0xa9, 0x82, 0x81, 0x00, 0xde, 0x00, 0xa9)
#endif

struct WidgetPluginInterface : public QUnknownInterface
{
    virtual QWidget *widget( QWidget *parent ) = 0;
    virtual QString name() const = 0;
};

This is a simple interface that provides a plugin name and a widget that is created with the supplied parent.

IID_WidgetPlugin defines a unique ID for this interface.

The plugin that we are writing provides a widget that draws an ellipse in its center. The code below implements the functionality that this plugin provides.

class EllipseWidget : public QWidget
{
    Q_OBJECT
public:
    EllipseWidget( QWidget *parent=0 ) : QWidget( parent, "Ellipse" )
    {
    }

protected:
    void paintEvent( QPaintEvent * )
    {
        QPainter p( this );
        p.drawEllipse( rect() );
    }
};

Subclassing the interface

Now you can subclass the WidgetPluginInterface:

struct CirclePlugin : public WidgetPluginInterface
{
public:
    virtual QWidget *widget( QWidget *parent );
    virtual QString name() const;

    QRESULT queryInterface( const QUuid&, QUnknownInterface** );
    Q_REFCOUNT

protected:
    CircleWidget *w;
    ulong ref;
};

There are two things to note in the CirclePlugin struct:

Implementing the interface

The constructor an destructor are straight-forward. The most important point is that ref must be initialised with 0.

CirclePlugin::CirclePlugin()
    : w(0), ref(0)
{
}

CirclePlugin::~CirclePlugin()
{
    delete w;
}

The queryInterface() function can be implemented using the following boilerplate code:

QRESULT CirclePlugin::queryInterface( const QUuid &uuid, QUnknownInterface **iface )
{
    *iface = 0;
    if ( uuid == IID_QUnknown )
        *iface = this;
    else if ( uuid == IID_WidgetPlugin )
        *iface = this;
    else
        return QS_FALSE;

    (*iface)->addRef();
    return QS_OK;
}

A plugin can provide several interfaces. At the very least QUnknownInterface is provided by all plugins.

The widget() function returns the widget.

QWidget *CirclePlugin::widget( QWidget *parent )
{
    if ( !w )
        w = new CircleWidget( parent );
    return w;
}

The name() function returns the name of the plugin.

QString CirclePlugin::name()
{
    return qApp->translate( "WidgetPlugin", "Circle" );
}

Creating an instance

You must also create an instance of the widget plugin using the following boilerplate code:

Q_EXPORT_INTERFACE()
{
    Q_CREATE_INSTANCE( CirclePlugin )
}

Loading Plugins

The recommended method for loading plugins is to use the PluginLoader class. The PluginLoader class provides simplified enumeration and loading of plugins and provides safety in cases where the system has been booted in Safe Mode.

PluginLoader loader( "Widgets" );
QStringList list = pluginLoader.list();
QStringList::Iterator it;
QValueList<WidgetPluginInterface*> widgetsList;
for ( it = list.begin(); it != list.end(); ++it ) {
    WidgetPluginInterface *iface = 0;
    if ( pluginLoader.queryInterface( *it, IID_WidgetPlugin, (QUnknownInterface**)&iface ) == QS_OK && iface ) {
        widgetsList.append( iface );
    }
}

The PluginLoader class expects the plugins to be installed in the $QPEDIR/plugins/type directory.


Copyright © 2001-2002 TrolltechTrademarks
Qtopia version 1.7.0