[Qt-interest] QTreeWidget - Dragging and Dropping to move items

David Ching dc at dcsoft.com
Sat May 16 17:18:14 CEST 2009


Hello, I have started with http://www.qtsoftware.com/developer/faqs/588 of a
QTreeWidget which allows dragging and dropping.  But I want to drag and drop
to MOVE top-level items within the tree, to change their order.  It works.
The mimeData() function returns a QMimeData with the index of the source
item, and the dropMimeData() receives the item that was dropped on:

QMimeData *QDDTreeWidget::mimeData(const QList<QTreeWidgetItem *> items)
const
{
	// Create a QByteArray to store the data for the drag.
	QByteArray ba;
	// Create a data stream that operates on the binary data
	QDataStream ds(&ba, QIODevice::WriteOnly);
	ds << indexOfTopLevelItem(items.at(0));
	QMimeData *md = new QMimeData;
	// Set the data associated with the mime type foo/bar to ba 
	md->setData("foo/bar", ba);
	return md;
}

bool QDDTreeWidget::dropMimeData(QTreeWidgetItem *parent, int index, const
						  QMimeData *data,
Qt::DropAction action)
{
	if (parent) {
		// Create a QByteArray from the mimedata associated with
foo/bar
		QByteArray ba = data->data("foo/bar");
		// Create a data stream that operates on the binary data
		QDataStream ds(&ba, QIODevice::ReadOnly);
		if (!ds.atEnd())
		{
			int sourceIndex;
			// Read a byte from the stream into the string
			ds >> sourceIndex;
			QTreeWidgetItem *movedItem = topLevelItem
(sourceIndex);	// remove it from old position
			emit itemMoved(movedItem, parent);	// <-- My
new signal; parent is item that was dropped on to
		}
	}

	return true;
}


The problem is that the code receiving the itemMoved() signal always inserts
the movedItem on top of the 'parent' item, so even if I drop onto the bottom
item in the tree, it is inserted above it.  There is no way to insert in the
bottom-most position of the tree.

Other drag and drop schemes show a thin horizontal line between the items
and the item is dropped onto the horizontal line.  The line can appear below
the bottommost item or above the topmost item.  Is there a Qt QTreeWidget
that does this?  

Another scheme would be to, when the drag is started, insert a dummy item at
the bottom of the tree so the user can drop on that to insert at the bottom.
Then remove the dummy item when the drop is complete.  I've experimented
with that but had issues with autoscrolling sometimes not showing the new
dummy item.  But perhaps this would be easier to get working?

Anyway, this dragging and dropping to re-order is a pretty common thing to
do, so I suspect someone has already solved this issue.

Thanks,
David




More information about the Qt-interest-old mailing list