Search code examples
c++qtqmlqt-quick

How to pass QList from QML to C++/Qt?


I'm trying to pass QList of integer from QML to C++ code, but somehow my approach is not working. With below approach am getting following error:

left of '->setParentItem' must point to class/struct/union/generic type
type is 'int *'

Any inputs to trouble shoot the issue is highly appreciated

Below is my code snippet

Header file

Q_PROPERTY(QDeclarativeListProperty<int> enableKey READ enableKey) 

QDeclarativeListProperty<int> enableKey(); //function declaration
QList<int> m_enableKeys;

cpp file

QDeclarativeListProperty<int> KeyboardContainer::enableKey()
{
    return QDeclarativeListProperty<int>(this, 0, &KeyboardContainer::append_list);
}

void KeyboardContainer::append_list(QDeclarativeListProperty<int> *list, int *key)
{
    int *ptrKey = qobject_cast<int *>(list->object);
    if (ptrKey) {
        key->setParentItem(ptrKey);
        ptrKey->m_enableKeys.append(key);
    }
}

Solution

  • You CAN'T use QDeclarativeListProperty (or QQmlListProperty in Qt5) with any other type than QObject derived ones. So int or QString will NEVER work.

    If you need to exchange a QStringList or a QList or anything that is an array of one of the basic types supported by QML, the easiest way to do it is to use QVariant on the C++ side, like this :

    #include <QObject>
    #include <QList>
    #include <QVariant>
    
    class KeyboardContainer : public QObject {
        Q_OBJECT
        Q_PROPERTY(QVariant enableKey READ   enableKey
                   WRITE  setEnableKey
                   NOTIFY enableKeyChanged)
    
    public:
        // Your getter method must match the same return type :
        QVariant enableKey() const {
            return QVariant::fromValue(m_enableKey);
        }
    
    public slots:
        // Your setter must put back the data from the QVariant to the QList<int>
        void setEnableKey (QVariant arg) {
            m_enableKey.clear();
            foreach (QVariant item, arg.toList()) {
                bool ok = false;
                int key = item.toInt(&ok);
                if (ok) {
                    m_enableKey.append(key);
                }
            }
            emit enableKeyChanged ();
        }
    
    signals:
        // you must have a signal named <property>Changed
        void enableKeyChanged();
    
    private:
        // the private member can be QList<int> for convenience
        QList<int> m_enableKey;
    };     
    

    On the QML side, simply affect a JS array of Number, the QML engine will automatically convert it to QVariant to make it comprehensible to Qt :

    KeyboardContainer.enableKeys = [12,48,26,49,10,3];
    

    That's all !