Reputation: 2447
I am trying to use instances of an abstract class as a property in one of my extended QQuickItems. I have a basic class, like this:
class VizFactory : public QQuickItem
{
Q_OBJECT;
Q_PROPERTY(VisualizationOptions * options READ options WRITE setOptions);
private:
VisualizationOptions * m_visualizationOptions;
public:
VizFactory(QQuickItem * parent = 0) : QQuickItem(parent) {}
~VizFactory() {}
VisualizationOptions * options() const;
void setOptions(VisualizationOptions * options);
};
Where VisualizationOptions
is an abstract class that extends some other classes, like LayoutOptions
and FooOptions
:
class VisualizationOptions : public QObject
{
Q_OBJECT
public:
VisualizationOptions(QObject * parent = 0) : QObject(parent) {}
virtual std::string getVisualizationName() const = 0;
};
I register everything in my main file using:
qmlRegisterUncreatableType<VisualizationOptions>("Wormhole", 1, 0, "VisualizationOptions",
QString("Cannot create abstract class VisualizationOptions"));
qmlRegisterType<LayoutOptions>("Wormhole", 1, 0, "LayoutOptions");
qmlRegisterType<FooOptions>("Wormhole", 1, 0, "FooOptions");
Then, I try to use it in a qml file by putting in:
VizFactory {
options: LayoutOptions {
type: "row"
FooOptions {}
LayoutOptions {
type: "col"
FooOptions {}
FooOptions {}
}
}
}
But, the error I'm getting is from the qml file on the line defining options
, saying: "Cannot assign to non-existent default property". Why is this happening? Am I not registering the types correctly? Am I instantiating the objects in QML incorrectly?
Upvotes: 3
Views: 472
Reputation: 244003
The problem is not caused by the abstract class but because the QObject
s do not have childItems
, unlike the QQuickItem
that does have that property.
The same thing you could see if you use QtObject:
QtObject{
QtObject{
}
}
message:
Cannot assign to non-existent default property
So there are 3 possible solutions:
Make VisualizationOptions inherit from QQuickItem and so you can have children.
Do not assign children, for example with your code should work the following:
VizFactory{
options: LayoutOptions{
}
}
use QQmlListproperty
I will show an example using the third method:
class VisualizationOptions: public QObject{
Q_OBJECT
Q_PROPERTY(QQmlListProperty<VisualizationOptions> childOptions READ options)
public:
using QObject::QObject;
virtual std::string getVisualizationName() const = 0;
QQmlListProperty<VisualizationOptions> options(){
return QQmlListProperty<VisualizationOptions>(this, this,
&VisualizationOptions::appendOption,
&VisualizationOptions::optionCount,
&VisualizationOptions::option,
&VisualizationOptions::clearOptions);
}
void appendOption(VisualizationOptions* p) {
m_childsoptions.append(p);
}
int optionCount() const{
return m_childsoptions.count();
}
VisualizationOptions *option(int index) const{
return m_childsoptions.at(index);
}
void clearOptions() {
m_childsoptions.clear();
}
private:
static void appendOption(QQmlListProperty<VisualizationOptions>* list, VisualizationOptions* p) {
reinterpret_cast<VisualizationOptions* >(list->data)->appendOption(p);
}
static void clearOptions(QQmlListProperty<VisualizationOptions>* list) {
reinterpret_cast<VisualizationOptions* >(list->data)->clearOptions();
}
static VisualizationOptions* option(QQmlListProperty<VisualizationOptions>* list, int i) {
return reinterpret_cast< VisualizationOptions* >(list->data)->option(i);
}
static int optionCount(QQmlListProperty<VisualizationOptions>* list) {
return reinterpret_cast< VisualizationOptions* >(list->data)->optionCount();
}
QVector<VisualizationOptions *> m_childsoptions;
};
*.qml
VizFactory{
options:
LayoutOptions{
type: "row"
childOptions: [
FooOptions{},
LayoutOptions{
type: "col"
childOptions: [
FooOptions {},
FooOptions {}
]
}
]
}
}
You can find the complete code in the following link.
Upvotes: 3