如何根据设置的视图调整模型?

时间:2019-09-13 00:33:19

标签: c++ qt model-view-controller qstringlistmodel

情况

我只有一个Qt模型,特别是从QStringListModel派生的StringModel,称为“模型”。

我有三个视图,特别是三个QListView,分别称为“ listView_1”,“ listView_2”和“ listView_3”。

所有这三个QListView都设置为一个模型,即:

(ui->listView_1)->setModel(model);
(ui->listView_2)->setModel(model);
(ui->listView_3)->setModel(model);

并发症

尽管我希望所有三个视图都引用相同的模型,但是它们从该模型显示的数据应该略有不同。该模型中指示视图中显示哪些数据的函数是从QStringListModel继承的“数据”成员函数,并定义为:

QVariant StringModel::data(const QModelIndex &index, int role) const
{
        if (!index.isValid()){
            return QVariant();
        }
        if (role == Qt::DisplayRole)
        {
            int col = index.column();
            int row = index.row();
            if (col == 0){
                QList<Contact*> list = contactList.findChildren<Contact*>();
                return list.at(row)->toString();//<<THIS STATEMENT MUST BE VARIABLE
            }
        }
        QVariant v;
        return v;
}

上面代码中的第12行返回要在视图上显示的数据,这就是我想根据视图而改变的return语句。

问题

模型视图控制器最佳实践指出,我们应该能够保持模型不变,并使用较小的调整来更改视图。因此,在没有为3个视图定义3个模型的情况下,如何调整数据函数以根据设置为它的视图返回变化的语句?或者,总结一下一个句子,如何根据设置的视图调整模型?

1 个答案:

答案 0 :(得分:2)

对于简单的用例,我建议您使用QIdentityProxyModel。下面是一个带有两个视图的小示例,其中一个视图以相反的顺序显示字符串。

您必须仔细考虑Qt::ItemDataRole::EditRoleQt::ItemDataRole::DisplayRole这两个角色,以使其看起来不明显。

main.cpp

#include <cmath>
#include <QApplication>
#include <QHBoxLayout>
#include <QStandardItemModel>
#include "ReverseModel.h"
#include <QListView>
#include <QFrame>

int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    auto frame = new QFrame;
    auto model = new QStandardItemModel;
    auto view1 = new QListView;
    auto view2 = new QListView;
    view1->setModel(model);
    auto reverseModel = new ReverseModel;
    reverseModel->setSourceModel(model);
    view2->setModel(reverseModel);
    frame->setLayout(new QHBoxLayout);
    frame->layout()->addWidget(view1);
    frame->layout()->addWidget(view2);
    model->appendRow(new QStandardItem("Test"));
    frame->show();
    return a.exec();
}

ReverseModel.h

#pragma once

#include <QIdentityProxyModel>
#include <algorithm>

class ReverseModel : public QIdentityProxyModel {
    Q_OBJECT
public: 
    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override {
        if (role == Qt::DisplayRole || role==Qt::EditRole) {
            auto data = QIdentityProxyModel::data(index);
            auto string = data.toString();
            std::reverse(string.begin(), string.end());
            return string;
        }
        else {
            return QIdentityProxyModel::data(index, role);
        }

    }

    bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override {
        if (role == Qt::EditRole ) {
            auto string = value.toString();
            std::reverse(string.begin(), string.end());
            QVariant reversedValue =string;
            return QIdentityProxyModel::setData(index, reversedValue, role);
        }
        else {
            return QIdentityProxyModel::setData(index, value, role);
        }
    }
};