2008-10-30 91 views
7

我有一个QDirModel,它的当前目录已设置。然后我有一个QListView这应该显示该目录中的文件。这工作正常。在树形模型中使用QSortFilterProxyModel

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

对于分层模型,过滤器递归地应用于所有子节点 。 如果父项与 筛选器不匹配,则其子项将不会显示为 。

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

回答

7

我们遇到了类似的工作,最终创建了我们自己的代理模型来完成我们的过滤。然而,通过文档查看你想要的东西(看起来这将是一个更常见的情况),我遇到了两种可能性。

  1. 您可能可以在QDirModel上设置名称过滤器并以这种方式过滤事物。我不知道这是否会像你想要的那样工作,或者如果名称过滤器也适用于目录。这些文件是稀疏的。
  2. 继承QSortFilterProxyModel并覆盖filterAcceptsRow函数。从文档:

自定义过滤行为可以通过重新实现filterAcceptsRow()和filterAcceptsColumn()函数来实现。

然后你大概会使用模型索引来检查索引项是一个目录(自动接受)还是一个文件(过滤器的文件名)。

1

获得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); 
} 
6

对于我这样的人谁感兴趣的以下行为:如果一个孩子的过滤器相匹配,那么它的祖先不应该被隐藏:

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) ; 
}