[Qt-interest] Need help with moving items in a QTreeWidget
Bob Hood
bhood2 at comcast.net
Thu Feb 3 03:20:52 CET 2011
On 2/2/2011 10:41 AM, Bob Hood wrote:
> I've been trying to figure this one out, and I'm not having much luck. I've
> got a QTreeWidget that has top-level parents, and under them are children
> without any other children. I want to be able to drag children and re-order
> them within their parents, but not allow them to be moved outside their parent
> (i.e., disallow re-parent). I understand the only way to realize this is to
> subclass QTreeWidget and provide my own drag-and-drop support, however, I
> cannot seem to get it to work correctly.
Ok, after paring down the code I posted, and realizing that I needed to
implement QDataStream operations for the Qt::UserRole-associated data that
each QTreeWidgetItem carries, I have the drag-and-drop operation working
(almost) the way I want and expect.
However, I still need some insight from somebody. When the dropEvent()
finally occurs, I cannot seem to find a way to determine where the drop will
actually end up. In other words, the visual cues that are provided during the
drag operation indicate either an insertion, or a re-parenting (dropping the
dragged child onto another child causes re-parenting). I want to disallow
this re-parenting, but I cannot find a way to determine if the drop point will
be an insert (moved to a new position under the original parent) or if it will
be a re-parent (parented to another child). In effect, I want the children
under a top-level parent to be moved around like a QListWidget -- no parenting
allowed.
Here's my dropEvent() logic:
void MyTreeWidget::dropEvent(QDropEvent *e)
{
const QMimeData* mime_data = e->mimeData();
if(!mime_data->hasFormat("application/mytype"))
{
e->ignore();
return;
}
if(e->keyboardModifiers() == Qt::NoModifier)
{
const QPoint pos = e->pos();
QTreeWidgetItem* target = itemAt(e->pos());
bool do_move = true;
// this is used to determine if the target is itself a child
if(target->parent() != (QTreeWidgetItem*)0)
do_move = false;
else
{
foreach(QTreeWidgetItem* item, selected_items)
{
// if target and item don't share the same parent...
if(target->parent() != item->parent())
{
// ...then don't allow the move
do_move = false;
break;
}
}
}
if(!do_move)
e->setDropAction(Qt::IgnoreAction);
else
{
QTreeWidget::dropEvent(e);
e->setDropAction(Qt::TargetMoveAction);
}
e->accept();
}
else if(e->proposedAction() == Qt::TargetMoveAction)
{
QTreeWidget::dropEvent(e);
e->acceptProposedAction();
}
else
QTreeWidget::dropEvent(e);
}
The problem is, with an insertion, the line:
QTreeWidgetItem* target = itemAt(e->pos());
still returns a child item, even though the visual feedback says that the drop
will be inserted above (or below) it. Without knowing this difference, I
cannot disallow re-parenting.
More information about the Qt-interest-old
mailing list