I use QAbstractItemModel/QTreeView mvc to organize work with kml tree. I experimentally found when drag and droped item in the tree insertRows(int , int , const QModelIndex &) and then removeRows(int , int , const QModelIndex &) methods of my model (that inherits QAbstractItemModel) are called. So, I did so. When insertRows called I save arguments:
bool KMLStorageModel::insertRows(int position, int rows, const QModelIndex &parent)
m_insertPosition = position;
m_insertRows = rows;
m_parentOfInsertPosition = parent;
Then, when removeRows called I do drag and drop operation using dragged item info saved before and position where item droped obtained with removeRows arguments:
bool KMLStorageModel::removeRows(int position, int rows, const QModelIndex &parent)
_ASSERT(m_insertRows == 1 && rows == 1);
m_move = false;
... //copying dragged item branch into the local temp variable and then insert it into the drop position
... //m_insertPosition, m_parentOfInsertPosition used here to determine dragged item
... //deleting original dragged item branch
Thus, firstly I copy dragged item branch and insert into the dropped place enframing this of beginInsertRows(...)/endInsertRows(), and then delete original dragged item branch enframing this of beginRemoveRows(...)/endRemoveRows().
Is this correct scenario?
(Sorry for my English)
With these implementations of insertRows() and removeRows() you will not be able to (de)populate your model. Returning false indicates that the insert/remove has failed.
You should reimplement "QAbstractItemModel::dropMimeData()":http://doc.trolltech.com/4.7/qabstractitemmodel.html#dropMimeData to handle the move and call insertRows() and removeRows() there.
Maybe "QAbstractItemModel::beginMoveRows()":http://doc.trolltech.com/4.7/qabstractitemmodel.html#beginMoveRows and "QAbstractItemModel::endMoveRows()":http://doc.trolltech.com/4.7/qabstractitemmodel.html#endMoveRows could be of help too. Theses functions are new since Qt 4.6 - I did not yet use them myself.
Should I reimplement QAbstractItemModel::dropMimeData() as you write even if I need only internal drag and drop (i. e. drag and drop in my single tree made using single QTreeView) and don't need drop anything dragged from any window, app etc?
What does "(de)populate" mean? Sorry, I can translate literally, but don't understand
Yes, drag and drop should be handled in dropMimeData().
insertRows() and removeRows() are involved in far more operations than just drag/drop. insertRows() is needed to put the actual data into your model (populate it), if you don't implement them your model will just break. The same goes for removeRows() to remove data from your model (depopulate it).
For the internal move I'd suggest that you have a look at beginMoveRows() and friends. They seem to be the right solution for your problem. I can't help you any further on these because we solved the problem long before these functions popped up.
BTW: QTreeView already contains some logic for handling drag'n'drop, maybe that fits your needs.
I read qt docs (QAbstractItemModel/QTreeView/[Model/View Programming]) again and again. But still don't understand how to do internal drag&drop in my tree based on QTreeModel/QAbstractItemModel. There is no examples showing what i need. My case is very similar to file system tree view in the windows explorer ("sceenshot":http://conan666.narod.ru/fstree.png), but I need allowed internal drag&drop only, there is no need to drop anything outside into my tree; should be allowed drag&droping only a single item or a single branch (like a sub folder in the windows explorer that contains other subfolders and files). Firstly dragged item copied into the drop place, then deleted from the dragged place. Now I have version of my tree made like described in the top working with no crashes or glitches, but it's time to do a fully correct version
Ok, QAbstractItemView already does some internal drag'n'drop stuff. It should be possible to do that stuff without reimplementing dropMimeData().
But it's really important that you implement insertRows(), removeRows() etc. pp. correctly because these are called from the provided implementation. In your implementation things get screwed up because QAbstractItemView::dropMimeData() relies on the rows to be inserted.
bool QAbstractItemModel::insertRows (int row, int count, const QModelIndex &parent)
This is a prototype of the method to be overridden. How do I know what data to insert? Here is just a place to insert
insertRows implementation should insert empty rows (or with default data).
There are very good explanations on the topic in "Model/View Programming":http://doc.trolltech.com/4.7/model-view-programming.html, especially regarding the drag'n'drop support in Section "Drag & drop support and MIME type handling":http://doc.trolltech.com/4.7/model-view-programming.html#drag-drop-support-and-mime-type-handling.