QStandardItem and default data role
-
My app uses mostly
QSql...Modelmodels but also someQStandardItemModels.Whether I like the approach or not, I have gotten used to the SQL stuff where, coming from
QAbstractItemModel, they all use:QVariant QAbstractItemModel::data(const QModelIndex &index, int role = Qt::DisplayRole) const bool QAbstractItemModel::setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole)i.e. the default roles for
data()/setData()areDisplayRole/EditRolerespectively.While refactoring other people's code, to my surprise I found that in the case of
QStandardItemModelit sticks to that, BUT forQStandardItemQVariant QStandardItem::data(int role = Qt::UserRole + 1) const void QStandardItem::setData(const QVariant &value, int role = Qt::UserRole + 1)i.e. both use a default of
Qt::UserRole + 1.Correct me if I'm wrong, because my brain is beginning to hurt here, but this means that:
standardItemModel.data(standardItemModel.index(row, col)) != standardItemModel.item(row, col).data()i.e.
QStandardItemModel::data()/setData()use different default roles fromQStandardItem::data()/setData(). With the code I am looking at mixing these two legitimate ways of addressingQStandardItemitems it's getting very hairy... :(What's going on here? This is a really bad idea :( Why is
QStandardItemdefaulting differently from everything else, is it just to confuse me? -
Because QStandardItemModel + QStandardItem is a convenience class and already provides access to Qt::DisplayRole and others via custom functions (setFont, setIcon, setText, setToolTip). There is no need to use QStandardItemModel::data() at all.
-
Because QStandardItemModel + QStandardItem is a convenience class and already provides access to Qt::DisplayRole and others via custom functions (setFont, setIcon, setText, setToolTip). There is no need to use QStandardItemModel::data() at all.
@Christian-Ehrlicher
Before I comment on what the problems are, did you mis-type:There is no need to use QStandardItemModel::data() at all.
Did you mean
QStandardItem:data()instead ofQStandardItemModel::data()? Or what? -
@JonB: It's from QAbstractItemModel::data().
-
@JonB: It's from QAbstractItemModel::data().
@Christian-Ehrlicher
I do not understand what you are talking about now. (Btw, yes, I know what is derived from what.) As I have said, there are two ways at getting at a standard model items' data:1. standardItemModel.data(standardItemModel.index(row, col)) 2. standardItemModel.item(row, col).data()The first is going via
QStandardItemModel, the second viaQStandardItem. Agreed? And you would assume they both return the same result, agreed? Well, they don't, because of the default role difference. -
@JonB said in QStandardItem and default data role:
And you would assume they both return the same result, agreed?
No, I don't agree here.
Since QStandardItemModel is a convenience class you should also stick at the convenience way on accessing the data via the QStandardModelItem and it's functions I wrote above. -
@JonB said in QStandardItem and default data role:
And you would assume they both return the same result, agreed?
No, I don't agree here.
Since QStandardItemModel is a convenience class you should also stick at the convenience way on accessing the data via the QStandardModelItem and it's functions I wrote above.@Christian-Ehrlicher
Right then.First of all I'm not interested in any of
setFont,setIcon,setToolTip. What I am interested in is the different data which can be stored/returned viasetData/data()using the two rolesDisplayRolevsEditRole.And second, it's all very well saying what one "should stick at", but I am talking about reviewing code written by someone else. When storing/retrieving data in a
QStandardItemModel, that person has sometimes usedQStandardItemModel::set/Data()directly and sometimes usedQStandardItemModel::item(...).set/Data(). Both of those address the sameQStandardItemin the model. You (I) would have thought they would set/return the same value. But they do not, because of the difference in the default roles between the two seemingly-identical approaches. So the code I'm reviewing is not right. :( Which is what I am whinging about. -
Yes, relying on the default value isn't that good sometimes... even in the qt module tests there were some issues with the default role which only came up after a change in the convenience QTable/Tree/ListWidget classes to publish the modified roles instead no roles (3rd argument in dataChanged())
-
Don't know if this works in Python but I C++ I would derive from QStandardItemModel, make data() private and replace all occurrences of QStandardItemModel with the new class. Then I would get a compiler warning as soon as DerivedClass::data() is called.
-
Don't know if this works in Python but I C++ I would derive from QStandardItemModel, make data() private and replace all occurrences of QStandardItemModel with the new class. Then I would get a compiler warning as soon as DerivedClass::data() is called.
make data() private
Nope, this is Python! Everything is public. Even if it's private it's still public. Unless Qt chose to rename the
data/setData()methods to__data()/__setData(). And even then they'd still be public really.Then I would get a compiler warning as soon as DerivedClass::data() is called.
This is Python, don't make me laugh ;-) Compiler? Warning?
:)
-
Don't know if this works in Python but I C++ I would derive from QStandardItemModel, make data() private and replace all occurrences of QStandardItemModel with the new class. Then I would get a compiler warning as soon as DerivedClass::data() is called.
@Christian-Ehrlicher
But here's what I don't get even if I tried to adopt what you say. Again, please correct me if I'm wrong.All these models are heavily used by the code from
QTableViews etc. The whole point is that uses thedata()/setData()methods (with defaultsDisplayRole/EditRole). So surely if you hide those two methods with privacy you won't be able to use your derived class from table views, no?Apparently unlike you, I do not see the problem in
QStandardItemModel::data()'s behaviour. I see the problem in the non-consistentQStandardItem::data()'s behaviour. I'm not sure whether that is getting across.In the code, at line #10 data is being set via
standardItemModel.setData(standardItemModel.index(0, 0), foo)Then at line #10,000 data is being read back from the same item via
bar = standardItemModel.item(0, 0).data()I expect
foo&barto be the same value. But they are not. -
@JonB said in QStandardItem and default data role:
But they are not.
Correct, because you're mixing the convenience class with the underlying QAIM.
--> standardItemModel.item(0,0)->setData(foo) is what you want if you want to use QStandardItemModel::data() without a parameter.
Or, as I said before - don't rely on default parameters at all. -
@JonB said in QStandardItem and default data role:
But they are not.
Correct, because you're mixing the convenience class with the underlying QAIM.
--> standardItemModel.item(0,0)->setData(foo) is what you want if you want to use QStandardItemModel::data() without a parameter.
Or, as I said before - don't rely on default parameters at all.@Christian-Ehrlicher
No! Unless yet again we are misunderstanding each other :)Let's be clear:
foowas my data value, not a role. Then quoting from what you have just written:standardItemModel.item(0,0)->setData(foo)This is using
QStandardItemModel::item()::setData().QStandardItemModel::item()is aQStandardItem.QStandardItem::setData()has default parameterint role = Qt::UserRole + 1.QStandardItemModel::data()This is using
QStandardItemModel::data()(notQStandardItem::data()), which has default parameterint role = Qt::DisplayRole.For consistency --- and assuming you are not passing any role explicitly --- one must either stick to doing data operations via paired
QStandardItemModel::set/Data(index(0, 0))or via pairedQStandardItemModel::item(0, 0)::set/Data(). Your example just broke that consistency, it's using one of each! The code I am looking at (not written by me, who now knows better) has equally broken that consistent pairing, and so is wrong. Hence I am now spending hours tracking down precisely where current code accesses data directly offQStandardItemModelvs viaQStandardItemModel::item().My original question was: to avoid just this, why [there must be a reason] does
QStandardItem::set/Data()useUserRole+1, instead ofDisplayRole/EditRoleas the respective role defaults just like sayQStandardItemModel::set/Data()does and same for other models? Then I wouldn't be crying in a bath over this.... -
QStandardItemModel is a convenience function which should be filled with QStandardItem::data()/setData(). If you mix it with QAbstractItemView::setData() then you also should use the corresponding QAIV::data() function.