PDA

View Full Version : Can Repeater delegate in Qml be made to behave in a generic way to the given Items?



ustulation
18th June 2013, 06:21
{quick 2.0, Qml Qt 5.1 beta}

I wanted to know if such an idiom would be possible in Qml: Below I have objLeftColumn which expects its children to expose a boolean m_bIsSelected and a MouseArea alias m_mouseProperty and uses them to make the collection of such children mutually exclusive, ie., only one of them can be in selected state. The followin works fine but I need to repeat it every time I want and specially if I wanted it for Row etc.

Column {
id: objLeftColumn

property int m_iLastButtonClicked: -1
property int m_iCurrentButtonClicked: -1

onM_iCurrentButtonClickedChanged: {
if(m_iLastButtonClicked != -1) {
objLeftColumn.children[m_iLastButtonClicked].m_bIsSelected = false
}
m_iLastButtonClicked = m_iCurrentButtonClicked
}

Repeater {
id: objLeftColumnRepeater

model: 5

delegate: ABCD {
id: objABCD

m_mouseProperty.onClicked: {
if(m_bIsSelected) {
objLeftColumn.m_iCurrentButtonClicked = index
}
else {
objLeftColumn.m_iLastButtonClicked = -1
objLeftColumn.m_iCurrentButtonClicked = -1
}
}
}
}
}

Can I write a generic objLeftColumn (in a separate qml file) that could arrange the given Items in Column while aslo dealing with exclusivity of their selection?

The idea is instead of giving the component to the delegate right there an then, I'll give it later and for each instantiation of the component (depending on numeric value of model above and below) the delegate: in Repeater should behave similarly.

eg., in psedo code:

in Exclusive.qml:

Column {
id: objLeftColumn

property int m_iLastButtonClicked: -1
property int m_iCurrentButtonClicked: -1

property alias m_delegate: objLeftColumnRepeater.delegate

onM_iCurrentButtonClickedChanged: {
if(m_iLastButtonClicked != -1) {
objLeftColumn.children[m_iLastButtonClicked].m_bIsSelected = false
}
m_iLastButtonClicked = m_iCurrentButtonClicked
}

Repeater {
id: objLeftColumnRepeater

model: 5
onItemAdded: {
//state of item can be manipulated but want to
//add behaviour to the item (like accessing a function through virtual mechanism in c++) eg:
/*item {
m_mouseProperty.onClicked: {
//do something
}
}*/
}
}
}

in SomeOther.qml:

Exclusive {
m_delegate: ABCD
}

Exclusive {
m_delegate: DEFG
}

etc..So this way Column in Exclusive is more generic and can be called with any Item assigned to its (Repeater's) delegate: and will behave similarly. Requirements: the item should expose m_mouseProperty (alias for MouseArea) and m_bIsSelected (bool) property.

wysota
18th June 2013, 08:02
Shouldn't something like that work?

Column {
id: col
property int selectedIndex: -1

Repeater {
model: 5
Rectangle {
width: 200; height: 50
color: col.selectedIndex == index ? "red" : "white"
MouseArea {
anchors.fill: parent
onClicked: col.selectedIndex = index
}
}
}
}

You can easily create a component from it like so:

Column {
id: col
property alias delegate: rep.delegate
property alias model: rep.model
property int selectedIndex: -1

Repeater {
id: rep
}
}

If you really want to, you can adjust the delegate to add a MouseArea to the delegate to have everything contained in a single component, probably more or less like so:

Column {
id: col
property Component delegate
property alias model: rep.model
property int selectedIndex: -1

Repeater {
id: rep
}
Component {
id: macmp
MouseArea {
anchors.fill: parent
onClicked: col.selectedIndex = index
}
}
onDelegateChanged: {
var obj = delegate.createInstance(rep) // or create the item elsewhere and assign it to the rep.delegate
var ma = macmp.createInstance(obj)
}
}

ustulation
18th June 2013, 20:31
no that part is clear to me. As I wrote in the comments to the code manipulating the delegate item's state is easy. How do you add a behaviour? eg.,


SomeComponent {
m_mouseProperty.onClicked: {
//add behaviour
}
}

here in SomeComponent.qml the component could already have implemented some behaviours on onClicked. What I believe I've done above is added to that behaviour so that in addition to all that it was doing on onClicked it will also do whatever it is asked to in above code. The question is can I somehow achieve this in delegate of a repeater (of a Column in this eg.):

Generic.qml

Column {
property alias m_delegate: objRepeater.delegate
property alias m_count: objRepeater.model
Repeater {
id: objRepeater
}
}

Now if I use Generic.qml it should add a behaviour to the component supplied as a delegate:

Generic {
m_delegate: SomeItemWith_m_mouseProperty
m_count: 5
}


now Generic should be able to add behaviour to m_mouseProperty (which is an alias to MouseArea in this eg.)


onM_delegateChanged: {
children[index].m_mouseProperty.onClicked: {
//Add behaviour...ie., Do something
}
}


this ofcourse gives an error. So i can modify the state (children[index].m_someProperty = false is perfectly legal) but can I also add behaviour (say on onClicked) like in the example above?

wysota
18th June 2013, 22:29
I don't understand what you mean. If you want to stack mouse areas then you can do that. If one area ignores an event, an underlying area will get it, etc.
If you want a series of functions to be executed as a result of an event then it should be possible as well -- you can create an array of javascript functions and have something execute them one after the other.