c++qtqmodelindexqabstractitemview

Programmatically select QModelIndexes in QAbstractItemView


I am trying to select items of abstract item view in Qt given their string values. I have already written function that finds any QModelIndex based on it's string content.

I am now trying to put all those QModelIndexes that I find into single selection. My method signature:

    // Will select all items that contain any of the strings
    // given by 1st argument
    virtual void selectItems(const QStringList&) override;

My implementation looks like this (but doesn't work properly):

void QAbstractItemViewResult::selectItems(const QStringList& list)
{
    if(list.size() > 0) {
        QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::ClearAndSelect;
        QItemSelection selection;
        Q_FOREACH(const QString text, list) {
            // Find index by string is a method I implemented earlier
            // The method works correctly
            QModelIndex index(findIndexByString(targetView_, list[0]));
            if(index.isValid()) {
                // This is an attempt to add model indx into selection
                selection.select(index, index);
            }
        }
        // When the selection is created, this should select it in index
        targetView_->selectionModel()->select(selection, flags);
    }
}

Problem is, this code always only selects first item in the list, eg. for "B1","C1","A1" it looks like this:

image description

The table has multi selection enabled:

image description

So how do I properly select multiple items programmatically? If you need the findIndexByString, it can be found here: https://github.com/Darker/qt-gui-test/blob/master/results/QAbstractItemViewResult.cpp#L5


Solution

  • You clear the selection on every iteration.

    Replace:

    QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::ClearAndSelect;
    

    by:

    QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::Select;
    

    EDIT: You pass list[0] instead of text:

    findIndexByString(targetView_, list[0])
    

    By the way, you should use a const reference in your loop:

    Q_FOREACH(const QString &text, list) {
    

    Or the native version if you use C++11 or superior:

    for (const QSring &text : list) {