2016-06-09 10:22 GMT+02:00 Elvis Stansvik <elvst...@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 <elvst...@gmail.com>: >> 2016-06-09 8:20 GMT+02:00 Elvis Stansvik <elvst...@gmail.com>: >>> 2016-06-09 7:54 GMT+02:00 Elvis Stansvik <elvst...@gmail.com>: >>>> 2016-06-08 23:59 GMT+02:00 Jason H <jh...@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" <elvst...@gmail.com> >>>>> To: "Kristoffersen, Even (NO14)" <even.kristoffer...@honeywell.com>, >>>>> "interest@qt-project.org Interest" <interest@qt-project.org> >>>>> >>>>> Subject: Re: [Interest] Awkwardness of delegates in heterogenous ListViews >>>>> >>>>> 2016-06-08 15:41 GMT+02:00 Kristoffersen, Even (NO14) >>>>> <even.kristoffer...@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....@qt-project.org] >>>>>> On >>>>>> Behalf Of Elvis Stansvik >>>>>> Sent: 8. juni 2016 15:34 >>>>>> To: interest@qt-project.org Interest <interest@qt-project.org> >>>>>> Subject: Re: [Interest] Awkwardness of delegates in heterogenous >>>>>> ListViews >>>>>> >>>>>> 2016-06-08 15:32 GMT+02:00 Elvis Stansvik <elvst...@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@qt-project.org >>>>>> http://lists.qt-project.org/mailman/listinfo/interest >>>>> >>>>> _______________________________________________ Interest mailing list >>>>> Interest@qt-project.org >>>>> http://lists.qt-project.org/mailman/listinfo/interest _______________________________________________ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest