QCheckBox's not changing state?



  • Does anyone see anything wrong w/ how I'm changing the states of my QCheckBox's, rather, how they're not changing? My checkboxes appear checked, but I am unable to change them to unchecked.

    QVariant MyTreeModel::data(const QModelIndex &index, int role) const
    {
        QModelIndex parent = index.parent();
        QModelIndex child = index.sibling(parent.row(), parent.column());
    
        if (!index.isValid())
            return QVariant();
    
        MyTreeItem *item = static_cast<MyTreeItem *>(index.internalPointer());
    
        if (role == Qt::CheckStateRole) {
            if (parent.row() == 0 && index.column() == 0)
                return static_cast<int>(item->getChecked() ? Qt::Checked :
                    Qt::Unchecked);
        }
    
        if (role != Qt::DisplayRole) 
            return QVariant();
    
        return item->data(index.column());
    }
    
    bool MyTreeModel::setData(const QModelIndex &index,
        const QVariant &value, int role)
    {
        QModelIndex parent = index.parent();
    
        if (role != Qt::EditRole && role != Qt::CheckStateRole)
            return false;
    
        MyTreeItem *item = getItem(index);
    
        bool result;
    
        if (role == Qt::CheckStateRole) {
            if (parent.row() == 0 && index.column() == 0) {
                bool chk = (item->getChecked() ? Qt::Unchecked : Qt::Checked);
    
                item->setChecked(chk);
    
                result = item->setData(index.column(), chk);
            }
        }
        else
            result = item->setData(index.column(), value);
    
        if (result)
            emit dataChanged(index, index, {role});
    
        return result;
    }


  • @SRaD
    I have no idea whether it has any relevance to your problem. But in setData() how is result set to anything if it's CheckStateRole and you are not on row == column == 0? Do you not get a compiler warning for "possibly uninitialized variable used"?


  • Qt Champions 2018

    Is MyTreeItem derived from QTreeWidgetItem? If so I don't see a need to reimplement setData() at all.



  • No. MyTreeItem is just a class. I used the example just like TreeItem from here ... https://doc.qt.io/qt-5/qtwidgets-itemviews-editabletreemodel-example.html

    And the model is derived from QAbstractItemModel.



  • @SRaD
    OK, apart from what I said before which I think you ought address, your logic in your setData() is wrong in the role == Qt::CheckStateRole && parent.row() == 0 && index.column() == 0 case.

                bool chk = (item->getChecked() ? Qt::Unchecked : Qt::Checked);
    
                item->setChecked(chk);
    
                result = item->setData(index.column(), chk);
    

    You set the chk you'll use as a reverse of the current item->getChecked(), i.e. it toggles each time it's called; and you pass that on to setChecked/setData(). But you're supposed to be using the value parameter to your setData(), which you're ignoring here, like you do in the else result = item->setData(index.column(), value); case. Your current checked/unchecked behaviour depends on how many times setData() happens to be called, or that it will only get called when it's time to toggle the check, both of which are quite wrong.



  • @JonB
    So I changed the logic to this, but I find that setData() isn't being called. The checkboxes do show up, so my model is in place, but I don't understand why this isn't called when I click on the items.

    bool MyTreeModel::setData(const QModelIndex &index,
    const QVariant &value, int role)
    {           
        QModelIndex parent = index.parent();
    
        std::cout << "value.toInt = " << value.toInt() << std::endl;
    
        if (role != Qt::EditRole && role != Qt::CheckStateRole)
            return false;
            
        MyTreeItem *item = getItem(index);
        
        bool result;
    
        if (role == Qt::CheckStateRole && (parent.row() == 0 && 
                index.column() == 0)) {
        
            Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
        
            // logic probably still isn't correct here, but i'm concerned with why it's not called
            bool check = (state == Qt::Checked);
            //item->setChecked(chk);
         
            result = item->setData(index.column(), check);
        }
        else  
            result = item->setData(index.column(), value);                         
                                                                               
        if (result)
            emit dataChanged(index, index, {role});                                
    
        return result;
    }

  • Qt Champions 2018

    What does your item->getChecked() look like?
    And do you really store try to store the check state and the edit role in one place?
    --> item->setData(index.column(), check);



  • @Christian-Ehrlicher
    My getChecked looks like the following:

    bool MyTreeItem::getChecked() const
    {
        return checked;
    }       
    
    void MyTreeItem::setChecked(bool set)
    {       
        checked = set;; 
    }
    

    Not sure about edit role && check state in one place. I thought if it was a checkbox, it had to be editable, and I thought setChecked() is where I needed to store it.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.