Results 1 to 2 of 2

Thread: QSqlRelationalDelegate displays foreign_key - id instead of name/value from Combobox

  1. #1
    Join Date
    Aug 2021
    Qt products
    Unix/X11 Windows

    Default QSqlRelationalDelegate displays foreign_key - id instead of name/value from Combobox

    I am trying to add new rows to QSqlRelationalModel which is represented in QTableView. This new row is populated by the user, and on fieldChange should be submitted to DB.

    I have set proper QSqlRelationalDelegate and proper QSqlRelations in the model:
    Qt Code:
    1. self.table_model = QSqlRelationalTableModel(main, database)
    2. self.table_model.setJoinMode(QSqlRelationalTableModel.JoinMode.LeftJoin)
    3. table_name = 'book_of_accounts'
    4. self.table_name = table_name
    5. self.table_model.setTable(table_name)
    7. self.table_model.setRelation(4, QSqlRelation('account_type', 'id', 'name'))
    8. self.table_model.setRelation(7, QSqlRelation('subconto1', 'id', 'name'))
    9. self.table_model.setRelation(8, QSqlRelation('subconto2', 'id', 'name'))
    10. self.table_model.setRelation(9, QSqlRelation('subconto3', 'id', 'name'))
    12. self.table_model.setEditStrategy(QSqlTableModel.EditStrategy.OnFieldChange)
    15. self.tableView = QtWidgets.QTableView(self.verticalLayoutWidget)
    16. self.tableView.setModel(self.table_model)
    17. self.tableView.setItemDelegate(QSqlRelationalDelegate(self.tableView))
    To copy to clipboard, switch view to plain text mode 

    Displaying and updating existing data from the database works fine. Columns with related data change to Comboboxes and I can choose options from the related tables.

    However, when I try to create a new record by adding a row to the model, Comboboxes allow me to choose the proper value from the dropdown list, but after choosing it, the value changes to the ID of the related record as if no relational delegate was set:

    Qt Code:
    1. def addRow(self):
    2. count = self.table_model.rowCount(QModelIndex())
    3. self.table_model.insertRows(count, 1)
    4. self.tableView.scrollToBottom()
    5. self.tableView.selectRow(count)
    To copy to clipboard, switch view to plain text mode 

    Here is how I can choose a correctly displayed option:

    But once I close the editor, the text is replaced with a foreign key:

    Once I fill out all fields and select another row, the data is submitted and the row is displayed correctly again. So this only happens while adding a new row.

    I am using a QFilterSortProxyModel too, but it has no effect on the described behavior. This bug is persistent in both pyqt5 and pyqt6.

    While debugging I discovered that in QSqlRelationalDelegate`s setModelData, contains the corresponding foreign keys when the method is executed.

    I have a SO question, which describes the problem with a bit more code as context.

    Am I missing something obvious here? How can tackle this issue?

  2. #2
    Join Date
    Oct 2009
    Thanked 10 Times in 10 Posts
    Qt products
    Unix/X11 Windows

    Default Re: QSqlRelationalDelegate displays foreign_key - id instead of name/value from Combo

    short answer: QFilterSortProxyModel cant work using a proxy model.

    long answer: need to subclass QSqlRelationalDelegate to search in the proxy mode, the source model. and call the base function using the model and index if the sourceModel()

    1- need to find the first not-proxy model using the 'index', and the mapped model index related to proxy index 'index' and return the source model index and the index mapped from the proxy model
    Qt Code:
    1. std::tuple<QAbstractItemModel *, QModelIndex> findSourceModel(QModelIndex index) const
    2. {
    3. QAbstractItemModel * source_model = (QAbstractItemModel *)index.model();
    4. QModelIndex source_index = index;
    6. while( source_model->inherits("QAbstractProxyModel") ){
    7. //qDebug() << "class name from proxy model " << source_model->metaObject()->className();
    8. source_index = static_cast<QAbstractProxyModel *>(source_model)->mapToSource(source_index);
    9. source_model = static_cast<QAbstractProxyModel *>(source_model)->sourceModel();
    10. }
    12. return {source_model, source_index};
    13. }
    To copy to clipboard, switch view to plain text mode 

    and use the returned values whit the base class implementation of QSqlRelationalDelegate

    Qt Code:
    1. QWidget *QSqlRelationalProxyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
    2. {
    3. auto[source_model, source_index] = findSourceModel(index);
    4. return QSqlRelationalDelegate::createEditor(parent,option,source_index);
    5. }
    To copy to clipboard, switch view to plain text mode 

    for a not proxy model. i refer to any subclass of QAbstractProxyModel, mainly a QSortProxyModelor QIdentityProxyModelsubclass

    I apologize for responding with a code in C++, but I haven't programmed in Python for a long time, it should be easy to convert it to Python.
    I hope it is useful to you
    Last edited by ecanela; 24th December 2023 at 06:25. Reason: updated contents

Similar Threads

  1. Replies: 0
    Last Post: 12th April 2017, 11:53
  2. QSqlRelationalDelegate
    By pippo42 in forum Qt Programming
    Replies: 1
    Last Post: 2nd May 2010, 13:05
  3. Replies: 1
    Last Post: 20th January 2010, 23:59
  4. QSqlRelationalDelegate (ComboBox) id on first show
    By janus in forum Qt Programming
    Replies: 1
    Last Post: 5th September 2008, 14:58
  5. Error in qsqlrelationaldelegate.h?
    By brcain in forum Qt Programming
    Replies: 3
    Last Post: 28th August 2006, 13:05

Tags for this Thread


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.