Results 1 to 2 of 2

Thread: QTreewidget with checkboxes

  1. #1
    Join Date
    Jul 2020
    Posts
    2
    Qt products
    Qt4
    Platforms
    Windows

    Default QTreewidget with checkboxes

    I created a treewidget in Qt. My goal is to create a simple library with CMakeLists.txt files. I have collected the project files in a directory. My goal is to access CMakeLists.txt files in project files and show them in a treewidget. There is no problem in this part.
    In step 2, I have to add checkboxes to the parents (each parent corresponds to a project) and put links to them. There are about 40 parents, each parent's child has other parent's listed. When I check any parent's, other parents listed in the child need to be checked as well. How can I do that?

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QTreewidget with checkboxes

    I think you need to separate the data structure you use to represent the CMakeLists files and their parent-child relationships from the QTreeWidget you use to display this data structure.

    One problem with QTreeWidget is that the model it uses cannot directly represent children that have more than one parent. Each QTreeWidgetItem has only zero or one parent, but can have zero or more children. With CMakeLists, a subproject, like a library, can be used in multiple higher level CMakeLists, so you don't have a simple parent-child relationship but a many-many relationship. It is a network, not a tree.

    You can model this with your own network data structure, where each node (representing a CMakeLists.txt file) can have zero or more parent nodes and zero or more child nodes. You need to be able to travel through this data structure from top to bottom (following parent -> child links) or bottom to top (following child -> parent links). Your data structure will look more like a mesh than a tree with a root and branches. Each element in this tree needs to have a "checked" flag (in addition to whatever other data you store).

    To map this into a QTreeWidget, you have to start at any top-level node of your data structure and work downwards, creating QTreeWidgetItem instances and inserting them into the tree widget. You need to store a pointer to the node in your data structure inside the QTreeWidgetItem, either as a data() member or by deriving a class from QTreeWidgetItem and storing it as a member variable. Note that in your QTreeWidget, every QTreeWidgetItem will be a unique instance, but the same data pointer from your data structure might be stored in more than one QTreeWidgetItem. This is how you handle the multiple-parent problem of your data structure in a tree that supports only a single parent for each item. When you look at your QTreeWidget, you could see the same CMakeLists file displayed at multiple places in it.

    So now your problem of checking projects comes down to setting the "checked" flag in your data structure and then traversing the data structure to set the checked flag in all of the parent nodes that depend on that one.

    Once that is done, you map the data structure checks to tree widget checks. You walk through your QTreeWidget from top to bottom. For each top-level QTreeWidgetItem, you retrieve the pointer to your data structure node, and set the QTreeWidgetItem's checked status appropriately, then follow the QTreeWidgetItem links to its children, retrieve their data structure pointers, set the check state, and so on, until you reach the end of that path through the tree. You then go back to the next top-level node and do it again for that one, and so on until you have handled all of the top level nodes and all of their children.

    If you are interacting with the QTreeWidget to check / uncheck nodes, you do this same process - when changing the check state of a node, you retrieve the pointer to the data structure and change -its- check state (and the state of everything it links to), then you use this information to update the tree widget. Don't do it the other way around (using the tree widget to update the data structure) because the tree widget doesn't contain all of the necessary information - it only holds -one- of the parents of any node.

    One more gotcha: A parent CMakeLists might depend on more than one checked child. So when you uncheck a child, you can't uncheck the parent automatically. You have to first check all of the other children of that parent to see if any of them are still checked. If they are, then you can't uncheck the parent.

    In CMakeLists terms, if a parent depends on two subprojects and both of them are checked, unchecking one project still means the parent has to be build, because building the other subproject will force it.

    By the way, the QAbstractItemModel class does not put any restrictions on the parent-child relationships in the model. It is very general in this regard. The specialization to QTreeWidget / QTreeView adds the restriction of one parent per child. If Qt supplied a widget that could display QAbstractItemModels of any complexity (like a network graph), then you could directly model your data structure as an abstract model and use the network graph widget to display it.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

Similar Threads

  1. Replies: 4
    Last Post: 22nd June 2015, 11:30
  2. How to use Checkboxes in QMenu?
    By Stravinsky in forum Newbie
    Replies: 3
    Last Post: 18th June 2015, 06:13
  3. Replies: 0
    Last Post: 21st October 2013, 10:16
  4. Replies: 2
    Last Post: 17th March 2008, 13:53
  5. checkboxes
    By abrou in forum Newbie
    Replies: 2
    Last Post: 1st February 2008, 19:52

Bookmarks

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.