Nominate our 2022 Qt Champions!

SQL Widget Mapper Example Weirdness

  • Hi, first post; pardon any mistakes or broken customs.

    I am fairly new to Qt. I found it confusing to install, but delightful to use. I've mostly been figuring it out on my own, with some references to the documentation and Stack.

    Currently, I am designing a program that grabs data from a SQLite database and packages it into a window where any user can read and edit. So far, so good. I have an Item table that holds item-specific information, and an id number that references the primary key of another table, Vendor to link it to vendor info. My early attempts used QSqlRelationalTableModel and a table view. This replaced the Item table's id reference with the 'name' from the Vendor table, at least that's what the user sees. I believe the underlying data is still that original id# from the Item table, if I'm reading it all right.

    I decided to show one record at a time though, and dropped the table view for a number of line edits, spinBoxes, etc. I wanted to create a comboBox to allow the Vendor to be changed by selecting from among the entries in the Vendor table. So I use a RelationalTableModel, grab the relation to make a new TableModel, slap that tableModel onto the combobox, and use a QDataWidgetMapper to push data into all the various widgets.

    This works. Mostly.

    Rather than put my own code here, I'll refer you all to the SQL Widget Mapper Example:

    For whatever reason, I am experiencing the exact same issues when running the example packaged in with my Qt5.5. Let me explain:

    Click on the combobox and it shows a list of options, presumably entries from a related table. Click on one. It sets the underlying data (the id in the original table) without issue. The combobox text/index(?) becomes the item you clicked on. That all works fine. But when moving back to this record, it doesn't update the combobox text/index. Instead, it shows whatever the text/index was from the last record before moving on to this one.

    Specific steps to replicate:

    1. Open Sql Widget Mapper Example in QtCreator, run
    2. Click 'Next'. Name field should read 'Bob', Type should read 'Work'.
    3. Change 'Work' to 'Other'.
    4. Click 'Previous' (Alice). Click 'Next' (Bob).
    5. Note: At this point Bob's 'Type' field shows 'Home' for me. Notably, this is Alice's 'Type', neither Bob's original 'Type' nor his recently set 'Type'.
    6. Optional: Change other records, then Next and Previous around to watch how the comboBox stops updating it's text/index once it has been changed, instead taking the value of whichever record was displayed immediately before.

    So my guess here is that the example code is right, which means my code is right, and that something about my environment or settings is off. I'm new to Qt and it's attendant Creator application, so probably I just need to flick a switch I've never heard about. But I guess there's the potential that this is some kind of bug?

    Can anyone replicate this behavior on a properly set up system? Any ideas what's going on here? Thanks for reading.

    tl;dr SQL Widget Mapper example's combobox stops updating the information on that record once it's been changed, instead cloning the most recent combobox entry when using the next/previous buttons (though the information in the db has likely been changed correctly)

  • Lifetime Qt Champion

    Very good description.

    I tried the sample. I get same result as you. It does not
    save the change of addresstype.
    If I change address ,the changed address is saved.

    I changed the database from memory to file and looked in it.
    the typeid field is never updated.
    So it seems that this
    model->setRelation(typeIndex, QSqlRelation("addresstype", "id", "description"));

    is not really working as expected.

  • Moderators

    @mrjj said:

    I changed the database from memory to file and looked in it.

    Because model->submit() is never called. Note that in the example the submit strategy is set to manual:


    in void Window::setupModel(). Still the model data should be updated at least to the point where it's visible in the UI. Possibly this is a bug, however I haven't the time right now to download and run the example, maybe this evening I'll try and report my findings.

  • Lifetime Qt Champion

    Thanks for input.
    But it does indeed save address changes?
    And I also tried with setEditStrategy to Row for test.

    Would be great if u in evening could have and tell if U see same results.

  • Moderators


    But it does indeed save address changes?

    It should, just not flushing them to the SQL database.

    Would be great if u in evening could have and tell if U see same results.

    I'll try!

  • Wow thanks for the quick replies!

    I hadn't thought to check the edit strategy of the sample code. Still, if this was all working as expected, the comboBox should update to either the old setting (if unsaved) or the new setting (if saved), but in practice it can be made to show the third, unaffected option.

    I didn't check the edit strategy, or the underlying status of the SQL database, because in my own code, I have a similar architecture which uses the OnFieldChange edit strategy and quick access to the underlying database. Using the same techniques, I can say that the changes -are- occurring as expected everywhere but in the visual component of the comboBox.

    For example:
    Data from the main table, Item, fills every other mapped widget correctly. Before any changes are made, it correctly relates the id to the Vendor table's relevant column, name, and correctly sets the text or index (I'm still not sure which of these it's using to find the entry) of the comboBox to match that related entry.

    After selecting a differing item from the comboBox, the correct change has been made. Specifically, the vendorID (related id) in the Item table has changed to the appropriate id from the Vendor table, through the visibly related name. No incorrect changes are made to other Item table data, nor is the Vendor table data modified at all. Honestly, if I could be satisfied forcing the window to close after making a change here, the whole process could be considered to be working perfectly.

    I have noticed that normally the comboBox will trigger both the currentIndexChanged and currentTextChanged slots when the QDataWidgetMapper runs toNext() and toPrevious(). Once the comboBox has been changed, however, it stops triggering either of these slots on any subsequent navigation to that entry in the model through those methods. I haven't tested this on the example, but I suspect a similar outcome.

    Hope that helps. I can dump my own code for review if necessary, but don't believe it varies very meaningfully from the example.

  • Moderators

    @JoeB, @mrjj
    I run that example on all my currently available Qt versions (5.5, 5.6 and the dev branch) and it's not working as expected on any of them. However seeing the behavior first I'd assume that there's something wrong with the example itself before going to the library code. Unfortunately, I haven't seen anything wrong with it, so I'm currently debugging the mapper widget. As investigations continue any finds I'll report here promptly.

  • Lifetime Qt Champion

    Thank you.

  • Moderators

    Well, it definitely seems like a bug. I muddled through some of the source and it does seem that the mapper sets the data correctly, at least as far as I can see in the debugger. My suspicion is that loading it back is broken for the combo box ...
    @JoeB, my suggestion is to file a bug report (I believe you could login with your forum credentials) and hopefully someone more versed in the internals would fix that up. Or even if you can you could try and fix it and submit your patch for review (eventually it should get integrated into the main branch). That's all from me for now.

    Kind regards.

  • I believe filing the bug report is the best course of action for my experience level. Thank you to everyone who replied. If there is an upvote or recommendation system that I'm missing, let me know so I can log my praise officially, and if I need to do anything further to make this question as answered, I can't find it. Thanks again.

  • Moderators

    You can give reputation points (the stars next to the name) by clicking on the up arrow or take such points by using the down arrow (for each post). You can bookmark posts with the favourite button. You mark the thread as solved by going down to the bottom, clicking the Topic tools button and selecting Mark as solved.

Log in to reply