Search code examples
c++qtqvariantqmap

Assigning to nested QVariantMap


#include <QtCore/QCoreApplication>
#include <QVariant>
#include <QtDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QVariantMap map;
    map["foo"] = QVariant(QVariantMap());
    map["baz"] = "asdf";
    qvariant_cast<QVariantMap>(map["foo"])["bar"] = "a";

    qDebug() << qvariant_cast<QVariantMap>(map["foo"])["bar"].toString();
    qDebug() << map["baz"].toString();

    return a.exec();
}

I am trying to assign to a QVariant within a nested QVariantMap. The first qDebug() outputs nothing, but the second outputs "asdf" as expected. How would I assign the "bar" key in the nested variable map to a value?


Solution

  • The issue is that qvariant_cast doesn't return a reference to the internals of the QVariant that it is operating on; it returns a copy. As such, if you overwrite the "foo" element in your top-level map with a new child map, the code will work properly:

    #include <QtCore/QCoreApplication>
    #include <QVariant>
    #include <QtDebug>
    
    int main(int argc, char** argv)
    {
        QCoreApplication a(argc, argv);
        QVariantMap map;
        map["foo"] = QVariant(QVariantMap());
        map["baz"] = "asdf";
    
        QVariantMap newMap;
        newMap["bar"] = "a";
        map["foo"] = QVariant(newMap);
    
        qDebug() << qvariant_cast<QVariantMap>(map["foo"])["bar"].toString();
        qDebug() << map["baz"].toString();
    
        return a.exec();
    }
    

    Presumably, you want to modify the existing map instead of overwritting it. You can accomplish this by copying the existing map, adding the new data (which will result in a deep copy), and then writing the map back in:

    QVariantMap existingMap = qvariant_cast<QVariantMap>(map["foo"]);
    existingMap["bar"] = "a";
    map["foo"] = QVariant(existingMap);
    

    If you're considering storing a large amount of data, you may wish to reconsider your use of QVariant.