实现双击‘属性组’节点打开属性数据展示面板

This commit is contained in:
duanshengchao 2025-03-24 18:13:06 +08:00
parent 492ddb5a36
commit f9ff317b46
28 changed files with 697 additions and 43 deletions

View File

@ -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

View File

@ -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>

View File

@ -0,0 +1,80 @@
#ifndef ATTRIBUTETABLEMODEL_H
#define ATTRIBUTETABLEMODEL_H
/**
* @brief attribute数据的Model类
*
*
* 1
* 2
* 3
* 41
* 5icon
* 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

33
include/attributeView.h Normal file
View File

@ -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

41
include/customTab.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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&);

View File

@ -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
{

View File

@ -3,7 +3,6 @@
#include <QObject>
#include <QFile>
#include <QTextStream>
#include <QDateTime>
// 日志宏定义

View File

@ -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

View File

@ -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);

61
include/tableEditModel.h Normal file
View File

@ -0,0 +1,61 @@
#ifndef TABLEEDITMODEL_H
#define TABLEEDITMODEL_H
/**
* @brief Model类
*
*
* 1
* 2
* 3
* 41
* 5icon
* 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

View File

@ -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

View File

@ -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);
}

25
source/attributeView.cpp Normal file
View File

@ -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()
{}

62
source/customTab.cpp Normal file
View File

@ -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);
}

View File

@ -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)
{
}

View File

@ -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)

View File

@ -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)

View File

@ -2,6 +2,7 @@
#include "settings.h"
#include <QFileInfo>
#include <QDir>
#include <QTextStream>
Logger& Logger::instance()
{

View File

@ -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);
}

View File

@ -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;
}

101
source/tableEditModel.cpp Normal file
View File

@ -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));
}

View File

@ -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)

View File

@ -32,37 +32,11 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
<number>-1</number>
</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 name="tabsClosable">
<bool>false</bool>
</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/>