Friday, February 06, 2015

Qt 5.4 QML -> C++ QVariant issues

I usually don't blog about what I do in my day-time job in my personal blog but since this may affect some of the KDE/Qt developers I will do this time.

Qt 5.4 was released three months ago; at Canonical we're starting to move the Ubuntu Pĥone codebase to it now and it has an important behavior change as noted in it's changes file (that is quite hard to find by the way, it took me like 5 minutes to find, and that's knowing it existed, searching for "qt 5.4 changelog" does not return that is the important page) that has affected us in many places

The important behavior change is that now some QVariants will be passed to C++ as QJSValue-QVariants instead of QStringList-QVariants, QMap-QVariants, etc so if your code did things like checking the variant type now it will fail, so basically for any C++ function that receives QVariants from QML you need to add extra code to unbox the QVariant, i.e.

void MyClass::myFunction(QVariant v)
    // unbox the QVariant-QJSValue
    if (v.userType() == qMetaTypeId<QJSValue>()) {
        v = v.value<QJSValue>().toVariant();
    // This is your old code that checks the type
    // of the QVariant is a valid one
    if (v.type() != QVariant::Map &&
        v.type() != QVariant::List &&
        v.type() != QVariant::StringList) {
        qWarning() << "Bad param" << v;
    // From here your old code that does things


hipersayan_x said...

myFunction is called from your Qml code right?, so, why not declare the type that you are expecting as argument? ie., instead of:

void MyClass::myFunction(QVariant v)


void MyClass::myFunction(QVariantList v)
void MyClass::myFunction(QStringList v)
void MyClass::myFunction(QVariantMap v)

QJSEngine can recognizes quite well the type of the arguments and call the appropriate method.

awais kamran said...

You have explained this topic really well that a beginner like me was able to understand it easily. C++ in Urdu