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

How to do post drag-drop processing in QTableView with custom model



  • Hello,
    I have a QTableView backed by a custom model MyModel (a subclass of QAbstractTableModel). In MyModel, I have overriden:

    bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) 
    {
          //My code
    
          bool returnVal = QAbstractTableModel::dropMimeData(data, action, row, 0, parent);
    
         //My code
    
         return returVal;
    }
    

    I have to call the superclass dropMimeData method, else I end up with duplicate rows.

    After MyModel::dropMimeData has finished, there is more additional steps the Qt framework does to complete the drag-drop of the rows.

    I want to implement actions after the drag-drop is complete. Is there some facility that I can use to execute code after the drag-drop is complete?

    Thanks.



  • Hi @JohnGa

    Have you enabled the drag and drop ?

    dragEnabled and acceptDrops.

    tableView->setEnableDrags(true)
    tableView->setAcceptDrops(true)
    


  • @Pradeep-P-N

    Yes, my drag-drop row moves are working fine. After MyModel::dropMimeData has finished, the Qt framework does more cleanup of the model. So, the drag-drop is NOT complete at the end of MyModel::dropMimeData.

    I want to execute code that will operate on all the rows in the model, after the drag-drop is complete. I am trying to figure out how I can execute code after the drag-drop is complete.

    Let's say I start with:
    Position-1 -> Row-1
    Position-2 -> Row-2
    Position-3 -> Row-3

    In the UI, I drag-drop Row-1 to be as follows:
    Position-1 -> Row-2
    Position-2 -> Row-1
    Position-3 -> Row-3

    When the above drag-drop of Row-1 is done in the UI, the code executes MyModel::dropMimeData. At the end of that MyModel::dropMimeData, the model collection looks like this:
    Row-1
    Row-2
    Row-1
    Row-3

    After, the Qt framework executes more framework code after MyModel:dropMimeData, them model collection looks like this:
    Row-2
    Row-1
    Row-3.

    I am trying to figure out what I need to do to execute a piece of code after the drag-drop is complete.


  • Lifetime Qt Champion

    For example just emit a signal, add a queued connection and do your work there.


  • Lifetime Qt Champion

    Hi,

    In addition to @Christian-Ehrlicher, QtConcurrent might also be of interest.



  • Thanks to everyone that is trying to help me. At a very high level, I want to execute code after drag-drop is complete within a QTableView, and the rows in my model have been re-arranged as per the new order. I have a custom model MyTableViewModel behind a QTableView. To implement my drag-drop, I implemented the dropMimeData method which does nothing but calling the "QAbstractTableModel::dropMimeData".

    Let's say I start with:
    Position 1 -> Row1
    Position 2 -> Row2
    Position 3 -> Row3.

    After I drag-drop Row1, from my debugging, I can see it first calling my dropMimeData method. This is "Stack 1" in the attached picture.

    After my dropMimeData is complete, the collection in MyTableViewModel shows:
    Row 1
    Row 2
    Row 1
    Row 3

    Then the Qt Framework calls the removeRows method in MyTableViewModel and cleans up. This is "Stack 2" in the attached picture. After this, the collection correctly shows:
    Row 2
    Row 1
    Row 3

    From the debug stackframes it looks like the Qt framework is has two separate events coming through when drag-drop happens. How can I recognize that both the phases are complete and then execute a piece of code?

    I see the suggestion about raising a custom signal. Where would I raise the signal after the drag-drop is complete?

    0_1560290543822_Qt issue.png


  • Lifetime Qt Champion

    What processing do you do that requires that precision ?



  • add a signal: void afterDrop();

    bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) 
    {
         const bool returnVal = QAbstractTableModel::dropMimeData(data, action, row, 0, parent);
         QTimer::singleShot(0,this,&MyModel::afterDrop);
         return returVal;
    }
    

    Now any slot connected to the afterDrop signal should be executed after everything completed


Log in to reply