Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. Custom c++ types exposed to QML
QtWS25 Last Chance

Custom c++ types exposed to QML

Scheduled Pinned Locked Moved Mobile and Embedded
4 Posts 3 Posters 4.6k 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.
  • D Offline
    D Offline
    deion
    wrote on last edited by
    #1

    Hi all,

    Im my c++ code I have a class AppEngine that has an instance member, userSettings of type UserSettings.
    The USerSettings class has Q_PROPERTY -ies like QString serverAddr, etc.
    I expose the userSettings object to C++ like this:
    In C++:

    @ QDeclarativeContext* ctxt = qmlViewer->rootContext(); // qmlViewer is of type QmlApplicationViewer which inherits from QDeclarativeView
    ctxt->setContextProperty("userSettings", &this->m_userSettings);
    @

    In QML I just referenced the userSettings variable and its properties:

    @console.log("!!! userSettings: conntype = " + userSettings.connectionType);@

    All is well; however I wanted to expose just a single object to QML, in my case the AppEngine object, and access the userSettings from QML using something like appEngine.userSettings.connectionType

    For this I declared my UserSettings type as a metaobject, I declared the instance userSettings member as a Q_PROPERTY in AppEngine class; however in QML when I try to access appEngine.userSettings.connectionType the connectionType is 'undefined'; It worked before as I used userSettings directly, without embedding it in appEngine, but I think it's more elegant to have one single root object exposed to QML and sub-objects accessed from this root object.

    Below is copy-paste from the relevant code:

    UserSettings.h

    @
    #ifndef USER_SETTINGS_H
    #define USER_SETTINGS_H

    #include <QObject>
    #include <QMetaType>

    typedef enum ConnectionType {
    CONN_INET = 0,
    CONN_BLUETOOTH = 1
    } ConnectionType;

    class QString;

    class UserSettings : public QObject
    {
    Q_OBJECT
    Q_PROPERTY(int connectionType
    READ connectionType
    WRITE setConnectionType
    NOTIFY connectionTypeChanged)
    …etc, omitted other properties, post was becoming longer than 6000 chars
    friend class AppEngine;

    public:
    UserSettings();
    UserSettings(const UserSettings& settings);
    UserSettings& operator=(const UserSettings& settings);
    virtual ~UserSettings();
    bool operator==(const UserSettings& rhs) const;
    bool operator!=(const UserSettings& rhs) const;

    // m_connectionType property
    void setConnectionType(int aConnectionType) {
        if (m_connectionType != aConnectionType) {
            m_connectionType = (ConnectionType) aConnectionType;
            emit connectionTypeChanged();
        }
    }
    int connectionType() const {
        return m_connectionType;
    }
    
    // m_inetServerAddr property
    void setInetServerAddr(const QString &aInetServerAddr) {
        if (m_inetServerAddr != aInetServerAddr) {
            m_inetServerAddr = aInetServerAddr;
            emit inetServerAddrChanged();
        }
    }
    QString inetServerAddr() const {
        return m_inetServerAddr;
    }
    
    // m_tcpPort property
    void setTcpPort(int aTcpPort) {
        if (m_tcpPort != aTcpPort) {
            m_tcpPort = aTcpPort;
            emit tcpPortChanged();
        }
    }
    int tcpPort() const {
        return m_tcpPort;
    }
    
    // m_btServerAddr property
    void setBtServerAddr(const QString &aBtServerAddr) {
        if (m_btServerAddr != aBtServerAddr) {
            m_btServerAddr = aBtServerAddr;
            emit btServerAddrChanged();
        }
    }
    QString btServerAddr() const {
        return m_btServerAddr;
    }
    
    // m_btServerName property
    void setBtServerName(const QString &aBtServerName) {
        if (m_btServerName != aBtServerName) {
            m_btServerName = aBtServerName;
            emit btServerNameChanged();
        }
    }
    QString btServerName() const {
        return m_btServerName;
    }
    

    signals:
    void connectionTypeChanged();
    void inetServerAddrChanged();
    void tcpPortChanged();
    void btServerAddrChanged();
    void btServerNameChanged();

    private:
    // Data:
    ConnectionType m_connectionType;
    QString m_inetServerAddr;
    int m_tcpPort;
    QString m_btServerAddr;
    QString m_btServerName;

    private:
    static void LoadSettings(UserSettings* settings);
    static void SaveSettings(const UserSettings* settings);
    };

    Q_DECLARE_METATYPE(UserSettings)

    #endif//USER_SETTINGS_H
    @

    AppEngine.h

    @
    #ifndef APP_ENGINE_H
    #define APP_ENGINE_H

    #include <QtGui/QApplication>
    #include <QCamera>
    #include "UserSettings.h"

    …etc

    class AppEngine : public QApplication
    {
    Q_OBJECT
    Q_PROPERTY(UserSettings userSettings
    READ userSettings)

    public:
    AppEngine(int &argc, char *argv);
    virtual ~AppEngine();
    void setUpQML(QmlApplicationViewer
    qmlViewer);
    UserSettings userSettings() const;
    ... etc
    private:
    // Data:
    UserSettings m_userSettings;
    ...etc
    }
    @

    AppEngine.cpp:
    @
    AppEngine::AppEngine(int &argc, char **argv):
    QApplication(argc, argv),
    ...etc
    {
    qRegisterMetaType<UserSettings>();
    UserSettings::LoadSettings(&m_userSettings);
    ...etc
    }

    void AppEngine::setUpQML(QmlApplicationViewer* qmlViewer)
    {
    QObject* rootObjMainQml = qmlViewer->rootObject();
    QDeclarativeContext* ctxt = qmlViewer->rootContext();
    ctxt->setContextProperty("appEngine", this);
    ...etc
    }

    UserSettings AppEngine::userSettings() const {
    return m_userSettings;
    }

    @

    And in QML (SettingsDlg.qml):
    @

    function show() {
        console.log("!!! userSettings: conntype = " + appEngine.userSettings.connectionType + "; inetServerAddr=" + appEngine.userSettings.inetServerAddr + "; tcpPort=" + appEngine.userSettings.tcpPort + "; btServerAddr=" + appEngine.userSettings.btServerAddr + "; btServerName=" + appEngine.userSettings.btServerName);
        connTypeList.selectedIdx = -1;
    

    ...etc
    }
    @

    And this is what I'm getting in console:
    @!!! userSettings: conntype = undefined; inetServerAddr=undefined; tcpPort=undefined; btServerAddr=undefined; btServerName=undefined@

    1 Reply Last reply
    0
    • V Offline
      V Offline
      vsorokin
      wrote on last edited by
      #2

      in AppEngine.h
      @public:
      ....
      Q_INVOKABLE UserSettings userSettings() const;@

      in Qml:
      @appEngine.userSettings().connectionType
      ... etc@

      --
      Vasiliy

      1 Reply Last reply
      0
      • D Offline
        D Offline
        deion
        wrote on last edited by
        #3

        Thanks Vass,

        I modified QML:
        @console.log("!!! userSettings: conntype = " + appEngine.userSettings().connectionType);@

        if in AppEngine.h I keep:

        @ Q_PROPERTY(UserSettings userSettings
        READ userSettings)
        @

        and modify the declaration @UserSettings userSettings() const;@ to @Q_INVOKABLE UserSettings userSettings() const;@
        I get the following error at run-time:
        TypeError: Result of expression 'appEngine.userSettings' [QVariant(UserSettings)] is not a function.

        If I remove in AppEngine.h:
        @ Q_PROPERTY(UserSettings userSettings
        READ userSettings)
        @
        and keep only @Q_INVOKABLE UserSettings userSettings() const;@

        I get the following:
        !!! userSettings: conntype = undefined

        Getting closer to resolving this, but not yet :D

        Thanks,
        Ionut

        1 Reply Last reply
        0
        • C Offline
          C Offline
          chriadam
          wrote on last edited by
          #4

          UserSettings derives from QObject? Then you want your property type (or invokable function return type) to be a UserSettings pointer. Passing a QObject in a QVariant (and between QML and C++, all types are marshalled into QVariants) probably isn't going to work as you hope.

          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