[Development] Controlling QML Imports

Alan Alpert 416365416c at gmail.com
Wed Dec 12 19:27:17 CET 2012

On Tue, Dec 11, 2012 at 5:27 PM, Jan Kundrát <jkt at flaska.net> wrote:
> On Tuesday, 11 December 2012 04:23:51 CEST, Alan Alpert wrote:
>> For finer-grained control over QML it would make sense to have an API
>> allowing import restrictions. Two usecases come to mind, platform
>> security contexts and scriptable applications.
> I'm currently using QML as a configuration language (being declarative looked like a great fit) in a random application. The end goal was to have one file per supported "type of thing" that the application works on. The description of each thing looks like this:
>   import foo.bar 1.0
>   ThingType {
>     // ...
>     SubThing {
>       // ...
>     }
>   }
> Because I'm stuck on 4.x for this particular application, I had to work with what is available now. In the end, I settled on:
> - Using just a QDeclarativeEngine as a good start -- no need for UI items in my use case
> - The ThingType and SubThing are actually implemented in C++
> - Enforcing that the top-level item created in QML is exactly the ThingType. This can be done when instantiating the component by checking its type via qobject_cast<QMLMyTypeThing*> and refusing to work with that QML file if this cast fails

This doesn't completely fix the problem, because if the wrong thing is
instantiated it will still be able to do things in the period while
and just after it is instantiated. For example there could be side
effects from them instantiating a different type which you exposed,
and they could still do stuff in the Component.onCompleted handler.

> - The ThingType has a QDeclarativeListProperty<QMLMySubThing> Q_PROPERTY which is also a default property. This way, the type of the children of the ThingType is enforced.

Actually this isn't enforcing the type of the children. That property
has its type enforced, but properties can be dynamically added in QML.
For example
import foo.bar 1.0
import QtQuick.Window 1.0 //Hypothetical back-port of QtQuick.Window to 4.x
ThingType {
    SubThing {}
    property Window window: Window { } //This will create a window

Being able to dynamically add properties is a core part of the
language and I think it would be far, far better to restrict the types
available than to try to disable dynamic properties for some objects.

> - If you need further enforcing of certain rules ("each ThingType has to be yellow"), you can inherit from QDeclarativeParserStatus and implement componentComplete. My code works like this:
>   if (!m_color.isYellow())
>     qmlInfo(this) << "The color must be yellow."
> - Because these errors are only warnings (and it looks like you cannot really trigger a fatal error from this stage), I have an isOk() method which I call before I use the data structure which gets created as a result of these QML files.
> If it was possible to prevent defining the QtQuick namespace from being available, that would solve half of my problems (with the required property validation being the remaining half).

Property validation within an item will always have to be done by the
item, so that's the best we'd be able to do.

> The blurb about qmlInfo() was in particular rather hard to discover -- I had read the docs about it before but could not recall the name of the function when I needed it. Searching for it via phrases like "qml error reporting" did not help much.

It's not one of the most public functions in QML. But there should
probably be a mention of it on the page about writing QML types in
C++, if anyone wants to try writing that.

Alan Alpert

More information about the Development mailing list