Search code examples
c++qtqt5qtsqlqsqltablemodel

Inserting row into QSqlTableModel


When a row is going to be edited, an index is passed into the editing dialogue.
The edit works fine.
When I want to add a row, I don't pass an index to the dialogue constructor, so it knows that it's supposed to add a new row.
Here's the code of function reacting to dialogue's buttons

void DialogAddCl::on_buttonBox_clicked(QAbstractButton *button)
{
    // prepare
    m->database().transaction();
    QString debugstr;
    auto chi4 = ui->buttonBox->buttonRole(button);
    int rowCount = m->rowCount();
    switch (chi4) {
    case QDialogButtonBox::AcceptRole:
        if (!ind->isValid())
            // insert
            if (!m->insertRow(rowCount, *ind))
            {
                QMessageBox::critical (this, "Error inserting into model", m->lastError().text(), QMessageBox::Cancel);
                break;
            }
            else
            {
                m->setData(m->index(rowCount, 0), rowCount+1);
            }
        else
        {
            // update
            rowCount = ind->row();
        }
        m->setData(m->index(rowCount, 1), ui->name->text());
        m->setData(m->index(rowCount, 2), ui->addr->text());
        // 12 other setData() calls

        if (m->submitAll())
        {
            m->database().commit();
        }
        else
        {
            // rollback if error
            m->database().rollback();
            debugstr = QString(m->database().lastError().text());
            QMessageBox::critical (this, "Database returned an error",
                                   m->database().lastError().text(), QMessageBox::Cancel);
        }
    case QDialogButtonBox::RejectRole:
        this->close();
        break;
    case QDialogButtonBox::ResetRole:
        fillFields();
        break;
    default:
        break;
    }

}

Here's a piece of dialogaddcl.h:

private:
    Ui::DialogAddCl *ui;
    QSqlTableModel* m;
    QModelIndex* ind;

So, m->submitAll() works fine if I edit an existing record, and fails if I try to submit freshly inserted row. I have checked with debugging, setData() calls work fine even when adding, so it's not DB expecting NOT NULL fields and giving an error.
By the way, maybe somebody can point out a method to catch the actual error text? I tried with debugstr, but it always only contains empty string. So does the error message that I print


Solution

  • To insert a row to QSqlTableModel you should not use setData() directly, if you must not use insertRecord(), where you indicate the row and the QSqlRecord. The QSqlRecord can be obtained through the record() method of the model.

    InsertDialog dial;
    if(dial.exec()== InsertDialog::Accepted){
        db.transaction();
        QString f = dial.firstname();
        QString l = dial.lastname();
    
        QSqlRecord record = model.record();
        /* since the id field has the autoincrement attribute,
         * it is not necessary to indicate its value,
         * that is because this field of the request is removed.
        */
        record.remove(record.indexOf("id"))
        record.setValue("firstname", f);
        record.setValue("lastname", l);
        /*-1 is set to indicate that it will be added to the last row*/
        if(model.insertRecord(-1, record)){
            qDebug()<<"successful insertion";
            model->submitAll();
        }
        else{
            db.rollback();
        }
    }
    

    In the following link you will find an example.