Expose abstract type as Q_PROPERTY to QML

2019-06-21 03:49发布

问题:

I am using Qt 4.8 with BB10.

I defined a base interface for classes to implement:

class AbstractImageProcessor : public QObject
{
public:
    AbstractImageProcessor(QObject * parent) : QObject(parent) {}
    virtual QImage process(const QByteArray &data) = 0;
    virtual ~AbstractImageProcessor(){ }
};

One such implementation that I want usable from QML looks like this:

class WebImageProcessor : public AbstractImageProcessor
{
    Q_OBJECT
    Q_PROPERTY(int maxHeight READ getMaxHeight WRITE setMaxHeight NOTIFY maxHeightChanged)
    Q_PROPERTY(int maxWidth READ getMaxWidth WRITE setMaxWidth NOTIFY maxWidthChanged)
    Q_PROPERTY(bool fit READ isFit NOTIFY fitChanged)
    public WebImageProcessor(QObject * parent = 0) : AbstractImageProcessor(parent) {}
    virtual ~WebImageProcessor() {}
    /* rest of code omitted */ 
};

I want to expose this AbstractImageProcessor as a property on another QML type:

class WebImageView : public bb::cascades::ImageView {
    Q_OBJECT
    Q_PROPERTY(AbstractImageProcessor* processor READ getProcessor WRITE setProcessor NOTIFY processorChanged)
    WebImageView(bb::cascades::Container * parent) : bb::cascades::ImageView(parent)  {}
    virtual WebImageView() {}
    /* rest of code omitted */
};

So I register my custom types with QML

//application.cpp
qmlRegisterUncreatableType<AbstractImageProcessor>("foo.controls", 1, 0, "AbstractImageProcessor", ""); ;
qmlRegisterType<WebImageProcessor>("foo.controls", 1, 0, "WebImageProcessor");
qmlRegisterType<WebImageView>("foo.controls", 1, 0, "WebImageView");

How I want to use it in QML

//main.qml
import foo.controls 1.0
/* omitted containers */

WebImageView { 
  processor: WebImageProcessor {
     maxHeight: 500
     maxWidth: 300
  } 
  /* rest of properties omitted */
}

But once I launch my application it fails to parse the qml document.

bb::cascades::QmlDocument: error when loading QML from: QUrl( "asset:///main.qml" )
--- errors: (asset:///main.qml:138:57: Cannot assign object to property) bb::cascades::QmlDocument:createRootObject document is not loaded or has errors, can't create root

In fact if I hover over the WebImageProcessor class in the editor, it says:

The super type of the component WebImageProcessor is unknown, some of its properties are not validated.

Now the thing is that the for example the built in cascades ListView exposes an abstract type as a Q_PROPERTY:

http://developer.blackberry.com/native/reference/cascades/bb_cascades_listview.html#property-datamodel

Event inspecting the header files of bb::cascades::ListView and bb::cascades::DataModel gives me no other clues because it's done essentially the same way.

Could it be that I have to register the types in a different way? If so how?

If I use WebImageProcessor in the Q_PROPERTY instead of the AbstractImageProcessor then it works as expected, but I want to expose the abstract type, and given that cascades does it then it's definitely possible somehow

Thanks

回答1:

Your AbstractImageProcessor declaration is lacking a Q_OBJECT macro, which is necessary to export the class to QtQuick.