Delegate for QSqlTableModel / QTableView - problem tabbing from one row to next when editing



  • Good evening,

    In order to learn more about database handling and Qt, I have set up a simple database in mysql and I am working on being able to edit existing and new records. It is working, but the behaviour is strange when I tab out of the row and into the next. If I press return while still in the row being edited, everything works as planned. If I tab out of the last field into the next row, it picks up the data from the next row and stores it. First of all, I had a suspicion this is a delegate issue, as I had the QSqlRelationalTableDelegate set up originally. I have subsequently removed the setDelegate() call, hoping that default behaviour would be correct. Alternatively, do I need to set up a signal/slot to catch the movement out of the row, then update the database?

    Here is the code:

    nametablewindow.h:
    @
    #ifndef NAMETABLEWINDOW_H
    #define NAMETABLEWINDOW_H

    #include <QtGui>
    #include <QtSql>

    enum { // Field names
    names_id = 0,
    names_firstname = 1,
    names_surname = 2,
    names_address_id = 3,
    names_comment = 4
    };

    class NameTableWindow: public QWidget
    {
    Q_OBJECT
    public:
    NameTableWindow(QWidget *parent = 0);
    //virtual bool insertRows(int row, int count, const QModelIndex & parent = QModelIndex());
    signals:

    public slots:
    void insert(void);
    void remove(void);

    private:
    QSqlTableModel *namesModel;

    QTableView *namesView;
    QLabel *namesLabel;
    QDialogButtonBox *buttonBox;
    

    };

    #endif // NAMETABLEWINDOW_H
    @

    nametablewindow.cpp
    @
    #include "nametablewindow.h"

    NameTableWindow::NameTableWindow(QWidget *parent) :
    QWidget(parent)
    {
    // Create model and load data query
    namesModel = new QSqlTableModel(this);
    namesModel->setTable("names");
    namesModel->setEditStrategy(QSqlTableModel::OnRowChange);

    // Set up the headers
    namesModel->setHeaderData(names_id,Qt::Horizontal, tr("id"));
    namesModel->setHeaderData(names_firstname, Qt::Horizontal, tr("First Name"));
    namesModel->setHeaderData(names_surname,Qt::Horizontal, tr("Surname"));
    namesModel->setHeaderData(names_address_id, Qt::Horizontal, tr("address id"));
    namesModel->setHeaderData(names_comment, Qt::Horizontal, tr("Comment"));
    
    // Load the table data
    namesModel->select();
    
    // Create the view
    namesView = new QTableView(this);
    namesView->setModel(namesModel);
    namesView->setEditTriggers(QAbstractItemView::AnyKeyPressed
                               | QAbstractItemView::DoubleClicked);
    
    // Removed - this delegate is for QSqlRelationalTableModel
    //namesView->setItemDelegate(new QSqlRelationalDelegate(this));
    
    namesView->setSelectionMode(QAbstractItemView::SingleSelection);
    namesView->setSelectionBehavior(QAbstractItemView::SelectRows); // select row not cell
    namesView->hideColumn(names_id);
    namesView->resizeColumnsToContents();
    namesView->horizontalHeader()->setStretchLastSection(true);
    
    // Set up Label
    namesLabel = new QLabel(tr("Names in Table"));
    namesLabel->setBuddy(namesView);
    
    QVBoxLayout *layout = new QVBoxLayout;
    
    layout->addWidget(namesLabel);
    layout->addWidget(namesView);
    
    connect(namesView, SIGNAL(activated(QModelIndex)),  namesModel, SLOT(submitAll()));
    
    buttonBox = new QDialogButtonBox;
    QPushButton *addButton = buttonBox->addButton(tr("Add"),QDialogButtonBox::ActionRole);
    QPushButton *rmButton = buttonBox->addButton(tr("Delete"),QDialogButtonBox::ActionRole);
    buttonBox->addButton(QDialogButtonBox::Ok);
    
    layout->addWidget(buttonBox);
    
    connect(rmButton, SIGNAL(clicked()), this, SLOT(remove()));
    connect(addButton, SIGNAL(clicked()), this, SLOT(insert()));
    connect(buttonBox, SIGNAL(accepted()), this, SLOT(close())); // SLOT(accept()));
    
    setLayout(layout);
    setWindowTitle(tr("Names Table"));
    
    namesView->setCurrentIndex(namesModel->index(0,0));
    

    }

    void NameTableWindow::insert()
    {
    int row = namesView->currentIndex().row();

    if (row < 0) // no record selected - add to end
        row = namesModel->rowCount();
    
    namesModel->insertRows(row,1);
    qDebug("rowCount(): %d", row);
    
    QModelIndex index = namesModel->index(row,0);
    namesView->setCurrentIndex(index);
    namesView->edit(index);
    

    }
    void NameTableWindow::remove()
    {
    int row = namesView->currentIndex().row();
    namesModel->removeRow(row);
    }
    @

    ...and for completion, main.cpp:
    @
    #include <QApplication>
    #include "mainwindow.h"
    #include "database.h"
    #include <iostream>
    #include "nametablewindow.h"

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);

    // The database connection needs to be made before any of the models are set
    // up, otherwise you will get "Database not open" errors and no data
    
    if (!createConnection()) {
        std::cerr << "Unable to open database" << std::endl;
        return 1;
    }
    
    NameTableWindow namesWindow;
    namesWindow.show();
    
    return a.exec(&#41;;
    

    }
    @

    I can post the remaining files if you want to have a go with running it yourself.

    I am sure I am missing something simple - I look forward to your help!

    Thanks!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.