QTableView Versus Row Drag/drop crashes
-
Hello,
i'm having trouble understanding how to implement a row drag/drop into my applications. Here are the constraints i have to live with.
1 - Can't subclass QtableView
2 - Must drag/drop full rows
3 - May drag between several views sharing the same modelThe approach is i install an event filter in the Qtableview to get my app to intercept by itself the events, get the ID of the row at the beginning of drag to cut the row using the cut function i already made for context menu, then on drop, insert the row still using the function from the context menu.
But before dealing with the cut/insert part i need to get the basics for drag/drop.
I can go up to the dragenter event, but once i move and/or drop the app crash, i'm trying something that probably don't exist or has been deleted already.Here is what i tried :
1 - View configuration and event filter setupvoid QtWidgetsSFIU_Alpha::configureTableViewForRowSelection(QList<QTableView*> tableViews) { for (QTableView* tableView : tableViews) { tableView->setSelectionMode(QAbstractItemView::SingleSelection); tableView->setSelectionBehavior(QAbstractItemView::SelectRows); } } void QtWidgetsSFIU_Alpha::configureDragAndDrop(QTableView* view) { if (view == nullptr) return; // Enable drag and drop for the serial views view->viewport()->installEventFilter(this); view->setDragEnabled(true); view->setAcceptDrops(true); view->setDropIndicatorShown(true); view->setDragDropMode(QAbstractItemView::InternalMove); view->setDefaultDropAction(Qt::MoveAction); view->setDragDropOverwriteMode(false); }
2 - I create small functions to manage the mouse events for clean drag and drop
void QtWidgetsSFIU_Alpha::mouseSerialViewPressEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { dragStartPosition = event->pos(); qDebug() << "Mouse pressed at " << dragStartPosition; } } void QtWidgetsSFIU_Alpha::mouseSerialViewMoveEvent(QMouseEvent* event) { if (!(event->buttons() & Qt::LeftButton)) { qDebug() << "Mouse released at " << event->pos(); return; } if ((event->pos() - dragStartPosition).manhattanLength() < QApplication::startDragDistance()){ qDebug() << "Mouse moved less than " << QApplication::startDragDistance(); return; } qDebug() << "Draged Started "; QDrag* drag = new QDrag(this); QMimeData* mimeData = new QMimeData; mimeData->setText("DragAndDropTest"); drag->setMimeData(mimeData); Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction); }
And finally the event filter
/** * @brief Filters events if this object has been installed as an event filter for the watched object. * @param obj Object being watched. * @param event Event received. * @return True if the event should be filtered (i.e., stopped); otherwise false. */ bool QtWidgetsSFIU_Alpha::eventFilter(QObject* obj, QEvent* event) { // Implement event filter for all mouse events if (event->type() == QEvent::MouseButtonPress) { QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event); mouseSerialViewPressEvent(mouseEvent); } else if (event->type() == QEvent::MouseMove) { QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event); mouseSerialViewMoveEvent(mouseEvent); } // Drag enter, drage move, drag leave, drop events are handled here if (event->type() == QEvent::DragEnter) { qDebug() << "DragEnter"; } else if (event->type() == QEvent::DragMove) { qDebug() << "DragMove"; } else if (event->type() == QEvent::DragLeave) { qDebug() << "DragLeave"; } else if (event->type() == QEvent::Drop) { qDebug() << "Drop"; } // standard event processing return QObject::eventFilter(obj, event); }
And this is where I'm having issues, for now, i put dummy MIME data just to check i understand how the events occurs in debug.
But the app keep crashing, i can see in the console the mouse press, the creation of the drag object, and the capture of the dragenter event, but can't see dragmove or dragleave, and even less drop. Instead something is trying so read a null object somewhere (Console output below)
Mouse pressed at QPoint(293,67) Mouse moved less than 10 Mouse moved less than 10 Mouse moved less than 10 Mouse moved less than 10 Mouse moved less than 10 Draged Started DragEnter Exception levée à 0x00007FF97E83A4D4 (Qt6Guid.dll) dans QtWidgetsSFIU_Alpha.exe : 0xC0000005 : Violation d'accès lors de la lecture de l'emplacement 0x0000000000000000.
I'm a bit lost and not sure how to troubleshoot this. Does anybody pointers ?
Thx
Jc -
Hello,
i'm having trouble understanding how to implement a row drag/drop into my applications. Here are the constraints i have to live with.
1 - Can't subclass QtableView
2 - Must drag/drop full rows
3 - May drag between several views sharing the same modelThe approach is i install an event filter in the Qtableview to get my app to intercept by itself the events, get the ID of the row at the beginning of drag to cut the row using the cut function i already made for context menu, then on drop, insert the row still using the function from the context menu.
But before dealing with the cut/insert part i need to get the basics for drag/drop.
I can go up to the dragenter event, but once i move and/or drop the app crash, i'm trying something that probably don't exist or has been deleted already.Here is what i tried :
1 - View configuration and event filter setupvoid QtWidgetsSFIU_Alpha::configureTableViewForRowSelection(QList<QTableView*> tableViews) { for (QTableView* tableView : tableViews) { tableView->setSelectionMode(QAbstractItemView::SingleSelection); tableView->setSelectionBehavior(QAbstractItemView::SelectRows); } } void QtWidgetsSFIU_Alpha::configureDragAndDrop(QTableView* view) { if (view == nullptr) return; // Enable drag and drop for the serial views view->viewport()->installEventFilter(this); view->setDragEnabled(true); view->setAcceptDrops(true); view->setDropIndicatorShown(true); view->setDragDropMode(QAbstractItemView::InternalMove); view->setDefaultDropAction(Qt::MoveAction); view->setDragDropOverwriteMode(false); }
2 - I create small functions to manage the mouse events for clean drag and drop
void QtWidgetsSFIU_Alpha::mouseSerialViewPressEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { dragStartPosition = event->pos(); qDebug() << "Mouse pressed at " << dragStartPosition; } } void QtWidgetsSFIU_Alpha::mouseSerialViewMoveEvent(QMouseEvent* event) { if (!(event->buttons() & Qt::LeftButton)) { qDebug() << "Mouse released at " << event->pos(); return; } if ((event->pos() - dragStartPosition).manhattanLength() < QApplication::startDragDistance()){ qDebug() << "Mouse moved less than " << QApplication::startDragDistance(); return; } qDebug() << "Draged Started "; QDrag* drag = new QDrag(this); QMimeData* mimeData = new QMimeData; mimeData->setText("DragAndDropTest"); drag->setMimeData(mimeData); Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction); }
And finally the event filter
/** * @brief Filters events if this object has been installed as an event filter for the watched object. * @param obj Object being watched. * @param event Event received. * @return True if the event should be filtered (i.e., stopped); otherwise false. */ bool QtWidgetsSFIU_Alpha::eventFilter(QObject* obj, QEvent* event) { // Implement event filter for all mouse events if (event->type() == QEvent::MouseButtonPress) { QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event); mouseSerialViewPressEvent(mouseEvent); } else if (event->type() == QEvent::MouseMove) { QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event); mouseSerialViewMoveEvent(mouseEvent); } // Drag enter, drage move, drag leave, drop events are handled here if (event->type() == QEvent::DragEnter) { qDebug() << "DragEnter"; } else if (event->type() == QEvent::DragMove) { qDebug() << "DragMove"; } else if (event->type() == QEvent::DragLeave) { qDebug() << "DragLeave"; } else if (event->type() == QEvent::Drop) { qDebug() << "Drop"; } // standard event processing return QObject::eventFilter(obj, event); }
And this is where I'm having issues, for now, i put dummy MIME data just to check i understand how the events occurs in debug.
But the app keep crashing, i can see in the console the mouse press, the creation of the drag object, and the capture of the dragenter event, but can't see dragmove or dragleave, and even less drop. Instead something is trying so read a null object somewhere (Console output below)
Mouse pressed at QPoint(293,67) Mouse moved less than 10 Mouse moved less than 10 Mouse moved less than 10 Mouse moved less than 10 Mouse moved less than 10 Draged Started DragEnter Exception levée à 0x00007FF97E83A4D4 (Qt6Guid.dll) dans QtWidgetsSFIU_Alpha.exe : 0xC0000005 : Violation d'accès lors de la lecture de l'emplacement 0x0000000000000000.
I'm a bit lost and not sure how to troubleshoot this. Does anybody pointers ?
Thx
Jc@Jyce said in QTableView Versus Row Drag/drop crashes:
But the app keep crashing,
That's why they invented debuggers.
-
Hi and welcome to devnet,
Strangely, you requirements sounds familiar from some years agol.
Anyway, one thing I haven't seen from your requirement is that the model class should not be subclassed so what about following the drag and drop part of the item view documentation and customize the model to manage that part so you don't need such hacks ? -
Hi and welcome to devnet,
Strangely, you requirements sounds familiar from some years agol.
Anyway, one thing I haven't seen from your requirement is that the model class should not be subclassed so what about following the drag and drop part of the item view documentation and customize the model to manage that part so you don't need such hacks ?@SGaist , thanks I'll look at the article, i guess requirements where not complete then :D
No the goal is to do with what i have and not subclass anything.Is the way i'm trying to use is consider too much of a hack as you mentioned ?
Implementing event filters seemed quit a common practice when i looked for solutions ?
I still would like to understand what I'm doing wrong here.@Christian-Ehrlicher, i would gladly track the issue with the breakpoints if i knew where to start :)
Putting it in the event handler does not help much as i constantly hit it, and if i filter on event from the table view i'm still ending up. Call stack is not helping much either :) -
@SGaist , thanks I'll look at the article, i guess requirements where not complete then :D
No the goal is to do with what i have and not subclass anything.Is the way i'm trying to use is consider too much of a hack as you mentioned ?
Implementing event filters seemed quit a common practice when i looked for solutions ?
I still would like to understand what I'm doing wrong here.@Christian-Ehrlicher, i would gladly track the issue with the breakpoints if i knew where to start :)
Putting it in the event handler does not help much as i constantly hit it, and if i filter on event from the table view i'm still ending up. Call stack is not helping much either :) -
@SGaist it's been a while since i put my hand on GUI with QT, i'm trying to re-learn step by step. working using the default features felt like a good idea but i have the feeling it might be a stoopid :)
What puzzles me is the fact that combining a provided QTableView and a provided QstandardItem model does not allow drag and drop since for example sorting works right of the bat.
From what i understand from the doc you recommended me, sub-classing at the model level seems to allow to keep various view in sync with much less work. Or less computation ?
-
@SGaist it's been a while since i put my hand on GUI with QT, i'm trying to re-learn step by step. working using the default features felt like a good idea but i have the feeling it might be a stoopid :)
What puzzles me is the fact that combining a provided QTableView and a provided QstandardItem model does not allow drag and drop since for example sorting works right of the bat.
From what i understand from the doc you recommended me, sub-classing at the model level seems to allow to keep various view in sync with much less work. Or less computation ?
@Jyce I am not following you here. Drag and drop works out of the box for the item views. You just have to activate the options.
Now you want to do something special so you have to adjust the code to your needs which is nothing unusual. -
@Jyce I am not following you here. Drag and drop works out of the box for the item views. You just have to activate the options.
Now you want to do something special so you have to adjust the code to your needs which is nothing unusual.Hello @SGaist, fully agree with you and understand.
I wrongly assumed that row drag and drop was part of the baseline behavior of the qtableview :)
I'm following the links you sent me and the various example to work on it (the source code of the Qtableview itslef provides a lot of information)