[Interest] Awkwardness of delegates in heterogenous ListViews

Elvis Stansvik elvstone at gmail.com
Thu Jun 9 10:34:51 CEST 2016


2016-06-09 10:22 GMT+02:00 Elvis Stansvik <elvstone at gmail.com>:
> Okay, this thread is getting long, but I've now found a solution I
> think I'm happy with, I thought I'd share it:
>
> First, my ColorDelegate, a delegate for items of type "color":
>
> ColorDelegate.qml:
>
> Row {
>     readonly property alias color: colorDialog.color
>
>     ColorButton {
>         color: value
>         onClicked: {
>             colorDialog.open()
>             colorDialog.currentColor = color
>         }
>     }
>
>     Text {
>         text: name
>         color: Style.foregroundColor
>         anchors.verticalCenter: parent.verticalCenter
>     }
>
>     ColorDialog {
>         id: colorDialog
>         title: name
>         showAlphaChannel: true
>     }
> }
>
> I'm here aliasing the color property of the ColorDialog I use to let
> the user choose the color. Note that this delegate has no references
> to ListView attached properties of its parent (or itself), so it makes
> no assumptions about how it is used (nested in a delegate or as a
> delegate itself), so it can be used in both scenarios (e.g. when I
> have a heterogenous list model, or a model where I know all items will
> be of type "color").
>
> Then my "super"-delegate ItemDelegate:
>
> ItemDelegate.qml:
>
> Item {
>     readonly property alias color: colorDelegate.color
>
>     height: 2 * TextSingleton.implicitHeight
>     width: parent.width
>
>     ColorDelegate {
>         id: colorDelegate
>         visible: type === "color"
>     }
>
>     Text {
>         visible: type === "flag"
>         text: "TODO: delegate for flag items"
>     }
>
>     Text {
>         visible: type === "choice"
>         text: "TODO: delegate for choice items"
>     }
> }
>
> Here I'm using Jason's suggestion of simply making the constituent
> delegates visible/invisible based on the type of the item, and again
> I'm aliasing the color property upwards, so the "super"-delegate has a
> color property.
>
> Then, in my actual ListView I have:
>
>     ListView {
>         model: themeModel
>         anchors.fill: parent
>
>         section.property: "section"
>         section.delegate: SectionDelegate { }
>
>         delegate: ItemDelegate {
>             onColorChanged: themeModel.setColor(index, color)
>         }
>     }
>
> Here, I know the model being used (themeModel), and handle changes in
> color (which equates to changes in color of the ColorDelegate further
> down) by calling my model's setColor slot.
>
> I'll now do it similarly for other types of items. I think this can
> work for me, since my item types are quite simple and "mutually
> exclusive" so to speak, so I won't have conflicting properties to
> alias.
>
> Thanks for all the input!

And as soon as I said that, I realize that this solution is bust: I
can't use the visible/invisible trick since the various delegates will
then make illegal uses of the items. I must use the Loader approach.
But if I use the loader approach, then my solution with propagating
the properties upwards with property aliases won't work, since the
Loader can't alias a property of the delegates since they're now
wrapped in Component.

Oh well, I think i'll just give up on having these delegates drop-in
usable in both scenarios.

Elvis

>
> Elvis
>
> 2016-06-09 9:38 GMT+02:00 Elvis Stansvik <elvstone at gmail.com>:
>> 2016-06-09 8:20 GMT+02:00 Elvis Stansvik <elvstone at gmail.com>:
>>> 2016-06-09 7:54 GMT+02:00 Elvis Stansvik <elvstone at gmail.com>:
>>>> 2016-06-08 23:59 GMT+02:00 Jason H <jhihn at gmx.com>:
>>>>> I'm coming into this late, but can't you just set up:
>>>>>
>>>>> Item { // delegate
>>>>>
>>>>>   Item {
>>>>>     id: view1
>>>>>      visible: some_data_item_property == true
>>>>>   }
>>>>>   Item {
>>>>>     id: view2
>>>>>     visible: !view1.visible
>>>>>   }
>>>>> }
>>>>>
>>>>> Then make view1 and view2 your different delegates? You're just going after
>>>>> two diferent views, right?
>>>>
>>>> Well it's ~5, but indeed that seems to work great! A little test:
>>>>
>>>>
>>>> import QtQuick 2.4
>>>> import QtQuick.Window 2.2
>>>>
>>>> import "."
>>>>
>>>> Window {
>>>>     title: "Test"
>>>>     width: 600
>>>>     height: 900
>>>>     visible: true
>>>>
>>>>     ListModel {
>>>>         id: listModel
>>>>         dynamicRoles: true
>>>>         Component.onCompleted: {
>>>>             append({
>>>>                 "type": "color",
>>>>                 "name": "foo",
>>>>                 "value": "red"
>>>>             });
>>>>             append({
>>>>                 "type": "flag",
>>>>                 "name": "bar",
>>>>                 "value": false
>>>>             });
>>>>             append({
>>>>                 "type": "choice",
>>>>                 "name": "bar",
>>>>                 "value": "Foo",
>>>>                 "choices": ["Foo", "Bar"]
>>>>             });
>>>>         }
>>>>     }
>>>>
>>>>     ListView {
>>>>         anchors.fill: parent
>>>>
>>>>         model: listModel
>>>>         delegate: Rectangle {
>>>>             implicitHeight: {
>>>>                 if (type === "color")
>>>>                     return colorDelegate.implicitHeight
>>>>                 if (type === "flag")
>>>>                     return flagDelegate.implicitHeight
>>>>                 if (type === "choice")
>>>>                     return choiceDelegate.implicitHeight
>>>>             }
>>>>             Text {
>>>>                 id: colorDelegate
>>>>                 text: value + " (color)"
>>>>                 visible: type === "color"
>>>>             }
>>>>             Text {
>>>>                 id: flagDelegate
>>>>                 text: value + " (flag)"
>>>>                 visible: type === "flag"
>>>>             }
>>>>             Text {
>>>>                 id: choiceDelegate
>>>>                 text: value + " (choice)"
>>>>                 visible: type === "choice"
>>>>             }
>>>>         }
>>>>     }
>>>> }
>>>>
>>>
>>> It does not really solve the "problem" though. Say one of my delegates
>>> is a ColorDelegate for when the item represents a color, and I want to
>>> provide editing (my model has a setColor(index, color)).
>>>
>>> I will then have to use parent.ListView.view.model.setColor(index,
>>> color), thereby tying the color delegate to this way of working: It
>>
>> It seems there is actually something called just "model" available in
>> the delegate and its children, but it's of type
>> QQmlDMAbstractItemModelData, and I get a TypeError if trying to treat
>> it as my custom model (e.g. calling my setColor(index, color) slot).
>>
>> Elvis
>>
>>> can't be reused in another context where I have a model known to
>>> consist of only colors (well not without artificially nesting it
>>> inside something else, like an invisible Rectangle, so that the
>>> reference to setColor works).
>>>
>>> On the C++ side, it's a bit easier to make delegates that are reusable
>>> in these two situations, since you work with createEditor and friends
>>> instead.
>>>
>>> Elvis
>>>
>>>>
>>>> I wonder why I haven't seen this approach before while searching around.
>>>>
>>>> Elvis
>>>>
>>>>>
>>>>> Sent: Wednesday, June 08, 2016 at 11:49 AM
>>>>> From: "Elvis Stansvik" <elvstone at gmail.com>
>>>>> To: "Kristoffersen, Even (NO14)" <Even.Kristoffersen at honeywell.com>,
>>>>> "interest at qt-project.org Interest" <interest at qt-project.org>
>>>>>
>>>>> Subject: Re: [Interest] Awkwardness of delegates in heterogenous ListViews
>>>>>
>>>>> 2016-06-08 15:41 GMT+02:00 Kristoffersen, Even (NO14)
>>>>> <Even.Kristoffersen at honeywell.com>:
>>>>>> Have you tried something like this in the delegate?
>>>>>>
>>>>>> property alias some_descriptive_name: parent
>>>>>
>>>>> It seems it's not allowed to use parent as the target of an alias (?):
>>>>>
>>>>> file:///home/estan/qte/qte/qml/ItemDelegate.qml:5 Invalid alias reference.
>>>>> Unable to find id "parent"
>>>>>
>>>>> And this would still tie my "subdelegates" to this structure. They could not
>>>>> be reused in other places, where lists are homogenous and I'm not using the
>>>>> Loader approach.
>>>>>
>>>>> But I guess there's really no way to make a delegate that can be used in
>>>>> both the "normal" situation and in the indirect-through-Loader approach.
>>>>>
>>>>> Elvis
>>>>>
>>>>>>
>>>>>> (Not tested, just an idea)
>>>>>>
>>>>>> -Even
>>>>>>
>>>>>> -----Original Message-----
>>>>>> From: Interest
>>>>>> [mailto:interest-bounces+even.kristoffersen=honeywell.com at qt-project.org] On
>>>>>> Behalf Of Elvis Stansvik
>>>>>> Sent: 8. juni 2016 15:34
>>>>>> To: interest at qt-project.org Interest <interest at qt-project.org>
>>>>>> Subject: Re: [Interest] Awkwardness of delegates in heterogenous ListViews
>>>>>>
>>>>>> 2016-06-08 15:32 GMT+02:00 Elvis Stansvik <elvstone at gmail.com>:
>>>>>>> Hi all,
>>>>>>>
>>>>>>> I'm currently using a "type" role in my items and then a Loader as
>>>>>>> delegate, to give a level of indirection and let me choose the actual
>>>>>>> delegate based on the "type" of the item.
>>>>>>>
>>>>>>> This explains it better (from my ListView):
>>>>>>>
>>>>>>> delegate: Loader {
>>>>>>> sourceComponent: {
>>>>>>> switch (type) {
>>>>>>> case "color":
>>>>>>> return colorDelegate
>>>>>>> case "flag":
>>>>>>> return flagDelegate
>>>>>>> ...
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>> Component {
>>>>>>> id: colorDelegate
>>>>>>>
>>>>>>> ColorDelegate { }
>>>>>>> }
>>>>>>>
>>>>>>> Component {
>>>>>>> id: flagDelegate
>>>>>>>
>>>>>>> FlagDelegate { }
>>>>>>> }
>>>>>>>
>>>>>>> ...
>>>>>>> }
>>>>>>>
>>>>>>> What I don't like with this approach is that inside my delegates, e.g.
>>>>>>> ColorDelegate.qml, I have to use parent.ListView.view.model to get a
>>>>>>
>>>>>> I should clarify: I have to use this notation since it is the parent (the
>>>>>> Loader) which is the real delegate and has the ListView attached properties.
>>>>>>
>>>>>> Elvis
>>>>>>
>>>>>>> reference to the model (needed for editing operations). The use of
>>>>>>> "parent" here assumes a certain layout, but I see no other way :(
>>>>>>>
>>>>>>> How have others solved the issue of delegates for heterogenous lists?
>>>>>>>
>>>>>>> Best regards,
>>>>>>> Elvis
>>>>>> _______________________________________________
>>>>>> Interest mailing list
>>>>>> Interest at qt-project.org
>>>>>> http://lists.qt-project.org/mailman/listinfo/interest
>>>>>
>>>>> _______________________________________________ Interest mailing list
>>>>> Interest at qt-project.org
>>>>> http://lists.qt-project.org/mailman/listinfo/interest



More information about the Interest mailing list