как перенести QAbstractItemModel в QtQuick (без определения ItemDelegate) - PullRequest
0 голосов
/ 24 февраля 2020

У меня есть QAbstractItemModel модель дерева для дерева сущностей Qt3D:

qt3dentitytreemodel.h:

#define QT3DENTITYTREEMODEL_H

#include <QAbstractItemModel>
#include <Qt3DCore/QEntity>

class Qt3DEntityTreeModel : public QAbstractItemModel
{
    Q_OBJECT
public:
    Q_PROPERTY(Qt3DCore::QEntity * rootEntity READ rootEntity WRITE setRootEntity NOTIFY rootEntityChanged)

    explicit Qt3DEntityTreeModel(QObject *parent = nullptr);

    void setRootEntity(Qt3DCore::QEntity *rootEntity);
    Qt3DCore::QEntity * rootEntity() const;

    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
    QModelIndex parent(const QModelIndex &child) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    int columnCount(const QModelIndex &parent = QModelIndex()) const override;
    Qt::ItemFlags flags(const QModelIndex &index) const override;

signals:
    void rootEntityChanged(Qt3DCore::QEntity *rootEntity);

private:
    Qt3DCore::QEntity *rootEntity_;
};

#endif // QT3DENTITYTREEMODEL_H

qt3dentitytreemodel. cpp:

#include "qt3dentitytreemodel.h"

Qt3DEntityTreeModel::Qt3DEntityTreeModel(QObject *parent)
    : QAbstractItemModel(parent)
{
}

void Qt3DEntityTreeModel::setRootEntity(Qt3DCore::QEntity *rootEntity)
{
    qDebug() << "Qt3DEntityTreeModel::setRootEntity" << rootEntity;

    auto old = rootEntity_;

    rootEntity_ = rootEntity;

    if(rootEntity_ != old)
        emit rootEntityChanged(rootEntity);
}

Qt3DCore::QEntity * Qt3DEntityTreeModel::rootEntity() const
{
    return rootEntity_;
}

QModelIndex Qt3DEntityTreeModel::index(int row, int column, const QModelIndex &parent) const
{
    if(!rootEntity_) return {};
    if(column != 0) return {};
    if(!parent.isValid())
    {
        if(row == 0) return createIndex(0, 0, rootEntity_);
    }
    else
    {
        auto entity = reinterpret_cast<Qt3DCore::QEntity*>(parent.internalPointer());
        if(!entity) return {};

        return createIndex(row, column, entity->childNodes().at(row));
    }
    return {};
}

QModelIndex Qt3DEntityTreeModel::parent(const QModelIndex &child) const
{
    if(!rootEntity_) return {};
    if(!child.isValid()) return {};

    auto entity = reinterpret_cast<Qt3DCore::QEntity*>(child.internalPointer());
    if(!entity) return {};

    auto parent = entity->parentNode();
    if(!parent) return {};

    auto grandParent = parent->parentNode();
    if(!grandParent) return createIndex(0, 0, parent);

    return createIndex(grandParent->childNodes().indexOf(parent), 0, parent);
}

QVariant Qt3DEntityTreeModel::data(const QModelIndex &index, int role) const
{    
    if(!rootEntity_) return {};
    if(!index.isValid()) return {};
    if(role != Qt::DisplayRole && role != DisplayRole) return {};

    auto entity = reinterpret_cast<Qt3DCore::QEntity*>(index.internalPointer());
    if(!entity) return {};

    QString data = entity->metaObject()->className();
    if(!entity->objectName().isEmpty())
            data += QString(" \"%1\"").arg(entity->objectName());
    return data;
}

QVariant Qt3DEntityTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    return {};
}

int Qt3DEntityTreeModel::rowCount(const QModelIndex &parent) const
{
    if(!parent.isValid()) return 1;

    auto entity = reinterpret_cast<Qt3DCore::QEntity*>(parent.internalPointer());
    if(!entity) return 0;
    return entity->childNodes().count();
}

int Qt3DEntityTreeModel::columnCount(const QModelIndex &parent) const
{
    return 1;
}

Qt::ItemFlags Qt3DEntityTreeModel::flags(const QModelIndex &index) const
{
    return {};
}

который отлично работает при отображении в QTreeView (QtWidgets):

auto treeView = new QTreeView();
auto treeModel = new Qt3DEntityTreeModel(treeView);
treeModel->setRootEntity(rootEntity);
treeView->setModel(treeModel);
treeView->resize(640, 480);
treeView->show();

screenshot

однако при использовании в элементах управления QtQuick TreeView я не вижу текст элемента и Я даже не могу развернуть элемент дерева root:

Item {
    ...

    Qt3DEntityTreeModel {
        id: entityTreeModel
        rootEntity: root
    }

    TreeView {
        model: entityTreeModel
        TableViewColumn {
            title: "Name"
            width: 200
        }
    }

    Scene3D {
        id: scene3d

        Entity {
            id: root
            ...
        }
    }
}

screenshot

Я также попытался явно определить роль в Qt3DEntityTreeModel:

qt3dentitytreemodel. h:

enum Roles {
    DisplayRole = Qt::UserRole + 1
};
QHash<int, QByteArray> roleNames() const override;

qt3dentitytreemodel. cpp:

QVariant Qt3DEntityTreeModel::data(const QModelIndex &index, int role) const
{    
    if(!rootEntity_) return {};
    if(!index.isValid()) return {};
    if(role != Qt::DisplayRole && role != DisplayRole) return {};
    ...
}

QHash<int, QByteArray> Qt3DEntityTreeModel::roleNames() const
{
    QHash<int, QByteArray> result;
    result.insert(DisplayRole, QByteArrayLiteral("display"));
    return result;
}

и определите соответствующее свойство роли в столбце QtQuick TreeView:

TreeView {
    model: entityTreeModel
    TableViewColumn {
        title: "Name"
        role: "display"
        width: 200
    }
}

, но по-прежнему ничего не показывает.

Есть ли что-то еще, чтобы иметь возможность использовать пользовательскую модель абстрактного элемента с TreeView QtQuick?

1 Ответ

0 голосов
/ 25 февраля 2020

Мне кажется, я нашел объяснение: модель создается до того, как дерево сущностей Qt3D будет "готово".

Если я создаю модель в C ++ после загрузки представления, тогда задайте модель как контекст это свойство отображается правильно в TreeView QML:

QQuickView view;
view.resize(500, 500);
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.setSource(QUrl("qrc:/main.qml"));

auto rootObject = view.rootObject();
auto rootEntity = rootObject->findChild<Qt3DCore::QEntity*>("theRootEntity");
qDebug() << "rootEntity:" << rootEntity;

auto treeModel = new Qt3DEntityTreeModel(&app);
treeModel->setRootEntity(rootEntity);

view.rootContext()->setContextProperty("theModel", treeModel);

view.show();

Основная проблема заключается в том, что моя модель не отслеживает обновления в дереве сущностей Qt3D и не отражает такие обновления.

...