Sorting with ignored items



  • Hi guys!

    I have child class from QSortFilterProxyModel. I need to sort items in model, but some items should be ignored and should be on top of table anyway.

    I try to override lessThan method, but it return exception 'invalid comparator'.

    How it can be implemented?


  • Qt Champions 2019

    @Craetor said in Sorting with ignored items:

    I try to override lessThan method, but it return exception 'invalid comparator'.

    Please show the code



  • Hi, i think it was solved.

    I just implement lessThan with return false.

    bool CSAbstractProxyModel::lessThan(const QModelIndex& sourceLeft, const QModelIndex& sourceRight) const
    {
    CSTreeItem* l_pLeft = SOURCE->getItem(sourceLeft);
    CSTreeItem* l_pRight = SOURCE->getItem(sourceRight);
    if(l_pLeft && l_pRight)
    {
    if(l_pLeft->GetIgnoreSort() || l_pRight->GetIgnoreSort())
    return false;
    }
    return Super::lessThan(sourceLeft, sourceRight);
    }



  • @Craetor

    if (l_pLeft->GetIgnoreSort() || l_pRight->GetIgnoreSort())
        return false;
    

    I don't think this is correct.

    Your lessThan() is called repeatedly with various items to compare. The return result is used to decide where the items go into the sorted result.

    You need to consider what happens in your case when one of l_pLeft/l_pRight has GetIgnoreSort() == true while the other has GetIgnoreSort() == false. You return false in both these cases. That means that sometimes a non-sort item is considered "less" than a sort item, sometimes the sort item is considered "less" than the non-sort item, depending on which one happens to be l_pLeft versus l_pRight, which is undefined/"random". It will even return a different answer as to which is "less" if you pass in the same two such items depending if you swap which one is left versus right.

    I don't know how big your data is, so it may not have shown up yet but it may be waiting to happen to you on a different/bigger dataset.

    http://doc.qt.io/qt-5/qsortfilterproxymodel.html#lessThan states:

    Returns true if the value of the item referred to by the given index source_left is less than the value of the item referred to by the given index source_right, otherwise returns false.

    To implement that, I think a more correct version would be something like:

    if(l_pLeft && l_pRight)
    {
        if (l_pLeft->GetIgnoreSort())
            return l_pRight->GetIgnoreSort() ? false : true;
        if (l_pRight->GetIgnoreSort())
            return false;
    }
    return Super::lessThan(sourceLeft, sourceRight);
    

    Thus my code's result is different from yours when left is ignore and right is not ignore: in that situation you would return false but I return true.

    P.S.
    Test case for you:

    1. Put just 2 items in your model, one with ignore-sort and one with respect-sort.
    2. Try it once where you start out with the ignore item as the first row and the respect item as the second row. Try it again with the respect item first and the ignore item second.
    3. My code should sort them correctly with the ignore first and the respect second from both starting situations.
    4. I believe your code will return different results: one of the two cases it will sort them correctly, but in the other case it will sort them the wrong way round.


  • @JonB, thanks, i will try your implementation.


Log in to reply