Reference to Qml Singleton Class Instance?

Reference to Qml Singleton Class Instance?

I have created a class called LoginService. I registered it to QT QML file by using qmlRegisterSingletonType, now the problem is I can't get the loginservice instance which instantiated by QML. My current c++ code is:

static QObject *qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine) {
    Q_UNUSED(engine);
    Q_UNUSED(scriptEngine);

    LoginService::m_pThis = new LoginService;
    return m_pThis;
}

qmlRegisterSingletonType<LoginService>("com.test.LoginService", 1, 0, "LoginService", &LoginService::qmlInstance);
1

1 Answer

If you want to access the singleton from C++, create a method that returns an instance other than qmlInstance:

loginservice.h

#ifndef LOGINSERVICE_H
#define LOGINSERVICE_H

#include <QObject>

class QQmlEngine;
class QJSEngine;

class LoginService : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
    static LoginService *instance();
    static QObject *qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine);

    QString name() const;
    void setName(const QString &name);
    Q_SIGNAL void nameChanged();

private:
    explicit LoginService(QObject *parent = nullptr);
    static LoginService* m_pThis;
    QString mName;
};

#endif // LOGINSERVICE_H

loginservice.cpp

#include "loginservice.h"

#include <QQmlEngine>

LoginService* LoginService::m_pThis = nullptr;
LoginService::LoginService(QObject *parent) : QObject(parent)
{

}

QString LoginService::name() const
{
    return mName;
}

void LoginService::setName(const QString &name)
{
    if(mName == name)
        return;
    mName = name;
    Q_EMIT nameChanged();
}

LoginService *LoginService::instance()
{
    if (m_pThis == nullptr) // avoid creation of new instances
        m_pThis = new LoginService;
    return m_pThis;
}

QObject *LoginService::qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine) {
    Q_UNUSED(engine);
    Q_UNUSED(scriptEngine);
    // C++ and QML instance they are the same instance
    return LoginService::instance();
}

main.cpp

#include "loginservice.h"

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDebug>

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

    QGuiApplication app(argc, argv);

    qmlRegisterSingletonType<LoginService>("com.test.LoginService", 1, 0, "LoginService", &LoginService::qmlInstance);


    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    // get instance in C++
    LoginService *service = LoginService::instance();

    qDebug()<<service->name();
    return app.exec();
}

main.qml

import QtQuick 2.9
import QtQuick.Window 2.2
import com.test.LoginService 1.0

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

   Component.onCompleted: LoginService.name = "testing"
}
4

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Alexander Ross
Author

Alexander Ross

Alexander Ross has covered the video game industry for a decade, writing deep dives on game design, esports tournaments, VR developments, and gaming culture.