Reputation: 4625
I have a QVariantList containing objects of different classes. I need to modify a member variable of one object held in the list. My code runs, but the object is not changing (looks like a copy of the object is being changed). Here is sample code similar to what I'm doing:
QVariantList l;
QVariant v = l.at(0);
MyClass c;
if (v.canConvert<MyClass >()) c = v.value<MyClass >();
c.myfield(10);
// l.at(0) has not changed
I also tried:
qvariant_cast<MyClass>(v).myfield(10)
but no difference. I want to change myfield of the object, not a copy of the object. How do I modify the 'myfield' field of the object held in the QVariant v.
Upvotes: 1
Views: 1827
Reputation: 769
QVariant::data()
is your friend. It wasn't officially documented before Qt6, but you can safely use it nevertheless with Qt5 too.
#include <QCoreApplication>
#include <QVariant>
#include <QDebug>
class MyClass
{
public:
int myfield {0};
};
Q_DECLARE_METATYPE(MyClass)
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qRegisterMetaType<MyClass>();
QVariantList l;
{
QVariant t;
MyClass mc;
t.setValue(mc);
l.append(t);
l.append(t);
l.append(t);
}
// ...
{
QVariant &v (l[0]); // obviously we don't use "at" since it's const and we need to modify the container
if(v.userType() != qMetaTypeId<MyClass>())
{
qWarning() << "Unexpected metatype " << QMetaType::typeName(v.userType());
return -1;
}
MyClass *const ptr {static_cast<MyClass*>(v.data())};
ptr->myfield = 10;
}
// ...
qDebug() << l.at(0).value<MyClass>().myfield; // returns 10
return 0;
}
Upvotes: 0
Reputation: 4354
Your object is copied here the first time:
QVariant v = l.at(0);
v
contains a new object. All your manipulations change this copy not the object in the list.
Change it to this:
QVariant& v = l.at(0);
Now you have a reference to the right QVariant stored in the list.
qvariant_cast
also creates a copy:
T qvariant_cast ( const QVariant & value )
And v.value<MyClass >()
too:
T QVariant::value () const
That's why you need to convert v
to MyClass
, change it and assign it back to v
. Here is one of possible solutions:
QVariantList l;
QVariant v& = l.at(0);
if (v.canConvert<MyClass >())
{
MyClass c = v.value<MyClass>();
c.myfield(10);
v = QVariant::fromValue(c);
}
Instead of using the reference you also you could still use QVariant v = l.at(0);
but at the end call l[0] = QVariant::fromValue(c)
.
Upvotes: 1
Reputation: 1723
Try using
c.myfield(10);
v = c;
See the following example as specified in QVariant docs.
QDataStream in(...); // (opening the previously written stream)
in >> v; // Reads an Int variant
int z = v.toInt(); // z = 123
qDebug("Type is %s", // prints "Type is int"
v.typeName());
v = v.toInt() + 100; // The variant now hold the value 223
v = QVariant(QStringList());
You can refer to the QVariant docs here
Upvotes: 0