[Interest] Define map of static items in QML

Elvis Stansvik elvstone at gmail.com
Fri Jun 3 17:55:49 CEST 2016


Hi Alejandro,

I realized I never got back to this and answered you, sorry about that.

2016-04-02 17:02 GMT+02:00 Alejandro Exojo <suy at badopi.org>:
> 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.

Thanks a lot for investigating these options. Your final solution is
nice, but I agree it's suprising how hard this was to do in QML, and
that the solution is still not 100% declarative.

What I ended up doing was abandon the idea of naming my objects with,
and using the ObjectModel approach and giving each page an id instead.
Simplified, something like this:

Window {
    visible: true

    ObjectModel {
        WelcomePage { id: welcomePage }
        SettingsPage { id: settingsPage }
        ScanPage { id: scanPage }
    }

    StackView {
        id: stackView
        anchors.fill: parent

        initialItem: welcomePage
    }
}

Then I can do e.g. stackView.push(scanPage) in other parts of my QML code.

It still feels like a little like abusing ObjectModel, since it's
meant to be used as a model for an item view, not as a general holder
of items which you don't want to be visible.

Cheers,
Elvis

>
>
> 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
> _______________________________________________
> Interest mailing list
> Interest at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/interest



More information about the Interest mailing list