[Development] The place of QML

Alan Alpert alan.alpert at nokia.com
Tue Apr 17 04:09:07 CEST 2012


I'm a little worried that the position of QML in Qt5 is not entirely clear. 
It's a great new technology, but that "new" part means that realistically it 
will not take over everything, everywhere, immediately upon the release of Qt 
5.0.0. To help place QML within the greater Qt context, I've written the 
following article. You will certainly need to read it if you think that Qt5 is 
pure QML (or pure C++)! It is also highly relevant to the increasing number of 
Qt developers writing QML APIs for their C++ functionality. The things I need 
feedback on are:
A) We need to establish a consensus on the role of QML within Qt.
B) Where would such an article go? Labs Blog? Qt 5 Book? Wiki or Doc page?

Now, here's the wall-of-text:

Writing QML modules in C++ for QML is an important part of the Qt/QML story 
and it helps to know what roles each part is supposed to play in the story. 
This article is written from the QML perspective, so the C++ referred to here 
is about when you implement your QML facing APIs in C++ (or implement the 
application backend in C++, for your QML frontend). The QML referred to here 
refers to the QML users of your API. This article is not relevant for QML 
facing APIs which are themselves written in QML, but those are expected to be 
extremely rare given QML's current stage of development.

QML is the User Experience (UX or UI, User Interface) layer. This means that 
the visual representation of the application is done with QML. It also means 
that logic reacting to user input is done in QML. This is highly advantageous 
in allowing the user interaction to affect the visual representation of the 
application directly. In order for user input logic to be done in QML, the 
application's functionality usually needs to be exposed in some way. This 
allows for the QML code to map the UX to the application abilities in a 
scripting language, for more versatility and rapid application development.

C++ is the data layer. This means that data manipulation and often the real 
functionality of the application remains in C++. What is exposed to QML is the 
UX abstraction of the functionality, such as an action you might find on a 
toolbar (e.g. save file). The programmatic instructions for implementing this 
on a computer remain in C++ (e.g. opening a file, writing data from the main 
view to the file, closing the file). Some logic can be done in the UX layer 
(e.g. passing the main view to the function instead of the C++ plugin assuming 
this) but only UX level abstractions should be exposed to QML. The logic of 
how to manipulate your application's data, if it is not exposed to the end 
user, should not be exposed to QML.

The split is right where a QML module's API usually lies (if the module is 
written in C++). So your API should be written with this split in mind. What 
this means in terms of API design is that such an API should expose results 
and high-level functionality to QML, anything which might be exposed directly 
to a user to manipulate. If the functionality is sufficiently low-level that 
it would never be directly called from the UI layer, try not to expose it. 
Instead, expose the higher level results that are expected so that more of the 
imperative logic can be done in C++, and to simplify any QML using it.

In the Qt/QML story it is important that you can always drop down to a, 
usually separate, C++ API for anything more complex or involved than is 
provided in the QML API. For example, in QtQuick 1.x subclassing 
QDeclarativeItem was the only solution for imperative painting in a QML scene 
because that usecase was not common enough for the first iteration (of course, 
QtQuick 2.x has the Canvas API). This is particularly true at this early 
development stage, because there is always a C++ application entry point. It 
is okay if a rare use-case is only serviced by the C++ API. There should 
usually be a C++ API as well as the QML API, although it may be shared with 
the QML API for implementation reasons.

As an example, consider file I/O. Your starting point for a QML file I/O 
plugin would be the high level QFile API, not the lower level QIODevice API. 
But even QFile exposes a lot of imperative object state and niche 
functionality. A QML File object could be as simple as filePath and contents 
properties to cover the majority of usecases. Upon changes to the filePath 
property (or item destruction) the underlying QFile could be closed and 
reopened. It could read the file contents into a buffer at that time for 
updating the contents property when read by QML. Changes to the contents 
property are treated as writes to the file. There is some inefficiency in this 
implementation compared to a C++ implementation, but (for this example at 
least) large files are a minority use case which is catered for using the C++ 
API. High-performance usecases will usually need to use the C++ API directly 
for the efficiencies given by having fine grained control. A Hex editor would 
likely need to expose its own file handling for the binary view of file data, 
but could still use the simple File element for a preview pane.

Alan Alpert
Senior Engineer
Nokia, Qt Development Frameworks

More information about the Development mailing list