完成属性编辑时自定义编辑控件的加载和上下游逻辑
This commit is contained in:
parent
32e7e649ae
commit
ac9858146f
|
|
@ -33,6 +33,7 @@ set(H_HEADER_FILES
|
||||||
include/multiLineHeaderView.h
|
include/multiLineHeaderView.h
|
||||||
include/modelInfoEditDialog.h
|
include/modelInfoEditDialog.h
|
||||||
include/sqlQueryExecutor.h
|
include/sqlQueryExecutor.h
|
||||||
|
include/attributeNamespace.h
|
||||||
include/attributeTableModel.h
|
include/attributeTableModel.h
|
||||||
include/attributeTableDelegate.h
|
include/attributeTableDelegate.h
|
||||||
include/attributeView.h
|
include/attributeView.h
|
||||||
|
|
@ -67,6 +68,7 @@ set(UI_FILES
|
||||||
ui/connectionDialog.ui
|
ui/connectionDialog.ui
|
||||||
ui/messageDialog.ui
|
ui/messageDialog.ui
|
||||||
ui/modelInfoEditDialog.ui
|
ui/modelInfoEditDialog.ui
|
||||||
|
ui/textEditWidget.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE QtCreatorProject>
|
<!DOCTYPE QtCreatorProject>
|
||||||
<!-- Written by QtCreator 13.0.2, 2025-04-03T14:28:51. -->
|
<!-- Written by QtCreator 13.0.2, 2025-04-03T18:33:56. -->
|
||||||
<qtcreator>
|
<qtcreator>
|
||||||
<data>
|
<data>
|
||||||
<variable>EnvironmentId</variable>
|
<variable>EnvironmentId</variable>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef ATTRIBUTENAMESPACE_H
|
||||||
|
#define ATTRIBUTENAMESPACE_H
|
||||||
|
|
||||||
|
namespace AttributeEidt
|
||||||
|
{
|
||||||
|
enum DataType
|
||||||
|
{
|
||||||
|
ENUM = 0,
|
||||||
|
TEXT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum DataRole
|
||||||
|
{
|
||||||
|
EditStatus = 100,
|
||||||
|
DataType
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -4,22 +4,64 @@
|
||||||
#include <QStyledItemDelegate>
|
#include <QStyledItemDelegate>
|
||||||
#include <QTableView>
|
#include <QTableView>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
namespace Ui {
|
||||||
|
class TextEditWidget;
|
||||||
|
}
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
class TextEditWidget : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit TextEditWidget(QWidget* parent = nullptr);
|
||||||
|
~TextEditWidget();
|
||||||
|
|
||||||
|
QString editText();
|
||||||
|
void setEditText(const QString&);
|
||||||
|
void setPrompt(const QString&);
|
||||||
|
void setRegularExpression(const QString&);
|
||||||
|
void setErrorInfo(const QString&);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void confirm();
|
||||||
|
void cancle();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//bool eventFilter(QObject*, QEvent*) override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onTextChanged();
|
||||||
|
void onBtnClicked_confirm();
|
||||||
|
void onBtnClicked_cancle();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::TextEditWidget* ui;
|
||||||
|
|
||||||
|
QString m_promptString; //提示字符
|
||||||
|
QString m_patternString; //正则表达式的模式字符
|
||||||
|
QRegularExpression m_regExp;
|
||||||
|
};
|
||||||
|
|
||||||
class AttributeTableDelegate : public QStyledItemDelegate
|
class AttributeTableDelegate : public QStyledItemDelegate
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit AttributeTableDelegate(QTableView* view, QObject* parent = nullptr);
|
explicit AttributeTableDelegate(QTableView* view, const QString& connection = "", QObject* parent = nullptr);
|
||||||
~AttributeTableDelegate();
|
~AttributeTableDelegate();
|
||||||
|
|
||||||
/*QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const override;
|
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const override;
|
||||||
|
//void destroyEditor(QWidget* editor, const QModelIndex& index) const override;
|
||||||
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
||||||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
||||||
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;*/
|
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||||
|
|
||||||
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool isEnumType(const QModelIndex&) const;
|
||||||
|
|
||||||
|
QString m_connection;
|
||||||
QTableView* m_tableView;
|
QTableView* m_tableView;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,13 @@ public:
|
||||||
Deleted
|
Deleted
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DataType //数据类型
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
QString type;
|
||||||
|
QString db; //为哪个数据库的可用类型
|
||||||
|
};
|
||||||
|
|
||||||
explicit AttributeTableModel(const ModelAttributeGroup& modelAttributeGroup
|
explicit AttributeTableModel(const ModelAttributeGroup& modelAttributeGroup
|
||||||
, QObject* parent = nullptr
|
, QObject* parent = nullptr
|
||||||
, const QString& connection = ""
|
, const QString& connection = ""
|
||||||
|
|
@ -68,6 +75,8 @@ public:
|
||||||
//展示列控制
|
//展示列控制
|
||||||
//void setVisibleColumns(const QStringList& columns);
|
//void setVisibleColumns(const QStringList& columns);
|
||||||
|
|
||||||
|
//others
|
||||||
|
QMap<int, DataType> getDataTypes() {return m_dataTypes;}
|
||||||
void triggerSyncSignal();
|
void triggerSyncSignal();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
@ -89,18 +98,12 @@ private:
|
||||||
EditState state = Clean;
|
EditState state = Clean;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DataType //数据类型
|
|
||||||
{
|
|
||||||
int id;
|
|
||||||
QString type;
|
|
||||||
QString db; //为哪个数据库的可用类型
|
|
||||||
};
|
|
||||||
|
|
||||||
void iniDisplayField();
|
void iniDisplayField();
|
||||||
void getDataTypes();
|
void getDataTypesFromDB();
|
||||||
void loadPageData(); // 加载当前页数据
|
void loadPageData(); // 加载当前页数据
|
||||||
void updateTotalCount(); // 更新总记录数
|
void updateTotalCount(); // 更新总记录数
|
||||||
QList<RowData> filterRowsByEditState(EditState);
|
QList<RowData> filterRowsByEditState(EditState);
|
||||||
|
int getDataTypeID(const QString&);
|
||||||
|
|
||||||
QString m_connection;
|
QString m_connection;
|
||||||
QString m_tableName;
|
QString m_tableName;
|
||||||
|
|
@ -111,6 +114,7 @@ private:
|
||||||
QList<RowData> m_currentPageData;
|
QList<RowData> m_currentPageData;
|
||||||
QHash<int, RowData> m_modifiedRows; //key:global row number
|
QHash<int, RowData> m_modifiedRows; //key:global row number
|
||||||
QMap<int, DataType> m_dataTypes;
|
QMap<int, DataType> m_dataTypes;
|
||||||
|
QHash<QString, int> m_reversalDataTypes; //dataType的反转,用来通过名称快速查找对应id
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //ATTRIBUTETABLEMODEL_H
|
#endif //ATTRIBUTETABLEMODEL_H
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,8 @@ public:
|
||||||
bool removeModel(const QString&, int);
|
bool removeModel(const QString&, int);
|
||||||
//属性相关
|
//属性相关
|
||||||
int getAttributeCount(const QString&, int, int);
|
int getAttributeCount(const QString&, int, int);
|
||||||
bool getAtrributeInfo(const QString&, const QString&, Attribute&);
|
bool getAttributeInfo(const QString&, const QString&, Attribute&);
|
||||||
|
bool attributeTypeExistsInDB(const QString&, const QString&);
|
||||||
bool batchInsertAttributes(const QString&, int, int, QList<Attribute>);
|
bool batchInsertAttributes(const QString&, int, int, QList<Attribute>);
|
||||||
bool batchDeleteAttributes(const QString&, int, int, QList<int>);
|
bool batchDeleteAttributes(const QString&, int, int, QList<int>);
|
||||||
bool batchUpdateAttributes(const QString&, int, int, QList<Attribute>);
|
bool batchUpdateAttributes(const QString&, int, int, QList<Attribute>);
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,117 @@
|
||||||
#include "attributeTableDelegate.h"
|
#include "attributeTableDelegate.h"
|
||||||
|
#include "attributeTableModel.h"
|
||||||
|
#include "attributeNamespace.h"
|
||||||
|
#include "sqlQueryExecutor.h"
|
||||||
|
#include "ui_textEditWidget.h"
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QLineEdit>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include <QRegularExpressionValidator>
|
||||||
|
|
||||||
AttributeTableDelegate::AttributeTableDelegate(QTableView* view, QObject *parent)
|
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::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)
|
: QStyledItemDelegate(parent)
|
||||||
, m_tableView(view)
|
, m_tableView(view)
|
||||||
|
, m_connection(connection)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -22,7 +130,7 @@ void AttributeTableDelegate::paint(QPainter* painter, const QStyleOptionViewItem
|
||||||
}
|
}
|
||||||
|
|
||||||
//处理加粗字体逻辑
|
//处理加粗字体逻辑
|
||||||
if(/*index.column() == 0 || */index.data(Qt::UserRole + 100).toBool())
|
if(/*index.column() == 0 || */index.data(Qt::UserRole + AttributeEidt::EditStatus).toBool())
|
||||||
{
|
{
|
||||||
opt.font.setBold(true);
|
opt.font.setBold(true);
|
||||||
//opt.palette.setColor(QPalette::Text, Qt::red);
|
//opt.palette.setColor(QPalette::Text, Qt::red);
|
||||||
|
|
@ -45,5 +153,130 @@ void AttributeTableDelegate::paint(QPainter* painter, const QStyleOptionViewItem
|
||||||
painter->restore();
|
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();
|
||||||
|
bool exists = SqlQueryExecutor::instance().attributeTypeExistsInDB(m_connection, strText);
|
||||||
|
if(exists)
|
||||||
|
textEditor->setErrorInfo(QString::fromWCharArray(L"该类型已存在"));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
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());
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "attributeTableModel.h"
|
#include "attributeTableModel.h"
|
||||||
|
#include "attributeNamespace.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "sqlQueryExecutor.h"
|
#include "sqlQueryExecutor.h"
|
||||||
|
|
||||||
|
|
@ -12,7 +13,7 @@ AttributeTableModel::AttributeTableModel(const ModelAttributeGroup& modelAttribu
|
||||||
m_paginationInfo.currentPage = 1;
|
m_paginationInfo.currentPage = 1;
|
||||||
m_paginationInfo.totalEntries = 0;
|
m_paginationInfo.totalEntries = 0;
|
||||||
|
|
||||||
getDataTypes();
|
getDataTypesFromDB();
|
||||||
iniDisplayField();
|
iniDisplayField();
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
@ -80,9 +81,20 @@ QVariant AttributeTableModel::data(const QModelIndex& index, int role) const
|
||||||
int dataCol = col - 1;
|
int dataCol = col - 1;
|
||||||
const RowData& rowData = m_currentPageData[row];
|
const RowData& rowData = m_currentPageData[row];
|
||||||
if (role == Qt::DisplayRole || role == Qt::EditRole)
|
if (role == Qt::DisplayRole || role == Qt::EditRole)
|
||||||
//return rowData.record.value(dataCol);
|
{
|
||||||
return rowData.values.value(dataCol);
|
if(dataCol == 2) //数据类型,存储的是id,展示text
|
||||||
else if (role == Qt::UserRole + 100) //以100来标识数据是否被编辑,在相关代理Delegate类实现中同步进行处理(文字加粗等效果)
|
{
|
||||||
|
int dataTypeID = rowData.values.value(dataCol).toInt();
|
||||||
|
const QString& dataTypeText = m_dataTypes.value(dataTypeID).type;
|
||||||
|
if(!dataTypeText.isEmpty())
|
||||||
|
return dataTypeText;
|
||||||
|
else
|
||||||
|
return dataTypeID;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return rowData.values.value(dataCol);
|
||||||
|
}
|
||||||
|
else if (role == Qt::UserRole + AttributeEidt::EditStatus) //在相关代理Delegate类实现中同步进行处理(文字加粗等效果)
|
||||||
return (rowData.state != Clean);
|
return (rowData.state != Clean);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,14 +117,21 @@ bool AttributeTableModel::setData(const QModelIndex &index, const QVariant &valu
|
||||||
int dataCol = index.column() - 1; //第一列显示了行号
|
int dataCol = index.column() - 1; //第一列显示了行号
|
||||||
//记录修改
|
//记录修改
|
||||||
RowData modifiedRow = m_currentPageData[row];
|
RowData modifiedRow = m_currentPageData[row];
|
||||||
//modifiedRow.record.setValue(dataCol, value);
|
if(dataCol == 2) //数据类型
|
||||||
modifiedRow.values[dataCol] = value;
|
{
|
||||||
|
QString dataType = value.toString();
|
||||||
|
int id = getDataTypeID(dataType);
|
||||||
|
modifiedRow.values[dataCol] = id;
|
||||||
|
//qDebug() << "dataType-id: " << id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
modifiedRow.values[dataCol] = value;
|
||||||
modifiedRow.state = (modifiedRow.state == New) ? New : Modified;
|
modifiedRow.state = (modifiedRow.state == New) ? New : Modified;
|
||||||
|
|
||||||
m_modifiedRows[globalRow] = modifiedRow;
|
m_modifiedRows[globalRow] = modifiedRow;
|
||||||
m_currentPageData[row] = modifiedRow;
|
m_currentPageData[row] = modifiedRow;
|
||||||
|
|
||||||
emit dataChanged(index, index, {role, Qt::UserRole + 100});
|
emit dataChanged(index, index, {role, Qt::UserRole + AttributeEidt::EditStatus});
|
||||||
emit syncDataStatus(m_modifiedRows.isEmpty(), m_paginationInfo);
|
emit syncDataStatus(m_modifiedRows.isEmpty(), m_paginationInfo);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -173,7 +192,7 @@ void AttributeTableModel::iniDisplayField()
|
||||||
FieldInfo field3;
|
FieldInfo field3;
|
||||||
field3.originalName = "data_type_id";
|
field3.originalName = "data_type_id";
|
||||||
field3.displayName = QString::fromWCharArray(L"数据类型");
|
field3.displayName = QString::fromWCharArray(L"数据类型");
|
||||||
//field3.dataType = "bigint";
|
field3.dataType = "character varying(64)";
|
||||||
m_displayField.append(field3);
|
m_displayField.append(field3);
|
||||||
|
|
||||||
FieldInfo field4;
|
FieldInfo field4;
|
||||||
|
|
@ -192,11 +211,13 @@ void AttributeTableModel::iniDisplayField()
|
||||||
for(int i = 0; i < m_displayField.count(); i++)
|
for(int i = 0; i < m_displayField.count(); i++)
|
||||||
{
|
{
|
||||||
QString strFiled = m_displayField.at(i).originalName;
|
QString strFiled = m_displayField.at(i).originalName;
|
||||||
|
if(strFiled == "data_type_id") //数据类型以字符串的方式显示
|
||||||
|
continue;
|
||||||
m_displayField[i].dataType = fieldType.value(strFiled);
|
m_displayField[i].dataType = fieldType.value(strFiled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttributeTableModel::getDataTypes()
|
void AttributeTableModel::getDataTypesFromDB()
|
||||||
{
|
{
|
||||||
QString strSQL = "SELECT * FROM basic.data_type ORDER BY id ASC";
|
QString strSQL = "SELECT * FROM basic.data_type ORDER BY id ASC";
|
||||||
try
|
try
|
||||||
|
|
@ -209,6 +230,7 @@ void AttributeTableModel::getDataTypes()
|
||||||
dataType.type = query.value(1).toString();
|
dataType.type = query.value(1).toString();
|
||||||
dataType.db = query.value(2).toString();
|
dataType.db = query.value(2).toString();
|
||||||
m_dataTypes.insert(dataType.id, dataType);
|
m_dataTypes.insert(dataType.id, dataType);
|
||||||
|
m_reversalDataTypes.insert(dataType.type, dataType.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const DatabaseException& e)
|
catch (const DatabaseException& e)
|
||||||
|
|
@ -217,6 +239,11 @@ void AttributeTableModel::getDataTypes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AttributeTableModel::getDataTypeID(const QString& type)
|
||||||
|
{
|
||||||
|
return m_reversalDataTypes.value(type, 11); //11是VARCHAR的id,作为默认值
|
||||||
|
}
|
||||||
|
|
||||||
void AttributeTableModel::loadPageData()
|
void AttributeTableModel::loadPageData()
|
||||||
{
|
{
|
||||||
m_currentPageData.clear();
|
m_currentPageData.clear();
|
||||||
|
|
@ -245,7 +272,7 @@ void AttributeTableModel::loadPageData()
|
||||||
{
|
{
|
||||||
Attribute attribute;
|
Attribute attribute;
|
||||||
attribute.id = query.value(0).toInt();
|
attribute.id = query.value(0).toInt();
|
||||||
if(SqlQueryExecutor::instance().getAtrributeInfo(m_connection, columns.join(", "), attribute))
|
if(SqlQueryExecutor::instance().getAttributeInfo(m_connection, columns.join(", "), attribute))
|
||||||
{
|
{
|
||||||
RowData data;
|
RowData data;
|
||||||
data.values.append(attribute.type);
|
data.values.append(attribute.type);
|
||||||
|
|
|
||||||
|
|
@ -12,15 +12,14 @@ AttributeView::AttributeView(const ModelAttributeGroup& modelAttributeGroup, QWi
|
||||||
, m_modelAttributeGroup(modelAttributeGroup)
|
, m_modelAttributeGroup(modelAttributeGroup)
|
||||||
{
|
{
|
||||||
m_tableView = new QTableView(this);
|
m_tableView = new QTableView(this);
|
||||||
// m_tableView->setAlternatingRowColors(true);
|
m_tableView->setStyleSheet("QTableView::item{padding-left:5px;} QTableView::item:selected{border:1px solid rgb(70,130,180);}");
|
||||||
// m_tableView->setStyleSheet("QTableView{alternate-background-color: rgb(240, 248, 255);}");
|
|
||||||
m_tableView->verticalHeader()->setVisible(false);
|
m_tableView->verticalHeader()->setVisible(false);
|
||||||
//m_tableView->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
//m_tableView->setTabKeyNavigation(false); //关闭tab键导航
|
||||||
|
|
||||||
m_attributeTableModel = new AttributeTableModel(m_modelAttributeGroup, this, m_connection, m_attributeTable);
|
m_attributeTableModel = new AttributeTableModel(m_modelAttributeGroup, this, m_connection, m_attributeTable);
|
||||||
m_tableView->setModel(m_attributeTableModel);
|
m_tableView->setModel(m_attributeTableModel);
|
||||||
|
|
||||||
AttributeTableDelegate* delegate = new AttributeTableDelegate(m_tableView, m_tableView);
|
AttributeTableDelegate* delegate = new AttributeTableDelegate(m_tableView, m_connection, m_tableView);
|
||||||
m_tableView->setItemDelegate(delegate);
|
m_tableView->setItemDelegate(delegate);
|
||||||
|
|
||||||
//自定义表头
|
//自定义表头
|
||||||
|
|
@ -41,7 +40,7 @@ AttributeView::AttributeView(const ModelAttributeGroup& modelAttributeGroup, QWi
|
||||||
}
|
}
|
||||||
m_tableView->setHorizontalHeader(m_multiLinHeader);
|
m_tableView->setHorizontalHeader(m_multiLinHeader);
|
||||||
//除了第一列其余列恢复可以手动调整模式
|
//除了第一列其余列恢复可以手动调整模式
|
||||||
QTimer::singleShot(1000, [=](){
|
QTimer::singleShot(1000, this, [=](){
|
||||||
for(int i = 1; i < m_multiLinHeader->count(); i++)
|
for(int i = 1; i < m_multiLinHeader->count(); i++)
|
||||||
m_multiLinHeader->setSectionResizeMode(i, QHeaderView::Interactive);
|
m_multiLinHeader->setSectionResizeMode(i, QHeaderView::Interactive);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,13 @@ ConnectionDialog::ConnectionDialog(QWidget *parent)
|
||||||
{
|
{
|
||||||
//Linux下默认的Qt::Dialog即使有父窗口也无法按照子窗口的行为进行展示,并且最大、最小按钮不好关闭,因此需要去掉Dialog属性,随之而来的问题是,模态无法起作用
|
//Linux下默认的Qt::Dialog即使有父窗口也无法按照子窗口的行为进行展示,并且最大、最小按钮不好关闭,因此需要去掉Dialog属性,随之而来的问题是,模态无法起作用
|
||||||
setWindowFlags(windowFlags() & ~Qt::Dialog);
|
setWindowFlags(windowFlags() & ~Qt::Dialog);
|
||||||
setStyleSheet("QDialog{border: 1px solid rgb(205,205,205);border-radius:5px;}");
|
setStyleSheet("QDialog{border: 1px solid rgb(205,205,205);border-radius:5px;background-color:rgb(245,245,245);}");
|
||||||
}
|
}
|
||||||
setModal(true);
|
else
|
||||||
|
{
|
||||||
|
setModal(true);
|
||||||
|
}
|
||||||
|
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ MessageDialog::MessageDialog(QWidget *parent)
|
||||||
{
|
{
|
||||||
//Linux下默认的Qt::Dialog即使有父窗口也无法按照子窗口的行为进行展示,并且最大、最小按钮不好关闭,因此需要去掉Dialog属性,随之而来的问题是,模态无法起作用
|
//Linux下默认的Qt::Dialog即使有父窗口也无法按照子窗口的行为进行展示,并且最大、最小按钮不好关闭,因此需要去掉Dialog属性,随之而来的问题是,模态无法起作用
|
||||||
setWindowFlags(windowFlags() & ~Qt::Dialog);
|
setWindowFlags(windowFlags() & ~Qt::Dialog);
|
||||||
setStyleSheet("QDialog{border: 1px solid rgb(205,205,205);border-radius:5px;background-color:rgb(245,245,245);}");
|
setStyleSheet("QDialog{border: 1px solid rgb(205,205,205);border-radius:5px;background-color:rgb(245,245,245);background-color:rgb(245,245,245);}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -446,7 +446,7 @@ int SqlQueryExecutor::getAttributeCount(const QString& connectionName, int model
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SqlQueryExecutor::getAtrributeInfo(const QString& connectionName, const QString& columns, Attribute& attribute)
|
bool SqlQueryExecutor::getAttributeInfo(const QString& connectionName, const QString& columns, Attribute& attribute)
|
||||||
{
|
{
|
||||||
QString strSQL = QString("SELECT %1 FROM basic.attribute WHERE id = %2").arg(columns).arg(attribute.id);
|
QString strSQL = QString("SELECT %1 FROM basic.attribute WHERE id = %2").arg(columns).arg(attribute.id);
|
||||||
try
|
try
|
||||||
|
|
@ -472,6 +472,23 @@ bool SqlQueryExecutor::getAtrributeInfo(const QString& connectionName, const QSt
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SqlQueryExecutor::attributeTypeExistsInDB(const QString& connectionName, const QString& type)
|
||||||
|
{
|
||||||
|
bool exists = false;
|
||||||
|
QString strSQL = "SELECT id FROM basic.attribute WHERE attribute = \'" + type + "\'";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
QSqlQuery query = executeSQL(connectionName, strSQL);
|
||||||
|
if(query.next())
|
||||||
|
exists = true;
|
||||||
|
}
|
||||||
|
catch (const DatabaseException& e)
|
||||||
|
{
|
||||||
|
exists = true;
|
||||||
|
}
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
|
||||||
bool SqlQueryExecutor::batchInsertAttributes(const QString& connectionName, int modelID, int attributeGroupID, QList<Attribute> attributes)
|
bool SqlQueryExecutor::batchInsertAttributes(const QString& connectionName, int modelID, int attributeGroupID, QList<Attribute> attributes)
|
||||||
{
|
{
|
||||||
//属于批量操作,需要开启事务
|
//属于批量操作,需要开启事务
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,214 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>TextEditWidget</class>
|
||||||
|
<widget class="QWidget" name="TextEditWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>204</width>
|
||||||
|
<height>94</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QWidget #TextEditWidget
|
||||||
|
{
|
||||||
|
border: 1px solid rgb(205,205,205);
|
||||||
|
background-color:rgb(255,255,255);
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="contentWidget" native="true">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QWidget #contentWidget
|
||||||
|
{
|
||||||
|
border: 1px solid rgb(205,205,205);
|
||||||
|
background-color:rgb(255,255,255);
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QPlainTextEdit" name="plainTextEdit">
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::FocusPolicy::ClickFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">background-color: transparent;
|
||||||
|
border:0px;
|
||||||
|
padding:2px;</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="bottomWidget" native="true">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>26</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>26</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QWidget #bottomWidget
|
||||||
|
{
|
||||||
|
background-color: transparent;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">color: rgb(255, 0, 0);
|
||||||
|
font: 8pt "Microsoft YaHei UI";</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>该类型已存在</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnCancle">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>51</width>
|
||||||
|
<height>26</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>51</width>
|
||||||
|
<height>26</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QPushButton
|
||||||
|
{
|
||||||
|
border: 1px solid rgb(205,205,205);
|
||||||
|
border-radius:5px;
|
||||||
|
}
|
||||||
|
QPushButton:hover
|
||||||
|
{
|
||||||
|
border-color: rgb(70,130,180);
|
||||||
|
}
|
||||||
|
QPushButton:pressed
|
||||||
|
{
|
||||||
|
background-color:rgba(70,130,180,50);
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>取消</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnConfirm">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>51</width>
|
||||||
|
<height>26</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>51</width>
|
||||||
|
<height>26</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QPushButton
|
||||||
|
{
|
||||||
|
color: rgb(250, 250, 250);
|
||||||
|
font: 10pt;
|
||||||
|
border:0px;
|
||||||
|
border-radius:5px;
|
||||||
|
background-color:rgb(67,160,249);
|
||||||
|
}
|
||||||
|
QPushButton:hover
|
||||||
|
{
|
||||||
|
background-color:rgb(55,131,204);
|
||||||
|
}
|
||||||
|
QPushButton:pressed
|
||||||
|
{
|
||||||
|
background-color:rgb(67,160,249);
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>确认</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
Loading…
Reference in New Issue