I need to switch off some parts of QML code, because this code has been done for demo purposes and it will be removed in final release. But the product will be used with these demo features for long, so I can't use a separate branch with demo features and constantly merge all new features to that branch - it's just not convenient. So it'd be nice to have this code running but easy to switch off and/or remove when needed. In C and C++ I use ifdef
macro for that, but is it possible to do the same in QML?
As @Mark suggested, context properties can be used in QML to decide in run time if some macro is enabled or not, but the example he provides does not address the case, when you need to instantiate an object based on this decision, but only covers case when inside a code block. So I will provide the full example of what I did.
In my case I exposed a class to QML only when a macro was defined during compile time:
main.cpp:
#ifdef SMTP_SUPPORT
qmlRegisterType<SmtpClientHelper>("com.some.plugin", 1, 0, "SmtpClient");
engine.rootContext()->setContextProperty("SMTP_SUPPORT", QVariant(true));
#else
engine.rootContext()->setContextProperty("SMTP_SUPPORT", QVariant(false));
#endif // SMTP_SUPPORT
Then on QML side I check this macro and decide if SmtpClient object must be created:
qml:
import QtQuick 2.0;
import com.some.plugin 1.0
Item {
id: root
// ...
property var smtpClient // No inside any function, need to instantiate the object
Component.onCompleted: {
if (SMTP_SUPPORT) {
smtpClient = Qt.createQmlObject(' \
import QtQuick 2.0; \
import com.some.plugin 1.0; \
SmtpClient { \
id: smtpClient; \
\
function setSenderEmail(email) { \
senderEmail = email; \
storage.save("common", "clientEmail", email); \
} \
} \
', root, "SmtpClient");
}
}
// Reference smtpClient normally, like if it was statically created
TextInput {
id: senderEmailLogin
anchors.fill: parent
font.pixelSize: Globals.defaultFontSize
text: smtpClient ? smtpClient.senderEmail : ""
onEditingFinished: if (smtpClient) smtpClient.setSenderEmail(text)
activeFocusOnPress: true
}
}
I think Loader should also do the job, so you could create a separate component, reference it in Loader's source
or sourceComponent
properties if C++ macro is defined, but I am not sure, because not sure if this component will be statically checked if (in my case) SmtpClient
type is available
It's not the same as an #ifdef because the decision making all happens at runtime, but I sometimes use this approach, which gives a similar usage pattern.
main.cpp
QQmlApplicationEngine engine;
#ifdef DEMO_MODE
engine.rootContext()->setContextProperty("DEMO_MODE", QVariant(true));
#else
engine.rootContext()->setContextProperty("DEMO_MODE", QVariant(false));
#endif
engine.load(QUrl("qrc:/ui/MainQmlFile.qml"));
then, from any .qml file in the project
if (DEMO_MODE) {
} else {
}
If you can refactor those parts into their own components, you have two options:
The first option is perhaps a bit closer to a C-style #ifdef
macro than using Loader
, as it works at the file level. As long as you don't overuse Loader
, though (e.g. as a delegate in a large view), they should both do the job fine.
#ifdef
is a preprocessor instructions, i.e. something processed at build time before the C or C++ compiler gets to see the code.
You could do the same using your text manipulation language of choice, processing the QML files at build time before they get processed e.g. by the Qt resource compiler.
You can also use class DebugC with function
Q_INVOKABLE bool isDebuggingEnable()
{
#ifdef QT_DEBUG
return true;
#else
return false;
#endif
}
and then register this class in qml
viewer->rootContext()->setContextProperty("stName", DebugCObj)
now you can easily call stName.isDebuggingEnable() method for checking debugging is enable or not in your QML file. its just a trick
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With