[Interest] Define map of static items in QML

Alejandro Exojo suy at badopi.org
Sat Apr 2 17:02:12 CEST 2016


El Wednesday 30 March 2016, Elvis Stansvik escribió:
> > not at all if that suit you for your key, it's all good. objectname is
> > just a string property after all. id would be a bad idea, since it
> > depend on the context instance.
> 
> Alright, then I think I'll do that, thanks.

This was an interesting thread. Is surprising that such a simple thing can't 
be done more elegantly. I've been trying to think of a "pretty" way, and it 
took me a bit to do it in QML only. The only really good solution would 
require some C++. Actually, a simple one would be to use

Since the objectName is OK for you, a solution that looks more elegant to me, 
would be laying out the objects directly under the default property of some 
element:

Root {
	A {objectName: "a"}
	B {objectName: "b"}
	C {objectName: "c"}
}

Then I thought you could access them by using something like 
QObject::findChild. Since that function is not exposed to QML, you would have 
either to make a similar one and expose it yourself.

I've tried to get a QML only solution that was pretty enough, and I've almost 
failed, since I've hit several limitations of the language that would have 
made this simpler.

Attempt 1:

// Helper.qml
QtObject {
    default property var stuff
    function get(name) {
        for (var i = 0; i < stuff.length; i++) {
            if (stuff[i].objectName == name)
                return stuff[i];
        }
    }
}
// Now you could do this in main.qml
ApplicationWindow {
    visible: true
    Helper {
        id: pages // Here you would add the Foo{} and Bar{} "pages"
        QtObject {objectName: "foo"}
        QtObject {objectName: "bar"}
        QtObject {objectName: "baz"}
    }
    Component.onCompleted: {
        console.log(pages.get("foo"));
    }
}

But no, doesn't work:

https://bugreports.qt.io/browse/QTBUG-10822

The default property gets overwritten each time, and it doesn't set a list. 
Only the last one remains. Item has a default property like that (and even 
QtObject could have it, probably left out for saving memory), but it's done in 
C++.

A possible workaround that would not be that nice here, because we don't want 
an Item as a helper, we want a QtObject:

http://lists.qt-project.org/pipermail/development/2013-October/013428.html


Attempt 2:

Since the default property can't be used, surrender and use a named one when 
assigning:

// Helper.qml
QtObject {
    // Now the property is not default
    property var stuff
    // ...
}
// main.qml
ApplicationWindow {
    visible: true
    Helper {
        id: screens
        stuff: [
            QtObject {objectName: "foo"},
            QtObject {objectName: "bar"},
            QtObject {objectName: "baz"}
        ]
    }
    Component.onCompleted: {
        console.log(screens.get("foo"));
    }
}

And this fails too:
main.qml:9 Cannot assign multiple values to a singular property


Attempt 3:

OK, the Helper is easily fixable now:

QtObject {
    property list<QtObject> stuff
    // ... same as before
}

Now you can get the main as previously. This finally works.


Again, if you had more possibilities in the QML language (like defining an 
enumeration in QML, for example) you could think of other solutions.

-- 
Alex (a.k.a. suy) | GPG ID 0x0B8B0BC2
http://barnacity.net/ | http://disperso.net



More information about the Interest mailing list