QTreeView Checkboxes

22,655

Solution 1

Firstly, you'll need to modify TreeItem to keep track of the checked state:

private:
    ...
    bool checked;

and a setter and getter:

bool isChecked() const { return checked; }
void setChecked( bool set ) { checked = set; }

Now the model will need to be modified so that the view knows about the check state:

QVariant TreeModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());

    if ( role == Qt::CheckStateRole && index.column() == 0 )
        return static_cast< int >( item->isChecked() ? Qt::Checked : Qt::Unchecked );

    if (role != Qt::DisplayRole)
        return QVariant();

    return item->data(index.column());
}

and modify the model's flags method to let views know that the model contains checkable items:

Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return 0;

    Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;

    if ( index.column() == 0 )
        flags |= Qt::ItemIsUserCheckable;

    return flags;
}

I think this should do it. If you want to be able to update the TreeItem check state when the user ticks and unpicks the items, then you'll need to provide the QAbstractItemModel::setData method in your TreeModel.

Solution 2

I converted the above to PyQt for my own purposes and figured I'd share.

def data(self, index, role):
    if not index.isValid():
        return None

    item = index.internalPointer();

    if role == Qt.CheckStateRole and index.column() == self.check_col:
        return int( Qt.Checked if item.isChecked() else Qt.Unchecked )

    return super(TreeModel, self).data(index, role)


def flags(self, index):
    if not index.isValid():
        return None

    if index.column() == self.check_col:
        flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsUserCheckable
    else:
        flags = super(TreeModel, self).flags(index)

    return flags


def setData(self, index, value, role=Qt.EditRole):
    if index.column() == self.check_col:
        if role == Qt.EditRole:
            return False
        if role == Qt.CheckStateRole:
            item = self.getItem(index)
            item.setChecked(value)
            self.dataChanged.emit(index, index)
            return True

    return super(TreeModel, self).setData(index, value, role)

Solution 3

Here is another PyQt complete woking example using QStandardItemModel:

model = QStandardItemModel()
parent_item = model.invisibleRootItem()  # type: QStandardItem
for row in [
    (Qt.Unchecked, 'unchecked'),
    (Qt.PartiallyChecked, 'partially'),
    (Qt.Checked, 'checked')
]:
    checked, text = row
    check_item = QStandardItem('')
    check_item.setCheckable(True)
    check_item.setCheckState(checked)
    parent_item.appendRow([check_item, QStandardItem(text)])
treeview.setModel(model)

Btw, this should also work for any C++ applications.

Share:
22,655
Drise
Author by

Drise

I am a career C++/Qt developer, with a passion for Python programming. I recently have added C# to my experience set, and have developed full stack C# applications using WPF and Xamarin.Forms. I am an Agile advocate and Scrum leader along with a Clean Code zealot. Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.

Updated on September 04, 2020

Comments

  • Drise
    Drise over 3 years

    I know this has been asked a bunch of times, but I cant seem to find anything relevant.

    Using the simpletreemodel tutorial that comes packaged with Qt, how would I add checkboxes?

  • Drise
    Drise over 12 years
    Very Cool! Exactly what I was looking for. However I found out that I should have been using the TreeWidget for what I'm trying to build. Thank you so much for the post however.
  • eMPee584
    eMPee584 almost 11 years
    Not that I could propose a better solution atm, but the boolean lacks the awesome TRISTATENESS of course. (f.e. for partly-selected folders)
  • atomSmasher
    atomSmasher about 8 years
    Old thread but is there any chance you could share the whole class?
  • Alexey Markov
    Alexey Markov about 3 years
    Very old thread, but there is an example of SimpleTreeModel for PyQt: gist.github.com/zhanglongqi/6994c2bc611bacb4c68f