Proposal: Qt Quick Designer Workflow

The classical Widget Designer is built around the distinction between declarative form and imperative logic. The declarative form is designable and stored in .ui files.

In Qml it is easy to mix declarative code and imperative code. If you add imperative instructions (affecting visual aspects) to your Qml files they are not purely declarative anymore and the visual representation in the visual editor will break. The visual editor needs a way to translate the visual description back into the text description. For imperative code this is not possible in general and the Qt Quick Designer does not even try.

The following snippet is illustrating a visual editor unfriendly:

Item {
width: 800
height: 600
Rectangle {
id: rectangle
width: 100
height: 100
}
Component.onCompleted: center(rectangle)
}

Component.onCompleted is called only once but the Qt Quick Designer can change the width and height multiple times. What could we do about it? Should we call Component.onCompleted after every change in the visual editor? It would work for the center script but what if there were an object creation. We could recreate the complete scene for every change but the latency would prevent any productive work.

The center function is transforming the position. How can the visual editor know that the position will be changed by the center function? You need an understanding of the intent of the code, which the visual editor doesn't have and generally cannot have. So we decided that the Qt Quick Designer is ignoring handlers and scripts.

The visual editor does evaluate bindings, since bindings are still declarative. But still the visual editor does not have any "understanding" of bindings. A binding is a black box for the visual editor.

If you open a file which depends heavily on handlers and scripts it can be looking very differently in the visual editor than in the application because the scripts can affect visual traits. For these cases the visual editor cannot be used to full extent.

Another aspect is the general workflow. Some people would still like to keep design and code completely apart like in the classical ui file approach. Luckily Qml already allows it but doesn't enforce it. This means any user of Qml can take his way of choice.

So we did research and came up with the following idea. Let's give an example how to break design and logic apart in Qml. The first file is edited in the visual editor and the second in the text editor. So there is again a clear boundary between declarative form and imperative logic.

CalculatorPage_ui.qml

import QtQuick 1.0
import com.nokia.symbian 1.0

Page {
id: calculatorPage

property Item button: button

Button {
id: button
x: 0
y: 195
width: 80
height: 80
text: "1"
}

states: [
State {
name: "horizontal"
when: screen.currentOrientation == Screen.Landscape

PropertyChanges {
target: button
x: 87
y: 45
}
}
]
}

CalculatorPage.qml

import QtQuick 1.0
import "calculator.js" as Calculator

CalculatorPage_ui {
Connections {
target: button
onClicked: Calculator.appendSign("1")
}
}

You can describe all your declarative stuff in the the ui file and then derive the file with the imperative logic from it. To get access to the internal objects you have to export them with the property Item itemId: itemId syntax. In the derived file you use Connections to add handlers to the object.

What do you think about it? Your opinion is very important to us.

Download a simple example application.


Blog Topics:

Comments