TSG
TSG

Reputation: 4625

Modify member variable of object held in QVariant

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

Answers (3)

ScumCoder
ScumCoder

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

Ezee
Ezee

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

Pratham
Pratham

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

Related Questions