Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Disable toplevel item of QTreeWidget
Forum Updated to NodeBB v4.3 + New Features

Disable toplevel item of QTreeWidget

Scheduled Pinned Locked Moved Unsolved General and Desktop
11 Posts 4 Posters 1.9k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Mummoc
    wrote on last edited by
    #1

    Hi everyone and happy new year to you all !!

    In my project i have a QTreeWidget filled with QTreeWidgetItems, each element of my tree has a checkbox (not the widget i just use the checkboxes of QTreeWidgetItem). And each toplevel item has one or several children.

    My question is can i disable a toplevel item without disabling it's children ? I want the toplevel item to be grayed out and non-clickable while still being able the see it's children and check/uncheck them.

    So far i can't seem to do that simply, adding a widget inside my QTreeWidgetItem and disabling that instead of the QTreeWidgetItem would work but seem like a hassle just for that. The other way would be to "simulate" the disable by catching keyboards/mouse events and changing the visuals manually but that also seems like a lot of work for not much.

    Thanks in advance for the reply :)

    1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi
      You should be able to change its flags for the parent item

      https://doc.qt.io/qt-5/qtreewidgetitem.html#flags

      https://doc.qt.io/qt-5/qtreewidgetitem.html#setFlags

      https://doc.qt.io/qt-5/qt.html#ItemFlag-enum

      1 Reply Last reply
      0
      • M Offline
        M Offline
        Mummoc
        wrote on last edited by
        #3

        First, thanks for the reply !
        I've already parsed the doc you linked times and times again and, unless i'm missing something, what you suggested was the first thing i tried, here's the constructor for my test project:

            this->setWindowTitle("QTreeWidget test");
        
            QTreeWidget* treeA = new QTreeWidget(this);
            treeA->setHeaderHidden(true);
        
            QTreeWidgetItem* parentItemA = new QTreeWidgetItem(treeA, QStringList(QString("parent 1")));
            QTreeWidgetItem* childItemA1 = new QTreeWidgetItem(parentItemA, QStringList(QString("child 1")));
            QTreeWidgetItem* childItemA2 = new QTreeWidgetItem(parentItemA, QStringList(QString("child 2")));
            QTreeWidgetItem* childItemA3 = new QTreeWidgetItem(childItemA1, QStringList(QString("child 3")));
            QTreeWidgetItem* childItemA4 = new QTreeWidgetItem(childItemA1, QStringList(QString("child 4")));
        
            QHBoxLayout* layout = new QHBoxLayout(this);
            layout->addWidget(treeA);
        
            childItemA1->setFlags(childItemA1->flags() & ~Qt::ItemIsEnabled);
        
            childItemA3->setFlags(childItemA3->flags() | Qt::ItemIsEnabled);
        

        It's simply a QTreeWidget filled with some QTreeWidgetItems. Here's the output :
        8139d436-c14b-42ec-ac5f-01d7f8a69c4f-image.png

        Child 1 is disabled but child 3 and 4 also are. I even manually re-set child 3's flag to IsEnabled to no avail.

        At this point i'm not sure if what i'm looking for is actually possible. It's not really important since i still managed to get the results i wanted but i would've preferred a cleaner solution.

        mrjjM JonBJ 2 Replies Last reply
        0
        • M Mummoc

          First, thanks for the reply !
          I've already parsed the doc you linked times and times again and, unless i'm missing something, what you suggested was the first thing i tried, here's the constructor for my test project:

              this->setWindowTitle("QTreeWidget test");
          
              QTreeWidget* treeA = new QTreeWidget(this);
              treeA->setHeaderHidden(true);
          
              QTreeWidgetItem* parentItemA = new QTreeWidgetItem(treeA, QStringList(QString("parent 1")));
              QTreeWidgetItem* childItemA1 = new QTreeWidgetItem(parentItemA, QStringList(QString("child 1")));
              QTreeWidgetItem* childItemA2 = new QTreeWidgetItem(parentItemA, QStringList(QString("child 2")));
              QTreeWidgetItem* childItemA3 = new QTreeWidgetItem(childItemA1, QStringList(QString("child 3")));
              QTreeWidgetItem* childItemA4 = new QTreeWidgetItem(childItemA1, QStringList(QString("child 4")));
          
              QHBoxLayout* layout = new QHBoxLayout(this);
              layout->addWidget(treeA);
          
              childItemA1->setFlags(childItemA1->flags() & ~Qt::ItemIsEnabled);
          
              childItemA3->setFlags(childItemA3->flags() | Qt::ItemIsEnabled);
          

          It's simply a QTreeWidget filled with some QTreeWidgetItems. Here's the output :
          8139d436-c14b-42ec-ac5f-01d7f8a69c4f-image.png

          Child 1 is disabled but child 3 and 4 also are. I even manually re-set child 3's flag to IsEnabled to no avail.

          At this point i'm not sure if what i'm looking for is actually possible. It's not really important since i still managed to get the results i wanted but i would've preferred a cleaner solution.

          mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by mrjj
          #4

          @Mummoc

          Hmm I must recall wrong and flags actually affect children also - to be "helpful" since in many cases it makes sense
          that if the parent is disabled, children are also.
          Sorry for the goose chase then :)

          Yep it does.

          void QTreeWidgetItem::setFlags(Qt::ItemFlags flags)
          {
              const bool enable = (flags & Qt::ItemIsEnabled);
              const bool changedState = bool(itemFlags & Qt::ItemIsEnabled) != enable;
              const bool changedExplicit = d->disabled != !enable;
              d->disabled = !enable;
              if (enable && par && !(par->itemFlags & Qt::ItemIsEnabled)) // inherit from parent
                  itemFlags = flags & ~Qt::ItemIsEnabled;
              else // this item is explicitly disabled or has no parent
                  itemFlags = flags;
              if (changedState && changedExplicit) { // if the propagate the change to the children
                  QStack<QTreeWidgetItem*> parents;
                  parents.push(this);
                  while (!parents.isEmpty()) {
                      QTreeWidgetItem *parent = parents.pop();
                      for (int i = 0; i < parent->children.count(); ++i) {
                          QTreeWidgetItem *child = parent->children.at(i);
                          if (!child->d->disabled) { // if not explicitly disabled
                              parents.push(child);
                              if (enable)
                                  child->itemFlags = child->itemFlags | Qt::ItemIsEnabled;
                              else
                                  child->itemFlags = child->itemFlags & ~Qt::ItemIsEnabled;
                              child->itemChanged(); // ### we may want to optimize this
                          }
                      }
                  }
              }
              itemChanged();
          }
          
          1 Reply Last reply
          0
          • M Mummoc

            First, thanks for the reply !
            I've already parsed the doc you linked times and times again and, unless i'm missing something, what you suggested was the first thing i tried, here's the constructor for my test project:

                this->setWindowTitle("QTreeWidget test");
            
                QTreeWidget* treeA = new QTreeWidget(this);
                treeA->setHeaderHidden(true);
            
                QTreeWidgetItem* parentItemA = new QTreeWidgetItem(treeA, QStringList(QString("parent 1")));
                QTreeWidgetItem* childItemA1 = new QTreeWidgetItem(parentItemA, QStringList(QString("child 1")));
                QTreeWidgetItem* childItemA2 = new QTreeWidgetItem(parentItemA, QStringList(QString("child 2")));
                QTreeWidgetItem* childItemA3 = new QTreeWidgetItem(childItemA1, QStringList(QString("child 3")));
                QTreeWidgetItem* childItemA4 = new QTreeWidgetItem(childItemA1, QStringList(QString("child 4")));
            
                QHBoxLayout* layout = new QHBoxLayout(this);
                layout->addWidget(treeA);
            
                childItemA1->setFlags(childItemA1->flags() & ~Qt::ItemIsEnabled);
            
                childItemA3->setFlags(childItemA3->flags() | Qt::ItemIsEnabled);
            

            It's simply a QTreeWidget filled with some QTreeWidgetItems. Here's the output :
            8139d436-c14b-42ec-ac5f-01d7f8a69c4f-image.png

            Child 1 is disabled but child 3 and 4 also are. I even manually re-set child 3's flag to IsEnabled to no avail.

            At this point i'm not sure if what i'm looking for is actually possible. It's not really important since i still managed to get the results i wanted but i would've preferred a cleaner solution.

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by
            #5

            @Mummoc
            Does it behave similarly if you try Qt::ItemIsSelectable in place of Qt::ItemIsEnabled?

            mrjjM 1 Reply Last reply
            1
            • JonBJ JonB

              @Mummoc
              Does it behave similarly if you try Qt::ItemIsSelectable in place of Qt::ItemIsEnabled?

              mrjjM Offline
              mrjjM Offline
              mrjj
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @JonB
              well
              childItemA1->setFlags(childItemA1->flags() & ~Qt::ItemIsSelectable);
              wont propagate but it dont look disabled.

              JonBJ 1 Reply Last reply
              0
              • mrjjM mrjj

                @JonB
                well
                childItemA1->setFlags(childItemA1->flags() & ~Qt::ItemIsSelectable);
                wont propagate but it dont look disabled.

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #7

                @mrjj
                True, but it's not selectable, which is at least what the OP asked for:

                I want the toplevel item to be grayed out and non-clickable

                1 Reply Last reply
                1
                • Christian EhrlicherC Offline
                  Christian EhrlicherC Offline
                  Christian Ehrlicher
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  QTreeWidget(Item) is a convenience model. If it does not suit for the usecase then you have to implement a model on your own.

                  Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                  Visit the Qt Academy at https://academy.qt.io/catalog

                  1 Reply Last reply
                  1
                  • M Offline
                    M Offline
                    Mummoc
                    wrote on last edited by Mummoc
                    #9

                    @Christian-Ehrlicher said in Disable toplevel item of QTreeWidget:

                    QTreeWidget(Item) is a convenience model. If it does not suit for the usecase then you have to implement a model on your own.

                    Yeah i feel that's what i'll have to do eventually. I recently picked up a project without much prior Qt experience, amongst many refactor i removed the QCheckBoxes inside the QTreeWidgetItems (to facilitate keyboard use with the tree since i didn't want to bother myself with keyboard events back then) and now i'll feel like i'll have to retrace back, oh well.

                    @mrjj

                    True, but it's not selectable, which is at least what the OP asked for:

                    My original issue was only a visual one since i already caught mouse and keyboard events to do what i want.

                    All in all thanks for your replies, what i wanted is in fact not possible so i'll have to find workarounds. Marking the post as solved.

                    JonBJ 1 Reply Last reply
                    0
                    • M Mummoc

                      @Christian-Ehrlicher said in Disable toplevel item of QTreeWidget:

                      QTreeWidget(Item) is a convenience model. If it does not suit for the usecase then you have to implement a model on your own.

                      Yeah i feel that's what i'll have to do eventually. I recently picked up a project without much prior Qt experience, amongst many refactor i removed the QCheckBoxes inside the QTreeWidgetItems (to facilitate keyboard use with the tree since i didn't want to bother myself with keyboard events back then) and now i'll feel like i'll have to retrace back, oh well.

                      @mrjj

                      True, but it's not selectable, which is at least what the OP asked for:

                      My original issue was only a visual one since i already caught mouse and keyboard events to do what i want.

                      All in all thanks for your replies, what i wanted is in fact not possible so i'll have to find workarounds. Marking the post as solved.

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by JonB
                      #10

                      @Mummoc
                      Yes, I believe what we are saying is: disabling a QTreeWidgetItem means disabling its descendants, which seems pretty reasonable. It is therefore not possible to have descendants which are themselves enabled.

                      That's why I suggested all you can use would be selectability (Qt::ItemIsSelectable) as that is allowed to vary such that a parent may be unselectable itself while a descendant is still selectable.

                      M 1 Reply Last reply
                      0
                      • JonBJ JonB

                        @Mummoc
                        Yes, I believe what we are saying is: disabling a QTreeWidgetItem means disabling its descendants, which seems pretty reasonable. It is therefore not possible to have descendants which are themselves enabled.

                        That's why I suggested all you can use would be selectability (Qt::ItemIsSelectable) as that is allowed to vary such that a parent may be unselectable itself while a descendant is still selectable.

                        M Offline
                        M Offline
                        Mummoc
                        wrote on last edited by
                        #11

                        @JonB

                        Yes, I believe what we are saying is: disabling a QTreeWidgetItem means disabling its descendants, which seems pretty reasonable. It is therefore not possible to have descendants which are themselves enabled.

                        Yes this seems pretty reasonable and expected as a behavior.

                        That's why I suggested all you can use would be selectability (Qt::ItemIsSelectable) as that is allowed to vary such that a parent may be unselectable itself while a descendant is still selectable.

                        I was already playing with this flag (and overriding mouse and keyboards events) for various reasons so my original problem was solely a visual one, so to simulate the graying i used QTreeWidgetItem->setForeground() with a gray color.
                        So far it does what i need (the checkbox of my QTreeWidgetItem isn't grayed out but this detail is so minor that i'm not bothering with that). So i'm calling it quit now.

                        1 Reply Last reply
                        1

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved