[Interest] Define map of static items in QML

Elvis Stansvik elvstone at gmail.com
Wed Mar 30 18:18:21 CEST 2016


Den 30 mar 2016 5:49 em skrev "Jérôme Godbout" <jerome at bodycad.com>:
>
> 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.

Elvis

>
> 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:
>>>>
>>>>
>>>
>>> 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/67db8861/attachment.html>


More information about the Interest mailing list