The code explained below can be found in test/test_plugin and test/test_app/application_context_test.
My First Plugin Object
ShapeInterface.h
We want to design to interface. So here's the interface. To let the Qt system know the interface, it is declared using Q_DECLARE_INTERFACE.
#ifndef SHAPE_INTERFACE_H_
#define SHAPE_INTERFACE_H_
class ShapeInterface
{
public:
virtual ~ShapeInterface() {}
virtual void draw () = 0;
};
Q_DECLARE_INTERFACE(ShapeInterface, "org.qic.test.ShapeInterface/1.0")
#endif
RectanglePlugin.h
Now, a plugin to implement the interface. This class has to derive from QObject and all the interfaces it implements. Use Q_INTERFACES to tell Qt the interfaces it implements. To define properties that refer to other objects, the QObject * should be wrapped in QVariant.
#ifndef RECTANGLE_PLUGIN_H_
#define RECTANGLE_PLUGIN_H_
#include <QObject>
#include <QtDebug>
#include <QVariant>
#include "ShapeInterface.h"
class RectanglePlugin : public QObject, public ShapeInterface
{
Q_OBJECT
Q_INTERFACES( ShapeInterface)
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(int size READ size WRITE setSize)
Q_PROPERTY(QVariant canvasObj READ canvasObj WRITE setCanvasObj)
public:
RectanglePlugin ()
{
_name = "rectangle_plugin";
_size = 0;
}
void draw ();
QVariant canvasObj ()
{
return QVariant::fromValue(_canvasObj);
}
void setCanvasObj (QVariant obj)
{
_canvasObj = obj.value<QObject *>();
}
int size () const
{
return _size;
}
void setSize (int size)
{
_size = size;
}
QString name () const
{
return _name;
}
void setName (QString & name)
{
_name = name;
}
public slots:
void init ()
{
_size = 200;
}
void setCanvasSize (int size)
{
_size = size;
}
void destroy ()
{
qDebug() << "In RectanglePlugin destroy method.";
}
protected:
QObject * _canvasObj;
QString _name;
int _size;
};
#endif
RectanglePlugin.cpp
Export the plugin using Q_EXPORT_PLUGIN2
#include <QtDebug>
#include <QString>
#include <QtPlugin>
#include <QtXml/QDomElement>
#include "RectanglePlugin.h"
void RectanglePlugin::draw ()
{
qDebug()<< "Drawing RectanglePlugin. ";
}
Q_EXPORT_PLUGIN2(rectangle_plugin, RectanglePlugin)
rectangle_plugin.pro
HEADERS += RectanglePlugin.h \
../ShapeInterface.h
SOURCES += RectanglePlugin.cpp
INCLUDEPATH += ../ \
./ \
../../../include
CONFIG += debug \
warn_on \
qt \
plugin
TEMPLATE = lib
Another Plugin Object
Canvas Object emits sizeChanged signal when its size property is set.
CanvasPlugin.h
#ifndef CANVAS_PLUGIN_H_
#define CANVAS_PLUGIN_H_
#include <QObject>
#include <QList>
#include <QMetaType>
#include <QVariant>
#include <QtDebug>
#include "ShapeInterface.h"
class CanvasPlugin : public QObject, public ShapeInterface
{
Q_OBJECT
Q_INTERFACES(ShapeInterface)
Q_PROPERTY(int size READ size WRITE setSize)
Q_PROPERTY(QVariant rectangleObj READ rectangleObj WRITE setRectangleObj)
public:
CanvasPlugin ()
{
_rectangleObj = NULL;
_size = 0;
}
virtual ~CanvasPlugin () {}
virtual void draw ();
QVariant rectangleObj ()
{
return QVariant::fromValue(_rectangleObj);
}
void setRectangleObj (QVariant obj)
{
_rectangleObj = obj.value<QObject *>();
}
int size () const
{
return _size;
}
void setSize (int size)
{
if (size != _size)
{
_size = size;
emit sizeChanged(_size);
}
}
public slots:
void init ()
{
_size = 200;
}
signals:
void sizeChanged(int newValue);
protected:
QObject * _rectangleObj;
int _size;
};
#endif
CanvasPlugin.cpp
#include <QtDebug>
#include <QString>
#include <QtPlugin>
#include "CanvasPlugin.h"
void
CanvasPlugin::draw ()
{
qDebug() << "Drawing CanvasPlugin.";
if (_rectangleObj)
{
ShapeInterface * shape = qobject_cast<ShapeInterface *>(_rectangleObj);
shape->draw();
}
}
Q_EXPORT_PLUGIN2(canvas_plugin, CanvasPlugin)
canvas_plugin.pro
HEADERS += ../ShapeInterface.h \
CanvasPlugin.h
SOURCES += CanvasPlugin.cpp
INCLUDEPATH += ../../../include \
./ \
../
CONFIG += debug \
warn_on \
qt \
plugin
TEMPLATE = lib
Configuration File
Now the configuration file to wire up the objects.
<objects>
<object id="rectangle"
plugin="${QIC_DIR}/test/test_plugin/rectangle_plugin/librectangle_plugin.so"
init-method="init" destroy-method="destroy" >
<property name="name">
<value><null/></value>
</property>
<property name="size">
<value>100</value>
</property>
</object>
<object id="canvas"
plugin="${QIC_DIR}/test/test_plugin/canvas_plugin/libcanvas_plugin.so" >
<property name="rectangleObj" ref="rectangle">
</property>
</object>
<!-- Wire the signal and slot. -->
<wire type="auto">
<sender id="canvas" signal="sizeChanged(int)">
</sender>
<receiver id="rectangle" method="setCanvasSize(int)">
</receiver>
</wire>
</objects>
Test the application
QString base = qic::Util::getEnvVariable("QIC_DIR");
base.append("/test/test_app/application_context_test/");
qic::XmlApplicationContext ctx(
QStringList() << (base + "application_context_10.xml") );
QObject * obj = ctx.getObject("canvas");
ShapeInterface * shape = qobject_cast<ShapeInterface *>(obj);
shape->draw();
obj->setProperty("size", 111);
obj = ctx.getObject( "rectangle");
int size = obj->property("size").value<int>();