2008-10-30 4 views
7

У меня есть QDirModel, у которого установлен текущий каталог. Затем у меня есть QListView, который должен показывать файлы в этом каталоге. Это прекрасно работает.Использование QSortFilterProxyModel с древовидной моделью

Теперь я хочу ограничить отображаемые файлы, поэтому он показывает только png файлов (имя файла заканчивается на .png). Проблема в том, что с помощью QSortFilterProxyModel и установки фильтра regexp будет пытаться сопоставить каждого родителя файлов. В соответствии с документацией:

Для иерархических моделей фильтр применяется рекурсивно для всех детей. Если родительский элемент не соответствует фильтру , ни один из его дочерних элементов не будет отображаться как .

Итак, как мне получить 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) ; 
} 
Смежные вопросы