如何检测QSqlRelationalTableModel关联的TableView是否发生数据变更?
实现退出时检测真实修改并询问保存的方案
针对你的需求,不用直接对比数据库,利用Qt模型的内存数据快照就能精准判断是否存在真实修改(编辑后恢复原状不触发询问),具体实现步骤如下:
1. 记录初始数据快照
在模型加载完成(model->select()之后),把当前模型的所有行数据保存为初始快照,作为类成员变量存储:
// 头文件中声明成员变量:QList<QVariantList> m_initialData; // 初始化模型后添加这段代码保存快照 model = new QSqlRelationalTableModel(this, *db); model->setTable("cv"); model->setFilter("cv_id = "+currentCV+""); model->removeColumns(0,1); model->select(); ui->tableView->show(); ui->tableView->setModel(model); // 保存初始数据快照 m_initialData.clear(); for (int row = 0; row < model->rowCount(); ++row) { QVariantList rowData; for (int col = 0; col < model->columnCount(); ++col) { // 用EditRole获取编辑态的数据,保证和用户编辑的内容一致 rowData.append(model->data(model->index(row, col), Qt::EditRole)); } m_initialData.append(rowData); }
2. 退出时的判断与处理逻辑
在退出操作的槽函数中,先检查模型是否有未提交修改,再对比当前数据和初始快照,确认是否存在真实变更:
void YourClass::onExitDatabaseClicked() { // 第一步:检查模型是否有未提交的修改痕迹 if (!model->isDirty()) { // 无任何编辑操作,直接退出 closeDatabase(); // 替换成你的退出数据库逻辑 return; } // 第二步:判断是否存在真实修改(排除编辑后恢复原状的情况) bool hasRealChanges = false; // 先判断行数是否变化(新增/删除行) if (model->rowCount() != m_initialData.size()) { hasRealChanges = true; } else { // 逐行逐列对比数据 for (int row = 0; row < model->rowCount(); ++row) { for (int col = 0; col < model->columnCount(); ++col) { QVariant current = model->data(model->index(row, col), Qt::EditRole); QVariant initial = m_initialData[row][col]; if (current != initial) { hasRealChanges = true; goto endCheck; // 找到差异直接终止循环 } } } } endCheck: // 第三步:根据判断结果处理 if (hasRealChanges) { QMessageBox::StandardButton reply = QMessageBox::question( this, "确认退出", "存在未保存的修改,是否保存?", QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel ); if (reply == QMessageBox::Save) { // 执行保存操作 if (!model->submitAll()) { QMessageBox::warning(this, "保存失败", model->lastError().text()); return; // 保存失败,不退出 } } else if (reply == QMessageBox::Cancel) { return; // 用户取消退出 } // 选择Discard则直接跳过保存,执行退出 } // 执行退出数据库的逻辑 closeDatabase(); }
关键说明
- 为什么用内存快照对比?因为模型的未提交修改只存在于内存中,直接对比数据库会忽略这些内存中的变更;同时快照能精准判断用户是否真的修改了数据(编辑后改回原状时,
isDirty()会返回true,但快照对比会发现无差异)。 - 如果你的模型支持新增/删除行,代码中已经通过行数对比处理了这种场景,确保新增或删除行也会触发询问。
内容的提问来源于stack exchange,提问作者user20324932
相关产品推荐
相关产品推荐

