I have a QComboBox populated from a relationModel of a QSqlRelationalTableModel and connected to a QDataWidgetMapper.
I select a row in the QTableView, this row (record) mapped to the QLineEdit and QComboBox widgets then I make some changes and save.
If I select another row and save without changing the QComboBox value, the value changes and submitted to the model.
I use the editable combobox not for adding items to the list, but to use the completer feature when I have a large list instead of dropping down the combobox view
Creating the db:
import sqlite3
conn = sqlite3.connect('customers.db')
c = conn.cursor()
c.execute("PRAGMA foreign_keys=on;")
c.execute("""CREATE TABLE IF NOT EXISTS provinces (
ProvinceId TEXT PRIMARY KEY,
Name TEXT NOT NULL
)""")
c.execute("""CREATE TABLE IF NOT EXISTS customers (
CustomerId TEXT PRIMARY KEY,
Name TEXT NOT NULL,
ProvinceId TEXT,
FOREIGN KEY (ProvinceId) REFERENCES provinces (ProvinceId)
ON UPDATE CASCADE
ON DELETE RESTRICT
)""")
c.execute("INSERT INTO provinces VALUES ('N', 'Northern')")
c.execute("INSERT INTO provinces VALUES ('E', 'Eastern')")
c.execute("INSERT INTO provinces VALUES ('W', 'Western')")
c.execute("INSERT INTO provinces VALUES ('S', 'Southern')")
c.execute("INSERT INTO provinces VALUES ('C', 'Central')")
c.execute("INSERT INTO customers VALUES ('1', 'customer1', 'N')")
c.execute("INSERT INTO customers VALUES ('2', 'customer2', 'E')")
c.execute("INSERT INTO customers VALUES ('3', 'customer3', 'W')")
c.execute("INSERT INTO customers VALUES ('4', 'customer4', 'S')")
c.execute("INSERT INTO customers VALUES ('5', 'customer5', 'C')")
conn.commit()
conn.close()
and here is the window:
from PyQt5.QtWidgets import *
from PyQt5.QtSql import *
class Window(QWidget):
def __init__(self):
super().__init__()
self.db = QSqlDatabase.addDatabase("QSQLITE")
self.db.setDatabaseName("customers.db")
self.db.open()
self.model = QSqlRelationalTableModel(self, self.db)
self.model.setTable("customers")
self.model.setRelation(2, QSqlRelation("provinces", "ProvinceId", "Name"))
self.model.setEditStrategy(QSqlTableModel.EditStrategy.OnManualSubmit)
self.model.select()
self.id = QLineEdit()
self.name = QLineEdit()
self.province = QComboBox()
# stuck here
self.province.setEditable(True)
self.province.setModel(self.model.relationModel(2))
self.province.setModelColumn(1)
self.province.setView(QTableView())
self.mapper = QDataWidgetMapper()
self.mapper.setItemDelegate(QSqlRelationalDelegate())
self.mapper.setModel(self.model)
self.mapper.addMapping(self.id, 0)
self.mapper.addMapping(self.name, 1)
self.mapper.addMapping(self.province, 2)
save = QPushButton("Save")
save.clicked.connect(self.submit)
self.tableView = QTableView()
self.tableView.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
self.tableView.setSelectionBehavior(QTableView.SelectionBehavior.SelectRows)
self.tableView.setModel(self.model)
self.tableView.clicked.connect(lambda: self.mapper.setCurrentModelIndex(self.tableView.currentIndex()))
vBox = QVBoxLayout()
vBox.addWidget(self.id)
vBox.addWidget(self.name)
vBox.addWidget(self.province)
vBox.addSpacing(20)
vBox.addWidget(save)
vBox.addWidget(self.tableView)
self.setLayout(vBox)
self.mapper.toFirst()
def submit(self):
self.mapper.submit()
self.model.submitAll()
def main():
import sys
App = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(App.exec_())
if __name__ == '__main__':
main()