How to find out the QQmlEngine instance of a singleton object?

3.2k views Asked by At

I have a class SingletonBaseClass that is defined in C++ and later extended in QML. In the qmldir file, it is marked as a Singleton:

// qmldir file
singleton SingletonClass 1.0 SingletonClass.qml

// SingletonClass.qml
import QtQml 2.0
pragma Singleton
SingletonBaseClass {
    // ...
}

This is the base class:

class SingletonBaseClass : public QObject 
{
    Q_OBJECT
    public:
    SingletonBaseClass(QObject* parent = nullptr) {}

    // Get the owner engine
    Q_INVOKABLE void someMethodCalledFromQml()
    {
        QQmlEngine* ownerEngine = ?
    }

    // Get the single instance of the given engine
    static SingletonBaseClass* instance(QQmlEngine* engine)
    {
        SingletonBaseClass* instance = ?
        return instance;
    } 

};
  1. How can I retrieve the QQmlEngine instance in SingletonBaseClass?
  2. How can I get a pointer to my singleton instance from within a static function?

Note: I have multiple QML engine instances in my application.

[Update]: I wasn't satisfied with the suggested workarounds and so I finally contributed this patch for 1. and QQmlEngine::singletonInstance() for 2. Both changes will be available in Qt 5.12.

1

There are 1 answers

2
eyllanesc On BEST ANSWER

If you want to get the QQmlEngine you can use the contextForObject() method as I show below:

Q_INVOKABLE void someMethodCalledFromQml()
{
    QQmlEngine *ownerEngine = QQmlEngine::contextForObject(this)->engine();
    qDebug()<<ownerEngine;
}

singletons in qml do not have a parent so a way to access them is by creating a property, for that we create a .qml and create an object with that property as the Singleton:

qrc:/tmp.qml

import QtQuick 2.0

QtObject {
    property var obj: SingletonClass
}

and then this element is accessed by the following code:

static SingletonBaseClass* instance(QQmlEngine* engine)
{
    QQmlComponent component(engine, QUrl("qrc:/tmp.qml"));
    QObject *item = component.create();
    SingletonBaseClass *instance = qvariant_cast<SingletonBaseClass *>(item->property("obj"));
    return instance;
}

In the following link we show an example.