Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple items selection from ListView

Tags:

qt

qml

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.

like image 849
Vedanshu Avatar asked Jul 18 '16 13:07

Vedanshu


1 Answers

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.

like image 106
Vedanshu Avatar answered Oct 13 '22 10:10

Vedanshu