Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Move items in a QSortFilterProxyModel



  • I have a tableview with takes a qsortfilterproxymodel and is filtered by a particular name.

    I have subclassed the qsortfilterproxymodel

    class FilterProxyModel : public QSortFilterProxyModel
    {
    	Q_OBJECT
    public:
    	FilterProxyModel(QObject *parent = 0);
    
    	void moveUp( const int itemIndex);
    	void moveDown( const int itemIndex);
    };
    

    and here's the implementation

    FilterProxyModel ::FilterProxyModel (QObject *parent) :
    	QSortFilterProxyModel(parent)
    {
    
    }
    
    void FilterProxyModel ::moveUp(const int itemIndex)
    {
    	if(itemIndex > 0 && itemIndex < rowCount())
    	{
    		beginMoveRows(QModelIndex(), itemIndex, itemIndex, QModelIndex(),
    					  itemIndex - 1);
    		moveRow(QModelIndex(), itemIndex, QModelIndex(), itemIndex - 1);
    		endMoveRows();
    	}
    }
    
    void FilterProxyModel ::moveDown(const int itemIndex)
    {
    	if(itemIndex >= 0 && itemIndex < rowCount() - 1)
    	{
    		beginMoveRows(QModelIndex(), itemIndex, itemIndex, QModelIndex(),
    					  itemIndex + 2);
    		moveRow(QModelIndex(), itemIndex, QModelIndex(), itemIndex + 2);
    		endMoveRows();
    	}
    }
    
    

    Here's how the model is initialized

    m_Model = new FilterProxyModel(this);
    m_Model ->setSourceModel(partiesModel);
    m_Model ->setFilterRegExp(QRegExp("party", Qt::CaseInsensitive, QRegExp::FixedString));
    m_Model ->setFilterKeyColumn(PartyModel::Action);
    

    I want to move the items using a push button, when i call the function the move doesn't happen. Could you tell me what I'm missing?



  • @Valerian

    • I believe your range is wrong, at least in ::moveDown. itemIndex + 2 doesn't seem right for a move by one row.... E.g. when itemIndex == rowCount() - 2 it will produce rowCount(), which is too high for beginMoveRows()?

    • beginMoveRows() can be passed more rows than you're actually moving. While debugging I would pass everything from 0 to rowCount() - 1 so that you can eliminate bad parameters to beginMoveRows() from being the issue.

    You are quite sure that with your QSortFilterProxyModel you are not imposing any kind of sort? Because adding/moving rows when Qt has sorting on always causes problems.



  • @JonB
    Yes I'm sure I'm not used any kind of sort. The move up function seems to select the next item but doesn't actually physically move it.



  • @Valerian



  • @JonB said in Move items in a QSortFilterProxyModel:

    That's why I suggested you start by setting the range to all rows and see how you go.

    I tried setting the following for the moveUp

    if(itemIndex > 0 && itemIndex < rowCount())
    {
    	qDebug() << "SSSSSSSSS " << beginMoveRows(QModelIndex(), 0, rowCount() - 1, QModelIndex(),
    					  itemIndex - 1);
    		moveRow(QModelIndex(), itemIndex, QModelIndex(), itemIndex - 1);
    		endMoveRows();
    	}
    

    and here's the response

    SSSSSSSSS  false
    10:14:16.649 18/07/2018 [FATAL] global\qglobal.cpp:3044 - ASSERT: "!this->isEmpty()" in file c:\users\qt\work\qt\qtbase\include\qtcore\../../src/corelib/tools/qstack.h, line 62
    10:14:35.029 18/07/2018 [FATAL] global\qglobal.cpp:3044 - ASSERT: "asize >= 0 && asize <= aalloc" in file c:\users\qt\work\qt\qtbase\include\qtcore\../../src/corelib/tools/qvector.h, line 535
    10:14:35.934 18/07/2018 [FATAL] global\qglobal.cpp:3044 - ASSERT: "uint(d->size) <= d->alloc" in file c:\users\qt\work\qt\qtbase\include\qtcore\../../src/corelib/tools/qvector.h, line 614
    10:14:36.198 18/07/2018 [FATAL] global\qglobal.cpp:3044 - ASSERT: "asize >= 0 && asize <= aalloc" in file c:\users\qt\work\qt\qtbase\include\qtcore\../../src/corelib/tools/qvector.h, line 535
    10:14:36.421 18/07/2018 [FATAL] global\qglobal.cpp:3044 - ASSERT: "uint(d->size) <= d->alloc" in file c:\users\qt\work\qt\qtbase\include\qtcore\../../src/corelib/tools/qvector.h, line 614
    10:14:36.909 18/07/2018 [FATAL] global\qglobal.cpp:3044 - ASSERT: "!this->isEmpty()" in file c:\users\qt\work\qt\qtbase\include\qtcore\../../src/corelib/tools/qstack.h, line 62
    


  • @Valerian
    Ignore my idea of passing "all" rows as range. Revert to whatever code you think is right for just one row. Then try again.

    The important thing is my second point, the return result of beginMoveRows() with whatever parameters you give it. Your debug shows it returned false. So long as it returns false in your case, it's not going to work, and you need to figure why not!



  • @JonB said in Move items in a QSortFilterProxyModel:

    he important thing is my second point, the return result of beginMoveRows() with whatever parameters you give it. Your debug shows it returned false. So long as it returns false in your case, it's not going to work, and you need to figure why not!

    I reverted the code and it returns true but the row isn't actually shifted



  • @Valerian
    Fair enough. Then I can only suggest you read that doc page carefully to understand what they are saying is required in each direction, and play with the parameters/which row/how far you move the row till you see something happening, and figure from there.



    • moveRow must already call beginMoveRows and endMoveRows inside itself so you are duplicating calls
    • moveRow is not implemented in any of Qt's model (as far as I'm aware) so it will probably just do nothing and return false (check the return value)

    What model are you using as source to this proxy?



  • @VRonin said in Move items in a QSortFilterProxyModel:

    What model are you using as source to this proxy?

    QAbstractTableModel



  • @VRonin
    Don't forget OP is claiming that one of his moveUp/moveDown does work, while the other does not....

    moveRow must already call beginMoveRows and endMoveRows inside itself so you are duplicating calls

    If that's true that might explain....!



  • @Valerian said in Move items in a QSortFilterProxyModel:

    QAbstractTableModel

    Did you reimplement moveRow?



  • @VRonin I re-implemeted it in the QSortFilterProxyModel. Didn't want to move rows in the main model



  • Can you post the implementation?



  • @Valerian
    I now realise you got your code from https://stackoverflow.com/a/43683619/489865, didn't you? Wasn't actually confirmed to be correct solution. I still don't get where the + 2 comes from, but there you are.

    IF @VRonin does not sort you out (so to speak :) ), I don't know, but maybe you should have a careful read of https://stackoverflow.com/a/12254935/489865. Not sure whether the following might affect you:

    (2) Yes if you don't use sorting, just filtering. Qt in such case erases entire internal mapping and re-builds it from scratch so the data will be just as they appear in source model



  • @VRonin said in Move items in a QSortFilterProxyModel:

    Can you post the implementation?

    I have already posted the implementation of the QSortFilterProxyModel. Are you seeking the implementation of the QAbstractTableModel?



  • @VRonin said in Move items in a QSortFilterProxyModel:

    Did you reimplement moveRow?

    @Valerian said in Move items in a QSortFilterProxyModel:

    I re-implemeted it in the QSortFilterProxyModel.

    I don't see an implementation of FilterProxyModel::moveRow (or rather FilterProxyModel::moveRows) above



  • @JonB said in Move items in a QSortFilterProxyModel:

    I now realise you got your code from https://stackoverflow.com/a/43683619/489865, didn't you? Wasn't actually confirmed to be correct solution. I still don't get where the + 2 comes from, but there you are.

    Yes I did pick it from there.

    Thanks for the other stackflow link. Will have a read on that.



  • @VRonin said in Move items in a QSortFilterProxyModel:

    I don't see an implementation of FilterProxyModel::moveRow (or rather FilterProxyModel::moveRows) above

    I haven't implement that. Not sure if I need to write that



  • @VRonin said in Move items in a QSortFilterProxyModel:

    Did you reimplement moveRow?

    @Valerian said in Move items in a QSortFilterProxyModel:

    I re-implemeted it in the QSortFilterProxyModel

    You lied to me!

    As I mentioned, the default implementation does nothing and returns false so calling it is pointless unless you reimplement it



  • @VRonin [I don't get what's happening in the pic? :( ]





  • @VRonin
    Dear Mr VRonin,

    Thank you for that link. I opened it from Firefox from the Ubuntu I sit inside as a VirtualBox under Windows Server.

    The video started, and then froze. My whole Linux guest box froze. Nothing other than a Windows TaskMan kill of the whole VBox was possible, killing my session and any work I had done but not committed!

    Please remind me never to risk clicking on such a link again! :) I shall have to manage without knowing the meaning of the pic now...



  • @JonB Sorry mate, it was just a stupid YouTube video of a guy saying carrots are good for eyesight, another guy shoving 2 carrots in his eyes and then the image above



  • @VRonin Thank you for your feedback. Will re-implement those functions and try



  • @VRonin Ohhhhh, I would never have figured that's what it was! All OK :)


Log in to reply