user408952
user408952

Reputation: 932

Getting old and new QStandardItem after drag-and-drop move

I'm trying to create a QTreeView which supports internal move of items and a way for me to detect the source and target of the move. When using a QTreeWidget I could override the dropEvent and do something like this:

void MyTreeWidget::dropEvent(QDropEvent* event)
{
    QList<QStandardItem*> dragItems = selectedItems();
    QTreeView::dropEvent(event);
    // here dragItems have been moved to the new places so I can do whatever I want
}

The reason I need to know the source and target position is to be able to push a command onto the undo stack that does the same move in the underlying data structure.

I've now switched to a QTreeView with a QStandardItemModel (creating a custom model that describes the underlying data structures would be too much work) but it seems to work a bit differently. After the call to QTreeView::dropEvent(...) it has created and added the new item but not removed the old one, so there's no way for me to determine the new index since it will change once it deletes the old item. I'm using this example to debug it:

#include <QtDebug>
#include <QApplication>
#include <QTreeView>
#include <QtGui/QStandardItemModel>

class MyTreeView : public QTreeView
{
    public:
        MyTreeView(QWidget* parent=0)
            : QTreeView(parent)
        {}

        void dropEvent(QDropEvent* event) {
            qDebug() << "rows before:" << model()->rowCount();
            QTreeView::dropEvent(event);
            qDebug() << "rows after:" << model()->rowCount();
        }

};

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    MyTreeView* tree = new MyTreeView();
    QStandardItemModel model(3, 1);
    for(int r = 0; r < model.rowCount(); r++)
        model.setItem(r, 0, new QStandardItem(QString("%0").arg(r)));

    tree->setDragEnabled(true);
    tree->viewport()->setAcceptDrops(true);
    tree->setDefaultDropAction(Qt::MoveAction);
    tree->setDropIndicatorShown(true);
    tree->setDragDropMode(QAbstractItemView::InternalMove);

    tree->setModel(&model);
    tree->show();

    return app.exec();
}

When I run this on Qt 5.4 (Windows 7) and drag-and-drop an item I get the following output:

rows before: 3
rows after: 4

When using a QTreeWidget it would have said:

rows before: 3
rows after: 3

Any ideas on how to solve this?

Upvotes: 0

Views: 1080

Answers (1)

ahmed
ahmed

Reputation: 5600

There is a better approach to get moved items using QAbstractItemModel::rowsMoved from the documentation:

This signal is emitted after rows have been moved within the model. The items between sourceStart and sourceEnd inclusive, under the given sourceParent item have been moved to destinationParent starting at the row destinationRow.

Also, i remember reading Using Undo/Redo with Item Views in QQ, best link i can find is this cached page and a French version

Upvotes: 1

Related Questions