实现双击‘属性组’节点打开属性数据展示面板
This commit is contained in:
parent
492ddb5a36
commit
f9ff317b46
|
|
@ -19,7 +19,7 @@ set(CMAKE_AUTOUIC_SEARCH_PATHS "ui")
|
|||
set(H_HEADER_FILES
|
||||
include/global.h
|
||||
include/logger.h
|
||||
include/mainWindow.h
|
||||
include/mainwindow.h
|
||||
include/dbManager.h
|
||||
include/dbBrowser.h
|
||||
include/dbStructureNode.h
|
||||
|
|
@ -32,13 +32,15 @@ set(H_HEADER_FILES
|
|||
include/customMenu.h
|
||||
include/modelInfoEditDialog.h
|
||||
include/sqlQueryExecutor.h
|
||||
include/attributeTableModel.h
|
||||
include/attributeView.h
|
||||
)
|
||||
|
||||
set(CPP_SOURCE_FILES
|
||||
source/main.cpp
|
||||
source/global.cpp
|
||||
source/logger.cpp
|
||||
source/mainWindow.cpp
|
||||
source/mainwindow.cpp
|
||||
source/dbManager.cpp
|
||||
source/dbBrowser.cpp
|
||||
source/dbStructureNode.cpp
|
||||
|
|
@ -51,10 +53,12 @@ set(CPP_SOURCE_FILES
|
|||
source/customMenu.cpp
|
||||
source/modelInfoEditDialog.cpp
|
||||
source/sqlQueryExecutor.cpp
|
||||
source/attributeTableModel.cpp
|
||||
source/attributeView.cpp
|
||||
)
|
||||
|
||||
set(UI_FILES
|
||||
ui/mainWindow.ui
|
||||
ui/mainwindow.ui
|
||||
ui/dbBrowser.ui
|
||||
ui/connectionDialog.ui
|
||||
ui/messageDialog.ui
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 13.0.2, 2025-03-12T22:30:36. -->
|
||||
<!-- Written by QtCreator 13.0.2, 2025-03-19T08:46:05. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
#ifndef ATTRIBUTETABLEMODEL_H
|
||||
#define ATTRIBUTETABLEMODEL_H
|
||||
|
||||
/**
|
||||
* @brief 用来处理attribute数据的Model类
|
||||
*
|
||||
* 基本功能包括:
|
||||
* 1、可以自定义显示数据表中的哪些列
|
||||
* 2、可以分页显示并自定义每页展示数量
|
||||
* 3、编辑的数据可以突出展示(如加粗、改色)
|
||||
* 4、最前方加入一个用于展示行号的列(行号从1开始)
|
||||
* 5、点击行号列可以实现选中标识(通过icon)
|
||||
* 6、哪一行被编辑,改行的行号指示可以加*进行标识
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QSqlRecord>
|
||||
|
||||
class AttributeTableModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum EditState
|
||||
{
|
||||
Clean = 0,
|
||||
Modified,
|
||||
New,
|
||||
Deleted
|
||||
};
|
||||
|
||||
explicit AttributeTableModel(QObject* parent = nullptr
|
||||
, const QString& connection = ""
|
||||
, const QString& modelID = ""
|
||||
, const QString& groupID = ""
|
||||
, const QString& tableName = "basic.attribute");
|
||||
~AttributeTableModel();
|
||||
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
//分页控制
|
||||
void setPageSize(int);
|
||||
int pageSize() const;
|
||||
void setCurrentPage(int);
|
||||
int currentPage() const;
|
||||
int totalPages() const;
|
||||
|
||||
//展示列控制
|
||||
void setVisibleColumns(const QStringList& columns);
|
||||
|
||||
private:
|
||||
struct RowData
|
||||
{
|
||||
QSqlRecord record;
|
||||
EditState state = Clean;
|
||||
};
|
||||
|
||||
void loadPageData(); // 加载当前页数据
|
||||
void updateTotalCount(); // 更新总记录数
|
||||
|
||||
QString m_connection;
|
||||
QString m_modelID;
|
||||
QString m_groupID;
|
||||
QString m_tableName;
|
||||
|
||||
int m_pageSize;
|
||||
int m_currentPage;
|
||||
int m_totalCount;
|
||||
QStringList m_visibleColumns;
|
||||
QList<RowData> m_currentPageData;
|
||||
QHash<int, RowData> m_modifiedRows; //key:global row number
|
||||
};
|
||||
|
||||
#endif //ATTRIBUTETABLEMODEL_H
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef ATTRIBUTEVIEW_H
|
||||
#define ATTRIBUTEVIEW_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QTableView;
|
||||
class AttributeTableModel;
|
||||
class QVBoxLayout;
|
||||
|
||||
class AttributeView : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AttributeView(QWidget *parent = nullptr
|
||||
, const QString& connection = ""
|
||||
, const QString& modelID = ""
|
||||
, const QString& groupID = ""
|
||||
, const QString& tableName = "basic.attribute");
|
||||
~AttributeView();
|
||||
|
||||
private:
|
||||
QString m_connection;
|
||||
QString m_modelID;
|
||||
QString m_groupID;
|
||||
QString m_attributeTable;
|
||||
|
||||
QTableView* m_tableView;
|
||||
AttributeTableModel* m_attributeTableModel;
|
||||
QVBoxLayout* m_vLayout;
|
||||
};
|
||||
|
||||
#endif //ATTRIBUTEVIEW_H
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#ifndef CUSTOMTAB_H
|
||||
#define CUSTOMTAB_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QLabel;
|
||||
class QPushButton;
|
||||
class QBoxLayout;
|
||||
class CustomTab : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CustomTab(QWidget *parent = nullptr);
|
||||
virtual ~CustomTab();
|
||||
|
||||
void setText(const QString&);
|
||||
const QString text();
|
||||
|
||||
void setIcon(const QIcon&);
|
||||
|
||||
signals:
|
||||
void closeTab(QWidget*);
|
||||
|
||||
protected:
|
||||
void enterEvent(QEnterEvent*);
|
||||
void leaveEvent(QEvent*);
|
||||
|
||||
private slots:
|
||||
void onCloseButtonClicked();
|
||||
|
||||
private:
|
||||
QIcon m_Icon;
|
||||
QSize m_IconSize;
|
||||
QLabel* m_pIconLabel;
|
||||
QLabel* m_pTitle;
|
||||
QPushButton* m_pCloseBtn;
|
||||
QBoxLayout* m_pLayout;
|
||||
};
|
||||
|
||||
#endif //CUSTOMTAB_H
|
||||
|
|
@ -1,3 +1,7 @@
|
|||
#ifndef DBBROWSER_H
|
||||
#define DBBROWSER_H
|
||||
|
||||
#include "global.h"
|
||||
#include <QWidget>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
|
@ -6,7 +10,7 @@ class DatabaseBrowser;
|
|||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
||||
class AttributeView;
|
||||
class DatabaseBrowser : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -15,6 +19,14 @@ public:
|
|||
DatabaseBrowser(QWidget *parent = nullptr);
|
||||
~DatabaseBrowser();
|
||||
|
||||
void addTab_attribute(const QString&, ModelAttributeGroup&);
|
||||
|
||||
private slots:
|
||||
void closeTab(QWidget*);
|
||||
|
||||
private:
|
||||
Ui::DatabaseBrowser *ui;
|
||||
QList<AttributeView> m_attributeViewList;
|
||||
};
|
||||
|
||||
#endif //DBBROWSER_H
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef DBSTRUCTUREVIEW_H
|
||||
#define DBSTRUCTUREVIEW_H
|
||||
|
||||
#include "global.h"
|
||||
#include <QTreeView>
|
||||
|
||||
class MainWindow;
|
||||
|
|
@ -36,6 +37,7 @@ private:
|
|||
|
||||
signals:
|
||||
void actionTrigger_addModel();
|
||||
void openAttributeInfo(const QString&, ModelAttributeGroup&);
|
||||
|
||||
private slots:
|
||||
void itemDoubleClick(const QModelIndex&);
|
||||
|
|
|
|||
|
|
@ -72,6 +72,19 @@ struct Model
|
|||
|
||||
};
|
||||
|
||||
struct ModelAttributeGroup
|
||||
{
|
||||
int modelID;
|
||||
int groupID;
|
||||
QString strModelName;
|
||||
QString strGroupName;
|
||||
|
||||
ModelAttributeGroup(int modelID, int groupID, QString strModelName, QString strGroupName)
|
||||
: modelID(modelID),
|
||||
groupID(groupID),
|
||||
strModelName(std::move(strModelName)),
|
||||
strGroupName(std::move(strGroupName)){}
|
||||
};
|
||||
|
||||
class DatabaseException : public std::runtime_error
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QDateTime>
|
||||
|
||||
// 日志宏定义
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ private slots:
|
|||
void onSIG_errorFormSQLExecutor(const QString& error);
|
||||
void onSIG_connectionStatusChanged(const QString& strConnectionName, bool bConnected);
|
||||
void onSIG_addModel(Model&);
|
||||
void onSIG_openAttributeInfo(const QString&, ModelAttributeGroup&);
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ public:
|
|||
bool addModel(const QString&, Model&);
|
||||
bool modelNameExistsInDB(const QString&, const QString&);
|
||||
bool modelTypeExistsInDB(const QString&, const QString&);
|
||||
bool removeMode(const QString&, int);
|
||||
bool removeModel(const QString&, int);
|
||||
int getAttributeCount(const QString&, const QString&);
|
||||
|
||||
signals:
|
||||
void errorOccurred(const QString& error);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
#ifndef TABLEEDITMODEL_H
|
||||
#define TABLEEDITMODEL_H
|
||||
|
||||
/**
|
||||
* @brief 用来加载显示数据库中数据表的Model类
|
||||
*
|
||||
* 基本功能包括:
|
||||
* 1、可以自定义显示数据表中的哪些列
|
||||
* 2、可以分页显示并自定义每页展示数量
|
||||
* 3、编辑的数据可以突出展示(如加粗、改色)
|
||||
* 4、最前方加入一个用于展示行号的列(行号从1开始)
|
||||
* 5、点击行号列可以实现选中标识(通过icon)
|
||||
* 6、哪一行被编辑,改行的行号指示可以加*进行标识
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QSqlTableModel>
|
||||
#include <QSqlRecord>
|
||||
|
||||
class TableEditModel : public QSqlTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TableEditModel(QObject* parent = nullptr, const QSqlDatabase& db = QSqlDatabase(), const QStringList &visibleColumns = {});
|
||||
~TableEditModel();
|
||||
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
//分页控制
|
||||
void setPageSize(int);
|
||||
int pageSize() const;
|
||||
void setCurrentPage(int);
|
||||
int currentPage() const;
|
||||
int totalPages() const;
|
||||
|
||||
//展示列控制
|
||||
void setVisibleColumns(const QStringList& columns);
|
||||
|
||||
protected:
|
||||
QString selectStatement() const override; //调用select()时会使用该函数重写后返回的语句
|
||||
|
||||
private:
|
||||
struct EditRecord //编辑记录
|
||||
{
|
||||
QSqlRecord original;
|
||||
QSqlRecord modified;
|
||||
bool isNew = false;
|
||||
bool isDeleted = false;
|
||||
};
|
||||
|
||||
int m_pageSize;
|
||||
int m_currentPage;
|
||||
int m_totalRecords;
|
||||
QStringList m_visibleColumns;
|
||||
QHash<int, EditRecord> m_editCache; //key:当前页中的row
|
||||
};
|
||||
|
||||
#endif //TABLEEDITMODEL_H
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
<RCC>
|
||||
<qresource prefix="img">
|
||||
<file>images/btn_close_pressed.png</file>
|
||||
<file>images/btn_close_default.png</file>
|
||||
<file>images/btn_close_hover.png</file>
|
||||
<file>images/icon_first.png</file>
|
||||
<file>images/icon_last.png</file>
|
||||
<file>images/icon_next.png</file>
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 178 B |
Binary file not shown.
|
After Width: | Height: | Size: 200 B |
Binary file not shown.
|
After Width: | Height: | Size: 197 B |
|
|
@ -0,0 +1,172 @@
|
|||
#include "attributeTableModel.h"
|
||||
#include "logger.h"
|
||||
#include "sqlQueryExecutor.h"
|
||||
|
||||
AttributeTableModel::AttributeTableModel(QObject* parent, const QString& connection, const QString& modelID, const QString& groupID, const QString& tableName)
|
||||
: QAbstractTableModel(parent)
|
||||
, m_connection(connection)
|
||||
, m_modelID(modelID)
|
||||
, m_groupID(groupID)
|
||||
, m_tableName(tableName)
|
||||
{
|
||||
m_pageSize = 100;
|
||||
m_currentPage = 1;
|
||||
m_totalCount = 0;
|
||||
|
||||
m_visibleColumns << "attribute" << "attribute_name" << "data_type_id" << "length_precision" << "default_value";
|
||||
}
|
||||
|
||||
AttributeTableModel::~AttributeTableModel()
|
||||
{}
|
||||
|
||||
QVariant AttributeTableModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
int row = index.row();
|
||||
int col = index.column();
|
||||
int globalRow = (m_currentPage - 1) * m_pageSize + row;
|
||||
|
||||
if(index.column() == 0) //第一列显示行号
|
||||
{
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
QString prefix;
|
||||
if(m_modifiedRows.contains(globalRow))
|
||||
{
|
||||
switch(m_modifiedRows[globalRow].state)
|
||||
{
|
||||
case Modified:
|
||||
prefix = "*";
|
||||
break;
|
||||
case New:
|
||||
prefix = "+";
|
||||
break;
|
||||
case Deleted:
|
||||
prefix = "-";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return prefix + QString::number(globalRow + 1);
|
||||
}
|
||||
case Qt::DecorationRole:
|
||||
return QVariant();
|
||||
case Qt::TextAlignmentRole:
|
||||
return Qt::AlignCenter; //行号居中展示
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int dataCol = col - 1;
|
||||
const RowData& rowData = m_currentPageData[row];
|
||||
if (role == Qt::DisplayRole || role == Qt::EditRole)
|
||||
return rowData.record.value(dataCol);
|
||||
else if (role == Qt::UserRole + 100) //以100来标识数据是否被编辑,在相关代理Delegate类实现中同步进行处理(文字加粗等效果)
|
||||
return (rowData.state != Clean);
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool AttributeTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (role != Qt::EditRole || index.column() == 0)
|
||||
return false;
|
||||
|
||||
int row = index.row();
|
||||
int globalRow = (m_currentPage - 1) * m_pageSize + row;
|
||||
int dataCol = index.column() - 1; //第一列显示了行号
|
||||
//记录修改
|
||||
RowData modifiedRow = m_currentPageData[row];
|
||||
modifiedRow.record.setValue(dataCol, value);
|
||||
modifiedRow.state = (modifiedRow.state == New) ? New : Modified;
|
||||
|
||||
m_modifiedRows[globalRow] = modifiedRow;
|
||||
m_currentPageData[row] = modifiedRow;
|
||||
|
||||
emit dataChanged(index, index, {role, Qt::UserRole + 100});
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant AttributeTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
{
|
||||
if(section == 0)
|
||||
return role == Qt::DisplayRole ? "No." : QVariant();
|
||||
else
|
||||
{
|
||||
return m_visibleColumns.value(section);
|
||||
}
|
||||
}
|
||||
return QAbstractTableModel::headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
int AttributeTableModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
return m_currentPageData.count();
|
||||
}
|
||||
|
||||
int AttributeTableModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return m_visibleColumns.isEmpty() ? 0 : m_visibleColumns.count() + 1;
|
||||
}
|
||||
|
||||
Qt::ItemFlags AttributeTableModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
Qt::ItemFlags flags = QAbstractTableModel::flags(index);
|
||||
if (index.column() != 0) //行号列不能编辑
|
||||
flags = flags | Qt::ItemIsEditable;
|
||||
return flags;
|
||||
}
|
||||
|
||||
void AttributeTableModel::loadPageData()
|
||||
{
|
||||
if (m_tableName.isEmpty())
|
||||
{
|
||||
LOG_ERROR("DB", QString("Attribute table name is empty, load data failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
beginResetModel();
|
||||
|
||||
QString strSQL = QString("SELECT %1 FROM %2 LIMIT %3 OFFSET %4")
|
||||
.arg(m_visibleColumns.join(", "))
|
||||
.arg(m_tableName)
|
||||
.arg(m_pageSize)
|
||||
.arg((m_currentPage - 1) * m_pageSize);
|
||||
try
|
||||
{
|
||||
QSqlQuery query = SqlQueryExecutor::instance().executeSQL(m_connection, strSQL);
|
||||
while(query.next())
|
||||
{
|
||||
RowData data;
|
||||
data.record = query.record();
|
||||
m_currentPageData.append(data);
|
||||
}
|
||||
}
|
||||
catch (const DatabaseException& e)
|
||||
{
|
||||
LOG_ERROR("SQL", QString::fromWCharArray(L"获取属性信息失败。modelID:%1, groupID:%2").arg(m_modelID, m_groupID));
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void AttributeTableModel::updateTotalCount()
|
||||
{
|
||||
if (m_tableName.isEmpty())
|
||||
{
|
||||
LOG_ERROR("SQL", QString::fromWCharArray(L"属性表名称为空,获取属性数量失败"));
|
||||
return;
|
||||
}
|
||||
|
||||
m_totalCount = SqlQueryExecutor::instance().getAttributeCount(m_connection, m_tableName);
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#include "attributeView.h"
|
||||
#include "attributeTableModel.h"
|
||||
#include <QTableView>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
AttributeView::AttributeView(QWidget* parent, const QString& connection, const QString& modelID, const QString& groupID, const QString& tableName)
|
||||
: QWidget(parent)
|
||||
, m_connection(connection)
|
||||
, m_modelID(modelID)
|
||||
, m_groupID(groupID)
|
||||
, m_attributeTable(tableName)
|
||||
{
|
||||
m_tableView = new QTableView(this);
|
||||
m_attributeTableModel = new AttributeTableModel(this, m_connection, m_modelID, m_groupID, m_attributeTable);
|
||||
m_tableView->setModel(m_attributeTableModel);
|
||||
|
||||
m_vLayout = new QVBoxLayout(this);
|
||||
m_vLayout->setSpacing(0);
|
||||
m_vLayout->setContentsMargins(0, 0, 0, 0);
|
||||
m_vLayout->addWidget(m_tableView);
|
||||
this->setLayout(m_vLayout);
|
||||
}
|
||||
|
||||
AttributeView::~AttributeView()
|
||||
{}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
#include "customTab.h"
|
||||
#include "qlabel.h"
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QBoxLayout>
|
||||
|
||||
CustomTab::CustomTab(QWidget* parent)
|
||||
:QWidget(parent)
|
||||
{
|
||||
m_pTitle = new QLabel(this);
|
||||
|
||||
m_IconSize = QSize(16,16);
|
||||
m_pIconLabel = new QLabel(this);
|
||||
m_pIconLabel->setMinimumSize(m_IconSize);
|
||||
m_pIconLabel->setMaximumSize(m_IconSize);
|
||||
|
||||
m_pCloseBtn = new QPushButton(this);
|
||||
connect(m_pCloseBtn, &QPushButton::clicked, this, &CustomTab::onCloseButtonClicked);
|
||||
m_pCloseBtn->setMinimumSize(m_IconSize);
|
||||
m_pCloseBtn->setMaximumSize(m_IconSize);
|
||||
m_pCloseBtn->setStyleSheet("QPushButton\n"
|
||||
"{\n"
|
||||
" border-image: url(:/img/images/btn_close_default.png);\n"
|
||||
"}\n"
|
||||
"QPushButton:hover\n"
|
||||
"{\n"
|
||||
" border-image: url(:/img/images/btn_close_hover.png);\n"
|
||||
"}\n"
|
||||
"QPushButton:pressed\n"
|
||||
"{\n"
|
||||
" border-image: url(:/img/images/btn_close_pressed.png);\n"
|
||||
"}");
|
||||
|
||||
m_pLayout = new QBoxLayout(QBoxLayout::LeftToRight);
|
||||
m_pLayout->setContentsMargins(9, 0, 0, 9);
|
||||
m_pLayout->setSpacing(1);
|
||||
m_pLayout->addWidget(m_pIconLabel);
|
||||
m_pLayout->addWidget(m_pTitle);
|
||||
m_pLayout->addWidget(m_pCloseBtn);
|
||||
setLayout(m_pLayout);
|
||||
|
||||
m_pCloseBtn->hide();
|
||||
}
|
||||
|
||||
CustomTab::~CustomTab()
|
||||
{
|
||||
}
|
||||
|
||||
void CustomTab::enterEvent(QEnterEvent* event)
|
||||
{
|
||||
m_pCloseBtn->show();
|
||||
}
|
||||
|
||||
void CustomTab::leaveEvent(QEvent* event)
|
||||
{
|
||||
m_pCloseBtn->hide();
|
||||
}
|
||||
|
||||
void CustomTab::onCloseButtonClicked()
|
||||
{
|
||||
emit closeTab(this);
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
#include "dbBrowser.h"
|
||||
#include "ui_dbBrowser.h"
|
||||
#include "attributeView.h"
|
||||
#include <QTabBar>
|
||||
|
||||
DatabaseBrowser::DatabaseBrowser(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
|
|
@ -12,3 +14,32 @@ DatabaseBrowser::~DatabaseBrowser()
|
|||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void DatabaseBrowser::addTab_attribute(const QString& connection, ModelAttributeGroup& attributeGroup)
|
||||
{
|
||||
AttributeView* view = new AttributeView(ui->tabWidget, connection, QString::number(attributeGroup.modelID), QString::number(attributeGroup.groupID));
|
||||
int index = ui->tabWidget->addTab(view, QIcon(":/img/images/icon_hierarchy.png"), attributeGroup.strGroupName);
|
||||
//添加自定义按钮
|
||||
QPushButton* closeBtn = new QPushButton("");
|
||||
closeBtn->setFixedSize(12, 12);
|
||||
closeBtn->setStyleSheet("QPushButton\n"
|
||||
"{\n"
|
||||
" border-image: url(:/img/images/btn_close_default.png);\n"
|
||||
"}\n"
|
||||
"QPushButton:hover\n"
|
||||
"{\n"
|
||||
" border-image: url(:/img/images/btn_close_hover.png);\n"
|
||||
"}\n"
|
||||
"QPushButton:pressed\n"
|
||||
"{\n"
|
||||
" border-image: url(:/img/images/btn_close_pressed.png);\n"
|
||||
"}");
|
||||
QTabBar* tabBar = ui->tabWidget->tabBar();
|
||||
tabBar->setTabButton(index, QTabBar::RightSide, closeBtn);
|
||||
|
||||
ui->tabWidget->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void DatabaseBrowser::closeTab(QWidget* tab)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ void DBStructureModel::removeDataModel(DBStructureNode* modelNode)
|
|||
}
|
||||
return;
|
||||
}
|
||||
bool result = SqlQueryExecutor::instance().removeMode(connNode->name(), modelID);
|
||||
bool result = SqlQueryExecutor::instance().removeModel(connNode->name(), modelID);
|
||||
if(!result)
|
||||
{
|
||||
if(m_pMainWindow)
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ void DBStructureView::onActionTrigger_removeModel()
|
|||
void DBStructureView::itemDoubleClick(const QModelIndex& index)
|
||||
{
|
||||
DBStructureNode* node = static_cast<DBStructureNode*>(index.internalPointer());
|
||||
if(node->type() == ConnectionNode )
|
||||
if(node->type() == ConnectionNode)
|
||||
{
|
||||
if(!m_curConnection.isEmpty()) //先断掉当前链接
|
||||
{
|
||||
|
|
@ -152,6 +152,19 @@ void DBStructureView::itemDoubleClick(const QModelIndex& index)
|
|||
m_curConnection = node->name();
|
||||
}
|
||||
}
|
||||
else if(node->type() == GroupNode)
|
||||
{
|
||||
DBStructureNode* parent = node->parentNode();
|
||||
if(parent && parent->type() == TableNode)
|
||||
{
|
||||
int modelID = parent->data(Qt::UserRole + NodeDataRole::ID).toInt();
|
||||
int groupID = node->data(Qt::UserRole + NodeDataRole::ID).toInt();
|
||||
QString modelName = parent->name();
|
||||
QString groupName = node->name();
|
||||
ModelAttributeGroup attributeGroup(modelID, groupID, modelName, groupName);
|
||||
emit openAttributeInfo(m_curConnection, attributeGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DBStructureView::showContextMenu(const QPoint& pos)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "settings.h"
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QTextStream>
|
||||
|
||||
Logger& Logger::instance()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ void MainWindow::initialize()
|
|||
m_pDBStrutureView = new DBStructureView(m_dbManager, this);
|
||||
m_pDBStrutureView->setMainWindow(this);
|
||||
connect(m_pDBStrutureView, &DBStructureView::actionTrigger_addModel, this, &MainWindow::onActionTrigger_addModel);
|
||||
connect(m_pDBStrutureView, &DBStructureView::openAttributeInfo, this, &MainWindow::onSIG_openAttributeInfo);
|
||||
ui->layoutDBStructure->addWidget(m_pDBStrutureView);
|
||||
m_pDBStrutureModel = new DBStructureModel(this);
|
||||
m_pDBStrutureModel->setMainWindow(this);
|
||||
|
|
@ -215,3 +216,9 @@ void MainWindow::onSIG_addModel(Model& model)
|
|||
QString connection = m_pDBStrutureView->curConnection();
|
||||
m_pDBStrutureModel->addDataModel(connection, model);
|
||||
}
|
||||
|
||||
void MainWindow::onSIG_openAttributeInfo(const QString& connection, ModelAttributeGroup& attributeGroup)
|
||||
{
|
||||
if(m_dbBrowser)
|
||||
m_dbBrowser->addTab_attribute(connection, attributeGroup);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ bool SqlQueryExecutor::modelTypeExistsInDB(const QString& connectionName, const
|
|||
return exists;
|
||||
}
|
||||
|
||||
bool SqlQueryExecutor::removeMode(const QString& connectionName, int modelID)
|
||||
bool SqlQueryExecutor::removeModel(const QString& connectionName, int modelID)
|
||||
{
|
||||
QString strSQL = "DELETE FROM basic.model_type WHERE id = :id"/* + QString::number(modelID)*/;
|
||||
QVariantHash params;
|
||||
|
|
@ -368,3 +368,21 @@ const QString SqlQueryExecutor::getArributeGropuName(const QString& strConnectio
|
|||
|
||||
return name;
|
||||
}
|
||||
|
||||
int SqlQueryExecutor::getAttributeCount(const QString& strConnectionName, const QString& tableName)
|
||||
{
|
||||
int count = 0;
|
||||
QString strSQL = QString("SELECT COUNT(*) FROM %1").arg(tableName);
|
||||
try
|
||||
{
|
||||
QSqlQuery query = executeSQL(strConnectionName, strSQL);
|
||||
if(query.next())
|
||||
count = query.value(0).toInt();
|
||||
}
|
||||
catch (const DatabaseException& e)
|
||||
{
|
||||
LOG_ERROR("SQL", QString::fromWCharArray(L"获取属性数量失败"));
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
#include "tableEditModel.h"
|
||||
|
||||
TableEditModel::TableEditModel(QObject *parent, const QSqlDatabase &db, const QStringList &visibleColumns)
|
||||
: QSqlTableModel(parent, db), m_visibleColumns(visibleColumns)
|
||||
{
|
||||
setEditStrategy(QSqlTableModel::OnManualSubmit); //对编辑数据手动进行提交
|
||||
|
||||
m_pageSize = 100;
|
||||
m_currentPage = 1;
|
||||
m_totalRecords = 0;
|
||||
}
|
||||
|
||||
TableEditModel::~TableEditModel()
|
||||
{}
|
||||
|
||||
//重写生成查询的方法
|
||||
QString TableEditModel::selectStatement() const
|
||||
{
|
||||
QString originalQuery = QSqlTableModel::selectStatement();
|
||||
QString newQuery;
|
||||
if(m_visibleColumns.isEmpty())
|
||||
newQuery = originalQuery;
|
||||
else
|
||||
{
|
||||
int fromInex = originalQuery.indexOf(" FROM ");
|
||||
QString selectPart = "SELECT " + m_visibleColumns.join(", ");
|
||||
newQuery = selectPart + originalQuery + selectPart.mid(fromInex);
|
||||
}
|
||||
newQuery = newQuery + QString(" LIMIT %1 OFFSET %2").arg(m_pageSize, (m_currentPage - 1) * m_pageSize);
|
||||
|
||||
return newQuery;
|
||||
}
|
||||
|
||||
QVariant TableEditModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if(index.column() == 0) //第一列显示行号
|
||||
{
|
||||
int golbalRow = (m_currentPage - 1) * m_pageSize + index.row();
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
QString displayRow = QString::number(golbalRow + 1);
|
||||
if(m_editCache.keys().contains(index.row()))
|
||||
displayRow = "*" + displayRow;
|
||||
return displayRow;
|
||||
}
|
||||
case Qt::DecorationRole:
|
||||
return QVariant();
|
||||
case Qt::TextAlignmentRole: //行号居中展示
|
||||
return Qt::AlignCenter;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
else if(role == Qt::UserRole + 100) //先以100来标识数据是否被编辑,在相关代理Delegate类实现中同步进行处理(文字加粗等效果)
|
||||
return isDirty(index);
|
||||
else
|
||||
return QSqlTableModel::data(createIndex(index.row(), index.column() - 1), role); //因为第一列显示行号,所以其它数据列要错位展示
|
||||
}
|
||||
|
||||
bool TableEditModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (!index.isValid() || index.column() == 0 || role != Qt::EditRole) //忽略行号列
|
||||
return false;
|
||||
|
||||
// if(index.column() == 0) //忽略行号列
|
||||
// return QSqlTableModel::setData(createIndex(index.row(), index.column()-1), value, role);
|
||||
|
||||
int row = index.row();
|
||||
if (row < 0 || row >= rowCount())
|
||||
return false;
|
||||
|
||||
//记录修改到缓存
|
||||
if(!m_editCache.contains(row))
|
||||
{
|
||||
EditRecord record;
|
||||
record.original = QSqlTableModel::record(row);
|
||||
m_editCache[row] = record;
|
||||
}
|
||||
m_editCache[row].modified.setValue(index.column() - 1, value);
|
||||
|
||||
emit dataChanged(index, index, {role});
|
||||
return true;
|
||||
}
|
||||
|
||||
int TableEditModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return QSqlTableModel::columnCount(parent) + 1; // 原始列数 + 行号列
|
||||
}
|
||||
|
||||
Qt::ItemFlags TableEditModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if(index.column() == 0) //行号列不可编辑
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
else return QSqlTableModel::flags(this->index(index.row(), index.column() - 1));
|
||||
}
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ QTableWidgetHoverDelegate::~QTableWidgetHoverDelegate()
|
|||
|
||||
void QTableWidgetHoverDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
if(option.state.testFlag(QStyle::State_MouseOver))
|
||||
if(option.state.testFlag(QStyle::State_MouseOver) && m_tableWiget)
|
||||
{
|
||||
QTableWidgetItem* hoveredItem = m_tableWiget->item(index.row(), index.column());
|
||||
if(hoveredItem)
|
||||
|
|
|
|||
|
|
@ -32,37 +32,11 @@
|
|||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="tabsClosable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="icon">
|
||||
<iconset resource="../resource/PowerModeler.qrc">
|
||||
<normaloff>:/img/images/icon_hierarchy2.png</normaloff>:/img/images/icon_hierarchy2.png</iconset>
|
||||
</attribute>
|
||||
<attribute name="title">
|
||||
<string>NULL</string>
|
||||
</attribute>
|
||||
<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>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTableView" name="tableView"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
|
@ -241,7 +215,7 @@ QPushButton:pressed
|
|||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>提交更改</string>
|
||||
<string>提交修改</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
|
@ -282,7 +256,7 @@ QPushButton:pressed
|
|||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>取销更改</string>
|
||||
<string>取销修改</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
|
|
|||
Loading…
Reference in New Issue