Results 1 to 5 of 5

Thread: Drag Drop problem with model views

  1. #1
    Join Date
    Apr 2010
    Posts
    77
    Thanks
    10
    Thanked 7 Times in 6 Posts
    Qt products
    Qt4
    Platforms
    MacOS X

    Default Drag Drop problem with model views

    Hi Guys

    I've got a QTreeView that I've setup so that I can drag and drop a node within the tree.
    That included reimplementing supportedDropActions(), mimeTypes(), mimeData(const QModelIndexList &indexes), bool dropMimeData(...) and removeRows().

    Most of it works fine:
    When I start the drag, mimeData() is called.
    When I drop the node, dropMimeData(...) gets called - It creates a new node from the mimeData and insert the node into the data structure (between beginInsertRows() and endInsertRows() ).
    It then automatically calls removeRows() which removes the original node.

    But there are some occasions where I need to reject the drop. If I simply return false in dropMimeData,
    the dragged node returns to its original position but then removeRows() is still called and the node gets removed.
    If I set up a flag so that the node isn't removed within removeRows(), it leaves the row there but makes it invisible.

    Does anyone know how to fix this?

    Thanks
    Jeff

  2. The following user says thank you to Jeffb for this useful post:


  3. #2
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Drag Drop problem with model views

    post the relevant code.
    Specially your dropMimeData().
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  4. The following user says thank you to high_flyer for this useful post:


  5. #3
    Join Date
    Apr 2010
    Posts
    77
    Thanks
    10
    Thanked 7 Times in 6 Posts
    Qt products
    Qt4
    Platforms
    MacOS X

    Default Re: Drag Drop problem with model views

    The model (JB_NodeModel) uses a helper class (dragDropHelper) that handles the various drag drop methods e.g. dropMimeData.


    Qt Code:
    1. bool JB_NodeModel::dropMimeData(const QMimeData *data,
    2. Qt::DropAction action,
    3. int row,
    4. int column,
    5. const QModelIndex &parent)
    6. {
    7. if (dragDropHelper)
    8. return dragDropHelper->dropMimeData(data,
    9. action,
    10. row,
    11. column,
    12. parent,
    13. this);
    14. else
    15. return QAbstractItemModel::dropMimeData(data,
    16. action,
    17. row,
    18. column,
    19. parent);
    20. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. bool JB_NMHP_DD_KwGrpsWidget::dropMimeData(const QMimeData *data,
    2. Qt::DropAction action,
    3. int row,
    4. int column,
    5. const QModelIndex &parent,
    6. JB_NodeModel *aNodeModel)
    7. {
    8. Q_CHECK_PTR(aNodeModel);
    9. bool handleDrop = true;
    10. JB_Node* movedNode = 0;
    11.  
    12. if (action == Qt::IgnoreAction)
    13. handleDrop = true;
    14.  
    15. if (!data->hasFormat("text/plain"))
    16. handleDrop = false;
    17. else if (column > 0)
    18. handleDrop = false;
    19. else
    20. {
    21. JB_Node* aParentNode = 0;
    22. if (modelWrapper->getJBNodeModel() == aNodeModel)
    23. {
    24. aParentNode = aNodeModel->nodeFromIndex(parent);
    25. Q_CHECK_PTR(aParentNode);
    26. }
    27. else
    28. JB_Utilities::getJBUtilities()->debugMB("ERROR: The Drag&Drop modelWrapper and nodeModel do not match", 0);
    29.  
    30. int beginRow;
    31. if (row >= 0)
    32. beginRow = row;
    33. else
    34. beginRow = 0;
    35. //beginRow = aParentNode->children.count();
    36.  
    37. QString aFirstNodePrimaryTableName;
    38. QString aFirstNodeLineage;
    39. QString aFirstNodeRowIDFieldName;
    40. QHash<QString, QVariant> aFirstNodeFieldValues;
    41.  
    42. QStringList nodesMimeDataTextList = JB_Utilities::getJBUtilities()->getTextListFromMimeData(data);
    43. QString firstNodeText = nodesMimeDataTextList.value(0);
    44. JB_Utilities::getJBUtilities()->getInfoFromMIMEDataText(firstNodeText,
    45. aFirstNodePrimaryTableName,
    46. aFirstNodeLineage,
    47. aFirstNodeRowIDFieldName,
    48. aFirstNodeFieldValues);
    49.  
    50. if (aFirstNodePrimaryTableName == "KeywordGroup")
    51. {
    52. if (nodesMimeDataTextList.size() > 1)
    53. JB_Utilities::getJBUtilities()->debugMB("ERROR: The Drag&Drop is trying to move more than one Keyword Group", 0);
    54. else
    55. {
    56. movedNode = aNodeModel->getNodeForNodeLineage(aFirstNodeLineage);
    57. Q_CHECK_PTR(movedNode);
    58. if (movedNode->parent == aParentNode)
    59. handleDrop = false;
    60. else
    61. {
    62. handleDrop = true;
    63. JB_Node* newFromMovedNode = new JB_Node(*movedNode);
    64. newFromMovedNode->children = movedNode->children;
    65. for (int i = 0; i < newFromMovedNode->children.count(); i++)
    66. newFromMovedNode->children.value(i)->parent = newFromMovedNode;
    67.  
    68. int parentRowID = aParentNode->getRowID();
    69. int unhashedParentRowID = JB_Utilities::getJBUtilities()->getUnHashedTreeLevelID(parentRowID);
    70.  
    71. QString kwGrpParentIDFieldName = "kwGrp_KwGrpParentID";
    72. if (newFromMovedNode->getMappedDBFieldNames().contains(kwGrpParentIDFieldName))
    73. {
    74. newFromMovedNode->setData("kwGrp_KwGrpParentID", QVariant(unhashedParentRowID));
    75. newFromMovedNode->setDragDropStatus(JB_DRAGDROP);
    76. aNodeModel->insertNode(aParentNode, beginRow, newFromMovedNode, false, true);
    77. }
    78. else
    79. JB_Utilities::getJBUtilities()->debugMB("ERROR: newFromMovedNode should have a kwGrp_KwGrpParentID field", 0);
    80. }
    81. }
    82. }
    83. }
    84.  
    85. if (handleDrop == false && movedNode)
    86. movedNode->setDragDropStatus(JB_CANCEL_DRAGDROP);
    87.  
    88. return handleDrop;
    89. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. Qt::DropActions JB_NMHP_DD_KwGrpsWidget::supportedDropActions() const
    2. {
    3. return Qt::MoveAction;
    4. }
    To copy to clipboard, switch view to plain text mode 

  6. The following user says thank you to Jeffb for this useful post:


  7. #4
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Drag Drop problem with model views

    can you show your removeRows() as well?
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  8. The following user says thank you to high_flyer for this useful post:


  9. #5
    Join Date
    Apr 2010
    Posts
    77
    Thanks
    10
    Thanked 7 Times in 6 Posts
    Qt products
    Qt4
    Platforms
    MacOS X

    Default Re: Drag Drop problem with model views

    Sure.

    This has actually changed a little. I wanted to stop a child node being dropped on it's parent - this was problematic with the underlying data structure. In the mean time I have changed the underlying structure so that it allows a child to be dropped on the parent.

    BUT...
    I still need to know why it didn't allow me to stop the row being removed when I cancelled the drop i.e. returned false in dropMimeData() as I will need to be able to do that shortly in another situation.

    Anyway, here's the implementation for removeRows().
    Thanks
    Jeff

    Qt Code:
    1. bool JB_NodeModel::removeRows(int row, int count, const QModelIndex &parent)
    2. {
    3. bool returnVal = false;
    4. for (int i = 0; i < count; i++)
    5. {
    6. int rowNum = row + i;
    7. returnVal = removeRow(rowNum, parent);
    8. }
    9. return returnVal;
    10. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. // NOTE: converting hashed tree IDs to normal DB IDs is handled in JB_DBTGeneric table
    2. bool JB_NodeModel::removeRow(int row, const QModelIndex &parent)
    3. {
    4. // The first table in the tablesUsedList is the one that rows can be inserted into or deleted from
    5. bool success = false;
    6. JB_Node* parentNode = rootNode;
    7.  
    8. if (parent.isValid())
    9. parentNode = nodeFromIndex(parent);
    10. Q_CHECK_PTR(parentNode);
    11.  
    12. int numChildren = parentNode->children.count();
    13. JB_Node* removedNode = parentNode->children.takeAt(row);
    14. QString oldLineage = removedNode->getNodeRowIDLineage();
    15.  
    16. int firstRow = row;
    17. int lastRow = row;
    18. if (nodesHashTable->contains(oldLineage))
    19. {
    20. beginRemoveRows(parent, firstRow, lastRow);
    21.  
    22. if (removedNode->getDragDropStatus() == JB_DRAGDROP)
    23. {
    24. int numberRemoved = nodesHashTable->removeFromLineageToNodesHash(oldLineage);
    25. if (numberRemoved == 1)
    26. success = true;
    27. }
    28. else // if it == JB_NO_DRAGDROP
    29. {
    30. // Don't actually delete anything - just set it to not Active. By setting IsDeleted to true, the model updates the row in the DB (but doesn't delete it at this point ?)
    31. removedNode->parent = 0;
    32. removedNode->setIsDeleted(true);
    33. int primaryTableNameEnum = tablesUsedList.value(0);
    34. QString isActiveFieldName = JB_DBTableFields::getTC()->getIsActiveFieldNameForTableEnum(primaryTableNameEnum);
    35. removedNode->setData(isActiveFieldName, QVariant(false));
    36. success = true;
    37. }
    38.  
    39. endRemoveRows();
    40. emit removingRow();
    41. }
    42.  
    43. bool equalHashes = nodesHashTable->isHashSizesEqual();
    44. Q_ASSERT(equalHashes == true);
    45.  
    46. removedNode->setDragDropStatus(JB_NO_DRAGDROP);
    47.  
    48. return success;
    49. }
    To copy to clipboard, switch view to plain text mode 


    Added after 4 minutes:


    Just found this link - looks like others have had problems with it too.

    https://bugreports.qt-project.org/browse/QTBUG-6679

    I'm using Mac, Lion OS 10.7.3


    Added after 45 minutes:


    I just changed the ex-treemodel example to return false from dropMimeData() and after running it and dragging and dropping a node, it still called deleteRows() on the dragged node and deleted it.
    So there is clearly a bug here.

    I commented out the code within removeRows and ran it again and it didn't delete the row or make it invisible (which is what happened and I put a flag into removeRows() to stop it from deleting the row on a cancelled drop) so I'm not sure why that happened but at least with a bit of fiddling there appears to be a workaround.

    Still it's a pretty decent bug that has been around for a couple of years according to the link above.

    Any other ideas are welcome.

    Jeff
    Last edited by Jeffb; 11th March 2012 at 05:07.

  10. The following user says thank you to Jeffb for this useful post:


Similar Threads

  1. Replies: 1
    Last Post: 2nd August 2010, 20:16
  2. Drag and drop between model views
    By larry104 in forum Qt Programming
    Replies: 20
    Last Post: 19th January 2008, 16:09
  3. Replies: 1
    Last Post: 30th November 2007, 11:55
  4. Drag Drop between Different Views
    By aamer4yu in forum Qt Programming
    Replies: 13
    Last Post: 8th December 2006, 04:29
  5. drag and drop with item views
    By castorvert in forum Qt Programming
    Replies: 14
    Last Post: 27th March 2006, 10:12

Tags for this Thread

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.