PDA

View Full Version : Filter tree view



Ginsengelf
19th October 2011, 12:17
Hi, I have a QTreeView with the following structure:


-1
|-A
| |-a
| |-b
|
|-B
| |-a
|
|-C
|-b

I would like to filter this and show only the nodes that contain a "a" item, like this:


-1
|-A
| |-a
|
|-B
|-a

but using a custom QSortFilterProxyModel I only achieved this:


-1
|-A
| |-a
|
|-B
| |-a
|
|-C

which is understandable since my filter condition is applied to the a,b,c items only.
I also tried to filter the filtered output with a second QSortFilterProxyModel, but that did not help since the hasChildren() method for the model indexes always returned 0 and all items got filtered out...

Is there a simple way to completely filter out the nodes that do not contain an "a" item (the "C" node in the example above)?

Thanks,

Ginsengelf

nix
19th October 2011, 15:10
I faced the same problem few month ago, I solve it by using the folowing class :

songtreeproxyfilter.h :

#ifndef SONGTREEPROXYFILTER_H
#define SONGTREEPROXYFILTER_H

#include <QSortFilterProxyModel>

class SongTreeProxyFilter : public QSortFilterProxyModel
{
public:
SongTreeProxyFilter(QObject *parent = NULL);
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
private :
bool hasToBeDisplayed(const QModelIndex index) const;
};

#endif // SONGTREEPROXYFILTER_H


songtreeproxyfilet.c

#include "songtreeproxyfilter.h"

#include <QtDebug>

SongTreeProxyFilter::SongTreeProxyFilter(QObject *parent):
QSortFilterProxyModel(parent)
{
}

bool SongTreeProxyFilter::filterAcceptsRow(int sourceRow,
const QModelIndex &sourceParent) const
{
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);

return hasToBeDisplayed(index);
}

bool SongTreeProxyFilter::hasToBeDisplayed(const QModelIndex index) const
{
bool result = false;
// How many child this element have
if ( sourceModel()->rowCount(index) > 0 )
{
for( int ii = 0; ii < sourceModel()->rowCount(index); ii++)
{
QModelIndex childIndex = sourceModel()->index(ii,0,index);
if ( ! childIndex.isValid() )
break;
result = hasToBeDisplayed(childIndex);
if (result)
{
// there is atless one element to display
break;
}
}
}
else
{
QModelIndex useIndex = sourceModel()->index(index.row(), 1, index.parent());
QString type = sourceModel()->data(useIndex, Qt::DisplayRole).toString();
if ( ! type.contains(filterRegExp()))
{
result = false;
}
else
{
result = true;
}
}
return result;
}


I hope it can help.