Hi!
I have a problem with Drag and Drop in my application. I have added Drag and Drop to my QTreeWidget subclass (class MyTreeWidget : public QTreeWidget) and it works almost fine. The only problem I experience is - the first click on the MyTreeWidget after drag and drop action is lost. I click (after drag and drop action) on a tree element but nothing happens. The element must become selected, but it doesn't.
If I use QListWidget instead of QTreeWidget then everything is alright.
I have wrote simplest example to demonstrate this issue:
// main.cpp
#include <QtGui>
#include "MyTreeWidget.h"
int main(int argc, char *argv[]) {
MyTreeWidget w;
w.show();
return app.exec();
}
// main.cpp
#include <QtGui>
#include "MyTreeWidget.h"
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MyTreeWidget w;
w.show();
return app.exec();
}
To copy to clipboard, switch view to plain text mode
// MyTreeWidget.h
#ifndef PROJECTLISTWIDGET_H
#define PROJECTLISTWIDGET_H
#include <QTreeWidget>
{
Q_OBJECT
public:
protected:
private:
void performDrag();
};
#endif
// MyTreeWidget.h
#ifndef PROJECTLISTWIDGET_H
#define PROJECTLISTWIDGET_H
#include <QTreeWidget>
class MyTreeWidget : public QTreeWidget
{
Q_OBJECT
public:
MyTreeWidget(QWidget *parent = 0);
protected:
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
private:
void performDrag();
QPoint startPos;
};
#endif
To copy to clipboard, switch view to plain text mode
// MyTreeWidget.cpp
#include <QtGui>
#include "MyTreeWidget.h"
setAcceptDrops(true);
}
if (e->button() == Qt::LeftButton)
startPos = e->pos();
}
if (e->buttons() & Qt::LeftButton) {
int distance = (e->pos() - startPos).manhattanLength();
performDrag();
}
}
}
}
}
void MyTreeWidget::performDrag() {
if (item) {
mimeData->setText(item->text(0));
drag->setMimeData(mimeData);
if (drag->exec(Qt::MoveAction) == Qt::MoveAction)
delete item;
}
}
// MyTreeWidget.cpp
#include <QtGui>
#include "MyTreeWidget.h"
MyTreeWidget::MyTreeWidget(QWidget *parent) : QTreeWidget(parent) {
setAcceptDrops(true);
(new QTreeWidgetItem(this))->setText(0, "1-one");
(new QTreeWidgetItem(this))->setText(0, "2-two");
(new QTreeWidgetItem(this))->setText(0, "3-three");
(new QTreeWidgetItem(this))->setText(0, "4-four");
(new QTreeWidgetItem(this))->setText(0, "5-five");
(new QTreeWidgetItem(this))->setText(0, "6-six");
(new QTreeWidgetItem(this))->setText(0, "7-seven");
}
void MyTreeWidget::mousePressEvent(QMouseEvent *e) {
if (e->button() == Qt::LeftButton)
startPos = e->pos();
QTreeWidget::mousePressEvent(e);
}
void MyTreeWidget::mouseMoveEvent(QMouseEvent *e) {
if (e->buttons() & Qt::LeftButton) {
int distance = (e->pos() - startPos).manhattanLength();
if (distance >= QApplication::startDragDistance())
performDrag();
}
QTreeWidget::mouseMoveEvent(e);
}
void MyTreeWidget::dragEnterEvent(QDragEnterEvent *e) {
}
void MyTreeWidget::dragMoveEvent(QDragMoveEvent *event) {
}
void MyTreeWidget::dropEvent(QDropEvent *event) {
}
void MyTreeWidget::performDrag() {
QTreeWidgetItem *item = currentItem();
if (item) {
QMimeData *mimeData = new QMimeData;
mimeData->setText(item->text(0));
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
if (drag->exec(Qt::MoveAction) == Qt::MoveAction)
delete item;
}
}
To copy to clipboard, switch view to plain text mode
I also looked in what is happening with a debugger and I have found out that QTreeWidget state() member function returns DragSelectingState when I click MyTreeWidget the first time after drag and drop action. Looks like this prevents element from being selected. So I have wrote this simple dirty-fix:
if (e->button() == Qt::LeftButton)
startPos = e->pos();
if (DragSelectingState == state()) // this two lines
setState(NoState); // fix the problem
}
void MyTreeWidget::mousePressEvent(QMouseEvent *e) {
if (e->button() == Qt::LeftButton)
startPos = e->pos();
if (DragSelectingState == state()) // this two lines
setState(NoState); // fix the problem
QTreeWidget::mousePressEvent(e);
}
To copy to clipboard, switch view to plain text mode
But I would like to know the reason of this behavior. Is it my bug (incorrectly implemented Drag and Drop) or Qt's one. I can not reproduce this behavior with QListWidget. So it looks like it is Qt's bug.
Any ideas would be greatly appreciated!
Thanks in advance!
Bookmarks