Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Access `QMap<K,V>` "where V QObject` from qml

Access `QMap<K,V>` "where V QObject` from qml

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
1 Posts 1 Posters 627 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    paulpv
    wrote on last edited by paulpv
    #1

    I have a fairly basic Hello World Qt Quick Application (Qt+Qml) at:
    https://github.com/paulpv/QtQmlHelloQVariantMap/

    In it I am trying to [learn how to] expose a QMap<K,V> to qml (read-only is fine for now).
    My end-goal is to expose a QMap<int, HotkeyInfo>, where HotkeyInfo is defined as:

    class HotkeyInfo : public QObject
    {
        Q_OBJECT
        ...
        Q_PROPERTY(QString computerName MEMBER m_computerName)
        Q_PROPERTY(QString appName MEMBER m_appName)
        ...
    private:
        QString m_computerName;
        QString m_appName;
    };
    
    using MapHotkeys = QMap<QString, QVariant>;
    
    class HotkeyManager : public QObject
    {
        Q_OBJECT
        ...
        Q_PROPERTY(MapHotkeys hotkeys MEMBER m_hotkeys)
    
        void add(const int key, HotkeyInfo* hotkeyInfo) {
            m_hotkeys[QString::number(key)] = QVariant::fromValue(hotkeyInfo);
        }
    
        void remove(const int key) {
            auto hotkeyInfo = m_hotkeys.take(QString::number(key)).value<HotkeyInfo*>();
            if (hotkeyInfo != nullptr) {
                delete hotkeyInfo;
            }
        }
        ...
    private:
        MapHotkeys m_hotkeys;
    }
    

    I populate the Map with:

    void initializeMessages(HotkeyManager& hotkeyManager)
    {
        // Ignore NewDeleteLeaks; ~HotkeyManager frees all added HotkeyInfos.
        hotkeyManager.add(1, new HotkeyInfo("computer1", "app2"));
        hotkeyManager.add(2, new HotkeyInfo("computer2", "app4"));
    }
    

    Qml code to read the HotkeyInfo properties...

    import QtQuick
    import QtQuick.Window
    
    ApplicationWindow {
        width: 640
        height: 480
        visible: true
        title: qsTr("Hello World")
    
        Component.onCompleted: {
            console.log(`Component.onCompleted`)
            console.log(`hotkeyManager=${hotkeyManager}`)
            var hotkeys = hotkeyManager.hotkeys
            console.log(`hotkeys=${hotkeys}`)
            var hotkeyInfo1 = hotkeys[1]
            console.log(`hotkeyInfo1=${hotkeyInfo1}`)
            console.log(`hotkeyInfo1.computerName=${hotkeyInfo1.computerName}`)
            console.log(`hotkeyInfo1.appName=${hotkeyInfo1.appName}`)
            var hotkeyInfo2 = hotkeys[2]
            console.log(`hotkeyInfo2=${hotkeyInfo2}`)
            console.log(`hotkeyInfo2.computerName=${hotkeyInfo2.computerName}`)
            console.log(`hotkeyInfo2.appName=${hotkeyInfo2.appName}`)
        }
    }
    

    My qml can see properties of the HotkeyInfo class just fine if I use QMap<String,QVariant> and convert the key to and from an int and values to and from HotkeyInfo*.

    qml: Component.onCompleted
    qml: hotkeyManager=HotkeyManager(0x930095fb78)
    qml: hotkeys=[object Object]
    qml: hotkeyInfo1=HotkeyInfo(0x263748f66a0)
    qml: hotkeyInfo1.computerName=computer1
    qml: hotkeyInfo1.appName=app2
    qml: hotkeyInfo2=HotkeyInfo(0x263748f6520)
    qml: hotkeyInfo2.computerName=computer2
    qml: hotkeyInfo2.appName=app4
    

    I am naive enough to think that I should not have to add extra code to convert to/from key and value types, and/or think that doing that means I might be doing something wrong; I would like to remove that extra code.

    If I just change the map to QMap<QString,HotkeyInfo*> then it can no longer access the map entries (ie: "stops working")

    qml: Component.onCompleted
    qml: hotkeyManager=HotkeyManager(0x16e5cff978)
    qml: hotkeys=QVariant(QMap<QString,HotkeyInfo*>, QMap(("1", HotkeyInfo(0x1b975ff7800))("2", HotkeyInfo(0x1b975ff8500))))
    qml: hotkeyInfo1=undefined
    qrc:/qt/qml/QtQmlHelloQVariantMap/Main.qml:21: TypeError: Cannot read property 'computerName' of undefined
    

    NOTE that the debug output still shows it knows the object types well enough to toString() them.

    If I just change the map to QMap<int,QVariant> then strangely also stops working.

    qml: Component.onCompleted
    qml: hotkeyManager=HotkeyManager(0x22c22ff618)
    qml: hotkeys=QVariant(QMap<int,QVariant>, QMap((1, QVariant(HotkeyInfo*, 0x1314e128ac0))(2, QVariant(HotkeyInfo*, 0x1314e1294c0))))
    qml: hotkeyInfo1=undefined
    qrc:/qt/qml/QtQmlHelloQVariantMap/Main.qml:21: TypeError: Cannot read property 'computerName' of undefined
    

    Interestingly, the qml code has no problem accessing the working QMap<String,QVariant> values using an int key; something seems to auto-convert that to a string.
    It seems odd that an int key does not work on a QMap<int,QVariant>, but an int key does work on a QMap<String,QVariant>.

    If I change the map to QMap<int,HotkeyInfo*> then it obviously also stops working.

    qml: Component.onCompleted
    qml: hotkeyManager=HotkeyManager(0xf7969afb58)
    qml: hotkeys=QVariant(QMap<int,HotkeyInfo*>, QMap((1, HotkeyInfo(0x2a033aeaab0))(2, HotkeyInfo(0x2a033ae8cb0))))
    qml: hotkeyInfo1=undefined
    qrc:/qt/qml/QtQmlHelloQVariantMap/Main.qml:21: TypeError: Cannot read property 'computerName' of undefined
    

    Can anyone suggest how to accomplish reading a QMap<?,QObject> from qml?

    AI chatbots seem useless on this.

    Thanks!

    Pv

    1 Reply Last reply
    0

    • Login

    • Login or register to search.
    • First post
      Last post
    0
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Get Qt Extensions
    • Unsolved