Использование QSortFilterProxyModel с моделью дерева - PullRequest
8 голосов
/ 30 октября 2008

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

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

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

Итак, как мне заставить QSortFilterProxyModel фильтровать только файлы в каталоге, а не каталоги, в которых он находится?

Ответы [ 5 ]

10 голосов
/ 06 июня 2012

Для таких людей, как я, которые интересуются следующим поведением: если ребенок соответствует фильтру, его предки не должны быть скрыты:

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) ;
}
7 голосов
/ 31 октября 2008

Мы столкнулись с чем-то похожим, где я работаю, и в итоге создали собственную модель прокси для нашей фильтрации. Однако, просматривая документацию на то, что вам нужно (кажется, что это более распространенный случай), я обнаружил две возможности.

  1. Возможно, вы сможете установить фильтр имен в QDirModel и фильтровать вещи таким образом. Я понятия не имею, будет ли это работать так, как вы хотите, или же фильтры имен применяются и к каталогам. Документация на них немногочисленна.
  2. Подкласс QSortFilterProxyModel и переопределить функцию filterAcceptsRow. Из документации:

Пользовательское поведение фильтрации может быть достигнуто путем переопределения функций filterAcceptsRow () и filterAcceptsColumn ().

Тогда вы, вероятно, можете использовать модельный индекс, чтобы проверить, является ли элемент индекса каталогом (автоматически принимать) или файлом (фильтром по имени файла).

1 голос
/ 07 марта 2019

Начиная с Qt 5.10, QSortFilterProxyModel имеет возможность рекурсивной фильтрации. Другими словами, если дочерний элемент соответствует фильтру, его родители также будут видны.

Извлечение QSortFilterProxyModel :: recursiveFilteringEnabled .

1 голос
/ 05 ноября 2010

получить 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);
}
0 голосов
/ 02 сентября 2015

Просто используйте KRecursiveFilterProxyModel модель из KItemModels KDE API

...