I want to select multiple items from a ListView
. In C++
I would have done something like this
if (clicked_card->is_selected) {
clicked_card->is_selected = false;
int i = 0;
while(selected_cards[i] != clicked_card) i++;
selected_cards.erase(selected_cards.begin() + i);
} else {
clicked_card->is_selected = true;
selected_cards.push_back(clicked_card);
}
The above code uses pointer for comparison. So how to so such selection in QML
. The solution I've come up with is something like this
Card.qml
Image {
id: delegate
property bool isSelected: false
...
MouseArea {
onClicked: {
if(isSelected === true) {
isSelected = false;
gameScene.deselectCard(selectSeq);
}
else {
isSelected = true;
gameScene.selectCard({'opParam': opParam, 'selectSeq': selectSeq});
}
}
}
}
GameScene.qml
Item {
id: gameScene
property var selectedCards: []
signal selectCard(variant userData)
onSelectCard: {
gameScene.selectedCards.push(userData)
}
signal deselectCard(variant userData)
onDeselectCard: {
for (var i = 0; i < gameScene.selectedCards.length; i += 1) {
if (gameScene.selectedCards[i].selectSeq == userData) {
gameScene.selectedCards.splice(i, 1);
break;
}
}
}
}
The problem with the above code is that I'm storing property isSelected
in a delegate which is created and destroyed by the system. So this is giving me false solution. Is there any better way of multiple selection or any improvements in the solution ? I'm using model
from C++ by subclassing QAbstractListModel
.
I found the answer in Qt
documentation. I simply have to use [DelegateModel][1]
. It has a group
property, for every group defined in a DelegateModel
two attached properties are added to each delegate item. The first of the form DelegateModel.in*GroupName*
holds whether the item belongs to the group and the second DelegateModel.*groupName*Index
holds the index of the item in that group.
import QtQuick 2.0
import QtQml.Models 2.2
Rectangle {
width: 200; height: 100
DelegateModel {
id: visualModel
model: ListModel {
ListElement { name: "Apple" }
ListElement { name: "Orange" }
}
groups: [
DelegateModelGroup { name: "selected" }
]
delegate: Rectangle {
id: item
height: 25
width: 200
Text {
text: {
var text = "Name: " + name
if (item.DelegateModel.inSelected)
text += " (" + item.DelegateModel.selectedIndex + ")"
return text;
}
}
MouseArea {
anchors.fill: parent
onClicked: item.DelegateModel.inSelected = !item.DelegateModel.inSelected
}
}
}
ListView {
anchors.fill: parent
model: visualModel
}
}
Other solution would have been to move the property isSelected
to C++ data model and use a getter and setter function to update the changes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With