Using QSortFilterProxyModel with a tree model

自古美人都是妖i 提交于 2019-12-03 03:13:14

For people like me who are interested in the following behaviour : if a child matches the filter, then its ancestors should not be hidden :

bool MySortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex & source_parent) const
{
    // custom behaviour :
    if(filterRegExp().isEmpty()==false)
    {
        // get source-model index for current row
        QModelIndex source_index = sourceModel()->index(source_row, this->filterKeyColumn(), source_parent) ;
        if(source_index.isValid())
        {
            // if any of children matches the filter, then current index matches the filter as well
            int i, nb = sourceModel()->rowCount(source_index) ;
            for(i=0; i<nb; ++i)
            {
                if(filterAcceptsRow(i, source_index))
                {
                    return true ;
                }
            }
            // check current index itself :
            QString key = sourceModel()->data(source_index, filterRole()).toString();
            return key.contains(filterRegExp()) ;
        }
    }
    // parent call for initial behaviour
    return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent) ;
}

We ran into something similar where I work, and ended up making our own proxy model to do our filtering. However, looking through the documentation for what you want (which seems like it would be a more common case), I came across two possibilities.

  1. You might be able to set a name filter on the QDirModel and filter things that way. I have no idea if this will work like you want, or if the name filters apply to directories also. The documentation is kind of sparse on these.
  2. Subclass the QSortFilterProxyModel and override the filterAcceptsRow function. From the documentation:

Custom filtering behavior can be achieved by reimplementing the filterAcceptsRow() and filterAcceptsColumn() functions.

Then you could presumably use the model index to check if the index item is a directory (automatically accept) or a file (filter on filename).

RoLi

derive qsortfilterproxymodel and then...

bool YourQSortFilterProxyModel::filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const
{
    if (source_parent == qobject_cast<QStandardItemModel*>(sourceModel())->invisibleRootItem()->index())
    {
        // always accept children of rootitem, since we want to filter their children 
        return true;
    }

    return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}

As of Qt 5.10, QSortFilterProxyModel has the option to filter recursively. In other words, if a child matches the filter, its parents will be visible as well.

Check out QSortFilterProxyModel::recursiveFilteringEnabled.

Just use KRecursiveFilterProxyModel model from the KItemModels KDE API

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!