Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

[Solved] -SqlRelation in Widgets, is possible?- (Actually, find index in QComboBox based on model data)



  • Hi,

    I need to make QDialogs to edit different types of SqlRecords. For instance, a QDialog to edit Customer records and another to edit User records.

    The QDialog should have a method load(int id) to fetch the record from the database.

    There are relational fields, for instance, city_id which should relate to the table cities. I want this field to be editable via QComboBox. Is there a way to do this? The QComboBox should show the list of city names but save the id of the city instead. (That, I know a way) But also, when fetching a new record, should take the city_id and select the corresponding city name. (That, I do not know)

    So I'm thinking there MUST be an easy way to do this I'm not aware of.. Right?



  • Did you set a delegate?

    @
    view->setItemDelegate(new QSqlRelationalDelegate(view));
    @

    As far as I know this should to the trick.

    It's just copied from examples/sql/relationaltablemodel.



  • What view? I don't really need a Relational Table Model, I something more like a Relational Record.
    The closest aproach I could find is using a QDataWidgetMapper, but that only works with a QSqlTableModel, not with QSqlRecords (at least i don't know how -- that would solve everything). I don't have a QSqlTableModel because I only need to edit ONE record which has to be loaded by its id. So I have a QSqlQuery like this:
    @
    int customerId = 123; // just an example. id will be provided by the user.
    QSqlQuery q;
    q.prepare("SELECT * FROM customer WHERE id = :id");
    q.bindValue(":id", customerId);
    q.exec();
    q.first();
    QSqlRecord rec = q.record();
    @
    The Dialog provides QWidgets to edit every relevant field of the record. (Mostly QLineEdits)
    That record has a city_id field. Which is of course a foreign key referencing the table cities.
    I need a QComboBox to work as a QSqlRelationalDelegate, so the user can edit the city_id field by selecting the city name. How can I achieve this?



  • If you do it all by hand:

    • load the cities data in a separate query (select name, id from cities)
    • put all the data in a combo box (text = name, userdata = id)
    • load your customer data
    • get the cities index in the combobox by findData with search for UserRole
    • set the combobox to the index found


  • [quote author="Volker" date="1294852654"]If you do it all by hand:

    • load the cities data in a separate query (select name, id from cities)
    • put all the data in a combo box (text = name, userdata = id)
    • load your customer data
    • get the cities index in the combobox by findData with search for UserRole
    • set the combobox to the index found
      [/quote]
      That's it! findData. That could work. Thank's Volker!

    Just a question though. I'm filling the QComboBox with setModel and setModelColumn. Is there a way to "setModelColumnForData" ? Or I need to make a loop and set it manually?



  • Ok nevermind, it's not possible. Read a few mailing list about this. It's not possible to properly work with QComboBox and models.



  • I almost wish QComboBox had a method like this:
    @
    int QComboBox::findData (int modelColumn, const QVariant & data, int role = Qt::UserRole, Qt::MatchFlags flags = static_castQt::MatchFlags ( Qt::MatchExactly | Qt::MatchCaseSensitive ) ) const@
    That would make things much simplier when working with models.

    Instead, the solution is to search the model like this:
    @ // find row
    QModelIndexList matches = ui->condAlIVAComboBox->model()->match(
    ui->condAlIVAComboBox->model()->index(0,0),
    Qt::EditRole,
    r.value("customer_vat_id"),
    1,
    Qt::MatchExactly
    );
    if (matches.isEmpty()) {
    // handle error
    } else {
    ui->condAlIVAComboBox->setCurrentIndex(matches.first().row());
    }
    @

    Just posting to give closure to the thread. It's now Solved. Thanks Volker for pointing me in the right way.



  • You could subclass QComboBox and add the convenience methods. It's not that hard. We did this in our project and it works pretty well. You could also make a designer plugin and use it in Qt Designer and Creator instead of the original combo boxes.


Log in to reply