Search code examples
qtqmlqqmlcontext

connect signal emitted from c++ to qml Connections


I am emitting a signal from c++ and trying to fetch the values using Connections in qml. The codes are compiling however, due to some unknown reason qml is not able to recognise "OnSomethingHappened" and signal emitted from c++ is "somethingHappened".

I know there can be other solutions but i need to use connections in qml. This is because of architecture used in qml.

qmlclient.h

#ifndef QMLMQTTCLIENT_H
#define QMLMQTTCLIENT_H

#include <QtCore/QMap>
#include <QtMqtt/QMqttClient>
#include <QtMqtt/QMqttSubscription>

class QmlMqttClient;

class QmlMqttSubscription : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QMqttTopicFilter topic MEMBER m_topic NOTIFY topicChanged)
public:
    QmlMqttSubscription(QMqttSubscription *s, QmlMqttClient *c);
    ~QmlMqttSubscription();

Q_SIGNALS:
    void topicChanged(QString);
    void messageReceived(QString &msg);
    void somethingHappened(QString text);

public slots:
    void handleMessage(const QMqttMessage &qmsg);

private:
    Q_DISABLE_COPY(QmlMqttSubscription)
    QMqttSubscription *sub;
    QmlMqttClient *client;
    QMqttTopicFilter m_topic;
};

class QmlMqttClient : public QMqttClient
{
    Q_OBJECT
public:
    QmlMqttClient(QObject *parent = nullptr);

    QmlMqttSubscription *subscribe(const QString &topic);

    void sub();
private:
    Q_DISABLE_COPY(QmlMqttClient)
};


#endif // QMLMQTTCLIENT_H*/

qmlmqttclient.cpp

#include "qmlmqttclient.h"
#include <QDebug>

QmlMqttClient::QmlMqttClient(QObject *parent)
    : QMqttClient(parent)
{
}

QmlMqttSubscription* QmlMqttClient::subscribe(const QString &topic)
{
    auto sub = QMqttClient::subscribe(topic, 0);
    auto result = new QmlMqttSubscription(sub, this);
    return result;
}

QmlMqttSubscription::QmlMqttSubscription(QMqttSubscription *s, QmlMqttClient *c)
    : sub(s)
    , client(c)
{
    connect(sub, &QMqttSubscription::messageReceived, this, &QmlMqttSubscription::handleMessage);
   // m_topic = sub->topic();
}

QmlMqttSubscription::~QmlMqttSubscription()
{

}

void QmlMqttSubscription::handleMessage(const QMqttMessage &qmsg)
{
    //emit messageReceived(qmsg.payload());

    emit somethingHappened(qmsg.payload());

    qDebug() << "value -> " + qmsg.payload();
}

main.cpp

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);


    QmlMqttClient *client =  new QmlMqttClient();
    client->setHostname("127.0.0.1");
    client->setPort(1883);

    client->connectToHost();
    qDebug() << client->state();

    QTimer timer;
    QObject::connect(&timer, &QTimer::timeout, [client]() {client->subscribe("/root/temp");});
    timer.setSingleShot(true);
    timer.start(5000);



    QQmlApplicationEngine engine;

    engine.rootContext()->setContextProperty("myModel",client);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

main.qml

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Rectangle {
        id: sensor
        color: "#ffffff"
        radius: 10
        x: 10
        y: 10

        property string address
        property string title
        property string unit

        Text{
            id: textField

            property var value : 0

            text: sensor.title + " " + value + " " + sensor.unit
            y:50
            font.family: "Helvetica"
            font.pointSize: 24
            anchors.horizontalCenter: parent.horizontalCenter
        }

        Connections
        {
            target: myModel

            onSomethingHappened: {
             console.log(" something happened " +text);
            }
        }
    }
}

On running the above codes console shows

QML debugging is enabled. Only use this in a safe environment.
1
qrc:/main.qml:33:9: QML Connections: Cannot assign to non-existent property "onSomethingHappened"
"value -> -50"
"value -> -50"
"value -> -50"

Solution

  • The signal you're trying to connect to is in QmlMqttSubscription class but your context property myModel object is of type QmlMqttClient.

    QmlMqttClient *client =  new QmlMqttClient();
    ...
    engine.rootContext()->setContextProperty("myModel",client);