#include "attributeTableModel.h" #include "attributeNamespace.h" #include "logger.h" #include "sqlQueryExecutor.h" #include AttributeTableModel::AttributeTableModel(const ModelAttributeGroup& modelAttributeGroup, QObject* parent, const QString& connection, const QString& tableName) : QAbstractTableModel(parent) , m_connection(connection) , m_tableName(tableName) , m_modelAttributeGroup(modelAttributeGroup) , m_selectionModel(nullptr) { m_filterChars_attributeType = ""; m_paginationInfo.entriesPerPage = 100; m_paginationInfo.currentPage = 1; m_paginationInfo.totalEntries = 0; getDataTypesFromDB(); iniDisplayField(); refresh(); } AttributeTableModel::~AttributeTableModel() {} QModelIndex AttributeTableModel::index(int row, int column, const QModelIndex& parent) const { if(!hasIndex(row, column, parent)) return QModelIndex(); int dataCol = column - 1; if(dataCol > m_displayField.count()) return QModelIndex(); return createIndex(row, column); } 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_paginationInfo.currentPage - 1) * m_paginationInfo.entriesPerPage + row; if(index.column() == 0) //第一列显示行号 { switch (role) { case Qt::DisplayRole: { QString mark; if(m_modifiedRows.contains(globalRow)) { switch(m_modifiedRows[globalRow].state) { case Modified: mark = "*"; break; case New: mark = "+"; break; case New | Modified: mark = "+"; break; case Deleted: mark = "-"; break; default: break; } } return QString::number(globalRow + 1) + mark; } 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) { if(dataCol == 2) //数据类型,存储的是id,展示text { 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); if(rowData.state == New) //新增列,整行加粗 return true; else //其它情况只对修改单元格加粗 return rowData.cellModified.value(dataCol, false); } } return QVariant(); } bool AttributeTableModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (role != Qt::EditRole || index.column() == 0) return false; // QModelIndex numberIndex = createIndex(index.row(), 0); // QString text = numberIndex.data(Qt::DisplayRole).toString(); // qDebug() << text; // if(text.contains("-")) //删除状态不可编辑 // return false; int row = index.row(); int globalRow = (m_paginationInfo.currentPage - 1) * m_paginationInfo.entriesPerPage + row; int dataCol = index.column() - 1; //第一列显示了行号 //记录修改 RowData modifiedRow = m_currentPageData[row]; if(dataCol == 2) //数据类型 { QString dataType = value.toString(); int id = getDataTypeID(dataType); modifiedRow.values[dataCol] = id; //qDebug() << "dataType-id: " << id; } else modifiedRow.values[dataCol] = value; modifiedRow.cellModified[dataCol] = true; //标记单元格 const int attributeID = modifiedRow.values.last().toInt(); if(attributeID == -1) //纯新建 modifiedRow.state = (modifiedRow.state == New) ? New : Modified; else modifiedRow.state = (modifiedRow.state == New) ? modifiedRow.state |= Modified : Modified; //新建时从已有数据进行的加载,然后再次编辑就会变为叠加态 m_modifiedRows[globalRow] = modifiedRow; m_currentPageData[row] = modifiedRow; emit dataChanged(index, index, {role, Qt::UserRole + AttributeEidt::EditStatus}); emit syncDataStatus(dataHasbeenModified(), m_paginationInfo); 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 { QString headerText = m_displayField.value(section - 1).displayName; if(!m_displayField.value(section - 1).dataType.isEmpty()) headerText = headerText + "\n" + m_displayField.value(section - 1).dataType; return headerText; } } 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_displayField.isEmpty() ? 0 : m_displayField.count() + 1; } Qt::ItemFlags AttributeTableModel::flags(const QModelIndex &index) const { Qt::ItemFlags flags = QAbstractTableModel::flags(index); QModelIndex numberIndex = createIndex(index.row(), 0); QString text = numberIndex.data(Qt::DisplayRole).toString(); if (index.column() != 0 && !text.contains("-")) //行号列和处于删除状态的item不能编辑 flags = flags | Qt::ItemIsEditable; return flags; } void AttributeTableModel::setSelectionModel(QItemSelectionModel* sm) { m_selectionModel = sm; connect(m_selectionModel, &QItemSelectionModel::selectionChanged, this, [this]{ //刷新整个区域 QModelIndex topLeft = createIndex(0, 0); QModelIndex bottomRight = createIndex(rowCount() - 1, columnCount() - 1); emit dataChanged(topLeft, bottomRight); }); } void AttributeTableModel::setModelAttributeGroup(const ModelAttributeGroup& modelAttributeGroup) { m_modelAttributeGroup = modelAttributeGroup; //重新刷新 m_paginationInfo.currentPage = 1; forceRefresh(); } bool AttributeTableModel::attributeTypeExistsInCurrentGroup(int id, const QString& type) { //先查找内存数据 for(RowData rowData : m_currentPageData) { if(rowData.values[0] == type) return true; } //再从数据库中查找,因为内存只存储当前页的数据 if(id != -1) //说明是之前创建过的属性(数据库中已存在) return SqlQueryExecutor::instance().attributeTypeUseByModelGroup(m_connection, id, m_modelAttributeGroup.modelID, m_modelAttributeGroup.groupID); return false; } void AttributeTableModel::updateRowThroughExisitingAttribute(int row, int attributeID) { //qDebug() << "row:" << row << " attributeID:" << attributeID; QStringList columns; for(int i = 0; i < m_displayField.count(); i++) columns << m_displayField.at(i).originalName; Attribute attribute; attribute.id = attributeID; if(SqlQueryExecutor::instance().getAttributeInfo(m_connection, columns.join(", "), attribute)) { RowData updateRow = m_currentPageData[row]; //updateRow.values.resize(m_displayField.count() + 1); updateRow.values[0] = attribute.type; updateRow.values[1] = attribute.name; updateRow.values[2] = attribute.dataTypeID; updateRow.values[3] = attribute.dataLength; updateRow.values[4] = attribute.defaultValue; updateRow.values[5] = attribute.isVisible; updateRow.values[6] = attribute.id;//将id存入最后,不做显示,删除或者修改数据的时候会用到 for(int i = 0; i < m_displayField.count(); i++) updateRow.cellModified[i] = true; //标记单元格 updateRow.state = (updateRow.state == New) ? New : Modified; m_currentPageData[row] = updateRow; int globalRow = (m_paginationInfo.currentPage - 1) * m_paginationInfo.entriesPerPage + row; m_modifiedRows[globalRow] = updateRow; QModelIndex topLeft = index(row, 1, QModelIndex()); QModelIndex bottomRight = index(row, m_displayField.count(), QModelIndex()); emit dataChanged(topLeft, bottomRight); } } void AttributeTableModel::iniDisplayField() { FieldInfo field1; field1.originalName = "attribute"; field1.displayName = QString::fromWCharArray(L"属性类别"); //field1.dataType = "character varying(128)"; m_displayField.append(field1); FieldInfo field2; field2.originalName = "attribute_name"; field2.displayName = QString::fromWCharArray(L"属性名称"); //field2.dataType = "character varying(64)"; m_displayField.append(field2); FieldInfo field3; field3.originalName = "data_type_id"; field3.displayName = QString::fromWCharArray(L"数据类型"); field3.dataType = "character varying(64)"; m_displayField.append(field3); FieldInfo field4; field4.originalName = "length_precision"; field4.displayName = QString::fromWCharArray(L"数据长度"); //field4.dataType = "integer"; m_displayField.append(field4); FieldInfo field5; field5.originalName = "default_value"; field5.displayName = QString::fromWCharArray(L"默认值"); //field5.dataType = "character varying(64)"; m_displayField.append(field5); FieldInfo field6; field6.originalName = "is_visible"; field6.displayName = QString::fromWCharArray(L"可见性"); //field6.dataType = "smallint"; m_displayField.append(field6); QHash fieldType = SqlQueryExecutor::instance().getFiledType(m_connection, "attribute", "basic"); for(int i = 0; i < m_displayField.count(); i++) { QString strFiled = m_displayField.at(i).originalName; if(strFiled == "data_type_id") //数据类型以字符串的方式显示 continue; m_displayField[i].dataType = fieldType.value(strFiled); } } void AttributeTableModel::getDataTypesFromDB() { QString strSQL = "SELECT * FROM basic.data_type ORDER BY id ASC"; try { QSqlQuery query = SqlQueryExecutor::instance().executeSQL(m_connection, strSQL); while(query.next()) { DataType dataType; dataType.id = query.value(0).toInt(); dataType.type = query.value(1).toString(); dataType.db = query.value(2).toString(); m_dataTypes.insert(dataType.id, dataType); m_reversalDataTypes.insert(dataType.type, dataType.id); } } catch (const DatabaseException& e) { LOG_ERROR("SQL", QString::fromWCharArray(L"获取数据类型失败")); } } int AttributeTableModel::getDataTypeID(const QString& type) { return m_reversalDataTypes.value(type, 11); //11是VARCHAR的id,作为默认值 } void AttributeTableModel::loadPageData() { m_currentPageData.clear(); /*if (m_tableName.isEmpty()) { LOG_ERROR("DB", QString("Attribute table name is empty, load data failed")); return; }*/ beginResetModel(); QStringList columns; for(int i = 0; i < m_displayField.count(); i++) columns << m_displayField.at(i).originalName; if(m_modelAttributeGroup.modelID == -1) //表示当前加载数据对象是所有属性 { columns.append("id"); //将id放到最后,和按照具体模型、具体属性组读取数据方式时逻辑统一,具体见下面分支逻辑 QString strSQL = QString("SELECT %1 FROM basic.attribute ORDER BY id ASC LIMIT %2 OFFSET %3") .arg(columns.join(", ")) .arg(m_paginationInfo.entriesPerPage) .arg((m_paginationInfo.currentPage - 1) * m_paginationInfo.entriesPerPage); try { QSqlQuery query = SqlQueryExecutor::instance().executeSQL(m_connection, strSQL); while(query.next()) { QString type = query.value(0).toString(); if(!m_filterChars_attributeType.isEmpty() && !type.contains(m_filterChars_attributeType)) continue; RowData data; for(int i = 0; i < columns.count(); i++) data.values.append(query.value(i)); m_currentPageData.append(data); } } catch (const DatabaseException& e) { LOG_ERROR("SQL", QString::fromWCharArray(L"获取属性信息失败(所有属性)。")); } } else //按具体模型的具体属性组读取数据 { QString strSQL = ""; bool isPublicGroup = SqlQueryExecutor::instance().isPublicAttributeGroup(m_connection, m_modelAttributeGroup.groupID); if(isPublicGroup) strSQL = QString("SELECT attribute_id FROM basic.model_attribute_public WHERE attribute_group_id = %1 ORDER BY id ASC LIMIT %2 OFFSET %3") .arg(m_modelAttributeGroup.groupID) .arg(m_paginationInfo.entriesPerPage) .arg((m_paginationInfo.currentPage - 1) * m_paginationInfo.entriesPerPage); //利用短路机制,当attribute_group_id!=-1时,括号整体为false,需要进行内部条件判断,=-1时,整体为true,忽略整体,也就忽略了attribute_group_id的条件判断 else strSQL = QString("SELECT attribute_id FROM basic.model_attribute WHERE model_type_id = %1 AND (attribute_group_id = %2 OR %2 = -1) ORDER BY id ASC LIMIT %3 OFFSET %4") .arg(m_modelAttributeGroup.modelID) .arg(m_modelAttributeGroup.groupID) .arg(m_paginationInfo.entriesPerPage) .arg((m_paginationInfo.currentPage - 1) * m_paginationInfo.entriesPerPage); try { QSqlQuery query = SqlQueryExecutor::instance().executeSQL(m_connection, strSQL); while(query.next()) { Attribute attribute; attribute.id = query.value(0).toInt(); if(SqlQueryExecutor::instance().getAttributeInfo(m_connection, columns.join(", "), attribute)) { if(!m_filterChars_attributeType.isEmpty() && !attribute.type.contains(m_filterChars_attributeType)) continue; RowData data; data.values.append(attribute.type); data.values.append(attribute.name); data.values.append(attribute.dataTypeID); data.values.append(attribute.dataLength); data.values.append(attribute.defaultValue); data.values.append(attribute.isVisible); data.values.append(attribute.id);//将id存入最后,不做显示,删除或者修改数据的时候会用到 m_currentPageData.append(data); } } } catch (const DatabaseException& e) { LOG_ERROR("SQL", QString::fromWCharArray(L"获取属性信息失败。modelID:%1, groupID:%2").arg(m_modelAttributeGroup.modelID, m_modelAttributeGroup.groupID)); } } endResetModel(); } void AttributeTableModel::setPageSize(int size) { if(m_paginationInfo.entriesPerPage != size && size > 0) { m_paginationInfo.entriesPerPage = size; refresh(); } } int AttributeTableModel::pageSize() const { return m_paginationInfo.entriesPerPage; } bool AttributeTableModel::setCurrentPage(int page) { if(m_paginationInfo.currentPage != page && page > 0 && page <= totalPages()) { m_paginationInfo.currentPage = page; refresh(); return true; } return false; } int AttributeTableModel::currentPage() const { return m_paginationInfo.currentPage; } int AttributeTableModel::totalPages() const { return qCeil(static_cast(m_paginationInfo.totalEntries) / m_paginationInfo.entriesPerPage); } void AttributeTableModel::previousPage() { if(m_paginationInfo.currentPage == 1) return; setCurrentPage(m_paginationInfo.currentPage--); } void AttributeTableModel::nextPage() { if(m_paginationInfo.currentPage == totalPages()) return; setCurrentPage(m_paginationInfo.currentPage++); } void AttributeTableModel::firstPage() { if(m_paginationInfo.currentPage == 1) return; setCurrentPage(1); } void AttributeTableModel::lastPage() { if(m_paginationInfo.currentPage == totalPages()) return; setCurrentPage(totalPages()); } void AttributeTableModel::updateTotalCount() { /*if (m_tableName.isEmpty()) { LOG_ERROR("SQL", QString::fromWCharArray(L"属性表名称为空,获取属性数量失败")); return; }*/ if(m_modelAttributeGroup.modelID == -1) m_paginationInfo.totalEntries = SqlQueryExecutor::instance().getAllAttributeCount(m_connection); else m_paginationInfo.totalEntries = SqlQueryExecutor::instance().getAttributeCount(m_connection, m_modelAttributeGroup.modelID, m_modelAttributeGroup.groupID); m_paginationInfo.totalPages = totalPages(); } QList AttributeTableModel::filterRowsByEditState(EditStateFlag state) { QList result; for(auto it = m_modifiedRows.begin(); it != m_modifiedRows.end(); it++) { if(it.value().state.testFlag(state)) result.append(it.value()); } return result; } /*void AttributeTableModel::setTable(const QString& tableName) { if(m_tableName == tableName) return; m_tableName = tableName; m_modifiedRows.clear(); refresh(); }*/ void AttributeTableModel::refresh() { if(dataHasbeenModified()) { emit showMessage(type_question, QString::fromWCharArray(L"提示"), QString::fromWCharArray(L"有编辑数据还未提交,确认要放弃吗?")); if(g_msgDlgBtn == btn_No) return; } m_modifiedRows.clear(); loadPageData(); updateTotalCount(); emit syncDataStatus(dataHasbeenModified(), m_paginationInfo); } void AttributeTableModel::forceRefresh() { m_modifiedRows.clear(); loadPageData(); updateTotalCount(); emit syncDataStatus(dataHasbeenModified(), m_paginationInfo); } void AttributeTableModel::insertRecord(int row) { if(row < 0 /*|| row > rowCount()*/) return; RowData newRow; newRow.state = New; newRow.values.resize(m_displayField.count() + 1); //多出一个位置给id newRow.values.last() = -1; //newRow.values[2] = 11; int globalRow = (m_paginationInfo.currentPage - 1) * m_paginationInfo.entriesPerPage + row; m_modifiedRows[globalRow] = newRow; beginInsertRows(QModelIndex(), row, row); m_currentPageData.insert(row, newRow); endInsertRows(); } void AttributeTableModel::addRecords(QVector> records) { QVector> validRecords; //首先过滤掉已经存在记录 for(const QVector& record : records) { int id = record.last().toInt(); //目前该函数的数据源都来‘属性选择器’(都是已创建好的属性) QString type = record.value(0).toString(); bool existed = attributeTypeExistsInCurrentGroup(id, type); if(!existed) validRecords.append(record); } if(validRecords.count() == 0) return; beginInsertRows(QModelIndex(), rowCount(), rowCount() + validRecords.count() - 1); int row = m_currentPageData.count(); for(const QVector& record : validRecords) { RowData newRow; newRow.state = New; newRow.values = record; int globalRow = (m_paginationInfo.currentPage - 1) * m_paginationInfo.entriesPerPage + row; m_modifiedRows[globalRow] = newRow; m_currentPageData.insert(row, newRow); row++; } endInsertRows(); } void AttributeTableModel::removeRecord() { //以第一列也就是编号列是否选中为判断依据,找出所有被选中的行 for(int row = 0; row < rowCount(); row++) { QModelIndex numberIndex = createIndex(row, 0); if(m_selectionModel && m_selectionModel->isSelected(numberIndex)) { if(removeRecord(row)) row--; } } } bool AttributeTableModel::removeRecord(int row) { if(row < 0 || row > rowCount()) return false; /*emit showMessage(type_question, QString::fromWCharArray(L"提示"), QString::fromWCharArray(L"确认要删除该记录吗?")); if(g_msgDlgBtn == btn_No) return;*/ int globalRow = (m_paginationInfo.currentPage - 1) * m_paginationInfo.entriesPerPage + row; if(m_currentPageData.at(row).state == New) //新添加未提交的记录,直接删除 { beginRemoveRows(QModelIndex(), row, row); m_modifiedRows.remove(globalRow); m_currentPageData.removeAt(row); endRemoveRows(); return true; } else //整行画红线进行标记 { m_currentPageData[row].state = Deleted; m_modifiedRows[globalRow] = m_currentPageData[row]; m_modifiedRows[globalRow].state = Deleted; QModelIndex topLeft = createIndex(row, 0); QModelIndex bottomRight = createIndex(row, columnCount() - 1); emit dataChanged(topLeft, bottomRight, {Qt::DisplayRole}); return false; } } void AttributeTableModel::submitChanges() { QList insertRows = filterRowsByEditState(New); bool insertCompleted = false; QList deleteRows = filterRowsByEditState(Deleted); bool deleteCompleted = false; QList updateRows = filterRowsByEditState(Modified); bool updateCompleted = false; //插入操作 if(!insertRows.isEmpty()) { QList insertAttributes; for(const RowData& rowData : insertRows) { QString type = rowData.values.value(0).toString(); QString name = rowData.values.value(1).toString(); if(type.isEmpty() || name.isEmpty()) continue; int dataTypeID = rowData.values.value(2).toInt(); int dataLength = -1; if(rowData.values.value(3).isValid()) dataLength = rowData.values.value(3).toInt(); QString defaultValue = "null"; if(rowData.values.value(4).isValid()) defaultValue = rowData.values.value(4).toString(); int isVisible = rowData.values.value(5).toInt(); int id = -1; if(rowData.values.size() == m_displayField.count() +1) id = rowData.values.value(m_displayField.count()).toInt(); insertAttributes.emplace_back(id, name, type, dataTypeID, dataLength, defaultValue, isVisible); } insertCompleted = SqlQueryExecutor::instance().batchInsertAttributes(m_connection, m_modelAttributeGroup.modelID, m_modelAttributeGroup.groupID, insertAttributes); } //删除操作 if(!deleteRows.isEmpty()) { QList deleteAttributes; for(const RowData& rowData : deleteRows) { if(rowData.values.count() != m_displayField.count() + 1) //loadPageData时,会把属性id放到valuse的最后,并且不做展示 continue; deleteAttributes.push_back(rowData.values.last().toInt()); } deleteCompleted = SqlQueryExecutor::instance().batchDeleteAttributes(m_connection, m_modelAttributeGroup.modelID, m_modelAttributeGroup.groupID, deleteAttributes); } //更新操作 if(!updateRows.isEmpty()) { QList updateAttributes; for(const RowData& rowData : updateRows) { if(rowData.values.count() != m_displayField.count() + 1) //loadPageData时,会把属性id放到valuse的最后,并且不做展示 continue; int id = rowData.values.last().toInt(); QString type = rowData.values.value(0).toString(); QString name = rowData.values.value(1).toString(); int dataTypeID = rowData.values.value(2).toInt(); int dataLength = -1; if(rowData.values.value(3).isValid()) dataLength = rowData.values.value(3).toInt(); QString defaultValue = "null"; if(rowData.values.value(4).isValid()) defaultValue = rowData.values.value(4).toString(); int isVisible = rowData.values.value(5).toInt(); updateAttributes.emplace_back(id, name, type, dataTypeID, dataLength, defaultValue, isVisible); } updateCompleted = SqlQueryExecutor::instance().batchUpdateAttributes(m_connection, m_modelAttributeGroup.modelID, m_modelAttributeGroup.groupID, updateAttributes); } if( (!insertRows.isEmpty() && !insertCompleted) && (!deleteRows.isEmpty() && !deleteCompleted) && (!updateRows.isEmpty() && !updateCompleted) ) { emit showMessage(type_warning, QString::fromWCharArray(L"错误"), QString::fromWCharArray(L"数据提交失败,详情可查看日志文件")); } m_modifiedRows.clear(); refresh(); } void AttributeTableModel::cancleChanges() { if(!dataHasbeenModified()) return; m_modifiedRows.clear(); loadPageData(); updateTotalCount(); emit syncDataStatus(dataHasbeenModified(), m_paginationInfo); } QVector> AttributeTableModel::getSelectedRowData() { QVector> result; for(int row = 0; row < rowCount(); row++) { QModelIndex numberIndex = createIndex(row, 0); if(m_selectionModel && m_selectionModel->isSelected(numberIndex)) result.append(m_currentPageData.at(row).values); } return result; } void AttributeTableModel::triggerSyncSignal() { emit syncDataStatus(dataHasbeenModified(), m_paginationInfo); }