There is a window with two QTableView widgets and a button, when clicked, changes are made to the model of the second QTableView , that is, the value of the field that appears in the first widget instead of the foreign key changes. The corresponding values ​​of the first QTableView also change, but there is no value in the QSqlRelationalDelegate QSqlRelationalDelegate . How to fix this error?

Main.cpp file:

 #include "mainwindow.h" #include <QApplication> #include <QtSql> #include "ui_mainwindow.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); QSqlDatabase db1 = QSqlDatabase::addDatabase("QSQLITE"); db1.setDatabaseName(":memory:"); db1.open(); QSqlQuery("CREATE TABLE test (a integer primary key, b integer)"); QSqlQuery("CREATE TABLE test2 (a integer primary key, s text)"); QSqlQuery("INSERT INTO test VALUES (1, 2), (2, 2), (3, 1);"); QSqlQuery("INSERT INTO test2 VALUES (1, 'a'), (2, 'b');"); QSqlRelationalTableModel *model = new QSqlRelationalTableModel(0, db1); model->setEditStrategy(QSqlTableModel::OnManualSubmit);; model->setTable("test"); model->setRelation(1, QSqlRelation("test2", "a", "s")); model->select(); w.ui->tableView->setModel(model); w.ui->tableView->setItemDelegate(new QSqlRelationalDelegate(w.ui->tableView)); QSqlTableModel *model2 = new QSqlTableModel(0, db1); model2->setEditStrategy(QSqlTableModel::OnManualSubmit);; model2->setTable("test2"); model2->select(); w.ui->tableView2->setModel(model2); return a.exec(); } 

File mainwindow.h:

 #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); public: Ui::MainWindow *ui; public slots: void bClicked(); }; #endif // MAINWINDOW_H 

File mainwindow.cpp:

 #include "mainwindow.h" #include "ui_mainwindow.h" #include <QtSql> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QWidget::connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(bClicked())); } void MainWindow::bClicked() { qobject_cast<QSqlTableModel*>(ui->tableView2->model())->submitAll(); qobject_cast<QSqlTableModel*>(ui->tableView->model())->select(); } MainWindow::~MainWindow() { delete ui; } 

On the form corresponding to the mainwindow.ui file, there are two QTableView widgets: tableView and tableView2, and a pushButton button.

  • And the result of the execution (ui->tableView2->model())->submitAll(); did you check? Maybe the changes made are not recorded? - aleks.andr
  • @ aleks.andr Now checked - returns true . And the data in the first view changed, only the values ​​in the delegate list do not change. I really tried it and QQSqlRelation and re-add, but still, the same values ​​as before pressing the button. - Im ieee
  • Try whether it will work not with a key-key relationship, but a key-field, that is, model->setRelation(2, QSqlRelation("test2", "a", "s")); - Cerbo
  • @Cerbo this code will generally QSqlRelation , since there are only two fields in the model, and the index starts at 0. - Im ieee

1 answer 1

After viewing the source code, Qt found what the error was.

The delegate gets the data from the model like this: sqlModel->relationModel(index.column()) . This relationModel model corresponding to the main table (test2 in my example) is stored in the internal QRelation object. When a new QSqlRelation link is QSqlRelation , which is assigned to the QRelation object, the QRelation object QRelation initialized and the model is initialized by calling model->select() , but only once. Therefore, when updating QSqlRelation this model is not updated and, accordingly, the delegate receives the “old” data.

The solution, obviously, is to independently update all relationModel models. However, in the general case it is not clear how many links were added (this value is private) and the numbers of the fields with links are unknown, so you need to add a field number, for example, to a vector, each time you add a link. All these corrections can be done by inheriting the class from QSqlRelationalTableModel . Code:

 MyRelModel::MyRelModel(QObject *parent, QSqlDatabase db) :QSqlRelationalTableModel(parent, db), relColumnIndices(0) { } void MyRelModel::setRelation(int column, const QSqlRelation &relation) { relColumnIndices.append(column); QSqlRelationalTableModel::setRelation(column, relation); } void MyRelModel::updateRelations() { for (int i = 0; i < relColumnIndices.size(); i++) { QSqlRelationalTableModel::relationModel(relColumnIndices.at(i))->select(); } } 

Then, when you need to update the QTableView model, you need to additionally call the updateRelations() method and then there will be no error.