207 lines
5.1 KiB
C++
207 lines
5.1 KiB
C++
#include "TableHeaderView.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)
|
||
{
|
||
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);
|
||
}
|
||
|
||
|
||
|
||
|