How to keep selection while adding new item to QSortFilterProxyModel?



  • Hello
    I have QSortFilterProxyModel which is set to QListView, I have line edit to search in list when I search item and I select it and than press to add new item(without clearing the filter line) the selection disappears. how can I keep it? and one more thing here when i select item and then do a search for another the result gets selected!


  • Moderators

    the question now is how exactly do you add the new item? Which methods to you use? Are you calling reset() after adding?



  • I do not call reset, I call
    @
    proxy->setSourceModel(model)
    @
    again, without it how sourceModel will be updated?


  • Moderators

    you wrote
    [quote author="tokafr" date="1422514280"]... and than press to add new item...[/quote]
    I wanted to know how do you add the new items? Or do i misunderstand something here?

    Anyways you should post some code to clear things up.



  • I have a button that shows me a dialog with fields, I fill them and press add, so item is added. the code of it is too large to write here :)



  • @ QModelIndexList indexes = listWidget->selectionModel()->selectedIndexes();
    QString text;
    QModelIndex ind;
    foreach(QModelIndex index, indexes)
    {
    //text = index.data(Qt::UserRole).toString();
    ind = proxy->mapToSource(index);
    }
    model->addRow(newConnection);
    proxy->setSourceModel(model);
    emit searchLine->textChanged(searchLine->text());
    ind = proxy->mapFromSource(ind);
    listWidget->selectionModel()->select(ind,QItemSelectionModel::Select);@



  • @
    void MainWindow::onNewFilterText(QString filter)
    {

    model->sort(0);
    proxy->setFilterRole(Qt::UserRole);
    proxy->setFilterCaseSensitivity(Qt::CaseInsensitive);
    proxy->setFilterWildcard(filter);

    }@

    textchanged() emits this


  • Moderators

    why do you reset the model?
    @proxy->setSourceModel(model);@
    This is actually not needed because the model is the same right?



  • I add item to a model, how does proxy knows that model changed.


  • Moderators

    Of course the model triggers a signal when a new row is added.

    What kind of source model do you use? Did you implement the addRow() method yourself? If so you need to make sure you emit the right signals then (by calling specific methods)

    -Actually you should reimplement insertRow().-

    See the docs for QAbstractItemModel::beginInsertRows() this will clear things up which parameters you need to pass to it.



  • and how parameters are passed, by using virtual void setData()?
    if so the indexing here is very complicated
    @
    void Model::addRow(Connection &item)
    {
    QModelIndex parent = index(dataList.count());
    QModelIndex currentIndex = index (dataList.count() +1);
    int row = dataList.size();
    insertRows(row, 1, parent);
    QVariant connection;
    connection.setValue(item);
    setData(currentIndex,connection,Qt::EditRole);
    @


  • Moderators

    This whole method is messed up. Since you are using a list view widget you will never ever have a parent index. So this will always be an invalid index.

    Forget about what i said you should reimplement insertRow().. sry for the confusion. Do something like this:
    @
    void Model::addConnection(Connection &item)
    {
    beginInsertRows( QModelIndex(), dataList.count(), dataList.count() ); //append 1 row to the end of the list
    dataList << item; //assuming dataList is a QList
    endInsertRows();
    }
    @

    So what happens is:

    you tell the model that you are about to insert new rows

    insert the new rows to your data structure (the same from which you get your data in the Model::data() hopefully)

    tell the model you are finished with inserting

    the model now tells the view/proxymodel that new rows were inserted

    the view updates and keeps it's selection / the proxy model reevaluates the filter for the newly added rows (when QSortFilterProxyModel::setDynamicSortFilter(true))

    Note: The proxymodel automatically forwards all the signals from the source model to the view automatically.



  • thank you, one more thing don't i need to emit dataChanged() signal?


  • Moderators

    no, since you already signaled that you added a completely new row.
    The dataChanged() signal is only necessary if data of an existing item/index has changed.



  • The root problem is that your selection model is based on the proxy model, and not on the source model of the proxy. That means that if your proxy removes items due to filtering, the selection model only knows that the item has gone away, and thus the item has to be removed from the selection. The selection model has no concept of proxies.

    KDE has created the "KLinkItemSelectionModel class"http://api.kde.org/4.5-api/kdelibs-apidocs/kdeui/html/classKLinkItemSelectionModel.html that tackles this issue. It allows mapping the selection through a proxy model. In your case, you could make a QItemSelectionModel instance on your source model, and use the proxy to get a mapped version of that in your actual view.



  • the problem is that after adding an item I sort the base model, and the selection index gets wrong.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.