Qt 将QSortFilterProxy模型与树模型结合使用

Qt 将QSortFilterProxy模型与树模型结合使用,qt,model-view-controller,qsortfilterproxymodel,Qt,Model View Controller,Qsortfilterproxymodel,我有一个QDirModel,其当前目录已设置。然后我有一个QListView,它应该显示该目录中的文件。这个很好用 现在我想限制显示的文件,所以它只显示png文件(文件名以.png结尾)。问题是,使用QSortFilterProxyModel并设置过滤器regexp将尝试匹配文件的每个父级。根据文件: 对于层次模型,过滤器是 递归地应用于所有子项。 如果父项与 筛选器,其子项都不会被删除 显示 那么,我如何让QSortFilterProxyModel只过滤目录中的文件,而不过滤它所在的目录呢?我

我有一个
QDirModel
,其当前目录已设置。然后我有一个
QListView
,它应该显示该目录中的文件。这个很好用

现在我想限制显示的文件,所以它只显示png文件(文件名以.png结尾)。问题是,使用
QSortFilterProxyModel
并设置过滤器regexp将尝试匹配文件的每个父级。根据文件:

对于层次模型,过滤器是 递归地应用于所有子项。 如果父项与 筛选器,其子项都不会被删除 显示


那么,我如何让
QSortFilterProxyModel
只过滤目录中的文件,而不过滤它所在的目录呢?

我们在我工作的地方遇到了类似的情况,并最终制作了自己的代理模型来进行过滤。然而,在查看文档以了解您想要什么(这似乎是一种更常见的情况),我发现了两种可能性

  • 您可以在QDirModel上设置名称过滤器,并以这种方式进行过滤。我不知道这是否会像你想要的那样工作,或者名称过滤器是否也适用于目录。关于这些方面的文档比较少
  • 子类化QSortFilterProxyModel并重写
    filterAcceptsRow
    函数。从文件中:
  • 通过重新实现filterAcceptsRow()和filterAcceptsColumn()函数,可以实现自定义筛选行为


    然后您可能会使用模型索引来检查索引项是目录(自动接受)还是文件(根据文件名筛选)。

    派生qsortfilterproxymodel,然后

    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);
    }
    
    bool YourQSortFilterProxyModel::filterAcceptsRow(int-source\u行,常量QModelIndex&source\u父)常量
    {
    if(source\u parent==qobject\u cast(sourceModel())->invisibleRootItem()->index())
    {
    //始终接受rootitem的子项,因为我们要筛选它们的子项
    返回true;
    }
    返回QSortFilterProxyModel::filterAcceptsRow(源行、源父行);
    }
    
    对于像我这样对以下行为感兴趣的人:如果一个孩子与过滤器匹配,那么它的祖先就不应该被隐藏:

    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) ;
    }
    
    bool MySortFilterProxyModel::filterAcceptsRow(int-source\u行,常量QModelIndex&source\u父)常量
    {
    //习惯行为:
    如果(filterRegExp().isEmpty()==false)
    {
    //获取当前行的源模型索引
    QModelIndex source\u index=sourceModel()->index(source\u行,this->filterKeyColumn(),source\u父项);
    if(source_index.isValid())
    {
    //如果任何子项与筛选器匹配,则当前索引也与筛选器匹配
    int i,nb=sourceModel()->rowCount(源索引);
    对于(i=0;idata(source_index,filterRole()).toString();
    return key.contains(filterRegExp());
    }
    }
    //家长呼吁家长采取最初的行为
    返回QSortFilterProxyModel::filterAcceptsRow(源行、源父行);
    }
    
    从Qt 5.10开始,只需使用KDE API中的模型即可,
    QSortFilterProxyModel
    具有递归筛选选项。换句话说,如果子级与筛选器匹配,则其父级也将可见


    退房。

    这太完美了,感谢您添加bc。这是我找到的第一个参考资料。