[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
 

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