Checking/addressing QRC resources from a QQmlExtensionPlugin.
-
I have a large static library that I've written that uses Qt. Normally I link this library with whichever application I'm developing. The library, among other things, provides several new widgets that are templated in the same way as QQuick Controls 2 controls, that is, a C++ class extending from QQuickItem is created that performs the bulk of the logic. This class is registered with qmlRegisterType. Then a QML file with a root item of that type is written that describes the look and feel of the control. There can be several of these QML files, one for each style. This works is pretty much the exact same way as 'quicktemplates2' and 'quickcontrols2' from the Qt source code.
When I register the final type (i.e. registering the QML file that 'extends' from the template C++ item), I call a function that determines which style is currently in use, and selects the QML file from the relevant style directory in my QRC file (the QRC file is part of the static library, loaded with 'Q_INIT_RESOURCE'). The function calls 'QQuickStyle::name()' to determine the current style, then generates the path to the QML file based on the style name (e.g. ':/Material/MyWidget.qml'). It then tries to generate a component from the QML file at this path (using 'QQmlComponent::create()'). If this fails, either because the file doesn't exist (I haven't created a version for this particular style), or because there is an error loading the QML, the function reverts to using the QML file for the default style (which is guaranteed to exist and be valid).
This scheme works fine in my applications, but I've recently been trying to create a QML extension plugin that links this static library (with varying degrees of success). I can get this plugin to load and run in both 'qmlscene' and 'qml2puppet' (QML Designer), but it always defaults to using the Default style, regardless of the style I set. I have determined that this is down to the previously stated function being unable to see the QML files in the QRC of the static library when called from the 'registerTypes' function of the QQmlExtensionPlugin. If I manually bypass the checks in this function and get the plugin to register the QML file from the style directory regardless of it's existence, then the correct version of the widget is displayed for the current style.
So it seems that my issue lies in not being able to access the QRC of my static library, despite calling 'Q_INIT_RESOURCE'. The function doesn't even get as far as trying to generate the component, so I believe the issue is that it simply cannot see the file. I've tried checking with 'QFile::exists(":/Material/MyWidget.qml")' and 'QFileInfo::exists()', but neither can see the file. It seems that the resources can be loaded just fine when the control is actually generated later, but at registration time the resource system doesn't seem to be available. Can anybody think of a reason why this might be?
-
I've determined the issue:
In static libs, applications and custom plugins, both forms of addressing QRC resources works, e.g.:
"qrc:/MyLib/MyItem.qml"
":/MyLib/MyItem.qml"
However, in QQmlExtensionPlugin, only the ':/' form appears to work, and 'qrc:/' doesn't work at all... This seems like unintended behaviour (certainly doesn't make sense to me), and possibly a bug? Can anybody confirm that this is intended/unintended behaviour?
Also, if I try to generate a QQmlComponent from within the QQmlExtensionPlugin(in this case to check that the qml resource parses without errors), it seems to hang indefinetly:
QQmlEngine engine; QQmlComponent component(&engine, ":/MyLib/MyItem.qml"); QObject *obj = component.create(); //Hangs here.
It will also hang if using the provided QQmlEngine pointer from the 'QQmlExtensionPlugin::initializeEngine' function.
-
Hi,
Are you linking several of your application components to that static library ?
-
@SGaist said in Checking/addressing QRC resources from a QQmlExtensionPlugin.:
Are you linking several of your application components to that static library ?
I'm afraid I don't understand what you mean by 'application components'. I have multiple applications that link this library, and they all work fine. My only issue is when I link the library into a qml plugin. The idea is to create a qml plugin that can be loaded by the Designer in Qt Creator, so I can do layouts with my custom widgets without manually editing the qml every time.
-
What I meant was: are you linking both your application and one (or more) plugin(s) used in your application to that static library ?
-
-
Well, depending on what you do with that plugin it might cause trouble. You'll be loading twice the same symbols in your application memory.
-
You can use QFile::exists even on QRC content IIRC.
-
I've determined the issue:
In static libs, applications and custom plugins, both forms of addressing QRC resources works, e.g.:
"qrc:/MyLib/MyItem.qml"
":/MyLib/MyItem.qml"
However, in QQmlExtensionPlugin, only the ':/' form appears to work, and 'qrc:/' doesn't work at all... This seems like unintended behaviour (certainly doesn't make sense to me), and possibly a bug? Can anybody confirm that this is intended/unintended behaviour?
Also, if I try to generate a QQmlComponent from within the QQmlExtensionPlugin(in this case to check that the qml resource parses without errors), it seems to hang indefinetly:
QQmlEngine engine; QQmlComponent component(&engine, ":/MyLib/MyItem.qml"); QObject *obj = component.create(); //Hangs here.
It will also hang if using the provided QQmlEngine pointer from the 'QQmlExtensionPlugin::initializeEngine' function.
-
You should check the bug report system to see if there something related.
If not please consider opening new report providing a minimal compilable example reproducing the behavior.
-
@SGaist I've been trying to use QFile::exists to do just that, it returns false and I know the resource I'm testing is correct.
https://forum.qt.io/topic/112882/how-to-check-if-a-resource-exists/3
[Edit] Since my original post I then changed the URI and instead of qrc:/ I used :/, it works with :/
-
I see: "qrc:/" is an URL scheme like http:/ or file:/ which is used when using QUrl. QFile on the other hand does no make use of schemes therefor the :/ which means: root of the "resources filesystem".