How do I implement a singleton provider for qmlRegisterSingletonType?
I want to use C ++ classes as Singleton instances in QML and figured I needed to register them in the qmlRegisterSingletonType. This function requires a function that provides an instance of a registered C ++ class. I am using latest Qt 5.3.1 with MinGW 4.8 enabled for Windows.
the documentation shows the following example of a provider function:
static QJSValue example_qjsvalue_singletontype_provider(QQmlEngine *engine,
QJSEngine *scriptEngine)
{
Q_UNUSED(engine)
static int seedValue = 5;
QJSValue example = scriptEngine->newObject();
example.setProperty("someProperty", seedValue++);
return example;
}
I tried to use this, but I get a compiler warning when I define an out-of-class function like this in a header, appearing in another cpp file, including the same header:
warning: 'QObject* example_qjsvalue_singletontype_provider(QQmlEngine*,
QJSEngine*)' defined but not used [-Wunused-function]
Also, it's just plain wrong to write a singleton provider that returns a new instance when called from different cpp files. So I tried my own implementation, where I use a static member of the class to return an instance:
// mysingleton.h
class MySingleton: public QObject
{
Q_OBJECT
Q_DISABLE_COPY(MySingleton)
public:
static QObject *qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine) {
Q_UNUSED(engine)
Q_UNUSED(scriptEngine)
if(!m_instance)
{
m_instance = new MySingleton();
}
return m_instance;
}
MySingleton(QObject* parent = 0)
:QObject(parent)
{}
private:
static QObject* m_instance;
};
I tried to log this with ...
qmlRegisterSingletonType<MySingleton>(uri, 1, 0, "MySingleton",
MySingleton::qmlInstance);
This solution also doesn't work, I get linker errors:
release/main.o:main.cpp:
(.text$_ZN11MySingleton11qmlInstanceEP10QQmlEngineP9QJSEngine[__ZN11MySingleton11
qmlInstanceEP10QQmlEngineP9QJSEngine]+0x42): undefined reference to
'MySingleton::m_instance'
What's the correct solution to provide the required Singleton instance with 1) a function outside the scope of the class and 2) a member function of the class?
Why does the example suggest creating a new instance every time the provider function is called?
source to share
it's just wrong to write a singleton provider that returns a new instance when called from different cpp files. So I tried my own implementation where I use a static member of the class to return an instance
Quoting from the documentation for the function qmlRegisterSingletonType
:
NOTE. The QObject singleton instance returned by the singleton provider belongs to the QML engine. For this reason, a singleton type provider function should not be implemented as a singleton type factory.
This means that this behavior, when a singleton type provider returns a new instance, is done on purpose, even though, as you may have noticed, it looks strange at first glance. So, your class implementation should look something like this:
class MySingleton: public QObject
{
Q_OBJECT
Q_DISABLE_COPY(MySingleton)
MySingleton() {}
public:
static QObject *qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine)
{
Q_UNUSED(engine);
Q_UNUSED(scriptEngine);
return new MySingleton;
}
};
Moreover, you must use the ampersand for MySingleton::qmlInstance
, since it is a member method. See this for more information. Then the registration should look like this:
qmlRegisterSingletonType<MySingleton>(uri, 1, 0, "MySingleton", &MySingleton::qmlInstance);
source to share