2

I have a model that contains several QStandardItemModels. Now I want to create a view that displays a TableView for each QStandardItemModel. I had the idea to have a ListView that has a TableView as delegate, something like this:

ListView {
    id: myListView

    anchors {
        fill: parent
        margins: 5
    }

    model: testModel
    delegate: CompareDelegate { }
}

And in CompareDelegate.qml:

Item {
    id: base

    width: 500
    height: 300

    TableView {
        anchors.fill: parent
    }
}

How do I get the TableView inside the delegate to use the appropriate QStandardItemModel within the model of the ListView? I hope the question is somewhat clear.

Thanks in advance.

1 Answer 1

2

Interesting use case... I am still not sure if it's a good idea and am wondering if there's a better way to do it, but I couldn't think of reasons why it's bad, so I tried it out of curiosity:

main.cpp

#include <QApplication>
#include <QtQml>
#include <QtWidgets>

class IndividualModel : public QStandardItemModel
{
public:
    IndividualModel(QObject* parent = 0) :
        QStandardItemModel(4, 2, parent)
    {
        for (int row = 0; row < 4; ++row) {
            QStandardItem *item0 = new QStandardItem;
            item0->setData(QString("row %1, column 0").arg(row), TitleRole);
            setItem(row, 0, item0);

            QStandardItem *item1 = new QStandardItem;
            item1->setData(QString("row %1, column 1").arg(row), AuthorRole);
            setItem(row, 1, item1);
        }
    }

    enum {
        TitleRole = Qt::UserRole,
        AuthorRole
    };

    QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE
    {
        QHash<int, QByteArray> names;
        names[TitleRole] = "title";
        names[AuthorRole] = "author";
        return names;
    }
};

class CompositeModel : public QAbstractItemModel
{
public:
    CompositeModel()
    {
        for (int i = 0; i < 3; ++i) {
            QStandardItemModel *model = new IndividualModel(this);
            mModels.append(model);
        }
    }

    enum {
        ModelRole = Qt::UserRole
    };

    QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE
    {
        if (!index.isValid())
            return QVariant();

        if (role != ModelRole)
            return QVariant();

        return QVariant::fromValue(mModels.at(index.row()));
    }

    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE
    {
        if (!hasIndex(row, column, parent))
            return QModelIndex();

        return createIndex(row, column);
    }

    QModelIndex parent(const QModelIndex &) const Q_DECL_OVERRIDE
    {
        return QModelIndex();
    }

    int rowCount(const QModelIndex & = QModelIndex()) const Q_DECL_OVERRIDE
    {
        return mModels.size();
    }

    int columnCount(const QModelIndex & = QModelIndex()) const Q_DECL_OVERRIDE
    {
        return 1;
    }

    QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE
    {
        QHash<int, QByteArray> names;
        names[ModelRole] = "individualModel";
        return names;
    }

private:
    Q_DISABLE_COPY(CompositeModel)

    QVector<QStandardItemModel*> mModels;
};

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

    QQmlApplicationEngine engine;

    CompositeModel compositeModel;
    engine.rootContext()->setContextProperty("compositeModel", QVariant::fromValue(&compositeModel));

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

    return app.exec();
}

main.qml

import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.0

Window {
    visible: true
    width: 300
    height: 600

    ListView {
        anchors.fill: parent
        model: compositeModel
        delegate: TableView {
            model: individualModel

            TableViewColumn {
                role: "title"
                title: "Title"
                width: 100
            }
            TableViewColumn {
                role: "author"
                title: "Author"
                width: 200
            }
        }
    }
}

This works, but... it crashes on exit. :)

I've been unable to reproduce it while debugging with Creator, so I've only been able to get a stack trace manually on the command line with gdb, which I'm not too familiar with (have always used debuggers in IDEs :)). The crash is in QML's guts somewhere, while accessing some property. However, I've spent too much time on this to not post the answer, and I think it is still useful. Maybe some kind soul will find the problem and edit my post. :)

Sign up to request clarification or add additional context in comments.

1 Comment

This is a great approach, thank you very much! Also, it's not crashing in my context.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.