How to Write Conditional Import Statements in Qml

How to write conditional import statements in QML?

Depending on what you want to achieve, a possible workaround is to use a Loader. But it does not import a module, it just allows to choose dynamically which QML component you'll use.

Loader
{
source: condition?"RedRectangle.qml":"BlueRectangle.qml"
}

QML import later module version only if available?

Conditional imports were requested as a feature for Qt 4.7, but have not been implemented yet; see the bug report for details.

However, it's possible to use a Loader to make sure that the import failure does not prevent the rest of the GUI from loading. This is outlined in one of the comments in the bug-report discussion.

FAILING CASE:

// MyContainer.qml
Item {
AlwaysAvailableType {
// ... etc
}
SometimesNonworkingType {
id: nonworking_thing
// ... FAILS to load!
}
}

Here, we assume that SometimesNonworkingType.qml contains the import statement that will fail on some systems but not others. When the QML engine tries to load MyContainer, it will fail, causing the entire QML loading operation to fail.

FIXED VERSION:

// MyContainer.qml
Item {
AlwaysAvailableType {
// ... etc
}
Loader {
source: "SometimesNonworkingType.qml"
property bool valid: item !== null

id: maybeworking_thing
// ... etc
}
}

maybeworking_thing.valid can be used to check if the SometimesNonworkingType was actually successfully loaded.

(Credit for finding the bug report: How to write conditional import statements in QML?)

QML how to create different types based on a condition

Try it with a Loader

Loader {
property bool shouldBeText
Component { id: rect; Rectangle {}}
Component { id: text; Text {}}
sourceComponent: shouldBeText ? text : rect
}

If statement in QML

You can do it like this:

color: (hand.callValue >= hand.handRaiseXBB) ? hand.handFoldColor : hand.handCallColor

You could also make a function to calculate it and then assign the color property with the return value of the function:

function getHandColor()
{
var handColor = hand.handCallColor
if(hand.callValue >= hand.handRaiseXBB)
{
handColor = hand.handFoldColor
}
return handColor
}
color: getHandColor()

Custom Button with conditional image and conditional text

As @BaCaRoZzo already suggested, using styles is preferable solution in this case since the item itself is still Button and so you can use all its properties and signals, including text property to pass your ueText text.

As for hiding elements inside, you can use visible property as suggested below:

UeButton.qml

Button {
id: ueButton
style: ButtonStyle {
background: Rectangle {
color: control.pressed ? "#CCC" : "#DEDEDE"
border.width: 1
border.color: "#999"
radius: 3
}
label: ColumnLayout {
id: layout
spacing: 10
Image {
Layout.alignment: Qt.AlignHCenter
source: control.iconSource
visible: control.iconSource !== ""
}

Text {
text: control.text
visible: control.text !== ""
}
}
}
}

Now using of this component is similar to regular Button:

UeButton {
anchors.centerIn: parent
text: "Some text"
iconSource: "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
}

Commenting out text or iconSource will change the button view

Introduce condition in delegate

As @derM comments one option is to use Loader, in the following example each point has an attribute called type that serves to distinguish which items should be drawn a rectangle or circle.

Marker.qml

import QtQuick 2.0
import QtLocation 5.6

MapQuickItem {
sourceItem: Loader{
sourceComponent:
if(type == 0)//some condition
return idRect
else if(type == 1) //another condition
return idCircle

}
Component{
id: idRect
Rectangle{
width: 20
height: 20
color: "blue"
}
}
Component{
id: idCircle
Rectangle{
color: "red"
width: 20
height: 20
radius: 50
}
}
}

main.qml

MapItemView {
model: navaidsModel
delegate: Marker{
coordinate: position
}
}

Output:

Sample Image

You can find a complete example in the following link.

How to simulate C-style ifdef macro 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



Related Topics



Leave a reply



Submit