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. How to add QCheckBox to column and make model appear in QTreeView.
QtWS25 Last Chance

How to add QCheckBox to column and make model appear in QTreeView.

Scheduled Pinned Locked Moved Unsolved General and Desktop
modelviewitemmodelcheckbox
6 Posts 3 Posters 3.1k Views
  • 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.
  • S Offline
    S Offline
    SRaD
    wrote on 26 Jan 2019, 19:16 last edited by SRaD
    #1

    I'm using Qt 5.12. I'm trying to create a custom model as opposed to custom views and delegates for reason like keeping my applications data in the model and not having to sync it externally.

    My goal is to have a tree like the following where I can add checkboxes to only specific child nodes.

    Column 1               Column 2
    
    `- Root
       |- System1
       |   |- subsystem1   checkbox
       |   `- subsystem2   checkbox
       `- System2
           |- subsystem3   
           `- subsystem4    
    

    Aside from not knowing how to get the checkbox to appear. the problem I'm having is that the model is not showing up in my QTreeView. The view is empty.

    MyTreeModel header:

    class MyTreeModel : public QAbstractItemModel
    {
        Q_OBJECT
    
        private:
            QObject *root_item;
    
        public:
            explicit MyTreeModel(QObject *, QObject *parent = 0);
    
            Qt::ItemFlags flags(const QModelIndex &index) const;
            QVariant data(const QModelIndex &index, int role) const;
            QVariant headerData(int section, Qt::Orientation orientation,
                int role = Qt::DisplayRole) const;
            QModelIndex index(int row, int column, const QModelIndex &parent =
                QModelIndex()) const;
            int columnCount(const QModelIndex &parent = QModelIndex()) const;
            int rowCount(const QModelIndex &parent = QModelIndex()) const;
            QModelIndex parent(const QModelIndex &index) const;
    };
    

    MyTreeModel source:

    MyTreeModel::MyTreeModel(QObject *obj, QObject *parent) :
        QAbstractItemModel(parent)
    {
        root_item = obj;
    }
    
    Qt::ItemFlags MyTreeModel::flags(const QModelIndex &index) const
    {
        if (!index.isValid())
            return Qt::ItemIsEnabled;
    
        return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
    }
    
    QVariant MyTreeModel::data(const QModelIndex &index, int role) const
    { 
        if (!index.isValid())
            return QVariant();
    
        if (role == Qt::DisplayRole) {
            switch (index.column()) {
                case 0:
                    return static_cast<QObject *>
                        (index.internalPointer())->objectName();
    
                case 1:
                    return static_cast<QObject *>
                        (index.internalPointer())->metaObject()->className();
    
                default:
                    break;
            }
        }
        else if (role == Qt::ToolTipRole) {
            // ...
        }
    
        return QVariant();
    }
    
    QVariant MyTreeModel::headerData(int section, Qt::Orientation orient,
        int role) const
    {
        if (role != Qt::DisplayRole || orient != Qt::Horizontal)
            return QVariant();
    
        switch (section)
        {
            case 0:
                return QString("object");
    
            case 1:
                return QString("class");
    
            default:
                return QVariant();
        }
    }
    
    QModelIndex MyTreeModel::index(int row, int column,
        const QModelIndex &parent) const
    {
        QObject *parentObject;
    
        if (!parent.isValid())
            parentObject = root_item;
        else
            parentObject = static_cast<QObject *>(parent.internalPointer());
    
        if (row >= 0 && row < parentObject->children().count())
            return createIndex(row, column, parentObject->children().at(row));
        else
            return QModelIndex();
    }
    
    int MyTreeModel::columnCount(const QModelIndex &parent) const
    {
        return 2;
    }
    
    int MyTreeModel::rowCount(const QModelIndex &parent) const
    {
        QObject *parentObject;
    
        if (!parent.isValid())
            parentObject = root_item;
        else
            parentObject = static_cast<QObject *>(parent.internalPointer());
    
        return parentObject->children().count();
    }
    
    QModelIndex MyTreeModel::parent(const QModelIndex &index) const
    {
        if (!index.isValid())
            return QModelIndex();
    
        QObject *indexObject = static_cast<QObject*>(index.internalPointer());
        QObject *parentObject = indexObject->parent();
    
        if (parentObject == root_item)
            return QModelIndex();
    
        QObject *grandParentObject = parentObject->parent();
    
        return createIndex(grandParentObject->children().indexOf(parentObject),
        0, parentObject);
    }           
    

    And I have this is my MainWindow constructor ...

    QObject root;
    QObject *subsys;
    
    root.setObjectName("Root");
        
    QObject *sys1 = new QObject(&root);
    sys1->setObjectName("System1");
    subsys = new QObject(sys1);
    subsys->setObjectName("subsystem1");
    subsys = new QObject(sys1);
    subsys->setObjectName("subsystem2");
    
    QObject *sys2 = new QObject(&root);
    bar->setObjectName("System2");
    subsys = new QObject(sys2);
    subsys->setObjectName("subsystem3");
    subsys = new QObject(sys2);
    subsys->setObjectName("subsystem4");
    
    MyTreeModel tree_model(&root);
    
    tree_view = new MyTreeView;
    tree_view->setModel(&tree_model);
                           
    projectLayout->addWidget(tree_view);    
    

    Any help appreciated.

    1 Reply Last reply
    0
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on 26 Jan 2019, 20:51 last edited by
      #2

      Your flags() reimplementation must return Qt::ItemIsUserCheckable and data() must return the desired checkState for Qt::CheckStateRole

      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
      2
      • S Offline
        S Offline
        SRaD
        wrote on 3 Feb 2019, 19:56 last edited by
        #3

        Still having issues with this. I initiate my tree as such ...

        MyTreeItem *root_item = new MyTreeItem;
        MyTreeModel tree_model(root_item);
        
        tree_view = new MyTreeView;
        tree_view->setModel(&tree_model);
        
        // ...
        
        projectLayout->addWidget(tree_view);
        

        Then I load a file and build the tree dynamically using ...

        {
            QString mps = QString::fromStdString("Root Item");
                                                                                   
            MyTreeItem* mp_item = model->get_root_item();
            mp_item->setObjectName(mps);
        
            for (auto& i : myList) {
                QString str = QString::fromStdString(m.get_text());
                                                                                   
                MyTreeItem *item = new MyTreeItem(mp_item);
                item->setObjectName(str);
            }
        }
        

        My problem is that I can't see anything loading in my view. The following is MyTreeModel.

        MyTreeModel::MyTreeModel(MyTreeItem *item, QObject *parent) :
            QAbstractItemModel(parent)
        {
            root_item = item;
        }
        
        MyTreeModel::~MyTreeModel()  
        {
            delete root_item;
        }
        
        Qt::ItemFlags MyTreeModel::flags(const QModelIndex &index) const
        {
            if (!index.isValid())
                return Qt::ItemIsEnabled;
        
            Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsEditable;
        
            if (index.column() == 1)
                flags | Qt::ItemIsUserCheckable;
        
            return flags;
        }
        
        QVariant MyTreeModel::data(const QModelIndex &index, int role) const
        {
            if (!index.isValid())
                return QVariant();
        
            MyTreeItem *mti = static_cast<MyTreeItem*>
                (index.internalPointer());
        
            if (role == Qt::CheckStateRole && index.column() == 1) {
                return static_cast<int>(mti->isChecked() ? Qt::Checked :
                    Qt::Unchecked);
            }
        
            if (role != Qt::DisplayRole && role != Qt::EditRole)
                return QVariant();
        
            MyTreeItem *item = getItem(index);
        
            return item->data(index.column());
        }
        
        QVariant MyTreeModel::headerData(int section, Qt::Orientation orient,
            int role) const
        {
            if (role != Qt::DisplayRole || orient != Qt::Horizontal)
                return QVariant();
        
            switch (section)
            {
                case 0:
                    return QString("Object");
        
                case 1:
                    return QString("Class");
        
                default:
                    return QVariant();
            }
        }
        
        QModelIndex MyTreeModel::index(int row, int column, 
            const QModelIndex &parent) const
        {
            MyTreeItem *parentObject;
        
            if (!parent.isValid())
                parentObject = root_item;
            else
                parentObject = static_cast<MyTreeItem *>(parent.internalPointer());
        
            if (row >= 0 && row < parentObject->children().count())
                return createIndex(row, column, parentObject->children().at(row));
            else
                return QModelIndex();
        }
        
        int MyTreeModel::columnCount(const QModelIndex &parent) const
        {
            return 2;
        }
        
        int MyTreeModel::rowCount(const QModelIndex &parent) const
        {
            MyTreeItem *parentObject;
        
            if (!parent.isValid())
                parentObject = root_item;
            else
                parentObject = static_cast<MyTreeItem *>(parent.internalPointer());
        
            return parentObject->children().count();
        }
        
        QModelIndex MyTreeModel::parent(const QModelIndex &index) const
        {
            if (!index.isValid())
                return QModelIndex();
        
            QObject *indexObject = static_cast<QObject*>(index.internalPointer());
            QObject *parentObject = indexObject->parent();
        
            if (parentObject == root_item)
                return QModelIndex();
        
            QObject *grandParentObject = parentObject->parent();
        
            return createIndex(grandParentObject->children().indexOf(parentObject),
                0, parentObject);
        }
        
        MyTreeItem* MyTreeModel::getItem(const QModelIndex &index) const
        {
            if (index.isValid()) {
                MyTreeItem *item = static_cast<MyTreeItem*>
                    (index.internalPointer());
        
                if (item)
                    return item;
            }
        
            return root_item;
        }
        
        MyTreeItem* MyTreeModel::get_root_item() {
            return root_item;
        }
        
        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on 3 Feb 2019, 21:15 last edited by
          #4

          Hi,

          @SRaD said in How to add QCheckBox to column and make model appear in QTreeView.:

          MyTreeModel tree_model(&root);

          tree_view = new MyTreeView;
          tree_view->setModel(&tree_model);

          tree_model is a local variable, it will be destroyed at the end of the method and thus your tree view won't have any data to show.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          1
          • S Offline
            S Offline
            SRaD
            wrote on 3 Feb 2019, 22:21 last edited by SRaD 2 Mar 2019, 22:27
            #5

            Thanks for catching that, however, I'm still not seeing any items. I am however seeing the headers get filled in now so at least something of it is working.

            After loading a file and dynamically creating new MyTreeItems, do I need to do anything to "reload" or refresh the view to get it to appear?

            Specifically, here's the piece of code that creates the items, but by this time, I've already called tree_view->setModel, which was called in the main window constructor..

            {
                QString mps = QString::fromStdString("Root Item");
                                                                                       
                MyTreeItem* mp_item = model->get_root_item();
                mp_item->setObjectName(mps);
            
                for (auto& i : myList) {
                    QString str = QString::fromStdString(m.get_text());
                                                                                       
                    MyTreeItem *item = new MyTreeItem(mp_item);
                    item->setObjectName(str);
                }
            }
            
            1 Reply Last reply
            0
            • Christian EhrlicherC Offline
              Christian EhrlicherC Offline
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on 4 Feb 2019, 05:55 last edited by Christian Ehrlicher 2 Apr 2019, 05:58
              #6

              I'm sorry but I don't think will compile.
              Please provide a minimal, compilable example which shows your problem. E.g

              int main (int argc, char **argv)
              {
                QApplication app(argc, argv);
                QTreeWidget treeWidget;
                QTreeWidgetItem *cities = new QTreeWidgetItem(&treeWidget);
                cities->setText(0, "Cities");
                treeWidget.show();
                return app.exec();
              }
              

              See http://doc.qt.io/qt-5/qtreewidgetitem.html#details

              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
              0

              • Login

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