Results 1 to 9 of 9

Thread: QTreeView Filter

  1. #1
    Join Date
    May 2008
    Posts
    12
    Thanked 2 Times in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default QTreeView Filter

    Hi All,

    I want to implement a filter for QTreeView.

    Qt Code:
    1. -Apple
    2. |____ Object_01
    3. |____ Object_02
    4. |____ XYZ
    5. -Banana
    6. |____ Object_03
    7. |____ Lemon
    8. - Orange
    9. |____ Rabbit
    10. |____ Object_04
    11. |____ Object_05
    To copy to clipboard, switch view to plain text mode 

    I have to use a LineEdit for dynamic filter. (Connection to textchange I have done)
    Conditions:
    1> With every Stroke of letter whole tree should be filtered.
    e.g. If in lineEdit I say Obj it should show, important thing is every word in the list should start with Obj.

    Qt Code:
    1. -Apple
    2. |____ Object_01
    3. |____ Object_02
    4. -Banana
    5. |____ Object_03
    6. - Orange
    7. |____ Object_04
    8. |____ Object_05
    To copy to clipboard, switch view to plain text mode 


    I tried using simple filter example(BasisSortFilter) it works perfectly fine for tree with only parents and no children. However it's not working with tree with childrens (above example)
    This quote I read while going through the documentation of qsortfilterproxymodel.
    For hierarchical models, the filter is applied recursively to all children. If a parent item doesn't match the filter, none of its children will be shown.

    This slot is connected to lineEdit with

    Qt Code:
    1. connect(FilterLineEdit, SIGNAL(textChanged(QString)),this, SLOT(filterChanged()));
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. void FilterDialog::filterChanged()
    2. {
    3. QRegExp::PatternSyntax syntax = QRegExp::RegExp;
    4. Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive;
    5. QString strPattern = "^" + FilterLineEdit->text();
    6. QRegExp regExp(strPattern, caseSensitivity);
    7. proxyModel->setFilterRegExp(regExp);
    8. }
    To copy to clipboard, switch view to plain text mode 

    Thanks in advance.

  2. #2
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: QTreeView Filter

    Well it is up to you. Subclass QSortFilterProxyModel and make sure parents get only invalid if no children passes the test.

  3. #3
    Join Date
    May 2008
    Posts
    12
    Thanked 2 Times in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTreeView Filter

    Hi Lykurg,

    Thanks for your reply, can you provide some code for that ?


    Thanks

  4. #4
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: QTreeView Filter

    No, but simply subclass and reimplement QSortFilterProxyModel::filterAcceptsRow(). The detailed description is good and there are some examples in the documentation as well. Try it first yourself, and if you can't manage it, post the code you have such far and we work on from that point.

  5. #5
    Join Date
    May 2008
    Posts
    12
    Thanked 2 Times in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTreeView Filter

    This problem is solved, I have put code for reference.

    Thanks to everyone, this forum rocks...


    Qt Code:
    1. QAbstractItemModel *FilterDialog::createModel(QObject *parent)
    2. {
    3.  
    4. QStandardItemModel *model = new QStandardItemModel(5, 1, parent);
    5. for( int r=0; r<5; r++ )
    6. {
    7. QStandardItem *item = new QStandardItem( QString("Row:%0").arg(r));
    8.  
    9. for( int i=0; i<3; i++ )
    10. {
    11. QStandardItem *child = new QStandardItem( QString("Item %0").arg(i) );
    12. child->setEditable( false );
    13. item->appendRow( child );
    14. }
    15.  
    16. model->setItem(r, 0, item);
    17. }
    18.  
    19. model->setHorizontalHeaderItem( 0, new QStandardItem( "Column 1" ) );
    20.  
    21. return model;
    22. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. FilterDialog::FilterDialog(QWidget *parent)
    2. : QDialog(parent)
    3. {
    4. setupUi(this);
    5. proxyModel = new SongTreeProxyFilter;
    6. proxyModel->setDynamicSortFilter(true);
    7. treeView->setModel(proxyModel);
    8. QAbstractItemModel * itemModel = createModel(this);
    9. proxyModel->setSourceModel(itemModel);
    10.  
    11. connect(FilterLineEdit, SIGNAL(textChanged(QString)),
    12. this, SLOT(filterChanged()));
    13.  
    14. }
    15.  
    16. void FilterDialog::filterChanged()
    17. {
    18. QRegExp::PatternSyntax syntax = QRegExp::RegExp;
    19.  
    20. Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive;
    21. QString strPattern = "^" + FilterLineEdit->text();
    22. QRegExp regExp(strPattern, caseSensitivity);
    23.  
    24. proxyModel->setFilterRegExp(regExp);
    25. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. //SubClass of QSortFilterProxyModel
    2. bool TreeProxyFilter::filterAcceptsRow(int sourceRow,
    3. const QModelIndex &sourceParent) const
    4. {
    5. QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
    6. return ShowThis(index);
    7. }
    8.  
    9. bool TreeProxyFilter::ShowThis(const QModelIndex index) const
    10. {
    11. bool retVal = false;
    12. //Gives you the info for number of childs with a parent
    13. if ( sourceModel()->rowCount(index) > 0 )
    14. {
    15. for( int nChild = 0; nChild < sourceModel()->rowCount(index); nChild++)
    16. {
    17. QModelIndex childIndex = sourceModel()->index(nChild,0,index);
    18. if ( ! childIndex.isValid() )
    19. break;
    20. retVal = ShowThis(childIndex);
    21. if (retVal)
    22. {
    23. break;
    24. }
    25. }
    26. }
    27. else
    28. {
    29. QModelIndex useIndex = sourceModel()->index(index.row(), 0, index.parent());
    30. QString type = sourceModel()->data(useIndex, Qt::DisplayRole).toString();
    31. if ( ! type.contains(filterRegExp()))
    32. {
    33. retVal = false;
    34. }
    35. else
    36. {
    37. retVal = true;
    38. }
    39. }
    40. return retVal;
    41. }
    To copy to clipboard, switch view to plain text mode 

  6. #6
    Join Date
    Feb 2012
    Posts
    2
    Qt products
    Qt4 Qt/Embedded

    Default Re: QTreeView Filter

    Esta implementación busca si los hijos cumple la condición y no utiliza funciones recursivas

    Qt Code:
    1. bool SortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
    2. {
    3. QList<QModelIndex> children;
    4. children << sourceModel()->index(source_row, 0, source_parent);
    5.  
    6. bool show = false;
    7. for(int i = 0; i < children.length(); i++)
    8. {
    9. if(show) break;
    10.  
    11. // Add sub Nodos
    12. //
    13. for(int c = 0; c < sourceModel()->rowCount(children[i]) ;c++)
    14. children.append(children[i].child(c,0));
    15.  
    16. QString type = sourceModel()->data(children[i], Qt::DisplayRole).toString();
    17. show = type.contains(filterRegExp());
    18. }
    19. return show;
    20. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by Bycross028; 17th December 2014 at 12:56.

  7. #7
    Join Date
    Dec 2013
    Posts
    14
    Thanks
    2
    Thanked 2 Times in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X Windows

    Default Re: QTreeView Filter

    the "filterAcceptsRow" method seems to be meant for recursion, so the shortest way would be (given colum 0 needs to be checked):

    Qt Code:
    1. bool MySortFilterProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
    2. {
    3. QModelIndex index = sourceModel()->index(row, 0, parent);
    4.  
    5. if (!index.isValid())
    6. return false;
    7.  
    8. if (index.data().toString().contains(filterRegExp()))
    9. return true;
    10.  
    11. int rows = sourceModel()->rowCount(index);
    12. for (row = 0; row < rows; r++)
    13. if (filterAcceptsRow(row, index))
    14. return true;
    15.  
    16. return false;
    17. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by t_3; 27th January 2015 at 11:34.

  8. The following 2 users say thank you to t_3 for this useful post:

    d_stranz (27th January 2015), Opa114 (25th December 2018)

  9. #8
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QTreeView Filter

    If I understand your question correctly, what you are saying is that if you return "false" for a certain row, then the children of that row are ignored, right? Unfortunately, that is how QSortFilterProxyModel works - as soon as one level of a tree returns false for filterAcceptsRow(), that row and all of its children are removed from further consideration.

    Think about what it would mean if it didn't work that way and continued the recursion into children. What kind of tree would that result in? A bunch of children, but no parent for those children because the parent row had been rejected.

    You probably need to rethink how you really want your filtering to work and maybe work out a few test cases by hand so you can get the logic right.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  10. #9
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QTreeView Filter

    In such a case it might be easier to implement the filtering in the model itself.

    Using a proxy looks convenient at first but it often has actually higher complexity due to working in such an abstracted way.

    Cheers,
    _

Similar Threads

  1. QTreeView::problems with the filter
    By Mint87 in forum Qt Programming
    Replies: 4
    Last Post: 18th November 2011, 13:03
  2. QFileDialog filter
    By wirasto in forum Newbie
    Replies: 12
    Last Post: 20th January 2010, 13:40
  3. Convolution filter
    By toutarrive in forum Qt Programming
    Replies: 5
    Last Post: 21st October 2009, 14:55
  4. Filter a table
    By Nefastious in forum Newbie
    Replies: 1
    Last Post: 18th September 2009, 11:45
  5. regarding keyboard filter....
    By sar_van81 in forum Qt Programming
    Replies: 1
    Last Post: 2nd January 2007, 17:28

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.