Развернуть определенные элементы в древовидной структуре во время фильтрации - PullRequest
0 голосов
/ 27 июня 2019

Давайте рассмотрим данные этого дерева:

Root
|-v A1
| |-- textA
|
|-v B1
| |-- textB

При поиске "A1" я хочу, чтобы элемент A1 НЕ расширялся (но расширялся, чтобы видеть детей):

Root
|-> A1

При поиске"textA" Я хочу, чтобы элемент A1 был расширен (чтобы увидеть соответствующий дочерний элемент):

Root
|-v A1
| |-- textA

(Стандартная) фильтрация, предоставляемая QSortFilterProxyModel, работает нормально, но я не вижу, как реализовать расширение, когданужна "вещь.

Я попробовал какой-то глупый код, и он не работал:

bool MySortFilterProxyModel::filterAcceptsRow(
  int sourceRow,
  const QModelIndex &sourceParent
) const {
  bool result = QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);

  if (m_tree) {
  //   if (result)
       m_tree->expand(sourceParent);
  }
 return result;
}

1 Ответ

0 голосов
/ 27 июня 2019

Я думаю, что следующее решение может вам немного помочь.

Я считаю разумным способом расширить предметы, если это всего лишь несколько детей с именем, которое ищут. Нерешенной проблемой может быть сворачивание детей, если изменить поле поиска. Например, введите C-0-0-0 в поле поиска, чтобы понять поведение моего решения.

#include <QApplication>
#include <QTreeView>
#include <QDebug>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QStandardItemModel>
#include <QSortFilterProxyModel>


int main(int argc, char **args)
{
    QApplication app(argc, args);
    auto frame = new QFrame;
    frame->setLayout(new QVBoxLayout);
    auto model = new QStandardItemModel;
    for (auto i=0; i<10; i++)
    {
        auto item = new QStandardItem(QString("A-%1").arg(i));
        model->appendRow(item);
        for (auto j=0; j<10; j++)
        {
            auto item2 = new QStandardItem(QString("B-%1-%2").arg(i).arg(j));
            item->appendRow(item2);
            for (auto k=0; k<10; k++)
            {
                auto item3 = new QStandardItem(QString("C-%1-%2-%3").arg(i).arg(j).arg(k));
                item2->appendRow(item3);
            }
        }
    }

    auto proxyModel = new QSortFilterProxyModel;
    proxyModel->setSourceModel(model);
    proxyModel->setRecursiveFilteringEnabled(true);
    auto view = new QTreeView;
    view->setModel(proxyModel);
    frame->layout()->addWidget(view);
    auto edit = new QLineEdit;
    frame->layout()->addWidget(edit);
    frame->show();
    QObject::connect(edit, &QLineEdit::textChanged, [&](auto test) {
        proxyModel->setFilterFixedString(test);
        Qt::MatchFlags flags;
        flags.setFlag(Qt::MatchFlag::MatchStartsWith, true);
        flags.setFlag(Qt::MatchFlag::MatchWrap, true);
        flags.setFlag(Qt::MatchFlag::MatchRecursive, true);
        auto indexList=proxyModel->match(proxyModel->index(0,0), Qt::ItemDataRole::DisplayRole, test, -1, flags);
        for (auto index : indexList)
        {
            auto expanderIndex = index.parent();
            while (expanderIndex.isValid())
            {
                view->expand(expanderIndex);
                expanderIndex = expanderIndex.parent();
            }

        }
        qDebug() << indexList.size();
    });
    app.exec();
}

Улучшенное решение

В следующем улучшенном решении используются только найденные индексы по модели без возможного различного поиска индексов, предоставляемых match.

main.cpp

#include <QApplication>
#include <QTreeView>
#include <QDebug>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QStandardItemModel>
#include <QSortFilterProxyModel>
#include "MyProxyModel.h"

int main(int argc, char **args)
{
    QApplication app(argc, args);
    auto frame = new QFrame;
    frame->setLayout(new QVBoxLayout);
    auto model = new QStandardItemModel;
    for (auto i=0; i<10; i++)
    {
        auto item = new QStandardItem(QString("A-%1").arg(i));
        model->appendRow(item);
        for (auto j=0; j<10; j++)
        {
            auto item2 = new QStandardItem(QString("B-%1-%2").arg(i).arg(j));
            item->appendRow(item2);
            for (auto k=0; k<10; k++)
            {
                auto item3 = new QStandardItem(QString("C-%1-%2-%3").arg(i).arg(j).arg(k));
                item2->appendRow(item3);
            }
        }
    }

    auto proxyModel = new MyProxyModel;
    proxyModel->setSourceModel(model);
    proxyModel->setRecursiveFilteringEnabled(true);
    auto view = new QTreeView;
    view->setModel(proxyModel);
    frame->layout()->addWidget(view);
    auto edit = new QLineEdit;
    frame->layout()->addWidget(edit);
    frame->show();
    QObject::connect(edit, &QLineEdit::textChanged, [&](auto test) {
        proxyModel->setFilterFixedString(test);
        if (test == "") return;
        view->collapseAll();
        QList<QModelIndex> acceptedIndices = proxyModel->findIndices();
        for (auto index : acceptedIndices)
        {
            auto expanderIndex = index.parent();
            while (expanderIndex.isValid())
            {
                view->expand(expanderIndex);
                expanderIndex = expanderIndex.parent();
            }

        }
        qDebug() << acceptedIndices.size();
    });
    app.exec();
}

MyProxyModel.h

#pragma once

#include <QSortFilterProxyModel>

class MyProxyModel : public QSortFilterProxyModel
{
    Q_OBJECT
public:
    QList<QModelIndex> findIndices() const
    {
        QList<QModelIndex> ret;
        for (auto iter=0; iter < rowCount(); iter++)
        {
            auto childIndex = index(iter, 0, QModelIndex());
            ret << recursivelyFindIndices(childIndex);
        }
        return ret;
    }


    bool rowAccepted(int source_row, const QModelIndex& source_parent) const
    {
        return filterAcceptsRow(source_row, source_parent);
    }
private:
    QList<QModelIndex> recursivelyFindIndices(const QModelIndex& ind) const
    {
        QList<QModelIndex> ret;
        if (rowAccepted(ind.row(), ind.parent()))
        {
            ret << ind;
        }
        for (auto iter=0; iter<rowCount(ind); iter++)
        {
            ret << recursivelyFindIndices(index(iter, 0, ind));
        }
        return ret;
    }
};
...