#include "ccheckboxmodel.h"
#include <QCheckBox>
#include <QApplication>
#include <QMouseEvent>
#include <qmessagebox.h>
#ifdef _MSC_VER
#pragma execution_character_set("utf-8")
#endif
#define CHECK_BOX_COLUMN 0
TableHeaderView::TableHeaderView(Qt::Orientation orientation, QWidget *parent)
: QHeaderView(orientation, parent),
m_bPressed(false),
m_bChecked(false),
m_bTristate(false),
m_bNoChange(false),
m_bMoving(false)
{
setSectionsClickable(true); // 响应鼠标
}
TableHeaderView::~TableHeaderView()
{
}
// 槽函数,用于更新复选框状态
void TableHeaderView::onStateChanged(int state)
{
if (state == Qt::PartiallyChecked) {
m_bTristate = true;
m_bNoChange = true;
}
else {
m_bNoChange = false;
}
m_bChecked = (state != Qt::Unchecked);
update();
}
// 绘制复选框
void TableHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
painter->save();
QHeaderView::paintSection(painter, rect, logicalIndex);
painter->restore();
if (logicalIndex == CHECK_BOX_COLUMN)
{
QStyleOptionButton option;
option.initFrom(this);
if (m_bChecked)
option.state |= QStyle::State_Sunken;
if (m_bTristate && m_bNoChange)
option.state |= QStyle::State_NoChange;
else
option.state |= m_bChecked ? QStyle::State_On : QStyle::State_Off;
if (testAttribute(Qt::WA_Hover) && underMouse()) {
if (m_bMoving)
option.state |= QStyle::State_MouseOver;
else
option.state &= ~QStyle::State_MouseOver;
}
QCheckBox checkBox;
option.iconSize = QSize(20, 20);
option.rect = rect;
style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &option, painter, &checkBox);
}
}
// 鼠标按下表头
void TableHeaderView::mousePressEvent(QMouseEvent *event)
{
qDebug("[mousePressEvent] type:%d, time:%lu", event->type(), event->timestamp());
int nColumn = logicalIndexAt(event->pos());
if ((event->buttons() & Qt::LeftButton) && (nColumn == CHECK_BOX_COLUMN))
{
m_bPressed = true;
}
else
{
QHeaderView::mousePressEvent(event);
}
}
// 鼠标从表头释放,发送信号,更新model数据
void TableHeaderView::mouseReleaseEvent(QMouseEvent *event)
{
if (m_bPressed)
{
if (m_bTristate && m_bNoChange)
{
m_bChecked = true;
m_bNoChange = false;
}
else
{
m_bChecked = !m_bChecked;
}
update();
Qt::CheckState state = m_bChecked ? Qt::Checked : Qt::Unchecked;
emit stateChanged(state);
updateSection(0);
}
else
{
QHeaderView::mouseReleaseEvent(event);
}
m_bPressed = false;
}
// 鼠标滑过、离开,更新复选框状态
bool TableHeaderView::event(QEvent *event)
{
updateSection(0);
if (event->type() == QEvent::Enter || event->type() == QEvent::Leave)
{
QMouseEvent *pEvent = static_cast<QMouseEvent *>(event);
int nColumn = logicalIndexAt(pEvent->x());
if (nColumn == CHECK_BOX_COLUMN)
{
m_bMoving = (event->type() == QEvent::Enter);
update();
return true;
}
}
return QHeaderView::event(event);
}
CheckBoxDelegate::CheckBoxDelegate(QObject *parent) :QStyledItemDelegate(parent)
{
}
CheckBoxDelegate::~CheckBoxDelegate()
{
}
// 绘制复选框
void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItem viewOption(option);
initStyleOption(&viewOption, index);
if (option.state.testFlag(QStyle::State_HasFocus))
viewOption.state = viewOption.state ^ QStyle::State_HasFocus;
QStyledItemDelegate::paint(painter, viewOption, index);
if (index.column() == CHECK_BOX_COLUMN)
{
bool data = index.model()->data(index, Qt::UserRole).toBool();
QStyleOptionButton checkBoxStyle;
checkBoxStyle.state = data ? QStyle::State_On : QStyle::State_Off;
checkBoxStyle.state |= QStyle::State_Enabled;
checkBoxStyle.iconSize = QSize(20, 20);
checkBoxStyle.rect = option.rect;
QCheckBox checkBox;
checkBoxStyle.iconSize = QSize(20, 20);
checkBoxStyle.rect = option.rect;
QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &checkBoxStyle, painter, &checkBox);
checkBox.setEnabled(false);
}
}
// 响应鼠标事件,更新数据
bool CheckBoxDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
QRect decorationRect = option.rect;
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
if (event->type() == QEvent::MouseButtonPress && decorationRect.contains(mouseEvent->pos()))
{
if (index.column() == CHECK_BOX_COLUMN)
{
bool data = model->data(index, Qt::UserRole).toBool();
model->setData(index, !data, Qt::UserRole);
}
}
return QStyledItemDelegate::editorEvent(event, model, option, index);
}