PDA

View Full Version : Can't catch DragLeaveEvent



steps
13th March 2012, 10:17
I have a QDialog with two QListWidgets. The user can copy items from the first list (availableItemsList) to the second (myList) via drag and drop. There he can reorder them and then confirm the dialog. I would like the user to be able to remove an item from the second list via drag and drop by simply dropping it outside the list widget; so far this is only possible by selecting the item and hitting delete.

The idea was to remove an item on receiving the DragLeaveEvent. To realize this, I have tried installing an event filter on the list widget (myList), but the DragLeaveEvent is never fired, even though the mouse cursor changes to the "not allowed" sign when an item is dragged outside myList, and neither is the DragEnterEvent fired every time I would expect it to be, not even when I drag a new item from the availableItemsList to myList. Here is my code (so far only qDebug output, no removal of the item):



MyDialog::MyDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::MyDialog)
{
/* ... */
ui->myList->installEventFilter(this);
}

bool MyDialog::eventFilter(QObject *obj, QEvent *event)
{
qDebug() << "Event Filter called with " << event->type();
if (event->type() == QEvent::DragLeave) {
qDebug() << event->type() << "= drag leave event.";
return true;
} else if (event->type() == QEvent::DragEnter) {
qDebug() << event->type() << "= drag enter event.";
return true;
} else {
// standard event processing
return QObject::eventFilter(obj, event);
}
}


List properties (dialog created with Qt Designer):

List 1 (availableItemsList):
- acceptDrops: false
- dragEnabled: false
- dragDropOverwriteMode: false
- dragDropMode: DragOnly
- defaultDropAction: IgnoreAction

List 2 (myList):
- acceptDrops: true (if value is set to false, nothing changes)
- dragEnabled: true (if value is set to false, nothing changes)
- dragDropOverwriteMode: true
- dragDropMode: DragDrop
- defaultDropAction: MoveAction

high_flyer
14th March 2012, 11:41
You are not checking for the obj receiving the event.
This should not be a problem, but see if you get at all events from your list:


bool MyDialog::eventFilter(QObject *obj, QEvent *event)
{
qDebug() << "Event Filter called with " << event->type();
if(obj == ui->myList)
{
if (event->type() == QEvent::DragLeave) {
qDebug() << event->type() << "= drag leave event.";
return true;
} else if (event->type() == QEvent::DragEnter) {
qDebug() << event->type() << "= drag enter event.";
return true;
}
}
else {
// standard event processing
return QObject::eventFilter(obj, event);
}
}

steps
14th March 2012, 16:40
Hi, I changed my code the way you suggested, but I don't see that it changed much with regard to the output I get. Specifically, I still don't get the dragLeaveEvent. I get the regular Enter and Leave events fine (10 and 11 respectively, see here (http://qt-project.org/doc/qt-4.8/qevent.html#Type-enum)), but not the dragEnter and dragLeave events (60 and 62).

high_flyer
14th March 2012, 16:55
The idea was to see if you are getting ANY events from this object.
Put a debug output before the first if(event()->type()...) statement and see if it gets printed out.

steps
14th March 2012, 17:09
Sorry, I was being unprecise. I changed my code to the following:



bool MyDialog::eventFilter(QObject *obj, QEvent *event)
{
if (obj == ui->myList) {
qDebug() << "Event Filter called with " << event->type();
if (event->type() == QEvent::DragLeave) {
qDebug() << event->type() << "= drag leave event.";
return true;
} else if (event->type() == QEvent::DragEnter) {
qDebug() << event->type() << "= drag enter event.";
return true;
} else if (event->type() == QEvent::Drop) {
qDebug() << event->type() << "= drop event.";
return true;
}
} else {
// standard event processing
return QObject::eventFilter(obj, event);
}
}


Result was as described above.

Spitfire
16th March 2012, 16:54
Two things:

1) List must have DragDropMode set to DragDrop or InternalMove, otherwise drag Enter/Leave events will not be delivered (don't ask why).
2) For another reason I don't know you can't reliably intercept drag enter/leave events using event filter. Subclass QListWidget and reimplement dragEnterEvent() and dragLeaveEvent().



class MyList : public QListWidget
{
public:
MyList( QWidget* parent = 0 ) : QListWidget( parent ) {}

void dragEnterEvent( QDragEnterEvent* e )
{
qDebug() << "Enter!";
QListWidget::dragEnterEvent( e );
}

void dragLeaveEvent( QDragLeaveEvent* e )
{
qDebug() << "Leave!";
QListWidget::dragLeaveEvent( e );
}
};


Maybe threre are some flags that could alter this behavious but I don't know them.

steps
22nd March 2012, 18:42
Yeah, I haven't found any way around subclassing either, that's why I posted here. Thanks for your help everyone!