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;
}
};
QQmlEngine
instance in SingletonBaseClass?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.
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.