PDA

View Full Version : setRecursiveFilteringEnabled() not available in qt4



mlte
26th July 2021, 15:53
Hi everyone!

I have implemented a Hierarchical table using the QTreeView in Qt5.
I am using the QSortFilterProxyModel() to implement the search feature in the QTreeView. It is working okay in Qt5.


proxyModel = new QSortFilterProxyModel(this);
proxyModel->setSourceModel(model_t);
proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
proxyModel->setFilterKeyColumn(0);
ui->treeView->setModel(proxyModel);
ui->treeView->setSortingEnabled(true);
proxyModel->setRecursiveFilteringEnabled(true);
ui->treeView->expandAll();

But now I want to run my code in the Qt4. However, I am getting the error that Qt 4 doesn't recognize "proxyModel->setRecursiveFilteringEnabled(true);" .

Is there any alternative for "proxyModel->setRecursiveFilteringEnabled(true);" in Qt 4?

ChristianEhrlicher
26th July 2021, 17:22
Do the recursive filtering by your own by deriving from QSortFilterProxyModel and reimplement filterAccetsRow()

mlte
28th July 2021, 15:48
Do the recursive filtering by your own by deriving from QSortFilterProxyModel and reimplement filterAccetsRow()

Sorry to ask you a silly question. But I couldn't understand well the working of Qsortfilterproxymodel.
Do you think if I reimplement the filterAcceptsRow() using the following code would it work. I have to search the QtreeView based on the 0 column entries.
Or do I have to modify the other function as well?



bool MySortFilterProxyModel::filterAcceptsRow(int sourceRow,
const QModelIndex &sourceParent) const
{
QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent);
QModelIndex index1 = sourceModel()->index(sourceRow, 1, sourceParent);
QModelIndex index2 = sourceModel()->index(sourceRow, 2, sourceParent);

return (sourceModel()->data(index0).toString().contains(filterRegExp())
|| sourceModel()->data(index1).toString().contains(filterRegExp()))
&& dateInRange(sourceModel()->data(index2).toDate());
}

Thanks in advance!

d_stranz
28th July 2021, 21:38
You've just copied and pasted the example from the documentation. If your columns don't contain the same information, or if you only want to look at column 0, then of course it won't work. It also doesn't implement recursive filtering, so it certainly won't do what the Qt5 version does.

In your initial post, you don't set any regular expression, so what exactly are you filtering based on? The default behavior of the proxy when there is no regexp is to accept everything.

Remember that the default behavior of QSortFilterProxyModel is to stop recursing as soon as filterAcceptsRow() returns false for any row. So even if a child row matches, if the parent doesn't the child row will never be examined and the parent row will not be displayed.

This is the opposite behavior that occurs when setRecursiveFilteringEnabled() is set to true. In that case, if any child row passes the test, then you want the parent to be displayed.

So if you want to implement recursive filtering the way it works in Qt5, you have to do the recursion yourself.

If you are using a QRegExp to hold the filter string, then your version of filterAcceptsRow() should look like this:

*** WARNING: Untested code. Might be buggy. ***


/*
* Implementation of manual recursive filtering for Qt < 5
*
*/

bool MySortFilterProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex & sourceParent ) const
{
#if QT_VERSION < 0x050000

// Qt is less than 5, so manually perform recursion

// Default QSortFilterProxyModel behavior for an empty regexp
if ( filterRegExp().isEmpty() )
return true;

QModelIndex index0 = sourceModel()->index( sourceRow, 0, sourceParent );

// If column0 at the current level matches, return true
if ( sourceModel()->data( index0, Qt::DisplayRole ).toString().contains( filterRegExp() ) )
return true;

// The current level doesn't match but if it has children, recurse to look at them
else if ( sourceModel()->hasChildren( index0 ) )
{
bool bResult = false;
int nRows = sourceModel()->rowCount( index0 );

// Look at each child row. If any one of them matches (bResult == true) then the loop will exit
for ( int nRow = 0; nRow < nRows && !bResult; ++nRow )
{
bResult = filterAcceptsRow( nRow, index0 );
}

// Return whatever the loop result was. If any child matches, this is true, otherwise it is false.
return bResult;
}

// Otherwise, nothing at this level or below it matches, so the whole subtree is ignored.
return false;

#else
// Qt version is > 4, so use default implementation
return QSortFilterProxyModel::filterAcceptsRow( sourceRow, sourceParent );

#endif
}