Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QTreeView Checkboxes

Tags:

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?

like image 492
Drise Avatar asked Nov 17 '11 22:11

Drise


3 Answers

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.

like image 169
JediLlama Avatar answered Sep 20 '22 21:09

JediLlama


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)
like image 33
taynaron Avatar answered Sep 21 '22 21:09

taynaron


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.

like image 1
Sebastian Wagner Avatar answered Sep 23 '22 21:09

Sebastian Wagner