You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 14:45:28