Results 1 to 4 of 4

Thread: Strange DnD behavior from QStandardItemModel and QTreeView

  1. #1
    Join Date
    Feb 2010
    Posts
    3

    Angry Strange DnD behavior from QStandardItemModel and QTreeView

    Hi, i have an irritating problem id like some help with if possible.

    QStandardItemModel behaves strangely when trying to disable drag and drop for the root item of a model. When disabling drag and drop for the invisibleRootItem() of the model all drop capability is removed from the rest of the tree as well, what i am wondering is whether this is the intended behavior or if i have found a bug (or perhaps i made a mistake somewhere, probably the most likely answer).

    Here is the source for an example i put together to show the problem, the top tree view has the root items drag and drop unchanged and the bottom tree view has the root item with Qt::NoItemFlags set. The child of the first items in both views has drag and drop set, the parent items has only enabled and selectable set.

    DnDTest.zip

    Any ideas, any at all, will be happily received as i am currently going nuts over this. No matter what i try i cant get this dang model to work as _I_ expect it to, that is to enable drop on the children even if the root item has drop disabled.

    Thank you for any help... really... any help at all.

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Strange DnD behavior from QStandardItemModel and QTreeView

    The root item represents the tree itself. If you disable d&d on the root item, you effectively disallow dropping anything on the canvas of the view (I think you should still be able to drop on items in the view).
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Feb 2010
    Posts
    3

    Default Re: Strange DnD behavior from QStandardItemModel and QTreeView

    The drop on the canvas is correctly disabled when removing drop on the root item, however, the drop capability on the items in the view is also disabled when the root item drop is disabled. This is the problem i have atm, i want to drag onto items in the view, but not onto the canvas itself. But as i disable drop on the canvas i also disable drop onto the items in the view, no matter what ItemFlags i use for the items.

    The example project i included has one view with a disabled root item and one view with the root item enabled. I was hoping someone could tell me if ive done something wrong by looking at the code or trying the program. Or tell me if ive found a bug for that matter.

  4. #4
    Join Date
    Feb 2010
    Posts
    3

    Default Re: Strange DnD behavior from QStandardItemModel and QTreeView

    After some more testing i have found out that it seems to be strange handling in QTreeView::dragMoveEvent() function that causes the strange behavior. If i subclass QTreeView and make my own dragMoveEvent() function i can get the view and model to accept the disabled drop on the root item (while still allowing child items to be dropped on), but not otherwise. What i had to do was check the flags myself for each item being dragged over to make the drop function correctly.

    Code needed: (beware, i dont claim this is complete... this is just a quick hack to verify my theory)

    Qt Code:
    1. void MyTreeView::dragMoveEvent(QDragMoveEvent *event) {
    2. QModelIndex index = indexAt(event->pos());
    3.  
    4. if (index.flags() & Qt::ItemIsDropEnabled) {
    5. event->accept();
    6. } else {
    7. QTreeView::dragMoveEvent(event);
    8. }
    9. }
    To copy to clipboard, switch view to plain text mode 

    The culprit was these lines in the implementation in QAbstractItemView:

    Qt Code:
    1. ...
    2. if (index.isValid() && d->showDropIndicator) {
    3. ...
    4. } else {
    5. d->dropIndicatorRect = QRect();
    6. d->dropIndicatorPosition = OnViewport;
    7. if (d->model->flags(rootIndex()) & Qt::ItemIsDropEnabled) {
    8. event->setDropAction(dropAction);
    9. event->accept(); // allow dropping in empty areas
    10. }
    11. }
    12. ...
    To copy to clipboard, switch view to plain text mode 

    As i had drop indicator disabled (i draw my own) the code only checks the root items flags and thus it disables all drop indicators for the children as well. If i were to decide this would be a bug... the handling should be the same whether you want to draw your own drop indicators or not.

    Below is the default implementation in QAbstractItemView:

    Qt Code:
    1. void QAbstractItemView::dragMoveEvent(QDragMoveEvent *event)
    2. {
    3. if (dragDropMode() == InternalMove
    4. && (event->source() != this || !(event->possibleActions() & Qt::MoveAction)))
    5. return;
    6.  
    7. // ignore by default
    8. event->ignore();
    9.  
    10. QModelIndex index = indexAt(event->pos());
    11. if (!(event->source() == this && selectedIndexes().contains(index))
    12. && d->canDecode(event)) {
    13. Qt::DropAction dropAction = (d->model->supportedDropActions() & event->proposedAction())
    14. ? event->proposedAction() : Qt::IgnoreAction;
    15.  
    16. if (index.isValid() && d->showDropIndicator) {
    17. QRect rect = visualRect(index);
    18. d->dropIndicatorPosition = d->position(event->pos(), rect);
    19. switch (d->dropIndicatorPosition) {
    20. case AboveItem:
    21. if (d->model->flags(index.parent()) & Qt::ItemIsDropEnabled) {
    22. d->dropIndicatorRect = QRect(rect.left(), rect.top(), rect.width(), 0);
    23. event->setDropAction(dropAction);
    24. event->accept();
    25. } else {
    26. d->dropIndicatorRect = QRect();
    27. }
    28. break;
    29. case BelowItem:
    30. if (d->model->flags(index.parent()) & Qt::ItemIsDropEnabled) {
    31. d->dropIndicatorRect = QRect(rect.left(), rect.bottom(), rect.width(), 0);
    32. event->setDropAction(dropAction);
    33. event->accept();
    34. } else {
    35. d->dropIndicatorRect = QRect();
    36. }
    37. break;
    38. case OnItem:
    39. if (d->model->flags(index) & Qt::ItemIsDropEnabled) {
    40. d->dropIndicatorRect = rect;
    41. event->setDropAction(dropAction);
    42. event->accept();
    43. } else {
    44. d->dropIndicatorRect = QRect();
    45. }
    46. break;
    47. case OnViewport:
    48. d->dropIndicatorRect = QRect();
    49. break;
    50. }
    51. } else {
    52. d->dropIndicatorRect = QRect();
    53. d->dropIndicatorPosition = OnViewport;
    54. if (d->model->flags(rootIndex()) & Qt::ItemIsDropEnabled) {
    55. event->setDropAction(dropAction);
    56. event->accept(); // allow dropping in empty areas
    57. }
    58. }
    59. d->viewport->update();
    60. } // can decode
    61.  
    62. if (d->shouldAutoScroll(event->pos()))
    63. startAutoScroll();
    64. }
    To copy to clipboard, switch view to plain text mode 

Similar Threads

  1. Strange behavior of QSqlTableModel
    By venomj in forum Qt Programming
    Replies: 0
    Last Post: 13th January 2010, 03:29
  2. QStandardItemModel Drag n Drop Behavior with QTreeView
    By johnmidd in forum Qt Programming
    Replies: 0
    Last Post: 5th November 2009, 19:53
  3. QComboBox strange behavior
    By Antebios in forum Newbie
    Replies: 2
    Last Post: 31st March 2009, 23:50
  4. Strange behavior of QSyntaxHighlighter in Qt3
    By lorebett in forum Qt Programming
    Replies: 1
    Last Post: 18th January 2009, 14:50
  5. Strange resize behavior
    By Lykurg in forum Newbie
    Replies: 3
    Last Post: 9th January 2007, 13:56

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.