如何使用Qt代理模型对表数据进行分组

时间:2018-06-03 13:42:30

标签: c++ qt qtableview qsortfilterproxymodel

我想从现有表生成一些简单的group和sum数据计算 并在另一个表/视图上显示结果。 (见图)

Group and sum table data

我通过重新实现QSortFilterProxyModel成功实现了这一点 我必须覆盖data()函数 并保留我自己的模型数据。

我不确定这是最好的方法,

我读了一些表格,建议为这类任务重新实现QAbstractProxyModel, 但我没有找到任何好的例子。

以下是我实施的部分

模型h文件

#include

typedef struct _TableItem_
{
    _TableItem_()
    {

    }

    _TableItem_(const QString& _oName, int _iValue)
    {
        this->iValue = _iValue;
        this->oName = _oName;
    }

    int iValue;
    QString oName;

}STABLE_ITEM;

typedef  QVector<STABLE_ITEM> TableData;

// Proxy model for doing group and count
class TableGroupModel : public QSortFilterProxyModel
{
    Q_OBJECT

private:
    mutable TableData m_oData;

    QVariant GetData(int iRow, int iColumn) const;
    bool AddItem(const QString & oName, int iValue) const;

protected:
    bool filterAcceptsRow(int iSourceRow, const QModelIndex &oSourceParent) const;
    QVariant data(const QModelIndex &oIndex, int role) const override;

public:
    TableGroupModel(QObject *parent = NULL) ;
    void Clear();

};

模型cpp文件

 #include "table_group_model.h"

TableGroupModel::TableGroupModel(QObject *parent)
    : QSortFilterProxyModel(parent)
{

}

void TableGroupModel::Clear()
{
    m_oData.clear();
}

QVariant TableGroupModel::GetData(int iRow, int iColumn) const
{
    switch (iColumn) {
    case 0: // Name column
        return m_oData.at(iRow).oName;
    case 1: // Value column
        return m_oData.at(iRow).iValue;
    default:
        break;
    }
    return QVariant();
}

bool TableGroupModel::AddItem(const QString &oName, int iValue) const
{
    // search for the item.
    auto oIt = std::find_if(m_oData.begin(), m_oData.end(),
                            [oName](const STABLE_ITEM & sTableItem){
        return (sTableItem.oName == oName);
    });

    // Item found ?
    if (oIt != m_oData.end())
    {
        // update values.
        (*oIt).iValue += iValue;

        // filter this row.
        return false;
    }

    // Append new item
    m_oData.append(STABLE_ITEM(oName, iValue));

    // accept this row
    return true;
}

bool TableGroupModel::filterAcceptsRow(int iSourceRow, const QModelIndex &oSourceParent) const
{
    QModelIndex oIndex=
            sourceModel()->index(iSourceRow, 0, oSourceParent);

    QString oValueName =
            sourceModel()->data(oIndex).toString();

    oIndex=
            sourceModel()->index(iSourceRow, 1, oSourceParent);

    int iValue =
            sourceModel()->data(oIndex).toInt();

    // append data
    return AddItem(oValueName, iValue);

}

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

    switch (role) {
    case Qt::DisplayRole:
        return GetData(oIndex.row(), oIndex.column());
    default:
        break;
    }

    return sourceModel()->data(oIndex,role);
}

主窗口cpp

#include "mainwindow.h"

#include <QTableView>
#include <QHBoxLayout>
#include "table_model.h"
#include "table_group_model.h"


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    this->setCentralWidget(InitTableWidget());

    // Fill table with data.
    FillTable();
}

MainWindow::~MainWindow()
{
}

QWidget *MainWindow::InitTableWidget()
{
    QHBoxLayout * poHTableLayout = new QHBoxLayout;

    // Table Model
    m_poTableModel.reset(new TableModel);

    // Table view
    QTableView * poTable = new QTableView(this);
    poTable->setModel(m_poTableModel.data());

    // Group table view
    QTableView * poGroupTable = new QTableView(this);
    m_poTableGroupModel.reset(new TableGroupModel(this));
    m_poTableGroupModel->setSourceModel(m_poTableModel.data());
    poGroupTable->setModel(m_poTableGroupModel.data());

    // Layout horizontal tables
    poHTableLayout->addWidget(poTable);
    poHTableLayout->addWidget(poGroupTable);

    QWidget * poTablesWidget = new QWidget(this);
    poTablesWidget->setLayout(poHTableLayout);

    return poTablesWidget;
}


void MainWindow::FillTable()
{
    TableData oTableData;
    oTableData.append(STABLE_ITEM("a",1));
    oTableData.append(STABLE_ITEM("a",2));
    oTableData.append(STABLE_ITEM("b",3));
    oTableData.append(STABLE_ITEM("c",4));
    oTableData.append(STABLE_ITEM("c",5));
    oTableData.append(STABLE_ITEM("a",7));

    m_poTableModel->DropTable(oTableData);

}

我的GitHub

中的完整代码

有什么建议吗?

0 个答案:

没有答案