首页 > 解决方案 > 如何使用 QAbstractItemModel 映射多级对象模型

问题描述

我开始学习 Qt 中的 MVC 模式。

我有简单的数据结构,如下所示:

class Stage
{
public:
    QString name;
    int number;
};

class Doc
{
public:
    Doc();
    ~Doc();
    QString name;
    int number;
    QList<Stage *> *stages;
};

我想在 TreeView 中查看这个结构。为此,我创建了模型类:

class Model: public QAbstractItemModel
{
    Q_OBJECT

public:
    Model(QObject *parent);
    ~Model();

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    QModelIndex index(int row, int column, const QModelIndex &parent) const;
    QModelIndex parent(const QModelIndex &index) const;
    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    int columnCount(const QModelIndex &parent = QModelIndex()) const;
    Qt::ItemFlags flags(const QModelIndex &index) const;
    QVariant headerData(int section, Qt::Orientation orientation,
                        int role = Qt::DisplayRole) const;
private:
    QList<Doc*> *docs;

如果我只有一级数据(没有阶段的文档),一切正常,但我不明白如何将第二个树级别添加到模型(阶段)?

代码示例(一级)

Model::Model(QObject *parent) : QAbstractItemModel(parent)
{
    docs = new QList<Doc*>();
    for (int i = 0; i < 3; ++i) {
        Doc *d = new Doc();
        d->name = "name_" + QString::number(i);
        d->number = i;
        docs->append(d);
    }
}

Model::~Model()
{
    delete docs;
}

QModelIndex Model::index(int row, int column, const QModelIndex &parent) const
{
    if (!parent.isValid()) {
        Doc *d = docs->at(row);
        return createIndex(row, column, d);
    } 
    return QModelIndex();
}

QModelIndex Model::parent(const QModelIndex &index) const
{
    return QModelIndex();
}

int Model::rowCount(const QModelIndex &parent) const
{
    int cnt = 0;
    if (!parent.isValid()) {
        cnt = docs->size();
    } 
    return cnt;
}

int Model::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return 3;
}

Qt::ItemFlags Model::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return nullptr;
    return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}

QVariant Model::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role != Qt::DisplayRole)
        return QVariant();

    if (orientation == Qt::Horizontal) {
        switch (section) {
        case 0:
            return tr("Number");
        case 1:
            return tr("Code");
        case 2:
            return tr("Stages count");
        default:
            return QVariant();
        }
    }
    return QVariant();
}

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

    if (role != Qt::DisplayRole)
        return QVariant();
    {
        Doc *d = static_cast<Doc*>(index.internalPointer());

        switch (index.column()) {
        case 0:
            return d->name;
        case 1:
            return d->number;
        case 2:
            return d->stages->size();
        default:
            break;
        }
    }
    return QVariant();
}

我认为它看起来像这样:

Model::Model(QObject *parent) : QAbstractItemModel(parent)
{
    docs = new QList<Doc*>();
    for (int i = 0; i < 3; ++i) {
        Doc *d = new Doc();
        d->name = "name_" + QString::number(i);
        d->number = i;
        for (int j = 5; j < 9; ++j) {
            Stage *s = new Stage();
            s->name = "name_" + QString::number(j);
            s->number = j;
            d->stages->append(s);
        }
        docs->append(d);
    }
}


QModelIndex Model::index(int row, int column, const QModelIndex &parent) const
{
    if (!parent.isValid()) {
        Doc *d = docs->at(row);
        return createIndex(row, column, d);
    } else {
        Stage *s = static_cast<Doc*>(parent.internalPointer())->stages->at(row);
        return createIndex(row, column, s);
    }
    return QModelIndex();
}

QModelIndex Model::parent(const QModelIndex &index) const
{
    if (!index.isValid())
        return QModelIndex();
    else if (index.parent().isValid())
        return createIndex(index.parent().row(), 0, index.internalPointer());
    return QModelIndex();
}

int Model::rowCount(const QModelIndex &parent) const
{
    int cnt = 0;
    if (!parent.isValid()) {
        cnt = docs->size();
    } else {
        cnt = static_cast<Doc*>(parent.parent().internalPointer())->stages->size();
    }
    return cnt;
}

但它的错误代码......

标签: c++qtmodel-view-controller

解决方案


推荐阅读