Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QSortFilterProxyModel -filterAcceptsRow()- filter parent Node and child Node
Forum Updated to NodeBB v4.3 + New Features

QSortFilterProxyModel -filterAcceptsRow()- filter parent Node and child Node

Scheduled Pinned Locked Moved General and Desktop
28 Posts 8 Posters 32.5k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    ManasQt
    wrote on last edited by
    #10

    Hi Andre,
    I have created TreeView based on QStandardItemModel,QStandardItem and added QSortFilterProxyModel but while I start searching/Filtering still I can see some delay and I have to call QTreeView.expandAll() every time.

    Donno how to solve this problem.

    1 Reply Last reply
    0
    • A Offline
      A Offline
      andre
      wrote on last edited by
      #11

      Please be a bit more clear in your description. Are you using a QSPM, or are you using the proxy model I presented above? How many items do you have in your tree? How deeply nested? Do you need to call expandAll for the filtering to work, or for the results of the search to be visible?

      1 Reply Last reply
      0
      • M Offline
        M Offline
        ManasQt
        wrote on last edited by
        #12

        hi Andre,

        bq. Q1)Are you using a QSPM, or are you using the proxy model I presented above?

        Created Tree Node by sub classing QStandardItem.

        Created model by sub classing QStandardItemModel .

        Applied sorting and filtering using sub classing QSortFilterPrxoyModel and implemented "filterAcceptsRow"

        Attached proxymodel to QTreeView

        bq. Q2)How many items do you have in your tree?

        2000 items

        bq. Q3)How deeply nested?

        QTreeview is basically only 4 level deep

        bq. Q4)Do you need to call expandAll for the filtering to work, or for the results of the search to be visible?

        I am using a QLineEdit widget for search/filter based on its "textChanged" Signal .While i start typing the resulted items in QTreeView are shown in collapsed mode every time and for this reason i have to call QTreeView.expandAll() always in "editingFinished" signal by pressing 'EnterKey'.

        hope this will helps you to understand .

        would appreciate if any one could help me to slove this problem,thanks in advance.

        1 Reply Last reply
        0
        • X Offline
          X Offline
          xcround
          wrote on last edited by
          #13

          Hi I'm having a similar problem, where I can only select the parent nodes.
          I have the following:
          @
          bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent)
          {
          ....
          if (!action.isEmpty())
          {
          QModelIndex index = sourceModel()->index(sourceRow,
          ACTION, sourceParent);

              for (int i = 0; i < sourceModel()->rowCount(sourceParent); i++)
              {
                  QModelIndex tmpIndex = sourceModel()->index(i,0,sourceParent);
                  if (tmpIndex.isValid())
                      hasAcceptedChildren(tmpIndex.row(), tmpIndex);
              }
          
              if (action != sourceModel()->data(index).toString())
                  return false;
          }
          

          ....
          }
          @

          Isn't this suppose to be it?
          Thanks.

          1 Reply Last reply
          0
          • M Offline
            M Offline
            ManasQt
            wrote on last edited by
            #14

            Hi xcround,

                 I am not clear , are you trying to filter parent as well as child?  
            

            I have accomplished this and here is the logic,

            @def filterAcceptsRow(self,sourceRow,sourceParent):
            if super(MySortFilterProxyModel,self).filterAcceptsRow(sourceRow,sourceParent):
            return True
            return self.hasAcceptedChildren(sourceRow,sourceParent)

            def hasAcceptedChildren(self,sourceRow,sourceParent):
            model=self.sourceModel()
            sourceIndex=model.index(sourceRow,0,sourceParent)
            if not sourceIndex.isValid():
            return False
            indexes=model.rowCount(sourceIndex)
            for i in range(indexes):
            if self.filterAcceptsRow(i,sourceIndex):
            return True
            return False

            @

            1 Reply Last reply
            0
            • X Offline
              X Offline
              xcround
              wrote on last edited by
              #15

              Yes, I would like to filter both parent and child.
              Also I forgot to mention, I have a return true in the end of the function.
              Thanks

              1 Reply Last reply
              0
              • X Offline
                X Offline
                xcround
                wrote on last edited by
                #16

                Here is the what I have now, but still is not filtering the parents and child.
                @
                bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent)
                {
                ....
                if (!action.isEmpty())
                {

                    QModelIndex index = sourceModel()->index(sourceRow,
                                                             ACTION, sourceParent);
                
                    if (hasAcceptedChildren(sourceRow, sourceParent))
                        return true;
                
                    if (action != sourceModel()->data(index).toString())
                        return false;
                }
                return true;
                

                }
                bool TableProxy::filterAcceptsRowItself(int sourceRow, const QModelIndex &sourceParent) const
                {
                return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
                }

                bool TableProxy::hasAcceptedChildren(int source_row, const QModelIndex &source_parent) const
                {
                QModelIndex item = source_parent;
                if (!item.isValid())
                {
                qDebug() << "item invalid" << source_parent.data().toString() << source_row;
                return false;
                }
                int childCount = item.model()->rowCount(item);

                if (childCount == 0)
                    return false;
                
                for (int i = 0; i < childCount; ++i)
                {
                    if (filterAcceptsRowItself(i, item))
                        return true;
                    //recursive call
                    if (hasAcceptedChildren(i, item))
                        return true;
                }
                
                return false;
                

                }
                @
                Thanks for the help

                1 Reply Last reply
                0
                • M Offline
                  M Offline
                  ManasQt
                  wrote on last edited by
                  #17

                  Hi xcround,
                  please make changes in your code according this python code and i am sure it will filter parent as well as child .
                  @
                  def filterAcceptsRow(self,sourceRow,sourceParent):
                  if super(MySortFilterProxyModel,self).filterAcceptsRow(sourceRow,sourceParent):
                  return True
                  return self.hasAcceptedChildren(sourceRow,sourceParent)

                  def hasAcceptedChildren(self,sourceRow,sourceParent):
                  model=self.sourceModel()
                  sourceIndex=model.index(sourceRow,0,sourceParent)
                  if not sourceIndex.isValid():
                  return False
                  indexes=model.rowCount(sourceIndex)
                  for i in range(indexes):
                  if self.filterAcceptsRow(i,sourceIndex):
                  return True
                  return False@

                  1 Reply Last reply
                  0
                  • M Offline
                    M Offline
                    ManasQt
                    wrote on last edited by
                    #18

                    Hi xcround,
                    I think in your case it would be some thing like this needs to be......
                    ( i am not a c/c++ guy)
                    @
                    bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent)
                    {
                    ....
                    if (!action.isEmpty())
                    {
                    if (QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent))
                    {
                    return true
                    }
                    return hasAcceptedChildren(sourceRow, sourceParent)
                    }
                    .........
                    }

                    bool TableProxy::hasAcceptedChildren(int source_row, const QModelIndex &source_parent) const
                    {
                    QModelIndex item = source_parent;
                    if (!item.isValid())
                    {
                    qDebug() << "item invalid" << source_parent.data().toString() << source_row;
                    return false;
                    }
                    int childCount = item.model()->rowCount(item);

                    if (childCount == 0)
                        return false;
                    
                    for (int i = 0; i < childCount; ++i)
                    {
                        if (filterAcceptsRow(i, item))
                            return true;
                    }
                    
                    return false;
                    

                    }@

                    1 Reply Last reply
                    0
                    • X Offline
                      X Offline
                      xcround
                      wrote on last edited by
                      #19

                      Sorry but from mine understanding I first need to check if the string matches the one I'm looking for.
                      So that's why I have the first if statement, and then I do what you said in the previous post.
                      @
                      f (!action.isEmpty())
                      {
                      QModelIndex index = sourceModel()->index(sourceRow,
                      ACTION, sourceParent);

                              if (action != sourceModel()->data(index).toString())
                                  return false;
                      
                              if ((QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent)))
                                  return true;
                      
                              return hasAcceptedChildren(sourceRow, sourceParent);
                          }
                      

                      @
                      Still trying to understand whats going wrong.

                      1 Reply Last reply
                      0
                      • B Offline
                        B Offline
                        burgerking
                        wrote on last edited by
                        #20

                        Hi qties,

                        at the first time I read the post from André I was so happy to find the solution I am searching for.
                        But unfortunately I am to stupid to get it work. Maybe you can help me.

                        If I use the standard QSortFilterProxyModel everything works good except the search at textChanged Signal.
                        But if I use the LeafFilterProxyModel (exactly as André has post it) an error occurs and I do not know what it means.

                        I hope somebady can help me.
                        Thank you.

                        @
                        LeafFilterProxyModel m_oProxyModel;
                        //QSortFilterProxyModel m_oProxyModel;
                        QStandardItemModel m_oItemModel; // manualy filled

                        m_oProxyModel.setSourceModel(&m_oItemModel);
                        m_tvDBC->setModel(&m_oProxyModel); // TreeView
                        m_lvDBC->setModel(&m_oStringModel); // ListView
                        @

                        @
                        void cClass::textChanged(QString text)
                        {
                        QRegExp::PatternSyntax pSyntax = QRegExp::PatternSyntax(QRegExp::FixedString);
                        QRegExp regExp(text, Qt::CaseInsensitive, pSyntax);

                        m_oProxyModel.setFilterRegExp(regExp);
                        m_oProxyModel.setFilterKeyColumn(-1);
                        }
                        @

                        @
                        Error 1 error LNK2001: unresolved external symbol "public: __thiscall
                        LeafFilterProxyModel::LeafFilterProxyModel(class QObject *)"
                        ??0LeafFilterProxyModel@@QAE@PAVQObject@@@Z) myobject.obj
                        @

                        1 Reply Last reply
                        0
                        • A Offline
                          A Offline
                          andre
                          wrote on last edited by
                          #21

                          Sounds like you forgot to add the .h file to your HEADERS section in your .pro file, and the .cpp file to the SOURCES section?

                          1 Reply Last reply
                          0
                          • R Offline
                            R Offline
                            Ruzik
                            wrote on last edited by
                            #22

                            What does _parent type in this string?
                            @bool filterAcceptsRow(int source_row, const QModelIndex &source;_parent) const;@
                            And wath does this argument do?
                            And second question:
                            source_parent is source->parent()?
                            And in advance sorry for stupid questions)

                            1 Reply Last reply
                            0
                            • A Offline
                              A Offline
                              andre
                              wrote on last edited by
                              #23

                              There was an unfortunate bug at the time in DevNet, that sometimes inserted ; at the wrong places in code sections. The code listing I posted suffered from this. The argument is supposed to be a single argument source_parent. I'll try to fixup the original posting. Thanks for noticing.

                              1 Reply Last reply
                              0
                              • R Offline
                                R Offline
                                Ruzik
                                wrote on last edited by
                                #24

                                It is clear.
                                One more thank you for your help!

                                1 Reply Last reply
                                0
                                • F Offline
                                  F Offline
                                  frankiefrank
                                  wrote on last edited by
                                  #25

                                  Thank you - this thread has been really helpful!

                                  "Roads? Where we're going, we don't need roads."

                                  1 Reply Last reply
                                  0
                                  • B Offline
                                    B Offline
                                    bycross028
                                    wrote on last edited by
                                    #26

                                    Esta implementación recorre todo los sub-Nodos del padre buscando que el filterRegExp coincida con el Qt::DisplayRole del sub-Nodo.

                                    El algoritmo no utiliza recursividad :D

                                    @bool SortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
                                    {
                                    QList<QModelIndex> children;
                                    children << sourceModel()->index(source_row, 0, source_parent);

                                    bool show = false;
                                    for(int i = 0; i < children.length(); i++)
                                    {
                                        if(show) break;
                                    
                                        // Add sub Nodos
                                        //
                                        for(int c = 0; c < sourceModel()->rowCount(children[i]) ;c++)
                                            children.append(children[i].child(c,0));
                                    
                                        QString type = sourceModel()->data(children[i], Qt::DisplayRole).toString();
                                        show = type.contains(filterRegExp());        
                                    }
                                    return show;
                                    

                                    }@

                                    1 Reply Last reply
                                    0
                                    • A Offline
                                      A Offline
                                      andre
                                      wrote on last edited by
                                      #27

                                      Could you keep posts to English in this forum please? There are specialized sub-forums for other languages.

                                      1 Reply Last reply
                                      0
                                      • A Offline
                                        A Offline
                                        andre
                                        wrote on last edited by
                                        #28

                                        Could you keep posts to English in this forum please? There are specialized sub-forums for other languages.

                                        1 Reply Last reply
                                        0
                                        • P pchar2 referenced this topic on
                                        • P pchar2 referenced this topic on

                                        • Login

                                        • Login or register to search.
                                        • First post
                                          Last post
                                        0
                                        • Categories
                                        • Recent
                                        • Tags
                                        • Popular
                                        • Users
                                        • Groups
                                        • Search
                                        • Get Qt Extensions
                                        • Unsolved