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