QAbstractListModel with base and derived class
-
Hi,
class A {}; class B : public A {};I implemented a
QAbstractListModelforA. Now I need one forB.QVariant ClassBListModel::data(const QModelIndex& index, int role) const { // There is no data in the root element if (!index.isValid()) { return QVariant(); } QVariant classAProperty = ClassAListModel::data(index,role); // Retrieved base property, return it if (!classAProperty .isNull()) { return baseProperty; } // Requested role is part of classB property switch (role) { case ClassBRole1: { return QVariant::fromValue<QString>(m_data[index.row()]->classBRole1()); break; } } }This is the approach I came up with. It's pretty simple. I just want to make sure it's qt-esque. Or is there another approach particularly designed for my needs?
-
I think I will go for the following approach:
BaseListModelimplementsprotected: QList<BaseClass*> m_dataAswell as all needed functions to work on the
BaseClass.
When needed, I will implement theDerivedListModeland all necessary functions. Calling theBaseListModelfunctionssetData,data,delete... and what not accordingly.
Theinsertimplementation will only be used by the lowest implementation of theListModelin the inheritance chain.
Byqobject_casting accordingly this approach should be fine. Decisively for this to work will be the correct usage ofinsert.Did I overlook anything?
-
Hi,
class A {}; class B : public A {};I implemented a
QAbstractListModelforA. Now I need one forB.QVariant ClassBListModel::data(const QModelIndex& index, int role) const { // There is no data in the root element if (!index.isValid()) { return QVariant(); } QVariant classAProperty = ClassAListModel::data(index,role); // Retrieved base property, return it if (!classAProperty .isNull()) { return baseProperty; } // Requested role is part of classB property switch (role) { case ClassBRole1: { return QVariant::fromValue<QString>(m_data[index.row()]->classBRole1()); break; } } }This is the approach I came up with. It's pretty simple. I just want to make sure it's qt-esque. Or is there another approach particularly designed for my needs?
@Redman
Hmm. A couple of comments.In your
m_data[index.row()]->classBRole1(), is them_dataa member ofclass Bor is it a (publicly exported) member of the baseclass A?If you are going distinguish by role whether data belongs to
class Aorclass Bthen I would suggest changing the order of your testing:switch (role) { case ClassBRole1: return m_data[index.row()]->classBRole1(); default: break; } return ClassAListModel::data(index,role);This would avoid doing two data lookups and would allow for a genuine null value in either case.
As your code stands, I wonder how you would intend to deal with
ClassBListModel::setData()? You would be in danger of makingClassAdo the storage, which you probably don't want.If you maintain separate
m_datas for each class you will have to duplicate code if you implement insert/delete rows etc. -
@Redman
Hmm. A couple of comments.In your
m_data[index.row()]->classBRole1(), is them_dataa member ofclass Bor is it a (publicly exported) member of the baseclass A?If you are going distinguish by role whether data belongs to
class Aorclass Bthen I would suggest changing the order of your testing:switch (role) { case ClassBRole1: return m_data[index.row()]->classBRole1(); default: break; } return ClassAListModel::data(index,role);This would avoid doing two data lookups and would allow for a genuine null value in either case.
As your code stands, I wonder how you would intend to deal with
ClassBListModel::setData()? You would be in danger of makingClassAdo the storage, which you probably don't want.If you maintain separate
m_datas for each class you will have to duplicate code if you implement insert/delete rows etc.@JonB said in QAbstractListModel with base and derived class:
@Redman
Hmm. A couple of comments.In your
m_data[index.row()]->classBRole1(), is them_dataa member ofclass Bor is it a (publicly exported) member of the baseclass A?Well, thats a good question. I'd assume that
m_datashould be the data fromClassBListModel. This leads toClassAListModelnot having access to data, hence not being able to provide the base class properties.Storing the data in
ClassAListModelmakes no sense to me in this scenario.If you are going distinguish by role whether data belongs to
class Aorclass Bthen I would suggest changing the order of your testing:switch (role) { case ClassBRole1: return m_data[index.row()]->classBRole1(); default: break; } return ClassAListModel::data(index,role);This would avoid doing two data lookups and would allow for a genuine null value in either case.
I do not see the benefit here. Please elaborate. To me it looks the same, just switched positions of
AandBproperty lookup.As your code stands, I wonder how you would intend to deal with
ClassBListModel::setData()? You would be in danger of makingClassAdo the storage, which you probably don't want.
If you maintain separatem_datas for each class you will have to duplicate code if you implement insert/delete rows etc.Agreed. This approach comes with some pitfalls.
Maybe to elaborate a bit further on the circumstances:
Class Bis not always implemented, hence theQAbstractListModelis not aswell. It is dependent on the project I am working on.So being able to use both approaches with the same api is desired.
-
I think I will go for the following approach:
BaseListModelimplementsprotected: QList<BaseClass*> m_dataAswell as all needed functions to work on the
BaseClass.
When needed, I will implement theDerivedListModeland all necessary functions. Calling theBaseListModelfunctionssetData,data,delete... and what not accordingly.
Theinsertimplementation will only be used by the lowest implementation of theListModelin the inheritance chain.
Byqobject_casting accordingly this approach should be fine. Decisively for this to work will be the correct usage ofinsert.Did I overlook anything?
-
@JonB said in QAbstractListModel with base and derived class:
@Redman
Hmm. A couple of comments.In your
m_data[index.row()]->classBRole1(), is them_dataa member ofclass Bor is it a (publicly exported) member of the baseclass A?Well, thats a good question. I'd assume that
m_datashould be the data fromClassBListModel. This leads toClassAListModelnot having access to data, hence not being able to provide the base class properties.Storing the data in
ClassAListModelmakes no sense to me in this scenario.If you are going distinguish by role whether data belongs to
class Aorclass Bthen I would suggest changing the order of your testing:switch (role) { case ClassBRole1: return m_data[index.row()]->classBRole1(); default: break; } return ClassAListModel::data(index,role);This would avoid doing two data lookups and would allow for a genuine null value in either case.
I do not see the benefit here. Please elaborate. To me it looks the same, just switched positions of
AandBproperty lookup.As your code stands, I wonder how you would intend to deal with
ClassBListModel::setData()? You would be in danger of makingClassAdo the storage, which you probably don't want.
If you maintain separatem_datas for each class you will have to duplicate code if you implement insert/delete rows etc.Agreed. This approach comes with some pitfalls.
Maybe to elaborate a bit further on the circumstances:
Class Bis not always implemented, hence theQAbstractListModelis not aswell. It is dependent on the project I am working on.So being able to use both approaches with the same api is desired.
@Redman said in QAbstractListModel with base and derived class:
I do not see the benefit here. Please elaborate. To me it looks the same, just switched positions of A and B property lookup.
100% yes. And as I wrote as a consequence:
This would avoid doing two data lookups and would allow for a genuine null value in either case.
So two benefits :)
-
R Redman has marked this topic as solved