Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get notified of internal item moves inside a QTreeWidget?

I subclassed a QTreeWidget, set its dragDropMode to InternalMove and populated it with custom items, some of which can be dragged, others accept drops. The user can move items around the tree as expected. But I need to be notified of the change in the order of items and react appropriately. Unfortunately, there are no signals associated with the movement of items inside the tree that I could connect to.

I tried getting a handle to the QTreeWidget's underlying model(), then connecting to its rowsMoved signal, but it doesn't seem to be emitted during internal moves.

I reimplemented QTreeWidget's dropEvent(), but there's no way to determine the destination row index there.

The dropMimeData() event doesn't get called at all for internal moves, apparently.

Any other approach I could try? Thanks.

like image 303
neuviemeporte Avatar asked Jul 17 '13 20:07

neuviemeporte


3 Answers

In the reimplemented dropEvent(), you should be able to find the destination row index and item:

void
subclass::dropEvent(QDropEvent* event)
{
  QModelIndex index = indexAt(event->pos());
  if (!index.isValid()) {  // just in case
    event->setDropAction(Qt::IgnoreAction);
    return;
  }
  QTreeWidgetItem* destination_item = itemFromIndex(index);
  ....
}
like image 122
Daniel Vérité Avatar answered Nov 06 '22 18:11

Daniel Vérité


The OP actually asked how to get notified about an internal move, that is how to do it without sub-classing QTreeWidget (at least that's how I use internal move since it's built-in functionality). I just found a way it can be done: connect to the QTreeWidget model's rowsInserted() signal!

connect(treeWidget->model(), SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(rowsInserted(const QModelIndex &, int, int)));
like image 44
René Avatar answered Nov 06 '22 19:11

René


Incidentally, I figured out an another way to find out which element moved exactly where, which sidesteps the whole dropIndicatorPosition() and the associated itemAbove(), itemBelow() mess, or may at least help somewhat in supplementing it when moving items between different parents:

void MyTreeWidget::dropEvent(QDropEvent *event)
{
    // get the list of the items that are about to be dragged
    QList<QTreeWidgetItem*> dragItems = selectedItems();

    // find out their row numbers before the drag
    QList<int> fromRows;
    QTreeWidgetItem *item;
    foreach(item, dragItems) fromRows.append(indexFromItem(item).row());

    // the default implementation takes care of the actual move inside the tree
    QTreeWidget::dropEvent(event);

    // query the indices of the dragged items again
    QList<int> toRows;
    foreach(item, dragItems) toRows.append(indexFromItem(item).row());

    // notify subscribers in some useful way
    emit itemsMoved(fromRows, toRows);
}
like image 39
neuviemeporte Avatar answered Nov 06 '22 17:11

neuviemeporte