GregD
GregD

Reputation: 195

Failure to build multi-widget QtDesigner plugin

I am attempting to create a single DLL "CustomPlugins" that contains two QtDesigner plugins. By replicating the WorldClockPlugin example I am able to get each of the plugins to work individually. However when I attempt to include both of them in a single DLL, I get the following build error:

LNK2005: _qt_plugin_instance already defined in moc_qledplugin.obj

It appears to me that by causing my plugin wrapper widgets to both inherit QDesignerCustomWidgetInterface it is resulting a multiple definition of the _qt_plugin_instance function. I've looked through the moc files and the customwidget header file (included by QDesignerCustomWidgetInterface) but cannot find any reference to this function.

QDesignerExportWidget is included in both of the plugin headers and QDESIGNER_WIDGET_EXPORT is included in both widget declarations.

Is it simply not possible to wrap two plugins in the same DLL? Or am I missing something?

Thank you.

Following is the code. qdragabletoolboxplugin.* files (not shown) are nearly identical to the qledplugin* files. Furthermore, qdragabletoolbox (also not shown) is declared in the same way as qled but obviously does something very different. For the sake of saving space I've left off those files and replaced some of the function definitions with ellipses.

.pro file:

QT          += widgets designer

QMAKE_LFLAGS += /INCREMENTAL:NO

TARGET      = $$qtLibraryTarget($$TARGET)
CONFIG     += plugin
TEMPLATE    = lib

target.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS += target

HEADERS     = qled.h \
              qledplugin.h \
              qdragabletoolbox.h \
              qdragabletoolboxplugin.h
SOURCES     = qled.cpp \
              qledplugin.cpp \
              qdragabletoolbox.cpp \
              qdragabletoolboxplugin.cpp

RESOURCES += CustomDesignerPlugins.qrc

qled.h:

#ifndef QLED_H
#define QLED_H

#include <QWidget>
#include <QPaintEvent>
#include <QPainter>
#include <QList>
#include <QColor>
#include <QGradient>
#include <QtDesigner/QDesignerExportWidget>

class QDESIGNER_WIDGET_EXPORT QLED : public QWidget
{
    Q_OBJECT

    Q_ENUMS(ledColor)
    Q_ENUMS(ledShape)

    Q_PROPERTY(ledColor offColor READ offColor WRITE setOffColor)
    Q_PROPERTY(ledColor onColor READ onColor WRITE setOnColor)
    Q_PROPERTY(bool shadow READ shadow WRITE setShadow)
    Q_PROPERTY(ledShape shape READ shape WRITE setShape)
    Q_PROPERTY(bool value READ value WRITE setValue)

public:
    enum ledColor { Red = 0, Orange, Yellow, Green, Blue, Indigo, Violet, Black, Gray, DarkGray };
    enum ledShape { Ellipse = 0, Rectangle, Circle, Square };

    explicit QLED(QWidget *parent = NULL);
    virtual ~QLED() { /*empty*/ }

    bool value() const { return mValue; }
    ledColor onColor() const { return mOnColor; }
    ledColor offColor() const { return mOffColor; }
    ledShape shape() const { return mShape; }
    bool shadow() const { return mShadow; }

signals:

public slots:
    void setValue(bool value) { mValue = value; update(); }
    void setShape(ledShape shape) { mShape = shape; update(); }
    void setOnColor(ledColor color) { mOnColor = color; update(); }
    void setOffColor(ledColor color) { mOffColor = color; update(); }
    void setShadow(bool b) { mShadow = b; update(); }
    void toggle() { mValue = !mValue; update(); }

protected:
    void paintEvent(QPaintEvent *event);

private:
    void drawBezel(QPainter *painter);
    void drawFace(QPainter *painter);
    void drawShadow(QPainter *painter);

private:
    bool mValue;

    ledColor mOnColor;
    ledColor mOffColor;

    bool mBezel;
    float  mBezelWidth;
    ledColor mBezelColor;

    bool mShadow;

    ledShape mShape;

    QList<QColor> colors;
};

#endif

qled.cpp

#include "qled.h"

QLED::QLED(QWidget *parent)
    : QWidget(parent)
{
    ...
}

void QLED::paintEvent(QPaintEvent *event)
{
    ...
}

void QLED::drawBezel(QPainter *painter)
{
    ...
}

void QLED::drawFace(QPainter *painter)
{
    ...
}

void QLED::drawShadow(QPainter *painter)
{
    ...
}

qledplugin.h

#ifndef QLEDPLUGIN_H
#define QLEDPLUGIN_H

#include <QDesignerCustomWidgetInterface>

class QLEDPlugin : public QObject, public QDesignerCustomWidgetInterface
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface" FILE "qled.json")
    Q_INTERFACES(QDesignerCustomWidgetInterface)

public:
    QLEDPlugin(QObject *parent = 0);

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

private:
    bool initialized;
};

#endif

qledplugin.cpp

#include "qled.h"
#include "qledplugin.h"

#include <QtPlugin>

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

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

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

QWidget *QLEDPlugin::createWidget(QWidget *parent)
{
    return new QLED(parent);
}

QString QLEDPlugin::name() const
{
    return QLatin1String("QLED");
}

QString QLEDPlugin::group() const
{
    return QLatin1String("Display Widgets");
}

QIcon QLEDPlugin::icon() const
{
    return QIcon(QLatin1String(":/QLED/LEDIcon.png"));
}

QString QLEDPlugin::toolTip() const
{
    return "Binary status indicator";
}

QString QLEDPlugin::whatsThis() const
{
    return "";
}

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

QString QLEDPlugin::domXml() const
{
    return "<ui language=\"c++\">\n"
            " <widget class=\"QLED\" name=\"qLed\">\n"
            "  <property name=\"geometry\">\n"
            "   <rect>\n"
            "    <x>0</x>\n"
            "    <y>0</y>\n"
            "    <width>25</width>\n"
            "    <height>25</height>\n"
            "   </rect>\n"
            "  </property>\n"
            " </widget>\n"
            "</ui>";;
}

QString QLEDPlugin::includeFile() const
{
    return QLatin1String("QtWidgets/QLED.h");
}

Upvotes: 2

Views: 793

Answers (1)

The compiler error message gives you all the information you need: you have two widgets, but you need just one plugin.

Instead of implementing QDesignerCustomWidgetInterface, implement QDesignerCustomWidgetCollectionInterface.

Upvotes: 3

Related Questions