天天看点

为QTableView添加批量处理界面操作

在与用户交互时,有时候需要提供批处理操作,尤其是有大量数据,且对每条数据操作都非常相似的时候,就必须提供批量操作,以简化用户的操作。

在这里,实现了对QTableView或QTableWidget行操作的批量处理。

以下是批处理的效果示例:

为QTableView添加批量处理界面操作

在这里,我将view的vertical HeadView重写为了可勾选的复选框栏,并提供了一些操作接口以方便勾选操作。

代码:

#ifndef CBATCHVERTICALHEADERVIEW_H
#define CBATCHVERTICALHEADERVIEW_H

/*
 * 这是为QTableView或者QTableWidget所写的一个批量操作控件。
 *
 * 它事实上就是View上的Vertical HeadView,只不错这里不再绘制行数,而是checkbox。
 *
 * 原理:在HeadView设置给View之后,通过HeadView返回的model,其实是View相关的Model,
 * 因此,我们将是否勾选的信息写入 model的第一列中的CheckedRole中,默认CheckedRole 为 Qt::UserRole+1
 * 如果和其他逻辑有冲突,可以修改CheckRole的实际值。然后重载paintSection,获取第一列的CheckRole的值,绘制
 * 相关图像即可。
 *
 * 由于View会在model变化时自动去重新绘制HeadView,因此剩下的交给Model/View固有逻辑即可。
 *
*/
#include <QHeaderView>
#include <QList>
#include <functional>

#define CheckedRole Qt::UserRole+1

class CBatchVerticalHeaderView : public QHeaderView
{
    Q_OBJECT
public:
    CBatchVerticalHeaderView(QWidget *parent = Q_NULLPTR);

    void SetAllSelected();
    void SetAllUnselected();
    void SetSelected(int section,bool selected);
    bool IsSelected(int section);
protected:
    //重载paint函数,改为绘制checkbox
    void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const;

private slots:
    void slotOnSectionClicked(int section);
};

#endif // CBATCHVERTICALHEADERVIEW_H
           
#include "BatchVerticalHeaderView.h"

#include <QDebug>
#include <QPainter>
#include <QStyle>
#include <QApplication>

static QRect CheckBoxRect(const QRect &rect)/*const*/
{
    //绘制按钮所需要的参数
    QStyleOptionButton checkBoxStyleOption;
    //按照给定的风格参数 返回元素子区域
    QRect checkBoxRect = QApplication::style()->subElementRect( QStyle::SE_CheckBoxIndicator, &checkBoxStyleOption);
    //返回QCheckBox坐标
    QPoint checkBoxPoint(rect.x() + rect.width() / 2 - checkBoxRect.width() / 2,
                         rect.y() + rect.height() / 2 - checkBoxRect.height() / 2);
    //返回QCheckBox几何形状
    return QRect(checkBoxPoint, checkBoxRect.size());
}

CBatchVerticalHeaderView::CBatchVerticalHeaderView(QWidget *parent)
    :QHeaderView(Qt::Vertical,parent)
{
    this->setSectionsClickable(true);
    this->setMinimumWidth(24);

    connect(this,SIGNAL(sectionClicked(int)),this,SLOT(slotOnSectionClicked(int)));
}

void CBatchVerticalHeaderView::SetAllSelected()
{
    QAbstractItemModel *model = this->model();
    for(int section = 0;section < count();++section)
    {
        QModelIndex index = model->index(section,0);
        model->setData(index,Qt::Checked,CheckedRole);

        this->setVisible(false);
        this->setVisible(true);
    }
}

void CBatchVerticalHeaderView::SetAllUnselected()
{
    QAbstractItemModel *model = this->model();
    for(int section = 0;section < count();++section)
    {
        QModelIndex index = model->index(section,0);
        model->setData(index,Qt::Unchecked,CheckedRole);

        this->setVisible(false);
        this->setVisible(true);
    }
}

void CBatchVerticalHeaderView::SetSelected(int section, bool selected)
{
    if(section < 0 || section >= this->count())
        return;

    QAbstractItemModel *model = this->model();
    QModelIndex index = model->index(section,0);
    Qt::CheckState oppsite = (selected) ? Qt::Checked : Qt::Unchecked;
    model->setData(index,oppsite,CheckedRole);

    this->setVisible(false);
    this->setVisible(true);
}

bool CBatchVerticalHeaderView::IsSelected(int section)
{
    if(section < 0 || section >= this->count())
        return false;

    QAbstractItemModel *model = this->model();
    QModelIndex index = model->index(section,0);
    Qt::CheckState checked = model->data(index,CheckedRole).value<Qt::CheckState>();

    return (checked == Qt::Checked) ? true : false;
}

void CBatchVerticalHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{  
#if 1
    QAbstractItemModel *model = this->model();
    QModelIndex index = model->index(logicalIndex,0);
    Qt::CheckState checkstate = model->data(index,CheckedRole).value<Qt::CheckState>();
    bool checked = (checkstate == Qt::Checked) ? true : false;

    QStyleOptionButton checkBoxStyleOption;
    checkBoxStyleOption.state |= QStyle::State_Enabled;
    checkBoxStyleOption.state |= checked? QStyle::State_On : QStyle::State_Off;
    checkBoxStyleOption.rect = CheckBoxRect(rect);

    QApplication::style()->drawControl(QStyle::CE_CheckBox,&checkBoxStyleOption,painter);
#else
    painter->setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing);

    QAbstractItemModel *model = this->model();
    QModelIndex index = model->index(logicalIndex,0);
    Qt::CheckState checkstate = model->data(index,CheckedRole).value<Qt::CheckState>();
    bool checked = (checkstate == Qt::Checked) ? true : false;

    QString pic = checked ? "checked.png" : "unchecked.png";
    painter->drawPixmap(rect,QPixmap(pic));
#endif
}

void CBatchVerticalHeaderView::slotOnSectionClicked(int section)
{
    if(section < 0 || section >= this->count())
        return;

    QAbstractItemModel *model = this->model();
    QModelIndex index = model->index(section,0);
    Qt::CheckState checked = model->data(index,CheckedRole).value<Qt::CheckState>();
    Qt::CheckState oppsite = (checked == Qt::Checked) ? Qt::Unchecked : Qt::Checked;
    model->setData(index,oppsite,CheckedRole);
}
           

继续阅读