Сохранить структуру, используя QSortFilterItemProxy - PullRequest
0 голосов
/ 09 апреля 2020

Так что я использую слегка настраиваемый QSortFilterProxyModel (только что реализованный filterAcceptsRows) для фильтрации элементов из QStandardItemModel. В настоящее время он отлично фильтрует, используя setFilterRegExp, но проблема, с которой я столкнулся, заключается в том, что, поскольку ProxyModel ищет только элементы, я теряю структуру. Например, допустим, у меня есть такая структура:

Root Folder 1
    |----Sub Folder 1
             |-----Item 1
             |-----Item 2
             |-----Item 3
    |----Sub Folder 2
             |-----Item 1
             |-----Item 2
             |-----Item 3
Root Folder 2
    |----Sub Folder 1
             |-----Item 1
             |-----Item 3
    |----Sub Folder 2
             |-----Item 1
             |-----Item 2
             |-----Item 3

После того, как я закончу фильтрацию, скажем, если имя items содержит '2', я получу

Item 2
Item 2
Item 2

Предпочтительно я хотел бы, чтобы он вывел:

Root Folder 1
    |----Sub Folder 1
             |-----Item 2
    |----Sub Folder 2
             |-----Item 2
Root Folder 2
    |----Sub Folder 2
             |-----Item 2

Я думал об использовании исходной модели и просто удалял элементы, если они не совпадают, но это определенно кажется неправильным способом go об этом. Я пытался получить родителя в filterAcceptsRows, но всегда кажется, что он нулевой.

Кажется, что это было бы легко сделать или просто пропустить настройку, которую я пропустил, но любая помощь будет принята с благодарностью!

Спасибо!

1 Ответ

1 голос
/ 09 апреля 2020

То, что вам нужно, это то, что filterAcceptsRow должен возвращать true, если либо сама строка проходит тест , либо любой из ее потомков проходит тест.

Исходя из этого, вы можете хочу попробовать что-то довольно простое c, такое как ...

class sort_filter_proxy: public QSortFilterProxyModel {
public:
  virtual bool filterAcceptsRow (int source_row, const QModelIndex &source_parent) const
    {
      if (!source_parent.isValid())
        return true;
      return test(source_parent.model()->index(source_row, 0, source_parent));
    }
private:
  bool test (const QModelIndex &source_index) const
    {
      if (!filterRegExp().isValid())
        return true;

      /*
       * Test source_index itself.
       */
      if (source_index.data(filterRole()).toString().contains(filterRegExp()))
        return true;

      /*
       * Test the children of source_index.
       */
      for (int row = 0; row < source_index.model()->rowCount(source_index); ++row)
        if (test(source_index.model()->index(row, 0, source_index)))
          return true;

      /*
       * Neither source_index nor any of its descendants passed the test.
       */
      return false;
    }
};

Это немного "грубая сила" в том, что одна и та же строка может быть проверена несколько раз, но если ваша модель не слишком большой, это не должно быть проблемой. Лучший алгоритм будет использовать дополнительные данные в пользовательской роли модели для кэширования результатов, генерируемых вызовами sort_filter_proxy::test.

...