QTreeView, QAbstractItemModel and internal move
-
Hi everyone,
I try to implement an internal move of items within a QTreeView with the mouse.
My model inherits from
QAbstractItemModel
with 2 columns. Each items of my model have a boolean, a name, the pointer to the parent and list of children. In the future, I intend to add other data inside my items.In my model, I set the flags for each valid
QModelIndex
to :Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
I implemented
moveRows
andmoveColumns
methods inside my custom Model.Unfortunately those methods are never called by the view.
For information, I enable the drag and drop on the QTreeView with
setDragEnable(true)
andsetDragDropMode(Qt::InternalMove)
.Do I need to implement all the mimeData functions just to move some data?
I can understand the reason of mimeData for drag and drop between widgets but in my case I just want to change the parent. I don't find any documentation/example that explains type of drag and drop move.
Thanks
Edit: I forgot to mention my environment: Windows 10/Mac OS X High Sierra, Qt 5.10.1, Visual studio 17, Clang
-
@Athius
moveRows() and moveColumns() are not called by QAbstractItemModel. Honestly i do not know what they are used for.Nevertheless the item view calls dropMimeData() on the model. The default implementation then calls decodeData().
Check the implementation of decodeData() to see what functions are called. Those are the ones you need to reimplement (likeinsertRows()
, ...). Then setData() is called on them. So by default the moving is "faked". -
Thanks for your answers.
@mpergand I try to call moveRow in it but there is no change. Worse: my data are not shown anymore ^^
@raven-worx I also try to use the default implementation of dropMimeData but when the moved item has some children, then only the item is shown without his children (the data are not corrupted, only the view).
I already re-implement insertRows but it didn't work.
I finally succeed by using
QStandardItemModel
and a custom Item that inherits fromQStandardItem
. There is some methods to re-implement:QStandardItem *clone() const; void read(QDataStream &in); void write(QDataStream &out) const;
I found on the Internet a pretty convenient way to put some custom data as pointer inside a QDataStream:
QDataStream & operator << (QDataStream & s, const Data *& data) { qulonglong ptrval(*reinterpret_cast<qulonglong *>(&data)); return s << ptrval; } QDataStream & operator >> (QDataStream & s, Data & data) { qulonglong ptrval; s >> ptrval; data = **reinterpret_cast<Data **>(&ptrval); return s; }
I don't know if it's the best way but it's working.
-
@Athius
Sure it works, here my code for a bookmark tree:bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { Q_UNUSED(column) if(action EQ Qt::IgnoreAction) return false; if(action EQ Qt::MoveAction) { QByteArray bytes=data->data(MIME_Bookmark); QDataStream stream(&bytes,QIODevice::QIODevice::ReadOnly); qintptr i; int r,c; stream>>i>>r>>c; QModelIndex index=createIndex(r,c,i); moveRow(index,index.row(),parent,row); } return true; }
Of course you need to create and return your custom data in mimeData () as well.