[Interest] Define map of static items in QML

Jérôme Godbout jerome at bodycad.com
Wed Mar 30 17:49:19 CEST 2016


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.

On Wed, Mar 30, 2016 at 11:24 AM, Elvis Stansvik <elvstone at gmail.com> wrote:

> 2016-03-30 17:22 GMT+02:00 Elvis Stansvik <elvstone at gmail.com>:
>
>> 2016-03-30 16:55 GMT+02:00 Jérôme Godbout <jerome at bodycad.com>:
>>
>>> You may want to have them declared as list of object with the key as a
>>> property of each entry, and build the map based on the list content.
>>>
>>> ex:
>>>
>>> *// May have to change the list type here*
>>> *property list<Screen> myScreens:*
>>> *[*
>>> *     WelcomeScreen { property string keyName: 'welcome' }*
>>> *   , OtherScreen { property string keyName: 'other' }*
>>> *]*
>>>
>>> *property var myScreenMap: listToMapByProperty(myScreens, 'keyName')*
>>>
>>> *// This can be put into pargma library .js*
>>> *function listToMapByProperty(list, mapKey)*
>>> *{*
>>> *   var rv = {};*
>>> *   for(var i = 0; i < list.length; ++i)*
>>> *   {*
>>> *      rv[list[i][mapKey]] = list[i];*
>>> *   }*
>>> *   return rv;*
>>> *}*
>>>
>>> This should be reusable and allow for easy declaration of Items/Objects.
>>> Just need the same property to be declared inside each one. You can also
>>> iterate on the list.
>>>
>>> Here's the result of this code with QtObject, but the idea is the same:
>>> *Item*
>>> *{*
>>> * property list<QtObject> myScreens:*
>>> * [*
>>> * QtObject { property string keyName: 'welcome' }*
>>> *   , QtObject { property string keyName: 'other' }*
>>> * ]*
>>>
>>> * property var myScreenMap: listToMapByProperty(myScreens, 'keyName')*
>>>
>>> * // This can be put into pargma library .js*
>>> * function listToMapByProperty(list, mapKey)*
>>> * {*
>>> *   var rv = {};*
>>> *   for(var i = 0; i < list.length; ++i)*
>>> *   {*
>>> *  rv[list[i][mapKey]] = list[i];*
>>> *   }*
>>> *   return rv;*
>>> * }*
>>> *}*
>>> resulting into those properties into the item:
>>> [image: Inline image 1]
>>>
>>>
>> Thanks a lot, I like this approach very much!
>>
>
> Btw, do you think it's a bad idea to use the objectName property for this
> purpose, instead of a custom keyName property like you did?
>
> Elvis
>
>
>>
>> Elvis
>>
>>
>>> On Wed, Mar 30, 2016 at 5:19 AM, Elvis Stansvik <elvstone at gmail.com>
>>> wrote:
>>>
>>>> 2016-03-30 11:08 GMT+02:00 Gianluca <gmaxera at gmail.com>:
>>>> >
>>>> > Il giorno 30/mar/2016, alle ore 09:46, Elvis Stansvik <
>>>> elvstone at gmail.com> ha scritto:
>>>> >
>>>> >> Hi Gianluca,
>>>> >>
>>>> >> 2016-03-30 10:16 GMT+02:00 Gianluca <gmaxera at gmail.com>:
>>>> >>>
>>>> >>> Il giorno 30/mar/2016, alle ore 07:43, Elvis Stansvik <
>>>> elvstone at gmail.com>
>>>> >>> ha scritto:
>>>> >>>
>>>> >>> Den 30 mar 2016 8:36 fm skrev "Elvis Stansvik" <elvstone at gmail.com
>>>> >:
>>>> >>>>
>>>> >>>> Hi all,
>>>> >>>>
>>>> >>>> I can understand why I can do
>>>> >>>>
>>>> >>>> property Item foo: Foo {}
>>>> >>>> property Item bar: Bar {}
>>>> >>>> property variant items: {
>>>> >>>>    "foo": foo,
>>>> >>>>    "bar": bar
>>>> >>>> }
>>>> >>>>
>>>> >>>> but not
>>>> >>>>
>>>> >>>> property variant items: {
>>>> >>>>    "foo": Foo{},
>>>> >>>>    "bar": Bar{}
>>>> >>>> }
>>>> >>>>
>>>> >>>> The first opening { in the second example probably puts me in JS
>>>> >>>> territory, where the Item {} syntax is not understood as a static
>>>> definition
>>>> >>>> of an item.
>>>> >>>>
>>>> >>>> However, is there some way of defining a map of static items like
>>>> this,
>>>> >>>> without having to bind the item instances to properties first?
>>>> Such that I
>>>> >>>> can later do e.g. items["foo"] to access an item?
>>>> >>>
>>>> >>> I should state my use case as well: I'm doing a small page based
>>>> embedded
>>>> >>> app (less than 20 pages), based on a StackView, where I'm
>>>> thankfully not
>>>> >>> hardware constrained (it's a fast PC). So I have no reason to use
>>>> Loader to
>>>> >>> load pages dynamically but was thinking of keeping them all
>>>> statically in a
>>>> >>> map, so that I can switch page based on the name of the page (e.g
>>>> >>> "WelcomeScreen") by calling some function or perhaps emitting a
>>>> signal with
>>>> >>> the name as argument.
>>>> >>>
>>>> >>> For this use cases (and others), I usually use one of the
>>>> ObjectModel,
>>>> >>> DelegateModel or Package (or the older VisualDataModel). They are
>>>> wonderful
>>>> >>> for creating models containing QML object and they can created as
>>>> you want.
>>>> >>> Also DelegateModel can contains groups so you can filter them, and
>>>> Package
>>>> >>> let you to name the items so you can access using dot syntax:
>>>> views.foo,
>>>> >>> views.bar
>>>> >>> In your case, I will use DelegateModel and access using numeric
>>>> index, but
>>>> >>> you can also explore Package and use the attached propertied
>>>> Package.name to
>>>> >>> give a name to all the views.
>>>> >>
>>>> >> Thanks a lot for the suggestions.
>>>> >>
>>>> >> I must ask though. Why would you use a DelegateModel in my case?
>>>> Would
>>>> >> you manage the name -> index mapping separately then? (to avoid
>>>> >> hardcoded indices throughout the code).
>>>> >>
>>>> >> I think I will go the Package route, the dot syntax seems like a nice
>>>> >> thing I can use.
>>>> >>
>>>> >> Elvis
>>>> >
>>>> > I think that the Package may be the best route for you, but I suppose
>>>> it can be used only with a DelegateModel and not alone. And of course, I
>>>> suggest you to give a try.
>>>>
>>>> Alright. Althought I came to think of something: Will not Package
>>>> require me to define the items fully inside the Package? E.g. I would
>>>> have to have my screens all defined in the same file, like:
>>>>
>>>> Package {
>>>>     WelcomeScreen {
>>>>         id: welcomeScreen
>>>>         Package.name: "welcomeScreen"
>>>>         ...
>>>>     }
>>>>     OtherScreen {
>>>>         id: otherScreen
>>>>         Package.name: "otherScreen"
>>>>         ...
>>>>     }
>>>>     ....
>>>> }
>>>>
>>>> My screens will be quite complex, and I would want to keep them in
>>>> separate QML files :/ So if using Package requires me to have them all
>>>> inline like this, I'll have to find some other solution.
>>>>
>>>> One idea I had was to abandon the idea with identifying screens by
>>>> their name as a string, and instead use a singleton (e.g. Screens.qml)
>>>> where I keep all the screens as properties, so I could do e.g.
>>>> Screens.welcomeScreen to refer to them. But I hit some trouble with
>>>> using multiple singletons (see my other most recent post to the list).
>>>>
>>>> > The Package has been added recently, before the introducing of
>>>> Package I used to use the Component.onCompleted to construct the name ->
>>>> index mapping. In this way, it’s less hardcoded and inside the definition
>>>> of the Items. So, if you move an item or you insert a new one in the
>>>> middle, the name -> index mapping is automatically updated without need to
>>>> touch anything.
>>>>
>>>> Alright, maybe Package is not for me though, considering the above,
>>>> and that you mention it needs a DelegateModel, which I don't think I
>>>> have any use for (the app is using a StackView as the central
>>>> navigation).
>>>>
>>>> Elvis
>>>>
>>>> >
>>>> > Ciao,
>>>> > Gianluca.
>>>> >
>>>> _______________________________________________
>>>> Interest mailing list
>>>> Interest at qt-project.org
>>>> http://lists.qt-project.org/mailman/listinfo/interest
>>>>
>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20160330/f7dc961c/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image.png
Type: image/png
Size: 12665 bytes
Desc: not available
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20160330/f7dc961c/attachment.png>


More information about the Interest mailing list