What's the best way to have QTableView and Database in sync after inserting the record?
Question: Let's suppose I have a QTableView with QSqlTableModel/Database. I don't want
to let user edit the cells in QTableView. There are CRUD buttons that open new
dialog forms and the user is supposed to enter data. After the user clicks
dialog's OK button, what is the best way to insert that new record to database
and view (to have them in sync), because database can be unavailable at the
time (for example, inserting to remote database while having internet
connection problems)?

My primary concern is I don't want to show phantom records in view and I want
the user to be aware the record is not entered in the database.

I put some python code (but for Qt my problem is the same) to illustrate this,
and have some other questions in comments:

    
    
    import sys
    from PyQt4.QtGui import *
    from PyQt4.QtCore import *
    from PyQt4.QtSql import *
    
    class Window(QWidget):
        def __init__(self, parent=None):
            QWidget.__init__(self, parent)
            self.model = QSqlTableModel(self)
            self.model.setTable("names")
            self.model.setHeaderData(0, Qt.Horizontal, "Id")
            self.model.setHeaderData(1, Qt.Horizontal, "Name")
            self.model.setEditStrategy(QSqlTableModel.OnManualSubmit)
            self.model.select()
    
            self.view = QTableView()
            self.view.setModel(self.model)
            self.view.setSelectionMode(QAbstractItemView.SingleSelection)
            self.view.setSelectionBehavior(QAbstractItemView.SelectRows)
            #self.view.setColumnHidden(0, True)
            self.view.resizeColumnsToContents()
            self.view.setEditTriggers(QAbstractItemView.NoEditTriggers)
            self.view.horizontalHeader().setStretchLastSection(True)
    
            addButton = QPushButton("Add")
            editButton = QPushButton("Edit")
            deleteButton = QPushButton("Delete")
            exitButton = QPushButton("Exit")
    
            hbox = QHBoxLayout()
            hbox.addWidget(addButton)
            hbox.addWidget(editButton)
            hbox.addWidget(deleteButton)
            hbox.addStretch()
            hbox.addWidget(exitButton)
    
            vbox = QVBoxLayout()
            vbox.addWidget(self.view)
            vbox.addLayout(hbox)
            self.setLayout(vbox)
    
            addButton.clicked.connect(self.addRecord)
            #editButton.clicked.connect(self.editRecord) # omitted for simplicity
            #deleteButton.clicked.connect(self.deleteRecord) # omitted for simplicity
            exitButton.clicked.connect(self.close)
    
        def addRecord(self):
            # just QInputDialog for simplicity
            value, ok = QInputDialog.getText(self, 'Input Dialog', 'Enter the name:')
            if not ok:
                return
    
            # Now, what is the best way to insert the record?
    
            # 1st approach, first in database, then model.select()
            # it seems like the most natural way to me
            query = QSqlQuery()
            query.prepare("INSERT INTO names (name) VALUES(:name)")
            query.bindValue( ":name", value )
            if query.exec_():
                self.model.select() # now we know the record is inserted to db
                # the problem with this approach is that select() can be slow
                # somehow position the view to newly added record?!
            else:
                pass
                # message to user
                # if the record can't be inserted to database, 
                # there's no way I will show that record in view
    
            # 2nd approach, first in view (model cache), then in database
            # actually, I don't know how to do this
            # can somebody instruct me?
            # maybe:
            # record = ...
            # self.model.insertRecord(-1, record) #
            # submitAll()
            # what if database is unavailable?
            # what if submitAll() fails?
            # in that case, how to have view and model in sync?
            # is this the right approach?
    
            # 3. is there some other approach?
    
    app = QApplication(sys.argv)
    db = QSqlDatabase.addDatabase("QSQLITE")
    db.setDatabaseName(":memory:")
    db.open()
    query = QSqlQuery()
    query.exec_("DROP TABLE names")
    query.exec_("CREATE TABLE names(id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, name TEXT)")
    query.exec_("INSERT INTO names VALUES(1, 'George')")
    query.exec_("INSERT INTO names VALUES(2, 'Rita')")
    query.exec_("INSERT INTO names VALUES(3, 'Jane')")
    query.exec_("INSERT INTO names VALUES(4, 'Steve')")
    query.exec_("INSERT INTO names VALUES(5, 'Maria')")
    query.exec_("INSERT INTO names VALUES(6, 'Bill')")
    window = Window()
    window.resize(600, 400)
    window.show()
    app.exec_()
    


Answer: You can still use `QSqlTableModel`. You can turn off all edit triggers in your
table view and then pass the model to your data capturing forms and let the
widgets bind to the model using `QDataWidgetMapper`, making sure the submit
mode is set to manual so you can validate fields first.

