[Development] The place of QML
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.
Nokia, Qt Development Frameworks
More information about the Development