每个代理的非平凡qt模型数据操作

时间:2015-09-25 14:18:58

标签: c++ qt

当我开始问here时,我试图在不同的视图中以不同的方式查看Qt中单个模型中包含的数据,而无需创建更多模型且不更改它。

更具体一点:我试图采用QString并在几个表格中逐字显示,并在其他情况下将其视为简单的操作。

命名一个这样的操作:一个表将反转字符串(此表只有一行,但由于程序相关原因,行编辑不起作用)并删除任何空格(保留在模型中,因为在其他视图中是必需的。)

编辑: 提供更完整,更具体的示例:Hello World - > Dlrow Olleh。 我想要反转大小写并检查完全由大写字母组成的单词 - 这些单词将完全保留为大写字母。

另一个计划的操作也删除了所有空格,但这次表格将是一个矩阵(所以我想要对索引函数进行一些更改)。

EDIT2:请注意,矩阵的大小会根据输入的大小而变化,以适应屏幕,因此索引(至少在表格本身中)不会保持不变。如果那很重要......

过去两天我一直试图弄清楚如何做到这一点,而且我能找到的最好的(除了阅读Qt文档之外,没有任何帮助)是 this article

但是,它并没有解释每一段代码的作用是否足够好,因此不允许像我这样不熟悉这个概念的人做出任何修改。代码以满足我的需求。

当然,我可以创建更多的模型,并在凌乱的底层之外执行所有这些操作,但我喜欢挑战自己,尽可能多地学习一些东西,找到更好,更有效的方法来做事。

在对子类化时,我需要在QAbstractProxyModel中实现什么,更重要的是 - 我该怎么做(解释代码将非常感激) 为了创建一个会提供这种行为的代码? (我知道每个代理可能会有所不同)

2 个答案:

答案 0 :(得分:1)

在您根据需要进行各种行为的必要测试用例修改问题之前,这里有一个简单的代理,它可以反转字符串值并删除所有空格:

class FlexibleProxy : public QIdentityProxyModel {
public:
  enum {
    StripSpaces = 0x1,
    Reverse = 0x2
  } Operation;
  Q_DECLARE_FLAGS(Operations, Operation)
private:
  Operations m_ops;
public:
  FlexibleProxy(Operations ops, QObject * parent = 0) :
    QIdentityProxyModel(parent), m_ops(ops) {}
  QVariant data(QModelIndex & index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE {
    auto val = QIdentityProxyModel::data(index, role);
    if ((role == Qt::DisplayRole || role == Qt::EditRole) 
        && val.userType() == QMetaType::QString) {
      auto str = val.toString();
      if (m_ops & StripSpaces) str.remove(QLatin1Char(' '));
      if (m_ops & Reverse) reverse(str);
      val.setValue(str);
    }
    return val;
  }
};
Q_DECLARE_OPERATORS_FOR_FLAGS(FlexibleProxy::Operations)

static void reverse(QString & str) {
  auto const size = str.size();
  for (int i = 0; i <= size/2; ++i) {
    std::swap(str[i], str[size-i]);
  }
}

使用:

FlexibleProxy proxy{FlexibleProxy::Reverse | FlexibleProxy::StripSpaces};
proxy.setSourceModel(...);
view.setModel(&proxy);

答案 1 :(得分:1)

由于您不需要数据过滤(根据您的OP),您可以使用QIdentityProxyModel。以下是所有类以及屏幕截图

mainwindow.cpp

#include "mainwindow.h"
#include "basemodel.h"
#include "identitymodel.h"

#include <QTableView>
#include <QBoxLayout>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QWidget* cWidget = new QWidget(this);
    setCentralWidget(cWidget);

    IdentityModel* normalModel = new IdentityModel(IdentityModel::UnModified, cWidget);
    IdentityModel* reverseModel = new IdentityModel(IdentityModel::Reverse, cWidget);
    IdentityModel* noSpaceModel = new IdentityModel(IdentityModel::NoSpace, cWidget);

    normalModel->setSourceModel(&BaseModel::instance());
    reverseModel->setSourceModel(&BaseModel::instance());
    noSpaceModel->setSourceModel(&BaseModel::instance());

    QTableView* view1 = new QTableView(cWidget);
    QTableView* view2 = new QTableView(cWidget);
    QTableView* view3 = new QTableView(cWidget);

    view1->setModel(normalModel);
    view2->setModel(reverseModel);
    view3->setModel(noSpaceModel);

    QHBoxLayout* hLayout = new QHBoxLayout(cWidget);
    hLayout->addWidget(view1);
    hLayout->addWidget(view2);
    hLayout->addWidget(view3);
}

basemodel.h

    #ifndef BASEMODEL_H
    #define BASEMODEL_H

    #include <QStringListModel>

    class BaseModel : public QStringListModel
    {
        Q_OBJECT

    public:

        static BaseModel& instance()
        {
            static BaseModel sInstance;
            return sInstance;
        }

        virtual int rowCount(const QModelIndex& parent) const
        {
            Q_UNUSED(parent);

            return m_dataList.size();
        }

        virtual QVariant data(const QModelIndex& modelIndex, int role) const;

    signals:

    public slots:

    private:

        explicit BaseModel(QObject* prnt=0);

        QStringList         m_dataList;
    };

    #endif // BASEMODEL_H

basemodel.cpp

    #include "basemodel.h"

    BaseModel::BaseModel(QObject* prnt)
        : QStringListModel(prnt),
          m_dataList({"Hello World", "Good Bye World"})
    {
    }

    QVariant BaseModel::data(const QModelIndex& modelIndex, int role) const
    {
        if (modelIndex.isValid() && modelIndex.row() < m_dataList.size() && role == Qt::DisplayRole) {
            return m_dataList.at(modelIndex.row());
        }
        return QVariant();
    }

identitymodel.h

#define IDENTITYMODEL_H

#include <QIdentityProxyModel>

class IdentityModel : public QIdentityProxyModel
{
    Q_OBJECT

public:

    enum StringMod
    {
        UnModified,
        Reverse,
        NoSpace
    };

    explicit IdentityModel(StringMod mod, QObject* prnt=0);

    virtual QVariant data(const QModelIndex& proxyIndex, int role) const;

signals:

public slots:

private:

    StringMod       m_stringMod;
};

identitymodel.cpp

#include "identitymodel.h"    
#include <algorithm>

IdentityModel::IdentityModel(StringMod mod, QObject* prnt)
    : QIdentityProxyModel(prnt),
      m_stringMod(mod)
{
}

QVariant IdentityModel::data(const QModelIndex& proxyIndex, int role) const
{
    QVariant dataToModify(QIdentityProxyModel::data(proxyIndex, role));
    if (role == Qt::DisplayRole && m_stringMod != UnModified) {
        QString str(dataToModify.toString());
        if (m_stringMod == NoSpace)
            return str.remove(' ');
        else {
            QByteArray ba(str.toUtf8());
            std::reverse(ba.data(), ba.data() + str.length());
            str = QString(ba);
        }
        return str;
    }
    return dataToModify;
}

ProxyModel