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

Layered Views



  • I have two classes that look like this:

    struct parent {
        QList<child> children;
    };
    
    struct child {
         int id;
    };
    

    I now want to represent those two classes in two views that are next to each other.
    Selecting a parent in the left view should show all of its children in the second view. I'm a bit unsure how to properly implement this. I created a QHash from parent to child_model in parent_model and then calling setModel for the child_view every time a new parent is selected.

    The issue there is that the selection-state and expansion state (or rather in general the entire internal state of the child_view is reset, which isn't great UX wise)

    I'm looking for pointers on how to approach this. Should I map from parent to child_view instead?
    Should I only have one child_model and a custom view that delegates its index/parent/etc. calls via the currently selected parent?

    Thanks in Advance
    Folling



  • So, no one has an answer for this?

    I find it hard to believe I'm the first person trying to display a one-to-many relationship in qt.

    Here's two approaches I came up with for now:

    1. Have a map of parent_model to child_model somewhere, and exchange the model in the view using QAbstractItemView::setModel.

    2. store all children in child_model and allow the creation of QProxyModel that will then only display the relevant children

    Both of these carry their own issues, so I find them subpar to an ideal solution.
    The first doesn't retain things like expansion or selection state, the second is imperformant~ish.


  • Lifetime Qt Champion

    Hi,

    So you have a list of parent struct containing a list of children struct ?

    Then you have have a main model on top of list of parent and have a filter proxy model that will return only the list of child to the second view and only the parents on the first view.



  • So you have a list of parent struct containing a list of children struct ?

    Indeed!

    Then you have have a main model on top of list of parent and have a filter proxy model that will return only the list of child to the second view and only the parents on the first view.

    So I have one model, that contains all data, and I construct proxy models of that, which only return the relevant data regarding some parameters (in this case, "only return the children of parent X")?

    And a follow up question: If the model manages both parent and child objects - how would I go about handling insertRows and such functionality? I could override it in the proxy model, but then I couldn't propagate the changes between multiple proxy models accessing the same data.


  • Lifetime Qt Champion

    Usually proxy models come between the main model and the view(s).



  • Pardon my intrusion, but that doesn't cover this part of the question for me:

    And a follow up question: If the model manages both parent and child objects - how would I go about handling insertRows and such functionality? I could override it in the proxy model, but then I couldn't propagate the changes between multiple proxy models accessing the same data.

    Or maybe I just overlooked it


  • Lifetime Qt Champion

    It depends on how you intend to manage your data from your application point of view.



  • As said in the iniital post - I will have multiple views.
    You have two list views next to each other - one for all parent objects and one for the selected parent's child objects. The second view needs to be updated whenever a new parent is selected.
    Parents and Children are accesed in multiple other points in the program, there is for example, also a tableview to look at all children of a parent in more detail. (Tableview uses custom delegates to allow users to make edits on the children in place).
    Removal and addition of children can hence happen in any place where a list of children is displayed.


  • Lifetime Qt Champion

    I was rather thinking of the backend side of stuff like where do this data come from ? What generates them ?



  • I'll try to give as much concise information as I can:

    The data is (almost always) generated by the user - an exception to this would be a shipped demo project, and in the future perhaps plugins.

    Children only ever have one parent, but parents can have multiple children. So it's a true 1:n relationship.

    The user can create parents, and assign children to them, as well as delete and reorder them.
    Both parents and children are part of a project's state, which is persisted through multiple iterations using messagepack.

    You can load a project at any time, which would completely switch out the data the program is currently using - similar to how you'd be able to with word/pretty much any IDE.

    Can't think of anything else that could be relevant - thanks for taking the time btw!


Log in to reply