QTreeView and Qt::ItemIsAutoTristate
-
I've spent a while now, faffing with the
QTreeViewand theQt::ItemIsAutoTristateflag to try and get parent/child tree items to check/uncheck/partially check where applicable.Can anyone point me towards a working solution for this, please?
I have a mostly-working
QAbstractItemModelimplementation (code base is too large to post) however, the final piece to the puzzle is getting these checkboxes to work in a tri-state fashion.Things I have done so far in the custom
QAbstractItemModelclass:- ORed in the
Qt::ItemIsAutoTristateflag together with theQt::ItemIsUserCheckableflag in theflagsfunction - Overridden the
hasChildrenfunction, returningtrue/falsewhere applicable - Overridden the
datafunction and return the correctQt::CheckStatevalue
I've now run out of ideas. Googling doesn't prove to be particularly useful either.
Any help would be mahoosively appreciated! Thanks.
- ORed in the
-
@VRonin thanks for replying.
I'm currently running Qt 5.10.1 however there is no reason why I cannot change to the latest.
I am subclassing the
modelto satisfy other needs.At the moment,
dataChangedonly emits two arguments however I see no reason why I could not emit a third argument. What would the 3rd argument be useful for? -
So please provide a simple testcase - a simple data() and setData() function with only the checkbox stuff will help to see what's going wrong. It does work for me.
-
@Christian-Ehrlicher Are you using a
QTreeViewor aQTreeWidget?Since I posted this question, I did a bit of digging around the
qtreeview.cppsource files and there was little mention of anythingcheckboxortristaterelated so I'm actually wondering whether this auto-tristate feature is supported out-the-box.I'll try and post some code shortly...
-
I don't see why QTreeView should somehow mention the QCheckBox at all. The only this QTreeView has to do (and which is done in QAbstractItemView) is to properly pas the Qt::CheckState role to the delegate and handle the click.
-
@Christian-Ehrlicher sorry, maybe I should have said that there was no mention of
CheckStaterather thancheckboxas I appreciate that theQTreeViewwould not need any reference to this. -
Ok, so I've taken the
editabletreemodelexample project and I've made the following changes to support checkboxes:treeitem.h:- Added a
Qt::CheckState checkedfield to theprivatemembers - Changed the
datafunction signature toQVariant data(int column, int role) const - Changed the
setDatafunction signature tobool setData(int column, const QVariant &value, int role)
treeitem.cpp:- Altered the
dataandsetDatafunctions as follows:
QVariant TreeItem::data(int column, int role) const { if (role == Qt::CheckStateRole) { if (column == 0) { return checked; } else { return QVariant(); } } return itemData.value(column); } bool TreeItem::setData(int column, const QVariant &value, int role) { if (column < 0 || column >= itemData.size()) return false; if ((column == 0) && (role == Qt::CheckStateRole)) { checked = (Qt::CheckState)value.toUInt(); return true; } itemData[column] = value; return true; }treemodel.cpp:- Updated all references to
dataorsetData, adding in theroleparameter except insetupModelDatawhereQt::EditRoleis passed as the 3rd argument - Altered the
flags,dataandsetDatafunctions as follows:
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const { if (!index.isValid()) return 0; return Qt::ItemIsEditable | QAbstractItemModel::flags(index) | Qt::ItemIsUserCheckable | Qt::ItemIsAutoTristate; } QVariant TreeModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); if (role != Qt::DisplayRole && role != Qt::EditRole && role != Qt::CheckStateRole) return QVariant(); TreeItem *item = getItem(index); return item->data(index.column(), role); } bool TreeModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (role != Qt::EditRole && role != Qt::CheckStateRole) return false; TreeItem *item = getItem(index); bool result = item->setData(index.column(), value, role); if (result) emit dataChanged(index, index, {role}); return result; }When I run the example, I can happily check/uncheck items in the
QTreeViewhowever, the tristate-ness is not propagated. - Added a
-
A checkbox can either be checked or unchecked. A tri-state state can only happen programatically e.g. when the children are checked and unchecked therefore the default delegate only supports checked/unchecked. The tri-state has to be calculated by the model. See for example the implementation in QTreeWidget: https://code.woboq.org/qt5/qtbase/src/widgets/itemviews/qtreewidget.cpp.html#1840
-
@Christian-Ehrlicher Ah ok, so it must be implemented programmatically.