Python 3.x 当与根节点或子节点匹配时,筛选QTreeView以返回节点

Python 3.x 当与根节点或子节点匹配时,筛选QTreeView以返回节点,python-3.x,filtering,pyqt5,qtreeview,Python 3.x,Filtering,Pyqt5,Qtreeview,我有一个通过qabstractemmodel填充数据的QTreeVIew,我可以使用QSortFilterProxyModel.setFilterRegExp过滤视图,但是如果我的过滤字符串与根节点不匹配,则返回子节点之间的非匹配项。换句话说,我用来在节点之间查找匹配项的字符串必须与根节点匹配才能返回任何内容 我想做的是让所有节点及其各自的父节点和子节点在匹配时返回到QTreeView。下面的树显示了当我搜索cat Animals cats Cats kittens cat

我有一个通过
qabstractemmodel
填充数据的QTreeVIew,我可以使用
QSortFilterProxyModel.setFilterRegExp
过滤视图,但是如果我的过滤字符串与根节点不匹配,则返回子节点之间的非匹配项。换句话说,我用来在节点之间查找匹配项的字符串必须与根节点匹配才能返回任何内容

我想做的是让所有节点及其各自的父节点和子节点在匹配时返回到QTreeView。下面的树显示了当我搜索
cat

Animals
   cats
Cats
   kittens
   cat
       cats
       mice
       lice
Cars
   fantasy cars
       Catmobile
当我现在搜索猫时,返回的是

Cats
   cats
       cats

通常使用QSortFilterProxyModel.filterAcceptsRow进行此操作。 在我的应用程序中,我是这样做的:

class SortModel(QSortFilterProxyModel):

  def __init__(self, parent=None):
    super(SortModel, self).__init__(parent)

  def filterAcceptsRow(self, source_row, source_parent):
    # check if an item is currently accepted 
    accepted = super(SortModel, self).filterAcceptsRow(source_row, source_parent)  

    if accepted:
        return True

    # if it is not accepted may be item parent could be accepted
    model = self.sourceModel()    
    # get item parent [In my app I use only two levels for items,
    # so you need to make a function out of this to make it work for n levels ]
    index = model.index(source_row, self.filterKeyColumn(), source_parent)
    has_parent = model.itemFromIndex(index).parent()
    # if there is a parent
    if has_parent:
        parent_index = self.mapFromSource(has_parent.index())
        # check if parent is accepted
        return super(SortModel, self).filterAcceptsRow(has_parent.row(), parent_index)

    return accepted
如果使用Qt 5.10,请禁用递归筛选或仅在需要时启用它:

def filterAcceptsRow(self, source_row, source_parent):
    accepted = super(SortModel, self).filterAcceptsRow(source_row, source_parent)

    if self.isRecursiveFilteringEnabled():
        return accepted
    else:
        if accepted:
            return True
    ...