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.
  • 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 Online
          JonBJ Online
          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 Online
              JonBJ Online
              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 Online
                    JonBJ Online
                    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