QStandardItem and default data role
-
My app uses mostly
QSql...Model
models but also someQStandardItemModel
s.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
/EditRole
respectively.While refactoring other people's code, to my surprise I found that in the case of
QStandardItemModel
it sticks to that, BUT forQStandardItem
QVariant 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 addressingQStandardItem
items it's getting very hairy... :(What's going on here? This is a really bad idea :( Why is
QStandardItem
defaulting 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 rolesDisplayRole
vsEditRole
.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 sameQStandardItem
in 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
QTableView
s 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
&bar
to 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:
foo
was 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 offQStandardItemModel
vs viaQStandardItemModel::item()
.My original question was: to avoid just this, why [there must be a reason] does
QStandardItem::set/Data()
useUserRole+1
, instead ofDisplayRole/EditRole
as 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.