PowerModeler/source/attributeTableModel.cpp

549 lines
18 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "attributeTableModel.h"
#include "attributeNamespace.h"
#include "logger.h"
#include "sqlQueryExecutor.h"
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_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 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);
}
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.state = (modifiedRow.state == New) ? New : Modified;
m_modifiedRows[globalRow] = modifiedRow;
m_currentPageData[row] = modifiedRow;
emit dataChanged(index, index, {role, Qt::UserRole + AttributeEidt::EditStatus});
emit syncDataStatus(m_modifiedRows.isEmpty(), 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
{
QModelIndex numberIndex = createIndex(index.row(), 0);
QString text = numberIndex.data(Qt::DisplayRole).toString();
Qt::ItemFlags flags = QAbstractTableModel::flags(index);
if (index.column() != 0 && !text.contains("-")) //行号列和处于删除状态的item不能编辑
flags = flags | Qt::ItemIsEditable;
return flags;
}
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);
QHash<QString, QString> 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();
QString strSQL = QString("SELECT attribute_id FROM basic.model_attribute WHERE model_type_id = %1 AND attribute_group_id = %2 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
{
QStringList columns;
for(int i = 0; i < m_displayField.count(); i++)
columns << m_displayField.at(i).originalName;
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))
{
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.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;
}
void AttributeTableModel::setCurrentPage(int page)
{
if(m_paginationInfo.currentPage != page && page > 0 && page <= totalPages())
{
m_paginationInfo.currentPage = page;
refresh();
}
}
int AttributeTableModel::currentPage() const
{
return m_paginationInfo.currentPage;
}
int AttributeTableModel::totalPages() const
{
return qCeil(static_cast<qreal>(m_paginationInfo.totalEntries) / m_paginationInfo.entriesPerPage);
}
void AttributeTableModel::previousPage()
{
if(m_paginationInfo.entriesPerPage == 1)
return;
setCurrentPage(m_paginationInfo.entriesPerPage--);
}
void AttributeTableModel::nextPage()
{
if(m_paginationInfo.entriesPerPage == totalPages())
return;
setCurrentPage(m_paginationInfo.entriesPerPage++);
}
void AttributeTableModel::firstPage()
{
if(m_paginationInfo.entriesPerPage == 1)
return;
setCurrentPage(1);
}
void AttributeTableModel::lastPage()
{
if(m_paginationInfo.entriesPerPage == totalPages())
return;
setCurrentPage(totalPages());
}
void AttributeTableModel::updateTotalCount()
{
/*if (m_tableName.isEmpty())
{
LOG_ERROR("SQL", QString::fromWCharArray(L"属性表名称为空,获取属性数量失败"));
return;
}*/
m_paginationInfo.totalEntries = SqlQueryExecutor::instance().getAttributeCount(m_connection, m_modelAttributeGroup.modelID, m_modelAttributeGroup.groupID);
}
QList<AttributeTableModel::RowData> AttributeTableModel::filterRowsByEditState(EditState state)
{
QList<RowData> result;
for(auto it = m_modifiedRows.begin(); it != m_modifiedRows.end(); it++)
{
if(it.value().state == 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(!m_modifiedRows.isEmpty())
{
emit showMessage(type_question, QString::fromWCharArray(L"提示"),
QString::fromWCharArray(L"有编辑数据还未提交,确认刷新放弃提交吗?"));
if(g_msgDlgBtn == btn_No)
return;
}
m_modifiedRows.clear();
loadPageData();
updateTotalCount();
emit syncDataStatus(m_modifiedRows.isEmpty(), m_paginationInfo);
}
void AttributeTableModel::insertRecord(int row)
{
if(row < 0 || row > rowCount())
return;
RowData newRow;
newRow.state = New;
newRow.values.resize(m_displayField.count());
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::removeRecord(int row)
{
if(row < 0 || row > rowCount())
return;
/*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();
}
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});
}
}
void AttributeTableModel::submitChanges()
{
QList<RowData> insertRows = filterRowsByEditState(New);
bool insertCompleted = false;
QList<RowData> deleteRows = filterRowsByEditState(Deleted);
bool deleteCompleted = false;
QList<RowData> updateRows = filterRowsByEditState(Modified);
bool updateCompleted = false;
//插入操作
if(!insertRows.isEmpty())
{
QList<Attribute> 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();
insertAttributes.emplace_back(-1, name, type, dataTypeID, dataLength, defaultValue);
}
insertCompleted = SqlQueryExecutor::instance().batchInsertAttributes(m_connection, m_modelAttributeGroup.modelID, m_modelAttributeGroup.groupID, insertAttributes);
}
//删除操作
if(!deleteRows.isEmpty())
{
QList<int> 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<Attribute> 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();
updateAttributes.emplace_back(id, name, type, dataTypeID, dataLength, defaultValue);
}
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(m_modifiedRows.isEmpty())
return;
m_modifiedRows.clear();
loadPageData();
updateTotalCount();
emit syncDataStatus(m_modifiedRows.isEmpty(), m_paginationInfo);
}
void AttributeTableModel::triggerSyncSignal()
{
emit syncDataStatus(m_modifiedRows.isEmpty(), m_paginationInfo);
}