PowerModeler/source/attributeTableDelegate.cpp

376 lines
14 KiB
C++
Raw Normal View History

#include "attributeTableDelegate.h"
#include "attributeTableModel.h"
#include "attributeNamespace.h"
#include "sqlQueryExecutor.h"
#include "ui_textEditWidget.h"
2025-04-11 17:14:17 +08:00
//#include "messageBox.h"
#include <QSpinBox>
#include <QComboBox>
#include <QLineEdit>
#include <QPainter>
2025-04-11 17:14:17 +08:00
#include <QTimer>
#include <QRegularExpressionValidator>
TextEditWidget::TextEditWidget(QWidget* parent)
: QWidget(parent), ui(new Ui::TextEditWidget)
{
ui->setupUi(this);
setWindowFlags(Qt::FramelessWindowHint);
m_promptString = "";
m_patternString = "";
connect(ui->plainTextEdit, &QPlainTextEdit::textChanged, this, &TextEditWidget::onTextChanged);
connect(ui->btnConfirm, &QPushButton::clicked, this, &TextEditWidget::onBtnClicked_confirm);
connect(ui->btnCancle, &QPushButton::clicked, this, &TextEditWidget::onBtnClicked_cancle);
}
TextEditWidget::~TextEditWidget()
{
delete ui;
}
// bool TextEditWidget::eventFilter(QObject* obj, QEvent* event)
// {
// if (event->type() == QEvent::KeyPress)
// {
// QKeyEvent* pKeyEvent = static_cast<QKeyEvent*>(event);
// if (pKeyEvent->key() == Qt::Key_Tab)
// {
// qDebug() << "Key_Tab";
// return true;
// }
// }
// return QWidget::eventFilter(obj, event);
// }
QString TextEditWidget::editText()
{
return ui->plainTextEdit->toPlainText();
}
void TextEditWidget::setEditText(const QString& text)
{
ui->plainTextEdit->setPlainText(text);
}
void TextEditWidget::setPrompt(const QString& prompt)
{
m_promptString = prompt;
ui->label->setText(m_promptString);
}
void TextEditWidget::setRegularExpression(const QString& pattern)
{
//QPlainTextEidt没有setValidator方法所以需要在textChanged槽函数中进行处理
/*QRegularExpression regExp(pattern);
QRegularExpressionValidator* validator = new QRegularExpressionValidator(regExp, this);
ui->plainTextEdit->setValidator(validator);*/
m_patternString = pattern;
m_regExp.setPattern(m_patternString.replace(1, 0 , "^"));
}
void TextEditWidget::setErrorInfo(const QString& errorInfo)
{
ui->label->setText(errorInfo);
}
2025-04-11 17:14:17 +08:00
void TextEditWidget::setFocusToTextEdit()
{
ui->plainTextEdit->setFocus();
ui->plainTextEdit->moveCursor(QTextCursor::End);
}
void TextEditWidget::onTextChanged()
{
ui->label->setText(m_promptString);
if(m_patternString.isEmpty())
return;
QString text = ui->plainTextEdit->toPlainText();
QString filtered = text;
filtered.replace(m_regExp, "");
//qDebug() << text << " " << m_regExp.pattern() << " " << filtered;
if (filtered != text)
{
// 保存光标位置,避免替换后光标跳转
QTextCursor cursor = ui->plainTextEdit->textCursor();
int pos = cursor.position();
ui->plainTextEdit->setPlainText(filtered);
cursor.setPosition(pos - (text.length() - filtered.length()));
ui->plainTextEdit->setTextCursor(cursor);
}
}
void TextEditWidget::onBtnClicked_confirm()
{
emit confirm();
}
void TextEditWidget::onBtnClicked_cancle()
{
emit cancle();
}
AttributeTableDelegate::AttributeTableDelegate(QTableView* view, const QString& connection, QObject *parent)
: QStyledItemDelegate(parent)
, m_tableView(view)
, m_connection(connection)
{
}
AttributeTableDelegate::~AttributeTableDelegate()
{}
void AttributeTableDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
2025-04-01 18:10:48 +08:00
//根据行号设置交替色
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
if ((index.row() + 1) % 2 == 0)
{
//opt.backgroundBrush = QBrush(QColor(243, 245, 249));
painter->fillRect(opt.rect, QColor(240, 248, 255));
}
2025-03-27 21:01:25 +08:00
2025-04-01 18:10:48 +08:00
//处理加粗字体逻辑
if(/*index.column() == 0 || */index.data(Qt::UserRole + AttributeEidt::EditStatus).toBool())
{
opt.font.setBold(true);
2025-03-27 21:01:25 +08:00
//opt.palette.setColor(QPalette::Text, Qt::red);
}
2025-03-27 21:01:25 +08:00
//处理被选择时的背景色注意如果qss中有设置会覆盖此处逻辑
if(option.state.testFlag(QStyle::State_Selected))
{
if(index.column() == 0)
painter->fillRect(opt.rect, QColor(70, 130, 180));
else
painter->fillRect(opt.rect, QColor(211, 241, 250));
}
//如果行号列(第一列)被选中,做整行处理
if(m_tableView && m_tableView->model() && index.column() != 0)
{
QModelIndex numberIndex = m_tableView->model()->index(index.row(), 0);
QItemSelectionModel *selectionModel = m_tableView->selectionModel();
if(selectionModel->isSelected(numberIndex))
painter->fillRect(opt.rect, QColor(211, 241, 250));
}
2025-04-01 18:10:48 +08:00
//先执行默认绘制(包括背景、文本等基础元素)
QStyledItemDelegate::paint(painter, opt, index);
2025-03-27 21:01:25 +08:00
//最后绘制删除线(确保位于最顶层)
if(m_tableView && m_tableView->model())
{
QModelIndex numberIndex = m_tableView->model()->index(index.row(), 0);
QString text = numberIndex.data(Qt::DisplayRole).toString();
if(text.contains("-"))
{
QRect rect = m_tableView->visualRect(index);
painter->save();
painter->setPen(Qt::red);
painter->drawLine(rect.left(), rect.y() + rect.height()*0.5, rect.right(), rect.y() + rect.height()*0.5); //painter属于view所以要以view的坐标系为标准
painter->restore();
}
}
}
QWidget* AttributeTableDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const
{
int dataCol = index.column() - 1;
if(dataCol == 0) //属性类型
{
TextEditWidget* textEditor = new TextEditWidget(parent);
2025-04-11 17:14:17 +08:00
textEditor->setPrompt(QString::fromWCharArray(L"类型必须为英文"));
textEditor->setRegularExpression("[A-Za-z0-9_]");
connect(textEditor, &TextEditWidget::confirm, this, [=]{
2025-04-11 17:14:17 +08:00
/*QString strText = textEditor->editText();
int id = SqlQueryExecutor::instance().getAttributeID(m_connection, strText);
2025-04-11 17:14:17 +08:00
if(id != -1)
textEditor->setErrorInfo(QString::fromWCharArray(L"该类型已存在"));
else
{
emit const_cast<AttributeTableDelegate*>(this)->commitData(textEditor);
emit const_cast<AttributeTableDelegate*>(this)->closeEditor(textEditor, QAbstractItemDelegate::NoHint);
2025-04-11 17:14:17 +08:00
}*/
//判断放在setModelData函数中因为那里会先进行是否做内容改变的判断
emit const_cast<AttributeTableDelegate*>(this)->commitData(textEditor);
emit const_cast<AttributeTableDelegate*>(this)->closeEditor(textEditor, QAbstractItemDelegate::NoHint);
if(m_tableView)
m_tableView->setFocus();
});
connect(textEditor, &TextEditWidget::cancle, this, [=]{
//createEditor为const成员函数而closeEditor是QAbstractItemDelegate的非const信号在const成员函数中不能直接调用需要转换为非const指针
emit const_cast<AttributeTableDelegate*>(this)->closeEditor(textEditor, QAbstractItemDelegate::NoHint);
if(m_tableView)
m_tableView->setFocus();
});
2025-04-11 17:14:17 +08:00
//延迟获取焦点,防止可能因渲染未完成失效
QTimer::singleShot(10, this, [textEditor]() {
textEditor->setFocusToTextEdit();
});
return textEditor;
}
else if(dataCol == 1 || dataCol == 4) //1-数据名称、4-默认值
{
TextEditWidget* textEditor = new TextEditWidget(parent);
connect(textEditor, &TextEditWidget::confirm, this, [=]{
emit const_cast<AttributeTableDelegate*>(this)->commitData(textEditor);
emit const_cast<AttributeTableDelegate*>(this)->closeEditor(textEditor, QAbstractItemDelegate::NoHint);
if(m_tableView)
m_tableView->setFocus();
});
connect(textEditor, &TextEditWidget::cancle, this, [=]{
emit const_cast<AttributeTableDelegate*>(this)->closeEditor(textEditor, QAbstractItemDelegate::NoHint);
if(m_tableView)
m_tableView->setFocus();
});
2025-04-11 17:14:17 +08:00
//延迟获取焦点,防止可能因渲染未完成失效
QTimer::singleShot(10, this, [textEditor]() {
textEditor->setFocusToTextEdit();
});
return textEditor;
}
else if(dataCol == 2) //数据类型
{
if(m_tableView)
{
auto* model = qobject_cast<AttributeTableModel*>(m_tableView->model());
if(model)
{
QMap<int, AttributeTableModel::DataType> dataTypes = model->getDataTypes();
QComboBox* comboBox = new QComboBox(parent);
for(auto dataType : dataTypes)
comboBox->addItem(dataType.type);
return comboBox;
}
}
}
else if(dataCol == 3) //数据长度
{
QSpinBox* spinBox = new QSpinBox(parent);
spinBox->setRange(-1, 999);
spinBox->setValue(0);
return spinBox;
}
2025-04-27 16:24:13 +08:00
else if(dataCol == 5) //可见性
{
QComboBox* comboBox = new QComboBox(parent);
comboBox->addItem("1");
comboBox->addItem("0");
return comboBox;
}
return QStyledItemDelegate::createEditor(parent, option, index);
}
2025-03-27 21:01:25 +08:00
// void AttributeTableDelegate::destroyEditor(QWidget* editor, const QModelIndex& index) const
// {
// emit const_cast<AttributeTableDelegate*>(this)->closeEditor(editor, QAbstractItemDelegate::NoHint);
// }
void AttributeTableDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
if(TextEditWidget* textEditor = qobject_cast<TextEditWidget*>(editor))
2025-04-11 17:14:17 +08:00
{
textEditor->setEditText(index.data(Qt::DisplayRole).toString());
2025-04-11 17:14:17 +08:00
//textEditor->setFocus();
}
else
QStyledItemDelegate::setEditorData(editor, index);
}
void AttributeTableDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QVariant newValue;
if(TextEditWidget* textEditor = qobject_cast<TextEditWidget*>(editor))
newValue = textEditor->editText();
else if(QLineEdit* lineEdit = qobject_cast<QLineEdit*>(editor))
newValue = lineEdit->text();
else if(QComboBox* comboBox = qobject_cast<QComboBox*>(editor))
newValue = comboBox->currentText();
else if(QSpinBox* spinBox = qobject_cast<QSpinBox*>(editor))
newValue = spinBox->value();
else
{
QStyledItemDelegate::setModelData(editor, model, index);
return;
}
QVariant oldValue = index.data(Qt::EditRole);
//qDebug() << "newValue: " << newValue.toString() << "oldValue: " << oldValue.toString();
if (newValue == oldValue)
return;
2025-04-11 17:14:17 +08:00
int dataCol = index.column() - 1;
if(dataCol == 0) //属性类型 做预先判断1.是否以已在同组中 2.是否已被创建
{
auto attributeTableModel = qobject_cast<AttributeTableModel*>(model);
auto textEditor = qobject_cast<TextEditWidget*>(editor);
if(attributeTableModel && textEditor)
{
QString strText = textEditor->editText();
int id = SqlQueryExecutor::instance().getAttributeID(m_connection, strText);
2025-04-11 17:14:17 +08:00
//1.是否以已在同组中(要同时从内存和数据库中都进行查找,避免遗漏已创建但未提交的数据)
bool existsInCurrentGropu = attributeTableModel->attributeTypeExistsInCurrentGroup(id, strText);
if(existsInCurrentGropu)
{
emit const_cast<AttributeTableDelegate*>(this)->showMessage(type_information, QString::fromWCharArray(L"提示"),
QString::fromWCharArray(L"该类型属性已在当前组中存在"));
return;
}
//2.是否已被创建
if(id != -1)
{
/*int result = MessageBox::show(t_question, QString::fromWCharArray(L"提示"), QString::fromWCharArray(L"该类型属性已创建,是否直接载入当前数据"));
if(result == QDialog::Accepted)
{
auto attributeTableModel = qobject_cast<AttributeTableModel*>(model);
attributeTableModel->updateRowThroughExisitingAttribute(index.row(), id);
return;
}
else
return;*/
emit const_cast<AttributeTableDelegate*>(this)->showMessage(type_question, QString::fromWCharArray(L"提示"),
QString::fromWCharArray(L"该类型属性已创建,是否直接载入当前数据"));
if(g_msgDlgBtn == btn_Yes)
{
attributeTableModel->updateRowThroughExisitingAttribute(index.row(), id);
return;
}
else
return;
}
}
}
model->setData(index, newValue, Qt::EditRole);
}
void AttributeTableDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(TextEditWidget* textEditor = qobject_cast<TextEditWidget*>(editor))
{
QSize editorSize = textEditor->size();
QRect optRect = option.rect;
QWidget* parentWidget = textEditor->parentWidget();
int nX = optRect.x();
if(parentWidget && (nX + editorSize.width()) > parentWidget->width())
nX = parentWidget->width() - editorSize.width();
int nY = optRect.bottom() - editorSize.height();
if(nY < 0)
nY = 0;
textEditor->setGeometry(nX, nY, editorSize.width(), editorSize.height());
}
else
editor->setGeometry(option.rect);
}
bool AttributeTableDelegate::isEnumType(const QModelIndex& index) const
{
return index.data(Qt::UserRole + AttributeEidt::DataType).toInt() == AttributeEidt::ENUM;
}