How to display sub-rows of QAbstractItemModel in Q

2019-05-28 16:14发布

问题:

I have my own class that inherits from QAbstractItemModel which has tree structure.

I use a couple of views, that display filtered data of this model, using classes derived from QSortFilterProxyModel.

My model structure looks like this:

root
|
-- A
|  |-A1
|  |-A2
|  |-A3
|
-- B
|  |-B1
|  |-B2
|
... and so on...

Where A, B .... are "main rows" (children of the root), and A1, A2, ... B1, B2... are "children rows" - node rows appended to "main rows".

Now, what I need to do is a QTableView that displays "children rows" only:

A1
A2
A3
B1
B2

But filtering methods I found in QSortFilterProxyModel (filterAcceptsRow, filterAcceptsColumn), operates on main rows only...

How can I do it?

(I found very similar question, but it is still unanswered: QTableView to display only leaves of a tree model implemented with QAbstractItemModel)

回答1:

I see 3 possible solutions for this problem. First two solutions offered Dmitry Sazonov in his comment for this question:

  1. Reimplement QAbstractProxyModel.
  2. Reimplement QAbstractItemModel and create another model for such view.

The third possible solution is little trick with reimplementation of QStyledItemDelegate for view. I make small example for such solution. I hope, it will be useful:

#include <QApplication>
#include <QTreeView>
#include <QStyledItemDelegate>
#include <QStandardItemModel>

class ZeroHightItemDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    ZeroHightItemDelegate(QObject* parent = 0)
        : QStyledItemDelegate(parent)
    {}
    ~ZeroHightItemDelegate(){}
public:
    QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const Q_DECL_OVERRIDE
    {
        static int defaultHeight = 0;
        static bool firstSizeHintFlag = true;
        QSize size = QStyledItemDelegate::sizeHint(option, index);
        if (firstSizeHintFlag){
            defaultHeight = size.height();
            firstSizeHintFlag = false;
        }
        const QAbstractItemModel* model = index.model();
        if (!model)
            return size;
        if (model->hasChildren(index))
            size.setHeight(0);
        else
            size.setHeight(defaultHeight);
        return size;
    }
};


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QTreeView myView;
    myView.setRootIsDecorated(false);
    QStandardItemModel* model = new QStandardItemModel(&myView);
    myView.setModel(model);

    model->insertColumns(0, 1);
    QStandardItem* headerItem = new QStandardItem("Header");
    model->setHorizontalHeaderItem(0, headerItem);

    QStandardItem* itemA = new QStandardItem("A");
    model->appendRow(itemA);
    QStandardItem* itemB = new QStandardItem("B");
    model->appendRow(itemB);
    QStandardItem* itemA1 = new QStandardItem("A1");
    QStandardItem* itemA2 = new QStandardItem("A2");
    itemA->appendRow(itemA1);
    itemA->appendRow(itemA2);
    QStandardItem* itemB1 = new QStandardItem("B1");
    QStandardItem* itemB2 = new QStandardItem("B2");
    QStandardItem* itemB3 = new QStandardItem("B3");
    itemB->appendRow(itemB1);
    itemB->appendRow(itemB2);
    itemB->appendRow(itemB3);
    myView.setItemDelegate(new ZeroHightItemDelegate(&myView));

    myView.expandAll();
    myView.show();

    return a.exec();
}

#include "main.moc"