7 окт. 2008 г.

Qt4: dynamic loading ui from an other ui, part 2

Ok, we've created a widget, which can load ui file.

Now, insert with widget to ui file:
<widget class="LoadableWidget" name="loadableWidget">
<property name="uiFilename">
<string>some.ui</string>
</property>
</widget>

Qt require meta info about widget class, but there is none, So if we try to load it... and haven't seen loadableWidget item.

So, we should create Custom Widget Plugin for LoadableWidget
LoadableWidgetPlugin.h:
#ifndef LOADABLEWIDGETPLUGIN_H
#define LOADABLEWIDGETPLUGIN_H

#include <QObject>
#include <QWidget>
#include <QIcon>
#include <QString>
#include <QDesignerCustomWidgetInterface>

class LoadableWidgetPlugin : public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
LoadableWidgetPlugin(QObject *);

bool isContainer() const;
bool isInitialized() const;
QIcon icon() const;
QString group() const;
QString toolTip() const;
QString whatsThis() const;
void initialize(QDesignerFormEditorInterface *);
QString domXml() const;
QString includeFile() const;
QString name() const;
QWidget *createWidget(QWidget *parent);

private:
bool initialized;
};

#endif /*LOADABLEWIDGETPLUGIN_H*/

LoadableWidgetPlugin.cpp:

#include "LoadableWidgetPlugin.h"
#include "LoadableWidget.h"

LoadableWidgetPlugin::LoadableWidgetPlugin(QObject *parent): QObject(parent){
initialized = false;
}

bool LoadableWidgetPlugin::isContainer() const {
return false;
}

bool LoadableWidgetPlugin::isInitialized() const {
return initialized;
}

QIcon LoadableWidgetPlugin::icon() const {
return QIcon();
}

QString LoadableWidgetPlugin::group() const {
return "Custom Widgets";
}

QString LoadableWidgetPlugin::toolTip() const {
return "LoadableWidget";
}

QString LoadableWidgetPlugin::whatsThis() const {
return "Loadable custom widget";
}

void LoadableWidgetPlugin::initialize(QDesignerFormEditorInterface *core){
Q_UNUSED(core)
if (initialized)
return;
initialized = true;
}

QWidget* LoadableWidgetPlugin::createWidget(QWidget *parent){
return new LoadableWidget(parent);
}

QString LoadableWidgetPlugin::domXml() const {
return "<widget class=\"LoadableWidget\" name=\"loadableWidget\"/>";
}

QString LoadableWidgetPlugin::includeFile() const {
return "loadablewidget.h";
}

QString LoadableWidgetPlugin::name() const {
return "LoadableWidget";
}
Q_EXPORT_PLUGIN(LoadableWidgetPlugin)


The last line Q_EXPORT_PLUGIN(LoadableWidgetPlugin) is qt plugin declaration.

now build project as library, components.pro :
CONFIG += uitools \
designer \
plugin
TEMPLATE = lib

HEADERS += LoadableWidget.h \
LoadableWidgetPlugin.h \
SOURCES = LoadableWidget.cpp \
LoadableWidgetPlugin.cpp


There is one at least pitfall:
  • Q_EXPORT_PLUGIN define the only one custom widget plugin per one library.

If it's necessary to define several custom widgets in the same library QDesignerCustomWidgetCollectionInterface should be used:
  • QDesignerCustomWidgetCollectionInterface has follow method:
    QList customWidgets()
    which contains necessary custom widget plugins
  • there is only one Q_EXPORT_PLUGIN declaration - Q_EXPORT_PLUGIN(CustomWidgets) - there are no any Q_EXPORT_PLUGIN declaration in subclasses of QDesignerCustomWidgetInterface

 #include customwidgetoneinterface.h
#include customwidgettwointerface.h
#include customwidgetthreeinterface.h

#include <QtDesigner/QtDesigner>
#include <QtCore/qplugin.h>

class CustomWidgets: public QObject, public QDesignerCustomWidgetCollectionInterface
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetCollectionInterface)

public:
CustomWidgets(QObject *parent = 0);

virtual QList<QDesignerCustomWidgetInterface*> customWidgets() const;

private:
QList<QDesignerCustomWidgetInterface*> widgets;
};

In the class constructor you add the interfaces to your custom widgets to the list which you return in the customWidgets() function:
CustomWidgets::CustomWidgets(QObject *parent)
: QObject(parent)
{
widgets << new CustomWidgetOneInterface(this))
<< new CustomWidgetTwoInterface(this))
<< new CustomWidgetThreeInterface(this));
}

QList<QDesignerCustomWidgetInterface*> CustomWidgets::customWidgets() const
{
return widgets;
}

Q_EXPORT_PLUGIN(CustomWidgets)

Комментариев нет: