PowerModeler/source/attributeTableDelegate.cpp

411 lines
15 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "attributeTableDelegate.h"
#include "attributeTableModel.h"
#include "attributeNamespace.h"
#include "sqlQueryExecutor.h"
#include "ui_textEditWidget.h"
//#include "messageBox.h"
#include <QSpinBox>
#include <QComboBox>
#include <QLineEdit>
#include <QPainter>
#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);
installEventFilter(this);
ui->plainTextEdit->installEventFilter(this);
}
TextEditWidget::~TextEditWidget()
{
delete ui;
}
bool TextEditWidget::eventFilter(QObject* obj, QEvent* event)
{
if(obj == this && event->type() == QEvent::MouseButtonPress)
return true; //戒断鼠标事件,防止传递给父组件(tableView)触发单元格切换造成的editor关闭
else if (obj == ui->plainTextEdit && event->type() == QEvent::KeyPress)
{
QKeyEvent* pKeyEvent = static_cast<QKeyEvent*>(event);
if (pKeyEvent->key() == Qt::Key_Escape)
{
emit closeWidget();
//return true;
}
}
return QWidget::eventFilter(obj, event);
}
// void TextEditWidget::mousePressEvent(QMouseEvent* event)
// {
// event->accept();
// }
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);
}
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
{
//根据行号设置交替色
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
if ((index.row() + 1) % 2 == 0)
{
//opt.backgroundBrush = QBrush(QColor(243, 245, 249));
painter->fillRect(opt.rect, QColor(49, 54, 63));
}
//处理加粗字体逻辑
if(/*index.column() == 0 || */index.data(Qt::UserRole + AttributeEidt::EditStatus).toBool())
{
opt.font.setBold(true);
opt.palette.setColor(QPalette::Text, Qt::red);
}
//处理被选择时的背景色注意如果qss中有设置会覆盖此处逻辑
if(option.state.testFlag(QStyle::State_Selected))
{
if(index.column() == 0)
painter->fillRect(opt.rect, QColor(49, 91, 125));
else
painter->fillRect(opt.rect, QColor(65, 122, 166));
}
//如果行号列(第一列)被选中,做整行处理
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(65, 122, 166));
}
//先执行默认绘制(包括背景、文本等基础元素)
QStyledItemDelegate::paint(painter, opt, index);
//最后绘制删除线(确保位于最顶层)
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);
textEditor->setPrompt(QString::fromWCharArray(L"类型必须为英文"));
textEditor->setRegularExpression("[A-Za-z0-9_$]");
connect(textEditor, &TextEditWidget::confirm, this, [=]{
/*QString strText = textEditor->editText();
int id = SqlQueryExecutor::instance().getAttributeID(m_connection, strText);
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);
}*/
//判断放在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();
});
connect(textEditor, &TextEditWidget::closeWidget, this, [=]{
if(m_tableView)
m_tableView->setFocus();
});
//延迟获取焦点,防止可能因渲染未完成失效
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();
});
connect(textEditor, &TextEditWidget::closeWidget, this, [=]{
if(m_tableView)
m_tableView->setFocus();
});
//延迟获取焦点,防止可能因渲染未完成失效
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->setStyleSheet("border-radius: 0px;");
spinBox->setRange(-1, 999);
spinBox->setValue(0);
return spinBox;
}
else if(dataCol == 5) //可见性
{
QComboBox* comboBox = new QComboBox(parent);
//comboBox->setStyleSheet("QComboBox{border-radius: 0px;background-color:rgb(67, 73, 87);}");
comboBox->addItem("1");
comboBox->addItem("0");
comboBox->addItem("2");
return comboBox;
}
return QStyledItemDelegate::createEditor(parent, option, index);
}
// 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))
{
textEditor->setEditText(index.data(Qt::DisplayRole).toString());
//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;
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);
//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 if(QComboBox* comboBox = qobject_cast<QComboBox*>(editor))
// {
// comboBox->setGeometry(option.rect);
// comboBox->setStyleSheet("border-radius: 0px;background-color:rgb(58, 63, 75);");
// }
else if(QSpinBox* spinBox = qobject_cast<QSpinBox*>(editor))
{
spinBox->setGeometry(option.rect.adjusted(-3,-3,3,3));
spinBox->setStyleSheet("background-color:rgb(58, 63, 75);"); //QSpinBox不能设置和border相关的项否则up button无法点击暂时不知道原因
}
else
{
editor->setGeometry(option.rect);
editor->setStyleSheet("border-radius: 0px;background-color:rgb(58, 63, 75);");
}
}
bool AttributeTableDelegate::isEnumType(const QModelIndex& index) const
{
return index.data(Qt::UserRole + AttributeEidt::DataType).toInt() == AttributeEidt::ENUM;
}