0

I implemented a subclass of QQuickPaintedItem to be used in QML which works on its own when registered through

qmlRegisterType<T>

Instances of this class are created at application startup and put into a QList that is stored inside a subclass of QAbstractItemModel. I thought I could easily return each of those objects in the model's data method and use them as the QML ListViews delegate. It now looks like this:

Model.cpp:

QVariant AbteilungsModel::data(const QModelIndex &index, int role) const
{
    if(index.isValid() && role == Qt::DisplayRole)
    {
        Abteilung* a = static_cast<Abteilung*>(index.internalPointer());
        return QVariant::fromValue(a);
    }
}

main.qml:

ListView {
    id: abteilungenListView
    anchors.fill: parent
    spacing: 5
    model: abteilungen
    delegate: modelData
}

I, of course, made the model available in QML via

void QQmlContext::setContextProperty(const QString & name, QObject * value)

but I don't know how to properly declare the ListViews delegate, since "modelData" doesn't work.

Does anyone have an idea if this is even possible or do you guys have a better solution? Any help is appreciated! :)

MrBolton
  • 47
  • 6

1 Answers1

1

It might be possible, but it goes against the whole MVC idea. Your model shouldn't know about your delegates. As a simplified example:

main.cpp

#include <QGuiApplication>
#include <QtQml>
#include <QtQuick>

class Abteilung : public QQuickPaintedItem
{
    Q_OBJECT
public:
    Abteilung() {
    }

    void paint(QPainter *painter) {
        painter->setPen(Qt::red);
        painter->drawRect(boundingRect().adjusted(0, 0, -painter->pen().width(), -painter->pen().width()));
    }
};

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    qmlRegisterType<Abteilung>("Test", 1, 0, "Abteilung");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));

    return app.exec();
}

#include "main.moc"

main.qml

import QtQuick 2.2
import QtQuick.Controls 1.1
import Test 1.0

ApplicationWindow {
    visible: true
    width: 640
    height: 480

    ListView {
        id: abteilungenListView
        anchors.fill: parent
        spacing: 5
        model: ListModel {
            Component.onCompleted: {
                for (var i = 0; i < 100; ++i) {
                    append({name: i});
                }
            }
        }

        delegate: Abteilung {
            width: abteilungenListView.width
            height: 40
        }
    }
}
Mitch
  • 23,716
  • 9
  • 83
  • 122
  • So I have to set the properties of my QQuickPaintedItem derived class in QML according to what the model returns, do I get that right? But they are already set in other instances, since they're being read from a database at application startup. – MrBolton Jul 04 '14 at 06:20
  • Yes, you should set them in QML, where each delegate has the relevant data for a particular index in the model. I don't know what you mean by "But they are already set in other instances, since they're being read from a database at application startup.". – Mitch Jul 04 '14 at 06:35
  • Well doing it this way means that there would be 2 instances of each object. One that stores the information to supply the model with data on the C++ side and one that draws the item on QML side, right? – MrBolton Jul 04 '14 at 06:41
  • It's hard to say without seeing your full code. The drawing, as far as I understand it from your question, is done within a `QQuickPaintedItem` subclass. That subclass should have some properties defined that can be set from within the QML instances of the delegates. – Mitch Jul 04 '14 at 07:51