BatteryMonitor/custom/delegate.cpp

650 lines
19 KiB
C++
Raw Normal View History

2024-10-31 16:48:38 +08:00
#include "delegate.h"
#include <QDebug>
#include <QSpinBox>
#include <QDateEdit>
#include <QCheckBox>
#include <QComboBox>
#include <QDateTimeEdit>
#include <QDateEdit>
#include <QPushButton>
#include <QLineEdit>
#include <QCalendarWidget>
#include <QProgressBar>
#include <QApplication>
#include <QPainter>
#include <QMouseEvent>
2024-11-07 16:04:50 +08:00
#include <QLabel>
2024-10-31 16:48:38 +08:00
#include <QTableView>
Delegate::Delegate(QObject *parent): QStyledItemDelegate(parent)
{
this->init();
}
QWidget *Delegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/*option*/, const QModelIndex &/*index*/) const
{
if(delegateType == "QCheckBox")
return 0;
/*创建编辑器*/
QWidget *editor = new QWidget(parent);
/*判断具体的委托,并将编辑器进行响应的设置*/
if(delegateType == "QSpinBox")
{
//必须加上parent负责QSpinBox显示在视图外面
QSpinBox *sbox = new QSpinBox(parent);
sbox->setRange(sboxMinValue,sboxMaxValue);
sbox->setSuffix(sboxSuffixStr);
sbox->setPrefix(sboxPrefixStr);
sbox->setSingleStep(sboxSingleStep);
sbox->setStepType(sboxStepType);
sbox->setValue(sboxInitValue);
editor = sbox;
connect(sbox,SIGNAL(valueChanged(int)),this,SLOT(on_valueChanged(int)));
}
else if(delegateType == "QDoubleSpinBox")
{
QDoubleSpinBox *sdbox = new QDoubleSpinBox(parent);
sdbox->setRange(0,100);
// sdbox->setSuffix(sboxSuffixStr);
// sdbox->setPrefix(sboxPrefixStr);
sdbox->setSingleStep(0.1);
// sdbox->setStepType(sboxStepType);
// sdbox->setValue(sboxInitValue);
editor = sdbox;
connect(sdbox,SIGNAL(valueChanged(double)),this,SLOT(on_valueChanged(double)));
}
else if(delegateType == "QComboBox")
{
QComboBox *cbox = new QComboBox(parent);
cbox->addItems(cboxItems);
cbox->setEditable(cboxEditable);
editor = cbox;
}
else if (delegateType == "QDateTimeEdit") {
QDateTimeEdit *dateTime = new QDateTimeEdit(parent);
dateTime->setCalendarPopup(true);
dateTime->setDisplayFormat("yyyy-MM-dd HH:mm:ss");
dateTime->calendarWidget()->setLocale(QLocale::Chinese);
editor = dateTime;
}
else if (delegateType == "QDateEdit") {
QDateEdit *date = new QDateEdit(parent);
date->setCalendarPopup(true);
date->setDisplayFormat("yyyy-MM-dd");
date->calendarWidget()->setLocale(QLocale::Chinese);
editor = date;
}
else if (delegateType == "QTimeEdit") {
QTimeEdit *time = new QTimeEdit(parent);
time->setDisplayFormat("HH:mm:ss");
editor = time;
}
else if (delegateType == "QLineEdit")
{
QLineEdit *lineEidt = new QLineEdit(parent);
2024-11-07 16:04:50 +08:00
// lineEidt->setReadOnly(true);
2024-10-31 16:48:38 +08:00
editor = lineEidt;
connect(lineEidt, SIGNAL(textChanged(QString)), this, SLOT(on_valueChanged(QString)));
}
2024-11-07 16:04:50 +08:00
else if (delegateType == "QLabel")
{
QLabel *label = new QLabel(parent);
editor = label;
connect(label, SIGNAL(textChanged(QString)), this, SLOT(on_valueChanged(QString)));
}
2024-10-31 16:48:38 +08:00
return editor;
}
void Delegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
auto value = index.model()->data(index, Qt::EditRole);
if(delegateType == "QSpinBox")
{
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->setValue(value.toInt());
}
else if(delegateType == "QDoubleSpinBox")
{
QDoubleSpinBox *dspinBox = static_cast<QDoubleSpinBox*>(editor);
dspinBox->setValue(value.toFloat());
}
else if(delegateType == "QComboBox")
{
QComboBox *cbox = static_cast<QComboBox*>(editor);
cbox->setCurrentText(value.toString());
}
else if (delegateType == "QDateTimeEdit")
{
QDateTimeEdit *dateTime = static_cast<QDateTimeEdit *>(editor);
dateTime->setDateTime(QDateTime::fromString(value.toString(), "yyyy-MM-dd HH:mm:ss"));
}
else if (delegateType == "QDateEdit")
{
QDateEdit *date = static_cast<QDateEdit *>(editor);
date->setDate(QDate::fromString(value.toString(), "yyyy-MM-dd"));
}
else if (delegateType == "QTimeEdit")
{
QTimeEdit *time = static_cast<QTimeEdit *>(editor);
time->setTime(QTime::fromString(value.toString(), "HH:mm:ss"));
}
else if (delegateType == "QLineEdit")
{
QLineEdit *lineEidt = static_cast<QLineEdit *>(editor);
lineEidt->setText(value.toString());
}
2024-11-07 16:04:50 +08:00
else if (delegateType == "QLabel")
{
QLabel *label = static_cast<QLabel *>(editor);
label->setText(value.toString());
}
2024-10-31 16:48:38 +08:00
else
{
QStyledItemDelegate::setEditorData(editor, index);
}
}
void Delegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
QVariant value = model->data(index);
if(delegateType == "QSpinBox")
{
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
value = spinBox->value();
}
if(delegateType == "QDoubleSpinBox")
{
QDoubleSpinBox *dspinBox = static_cast<QDoubleSpinBox*>(editor);
value = dspinBox->value();
}
else if(delegateType == "QComboBox")
{
QComboBox *cbox = static_cast<QComboBox*>(editor);
value = cbox->currentText();
}
else if (delegateType == "QDateTimeEdit")
{
QDateTimeEdit *dateTime = static_cast<QDateTimeEdit *>(editor);
value = dateTime->dateTime().toString("yyyy-MM-dd HH:mm:ss");
}
else if (delegateType == "QDateEdit")
{
QDateEdit *date = static_cast<QDateEdit *>(editor);
value = date->date().toString("yyyy-MM-dd");
}
else if (delegateType == "QTimeEdit")
{
QTimeEdit *time = static_cast<QTimeEdit *>(editor);
value = time->time().toString("HH:mm:ss");
}
else if (delegateType == "QLineEdit")
{
QLineEdit *lineEidt = static_cast<QLineEdit *>(editor);
value = lineEidt->text();
}
2024-11-07 16:04:50 +08:00
else if (delegateType == "QLabel")
{
QLabel *label = static_cast<QLabel *>(editor);
value = label->text();
}
2024-10-31 16:48:38 +08:00
model->setData(index, value, Qt::EditRole);
}
void Delegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &/* index */) const
{
editor->setGeometry(option.rect);
}
void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(index.column() == delegateColumnID)
{
if(delegateType == "QProgressBar")
{
drawProgressBar(painter,option,index);
}
else if(delegateType == "QCheckBox")
{
drawCheckBox(painter,option,index);
}
else if(delegateType == "QPushButton")
{
drawPushButton(painter,option,index);
}
else if(delegateType == "QPixmap" && judgmentColumn>=0)
{
drawPixmap(painter,option,index);
}
else if (delegateType == "QLineEdit" && delegatePwd)
{
drawLineEdit(painter, option, index);
}
2024-11-07 16:04:50 +08:00
2024-10-31 16:48:38 +08:00
}//if
else
{
QStyledItemDelegate::paint(painter,option,index);
}
}
bool Delegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
//Qt6中如果调用了 qApp->setStyleSheet 设置了全局样式的话,鼠标移动也会触发 editorEvent TNND
if (event->type() == QEvent::MouseMove) {
return false;
}
//处理编辑数据
QString data = index.data(Qt::DisplayRole).toString();
if (delegateType == "QCheckBox") {
//鼠标松开不用处理,不然会重复设置
if (event->type() == QEvent::MouseButtonRelease) {
return false;
}
//如果当前的文字和设置的选中文字一致则说明是选中
checkedText = (data == checkBoxChecked ? checkBoxUnchecked : checkBoxChecked);
model->setData(index, checkedText, Qt::EditRole);
emit valueChanged(checkedText);
} else if (delegateType == "QPushButton") {
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
mousePoint = mouseEvent->pos();
mousePressed = false;
//没有按钮对应的值则不处理
QStringList list = data.split("|");
int count = list.count();
if (data.isEmpty() || count == 0) {
return false;
}
//根据按钮数量自动计算按钮对应的区域
int x = option.rect.x();
int y = option.rect.y();
int width = option.rect.width() / count;
int height = option.rect.height();
QList<QRect> btnRect;
for (int i = 0; i < count; ++i) {
btnRect << QRect(x + i * width, y, width, height);
}
if (event->type() == QEvent::MouseButtonPress) {
//鼠标按下更新对应按钮区域是否按下,并判断按下的区域是哪个按钮,发送对应的按钮索引和index
for (int i = 0; i < count; ++i) {
if (btnRect.at(i).contains(mousePoint)) {
mousePressed = true;
emit buttonClicked(i, index);
break;
}
}
}
//需要返回真表示需要继续绘制
return true;
}
//和事件过滤器类似,也需要继续返回执行
return QStyledItemDelegate::editorEvent(event, model, option, index);
}
void Delegate::init()
{
delegateType = "QSpinBox";
delegateColumnID = -1;
sboxMaxValue = 100;
sboxMinValue = 0;
sboxPrefixStr = "";
sboxSuffixStr = "";
sboxSingleStep = 1;
sboxInitValue = 0;
sboxStepType = QAbstractSpinBox::DefaultStepType;
cboxItems.clear();
cboxEditable = true;
checkBoxChecked = "true";
checkBoxUnchecked = "false";
pgbarMax = 100;
pgbarMin = 0;
pgbarAlignment = Qt::AlignCenter;
isTextVisible = true;
invertedAppearance = false;
imgOk = QPixmap(":/corr.png");
imgNo = QPixmap(":/erro.png");
imgWidth = 20;
imgHeigth = 20;
judgmentColumn = -1;
judgmentValue = "错误";
judgmentCondition = "contains";
}
void Delegate::checkData(const QString &data,bool *selse)const
{
if (judgmentCondition == "==") {
if (data == judgmentValue) {
*selse = true;
}
} else if (judgmentCondition == ">") {
if (data.toDouble() > judgmentValue.toDouble()) {
*selse = true;
}
} else if (judgmentCondition == ">=") {
if (data.toDouble() >= judgmentValue.toDouble()) {
*selse = true;
}
} else if (judgmentCondition == "<") {
if (data.toDouble() < judgmentValue.toDouble()) {
*selse = true;
}
} else if (judgmentCondition == "<=") {
if (data.toDouble() <= judgmentValue.toDouble()) {
*selse = true;
}
} else if (judgmentCondition == "!=") {
if (data != judgmentValue) {
*selse = true;
}
} else if (judgmentCondition == "contains") {
QStringList list = judgmentValue.split("|");
foreach (QString value, list) {
if (data.contains(value)) {
*selse = true;
break;
}
}
}
}
void Delegate::drawProgressBar(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index)const
{
//获得视图中的值
int value = index.model()->data(index,Qt::DisplayRole).toInt();
//创建包含QProgressBar样式信息类
QStyleOptionProgressBar soPgbar;
//使用我们创建的pgBar初始化soPgbar
soPgbar.initFrom(pgBar);
//设置最大值和最小值
soPgbar.maximum = pgbarMax;
soPgbar.minimum = pgbarMin;
//设置进度条值
soPgbar.progress = value;
//设置状态
soPgbar.state |= QStyle::State_Enabled;
soPgbar.state |= QStyle::State_Horizontal;
//设置位置和大小
soPgbar.rect = option.rect;
//设置文本
soPgbar.text = QString("%1%").arg(value);
//设置文本是否可见
soPgbar.textVisible = isTextVisible;
//设置文本居中
soPgbar.textAlignment = pgbarAlignment;
//设置进度条的进度方向
soPgbar.invertedAppearance = invertedAppearance;
//绘制
QApplication::style()->drawControl(QStyle::CE_ProgressBar,&soPgbar,painter,pgBar);
}
void Delegate::drawCheckBox(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
//处理复选框委托,判断是否选中,设置选中状态
QString data = index.data(Qt::EditRole).toString();
bool checked = (data == checkBoxChecked);
QStyleOptionButton styleOption;
styleOption.initFrom(checkBox);
styleOption.state = checked ? QStyle::State_On : QStyle::State_Off;
styleOption.state |= QStyle::State_Enabled;
//设置居中正方形区域
int width = option.rect.width();
int height = option.rect.height();
int size = qMin(width, height);
int x = option.rect.center().x() - (size / 4);
int y = option.rect.y();
styleOption.rect = QRect(x, y, size, size);
QApplication::style()->drawControl(QStyle::CE_CheckBox, &styleOption, painter, checkBox);
}
void Delegate::drawPushButton(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
//没有按钮对应的值则不处理
QString data = index.data(Qt::DisplayRole).toString();
QStringList list = data.split("|");
int count = list.count();
if (data.isEmpty() || count == 0) {
return;
}
//处理按钮集合委托,自动计算分配宽度
int x = option.rect.x();
int y = option.rect.y();
int width = option.rect.width() / count;
int height = option.rect.height();
//分别绘制按钮集合
for (int i = 0; i < count; ++i) {
QStyleOptionButton styleOption;
styleOption.initFrom(button);
styleOption.rect = QRect(x + i * width, y, width, height);
styleOption.text = list.at(i);
styleOption.state |= QStyle::State_Enabled;
//鼠标按下更新对应的样式
if (mousePressed) {
if (styleOption.rect.contains(mousePoint)) {
styleOption.state |= QStyle::State_Sunken;
}
}
//第四个参数也可以为空,为空的话就不能应用样式表
QApplication::style()->drawControl(QStyle::CE_PushButton, &styleOption, painter, button);
}
}
void Delegate::drawPixmap(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QString data = index.model()->index(index.row(),judgmentColumn).data().toString();
bool selse;
checkData(data,&selse);
//图标自动缩放到指定大小
QPixmap pixmap = (selse?imgOk:imgNo);
pixmap = pixmap.scaled(QSize(imgWidth, imgHeigth), Qt::KeepAspectRatio, Qt::SmoothTransformation);
QApplication::style()->drawItemPixmap(painter, option.rect, Qt::AlignCenter, pixmap);
}
void Delegate::drawLineEdit(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
//统计数量,转换成对应数量的密码样式
QString value = index.model()->data(index, Qt::DisplayRole).toString();
int len = value.length();
QString text;
for (int i = 0; i < len; ++i)
{
text += "";
}
QRect rect = option.rect;
rect.setX(rect.x() + 2);
painter->drawText(rect, Qt::AlignCenter, text);
}
void Delegate::on_valueChanged(int value)
{
emit valueChanged(QString("%1").arg(value));
}
void Delegate::on_valueChanged(double value)
{
emit valueChanged(QString("%1").arg(value));
}
void Delegate::on_valueChanged(QString value)
{
emit valueChanged(QString("%1").arg(value));
}
void Delegate::setDelegateType(const QString &delegateType)
{
this->delegateType = delegateType;
/*将需要使用paint绘制的控件在这里new出来。
*paint函数中new呢
* const成员函数paint中分配非静态数据成员
*/
if(delegateType == "QProgressBar")
{
pgBar = new QProgressBar;
}
else if(delegateType == "QPushButton")
{
button = new QPushButton;
}
else if (delegateType == "QCheckBox")
{
checkBox = new QCheckBox;
}
}
void Delegate::setDelegateColumn(const int delegateColumnID)
{
this->delegateColumnID = delegateColumnID;
}
void Delegate::setSboxMaxValue(const int max)
{
sboxMaxValue = max;
}
void Delegate::setSboxMinValue(const int min)
{
sboxMinValue = min;
}
void Delegate::setSboxPrefixStr(const QString &prefix)
{
sboxPrefixStr = prefix;
}
void Delegate::setSboxSuffixStr(const QString &suffix)
{
sboxSuffixStr = suffix;
}
void Delegate::setSboxSingleStep(const int SingleStep)
{
sboxSingleStep = SingleStep;
}
void Delegate::setSboxInitValue(const int initValue)
{
sboxInitValue = initValue;
}
void Delegate::setSboxStepType(QAbstractSpinBox::StepType st)
{
sboxStepType = st;
}
void Delegate::setCboxItems(const QStringList &items)
{
cboxItems = items;
}
void Delegate::setCboxEditable(bool editable)
{
cboxEditable = editable;
}
void Delegate::setPgBarRange(const int min, const int max)
{
pgbarMin = min;
pgbarMax = max;
}
void Delegate::setPgBarTextVisible(bool isTextVisible)
{
this->isTextVisible = isTextVisible;
}
void Delegate::setPgBarAlignment(Qt::Alignment pgbarAlignment)
{
this->pgbarAlignment = pgbarAlignment;
}
void Delegate::setInvertedAppearance(bool invertedAppearance)
{
this->invertedAppearance = invertedAppearance;
}
void Delegate::setCheckBoxText(const QString &checkBoxChecked, const QString &checkBoxUnchecked)
{
this->checkBoxChecked = checkBoxChecked;
this->checkBoxUnchecked = checkBoxUnchecked;
}
void Delegate::setImgOk(const QPixmap &imgOk)
{
this->imgOk = imgOk;
}
void Delegate::setImgNo(const QPixmap &imgNo)
{
this->imgNo = imgNo;
}
void Delegate::setImgSize(int width,int heigth)
{
this->imgWidth = width;
this->imgHeigth = heigth;
}
void Delegate::setJudgmentColumn(int column)
{
this->judgmentColumn = column;
}
void Delegate::setJudgmentValue(const QString &value)
{
this->judgmentValue = value;
}
void Delegate::setJudgmentCondition(const QString &condition)
{
this->judgmentCondition = condition;
}
void Delegate::setDelegatePwd(bool showDelegatePwd)
{
this->delegatePwd = showDelegatePwd;
}
void Delegate::setComboBox(QAbstractItemView *view, QAbstractItemModel *model)
{
for (int row = 0; row < model->rowCount(); ++row) {
QComboBox *comboBox = new QComboBox();
comboBox->addItems(cboxItems);
view->setIndexWidget(model->index(row, delegateColumnID), comboBox);
}
}