Results 1 to 5 of 5

Thread: QStandardItem::clone() not being called for Drag and Drop

  1. #1
    Join Date
    Sep 2007
    Posts
    14
    Thanks
    5
    Qt products
    Qt4
    Platforms
    MacOS X Windows

    Default QStandardItem::clone() not being called for Drag and Drop

    I have a Qt application where I am using a QStandardItemModel derived class, and a QTreeView to interact with it. I would like to enable drag and drop to copy and move items around the model. To enable this, I have done the following:

    • In QStandardItem subclasses that represent leaf nodes: setDragEnabled(true) and override clone() to return a real copy of the item.
    • In QStandardItem subclasses that represent Folder nodes: setDropEnabled(true)
    • In QTreeView: setDragEnabled(true); setAcceptDrops(true); setDropIndicatorShown(true);


    Drag and Drop works to the extent that it honors which items can be dragged and which can accept drops. However, whether moving or copying it does not create new items using my clone() functions. It only copies the settings and data available to the QStandardItem base class, losing subclass overrides and such.

    How do I get the model and views to make use of my clone() functions, or work around this?

    Thank you for any assistance.

  2. #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: QStandardItem::clone() not being called for Drag and Drop

    It only copies the settings and data available to the QStandardItem base class, losing subclass overrides and such.
    Show this part of your code.
    ==========================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.

  3. #3
    Join Date
    Sep 2007
    Posts
    14
    Thanks
    5
    Qt products
    Qt4
    Platforms
    MacOS X Windows

    Default Re: QStandardItem::clone() not being called for Drag and Drop

    Quote Originally Posted by high_flyer View Post
    Show this part of your code.
    Ok, here is how I am initializing my TreeView in the contructor:

    Qt Code:
    1. setModel(SceneModel::instance());
    2. setContextMenuPolicy(Qt::CustomContextMenu);
    3. setSelectionBehavior(QAbstractItemView::SelectRows);
    4. setDragEnabled(true);
    5. setAcceptDrops(true);
    6. setDropIndicatorShown(true);
    7. setHeaderHidden(true);
    8.  
    9. connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(onContextRequested(const QPoint&)));
    To copy to clipboard, switch view to plain text mode 

    And the main functionality that I am losing. This code calls a context handler for my custom item classes. It gets run, but since the new items are not of the right type, it does nothing with the actual items.

    Qt Code:
    1. void SceneTree::onContextRequested(const QPoint& pos)
    2. {
    3. QModelIndex ItemIndex(indexAt(pos));
    4.  
    5. if (false == ItemIndex.isValid())
    6. return;
    7.  
    8. QStandardItem *Item = SceneModel::instance()->itemFromIndex(ItemIndex);
    9.  
    10. if ( SceneModel::SCN_OBJ_REF == Item->type() )
    11. {
    12. SceneObjectRef* scnItem = dynamic_cast<SceneObjectRef*>(Item);
    13. scnItem->getSceneObject()->onContextRequested( mapToGlobal(pos) );
    14. }
    15. }
    To copy to clipboard, switch view to plain text mode 
    Here is code from my subclass of QStandardItem which populates a lot of the model, including overrides and copy constructor. (SceneItem is an empty QStandardItem subclass, a placeholder for other common item functionality to come later. SceneObj is an object not directly part of the data model, but only referenced by the model.)

    Qt Code:
    1. SceneObjectRef::SceneObjectRef(const SceneObjectRef &Other)
    2. : QObject(), SceneItem(), scnObject(Other.scnObject)
    3. {
    4. init();
    5. }
    6.  
    7.  
    8. int SceneObjectRef::type() const
    9. {
    10. return SceneModel::SCN_OBJ_REF;
    11. }
    12.  
    13. void SceneObjectRef::setData(const QVariant &value, int role)
    14. {
    15. QStandardItem::setData(value, role);
    16.  
    17. if ( Qt::EditRole == role && value.toString() != scnObject->objectName())
    18. scnObject->setName(value.toString());
    19. }
    20.  
    21. // This is never getting called.
    22. QStandardItem* SceneObjectRef::clone() const
    23. {
    24. SceneObjectRef* clonedItem = new SceneObjectRef(*this);
    25.  
    26. for ( int i = 0; i < rowCount(); i++)
    27. clonedItem->appendRow( child(i)->clone() );
    28.  
    29. return clonedItem;
    30. }
    31.  
    32.  
    33. void SceneObjectRef::init()
    34. {
    35. setDragEnabled(true);
    36. setDropEnabled(false);
    37. setText(scnObject->objectName());
    38.  
    39. connect(scnObject.data(), SIGNAL(NameChanged(const QString&)), SLOT(onNameChanged(const QString&)));
    40. }
    41.  
    42. void SceneObjectRef::onNameChanged(const QString &Name)
    43. {
    44. if ( text() != Name)
    45. setText(Name);
    46. }
    To copy to clipboard, switch view to plain text mode 
    So it is really the name synching and context handling that I am losing.
    Last edited by AaronMK; 19th August 2011 at 16:34.

  4. #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: QStandardItem::clone() not being called for Drag and Drop

    Your post is a bit too much for me at this hour...
    However in your original post you write:
    It only copies the settings and data available to the QStandardItem base class, losing subclass overrides and such.
    And in your code you use QStandardItem so no wonder that its all you get.
    Also you say this should happen during drag and drop, but I see nothing that has to do with drag and drop in your code...

    It would help if you could "distill" the problem in to one line of code - which line would be it be from all you have posted, and why?

    And the main functionality that I am losing. This code calls a context handler for my custom item classes. It gets run, but since the new items are not of the right type, it does nothing with the actual items.
    But in your code:
    Qt Code:
    1. int SceneObjectRef::type() const
    2. {
    3. return SceneModel::SCN_OBJ_REF;
    4. }
    To copy to clipboard, switch view to plain text mode 
    does returns the correct type... so why do you think it should not be the correct type?

    Oh, one more thing:
    It only copies the settings and data available to the QStandardItem base class, losing subclass overrides and such.
    You didn't forget 'virtual' did you?
    ==========================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.

  5. #5
    Join Date
    Sep 2007
    Posts
    14
    Thanks
    5
    Qt products
    Qt4
    Platforms
    MacOS X Windows

    Default Re: QStandardItem::clone() not being called for Drag and Drop

    Thank you for the feedback. (Sorry for the delay in response)

    You are correct, type() is returning the correct type, and if I manually insert the SceneObjectRef objects into the model, they function as expected, but copies the model automatically makes it never enters my override, which is marked virtual. What I really suspect is happening is that it is using a default QStandardItem prototype for the drag copy/move operations, not clone(). (If I understand the documentation correctly, this is controlled by QStandardItemModel::setItemPrototype(), but I don't know what single protoype I would use to get polymorphic functionality.)

    I was able to get around this by deriving from the class defined in the attached files, but it is a bit round-about. I ended up encoding pointers to the model items in mimedata, decoding on drop, and calling clone. While the code does not specifically handle move, it seems like I am getting that for "free".

    If there is a more proper way of achieving this, I really am curious (especially if this will have side effects), but this is working for now.
    Attached Files Attached Files

Similar Threads

  1. Replies: 2
    Last Post: 13th October 2010, 21:51
  2. Replies: 3
    Last Post: 10th June 2010, 15:13
  3. Replies: 0
    Last Post: 4th May 2010, 10:24
  4. Drag and Drop, dropEvent not being called?
    By steg90 in forum Qt Programming
    Replies: 36
    Last Post: 22nd May 2007, 07:03
  5. Drag and Drop (drop example)
    By din9 in forum Qt Programming
    Replies: 1
    Last Post: 23rd January 2006, 18:03

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.