Custom c++ types exposed to QML
-
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@ -
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 = undefinedGetting closer to resolving this, but not yet :D
Thanks,
Ionut -
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.