PowerModeler/source/attributeTableDelegate.cpp

347 lines
13 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);
//不设置焦点策略点击按钮后会触发tableView的Tab键原因尚不清楚
ui->btnConfirm->setFocusPolicy(Qt::NoFocus);
ui->btnCancle->setFocusPolicy(Qt::NoFocus);
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);
}
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(240, 248, 255));
}
//处理加粗字体逻辑
if(/*index.column() == 0 || */index.data(Qt::UserRole + AttributeEidt::EditStatus).toBool())
{
opt.font.setBold(true);
//opt.palette.setColor(QPalette::Text, Qt::red);
}
//先执行默认绘制(包括背景、文本等基础元素)
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().attributeTypeExistsInDB(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);
});
connect(textEditor, &TextEditWidget::cancle, this, [=]{
//createEditor为const成员函数而closeEditor是QAbstractItemDelegate的非const信号在const成员函数中不能直接调用需要转换为非const指针
emit const_cast<AttributeTableDelegate*>(this)->closeEditor(textEditor, QAbstractItemDelegate::NoHint);
});
//延迟获取焦点,防止可能因渲染未完成失效
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);
});
connect(textEditor, &TextEditWidget::cancle, this, [=]{
emit const_cast<AttributeTableDelegate*>(this)->closeEditor(textEditor, QAbstractItemDelegate::NoHint);
});
//延迟获取焦点,防止可能因渲染未完成失效
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;
}
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().attributeTypeExistsInDB(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
editor->setGeometry(option.rect);
}
bool AttributeTableDelegate::isEnumType(const QModelIndex& index) const
{
return index.data(Qt::UserRole + AttributeEidt::DataType).toInt() == AttributeEidt::ENUM;
}