Support for constructing QStandardItem objects from QVariant references?
-
I'm lost, can you provide an example of what you'd do?
I am just curious if it will ever become supported to create Qt standard items like the following.
auto mcds(QVariant::fromValue(my_custom_data_structure)); auto si1(new QStandardItem(Qt::DisplayRole, mcds)); auto my_parameters(qMakePair(mcds, Qt::DisplayRole)); auto si2(new QStandardItem(my_parameters)); auto sim(new QStandardItemModel); sim->appendRow(si1); sim->appendRow(si2);
-
Ok, now I get it.
auto si1(new QStandardItem(Qt::DisplayRole, mcds));
has the same problem as above. as(int,int)
is a clash. You can go around it using sfinae but I still think it's a hard sell to add itThe
qMakePair
is actually unnecessarily limited, you can actually pass a wholeQMap<int,QVariant>
and forward it toQStandardItemPrivate::setItemData
-
The qMakePair is actually unnecessarily limited,
This can be useful when only two values should be passed by a single constructor argument instead of two parameters which are needed for calling the function “QStandardItem::setData”.
The generated data type should be unique just for the desired function overloading.you can actually pass a whole QMap<int,QVariant>
I find that such a map would not be needed for the shown source code example.
-
@elfring said in Support for constructing QStandardItem objects from QVariant references?:
I find that such a map would not be needed for the shown source code example.
What I meant is that a map is a more generic solution:
new QStandardItem({std::make_pair<QVariant,int>(mcds, Qt::DisplayRole)})
; would bind to the map version of the constructor@elfring said in Support for constructing QStandardItem objects from QVariant references?:
Can this possibility be added to the public construction parameters for the class “QStandardItem”?
Don't see why not. Open a ticket on https://bugreports.qt.io and post the link here. Make sure to mark the component as
Core: Item Models
. If David Faure gives the green light I'll add it -
@VRonin said in Support for constructing QStandardItem objects from QVariant references?:
@elfring said in Support for constructing QStandardItem objects from QVariant references?:
Can this possibility be added to the public construction parameters for the class “QStandardItem”?
Don't see why not. Open a ticket on https://bugreports.qt.io and post the link here. Make sure to mark the component as
Core: Item Models
. If David Faure gives the green light I'll add itBefore going down this path... isn't it better to subclass QStandardItem? http://doc.qt.io/qt-5/qstandarditem.html#subclassing
I presume the new constructor is to make QStandardItem work with a custom data type. If this is the case, then it's way better to have a constructor (AND getter + setter) that takes the custom type directly, without having to do QVariant conversion:
class MyItem : public QStandardItem { public: // NICE: Constructor for your custom type MyItem(MyData *value); // NICE: Getter and setter for your custom type. No need to convert to/from with QVariants const MyData *myData() const; // IMPORTANT! const MyData -- The pointer should not allow editing void setMyData(MyData *value) { // TODO: Ensure that old data is freed, or use smart pointers m_data = value; emitDataChanged(); // IMPORTANT! Notifies the view that the data has changed } // Allow the models/views to access your data through the standard interface QVariant data(int role) const override; void setData(const QVariant &value, int role) override; // ... // Other functions that might also be worth reimplementing are // Destructor, clone(), type(), read(), write(), operator<() private: MyData *m_data; };
Overall though, I don't like
QStandardItemModel
. Except for quick prototypes, I think custom data structures are much better served by subclassingQAbstract(Item|Table)Model
directly. -
… that takes the custom type directly, without having to do QVariant conversion:
I imagine that this another software development challenge if you need to work with the provided generic (or standard) programming interfaces.
class MyItem : public QStandardItem {
…
MyData *m_data;
};I find the specification of this member variable questionable for such a software design approach because the base class should take care of the desired data storage.
You might add attributes there for other design reasons. -
@elfring said in Support for constructing QStandardItem objects from QVariant references?:
… that takes the custom type directly, without having to do QVariant conversion:
I imagine that this another software development challenge if you need to work with the provided generic (or standard) programming interfaces.
Sorry, I didn't understand this. Could you rephrase it?
I find the specification of this member variable questionable for such a software design approach because the base class should take care of the desired data storage.
That's true, but you also didn't like converting/copying data in/out of QVariant. That's why I suggested this design, as a compromise to meet your different goals.
Like I mentioned before, QStandardItemModel is not well-suited for handling custom data structures. If you want a clean software design AND avoid converting/copying data, then avoid QStandardItemModel. Subclass QAbstractItemModel instead.
-
Could you rephrase it?
The class “QVariant” is a generic programming interface for the handling of known data structures.
That's true,
Thanks for your acknowledgement.
but you also didn't like converting/copying data in/out of QVariant.
Yes. - Thus I am looking again for useful software adjustments there.
Subclass QAbstractItemModel instead.
I would appreciate if I can reuse existing functionality from a higher level base class.
-
@JKSH said in Support for constructing QStandardItem objects from QVariant references?:
QStandardItemModel is not well-suited for handling custom data structures.
I disagree. It is not performance-efficient but it is generic enough to handle all kinds of custom metatypes
@elfring said in Support for constructing QStandardItem objects from QVariant references?:
I would appreciate if I can reuse existing functionality from a higher level base class.
Since we are moving one step higher, why not be even more generic:
QAbstractItemModel* model = new QStandardItemModel(parent);
This allows you to:
- use
QStandardItemModel
instead of subclassing your own - use your custom data types seamlessly as
QAbstractItemModel
always usesQVariant
- Lets you abstract the implementation of the model by using the API that is guaranteed to be available in every model
- use
-
It is not performance-efficient
Will this information trigger any further software evolution?
but it is generic enough to handle all kinds of custom metatypes
This design aspect is reasonably documented.
Since we are moving one step higher, why not be even more generic:
QAbstractItemModel* model = new QStandardItemModel(parent);
This data structure combines standard (or also custom) items.
use QStandardItemModel instead of subclassing your own
A derivation from an item class is needed if you would like to add member functions there.
It is a matter how the desired software behaviour is assigned to specific items or corresponding models overall. -
@elfring said in Support for constructing QStandardItem objects from QVariant references?:
It is not performance-efficient
Will this information trigger any further software evolution?
No. Because... (see below)
I would appreciate if I can reuse existing functionality from a higher level base class.
...remember, engineering involves finding the right balance. In general, these are the trade-offs when you choose a high-level API:
- Pros:
- Simple, easy to use
- More protections against errors
- Cons:
- Less performant
- Less flexible
When you choose the pros of the high-level QStandardItemModel, you also choose the cons.
- Pros:
-
@VRonin said in Support for constructing QStandardItem objects from QVariant references?:
@JKSH said in Support for constructing QStandardItem objects from QVariant references?:
QStandardItemModel is not well-suited for handling custom data structures.
I disagree. It is not performance-efficient but it is generic enough to handle all kinds of custom metatypes
I agree that it's generic enough to handle custom types. I just don't think it handles them nicely. (And to clarify, I was talking about custom, multi-element data structures that can't be easily represented by 1 string.)
My main gripe is this: 1 Item represents 1 "cell" in the View, and by default each cell only shows 1 "element". Thus, if I were to squeeze a complex multi-element data structure into an Item, then I'd need to write a custom Delegate too.
But anyway, this is a matter of personal preference. There's still a place for QStandardItemModel and I'm still happy to help someone use it if they want to.
Since we are moving one step higher, why not be even more generic:
I believe that's going lower-level, not higher-level... right...?
-
@JKSH said in Support for constructing QStandardItem objects from QVariant references?:
then I'd need to write a custom Delegate too.
100% agree on this point
I believe that's going lower-level, not higher-level
I meant higher level of abstraction (i.e. just look at the interface, not the implementation)
I would prefer to adjust the remaining development challenges somehow in this area.
Then a custom model is the way to go but it is not easy for people approaching Qt for the first time.
P.S.
It might be just a language issue but this is not StackOverflow, you won't get shouted at if you don't use exact technical terminology all the time, you can relax -
@VRonin said in Support for constructing QStandardItem objects from QVariant references?:
It might be just a language issue but this is not StackOverflow, you won't get shouted at if you don't use exact technical terminology all the time, you can relax
+1 for pointing out that this forum is not like The Gestapo from SO!
-
@elfring said in Support for constructing QStandardItem objects from QVariant references?:
I would appreciate if I can reuse existing functionality from a higher level base class.
Sorry! I just re-read this line and realized you said "higher level base class". In this case, please ignore what I said about choosing pros and cons.