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)
-
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-3In the UI, I drag-drop Row-1 to be as follows:
Position-1 -> Row-2
Position-2 -> Row-1
Position-3 -> Row-3When 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-3After, 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.
-
For example just emit a signal, add a queued connection and do your work there.
-
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 3Then 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 3From 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?
-
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