PDA

View Full Version : Qt5 drag 'n drop problem : dropEvent never called



known
17th July 2015, 11:20
Hi all,

I'm facing a problem with Drag 'N Drop : I started my design using Fridge Magnets exemple (http://doc.qt.io/qt-4.8///qt-draganddrop-fridgemagnets-example.html). But now I'm trying to integrate the modified code to my main app. Thing is I can't drop my widget anymore. I suspect it has to do with the fact that I'm now trying to drag 'n drop my widgets on a QFrame, whereas on the Qt Exemple it doesn't go like that.

I've pasted some code :


BeaconWidgetDrag::BeaconWidgetDrag(QWidget *parent)
: QWidget(parent)
{
BeaconWidget * test;

int x = 5;
int y = 5;

test = new BeaconWidget("x01", BeaconStateDown, this);

test->move(x, y);
test->show();
test->setAttribute(Qt::WA_DeleteOnClose);

//setMinimumSize(400, qMax(200, y));
setAcceptDrops(true);
}

BeaconWidgetDrag::~BeaconWidgetDrag()
{

}

void BeaconWidgetDrag::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat("application/x-beaconwidget")) {
if (children().contains(event->source())) {
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
event->acceptProposedAction();
}
} else if (event->mimeData()->hasText()) {
event->acceptProposedAction();
} else {
event->ignore();
}
}

void BeaconWidgetDrag::dragMoveEvent(QDragMoveEvent *event)
{
if (event->mimeData()->hasFormat("application/x-beaconwidget")) {
if (children().contains(event->source())) {
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
event->acceptProposedAction();
}
} else if (event->mimeData()->hasText()) {
event->acceptProposedAction();
} else {
event->ignore();
}
}

void BeaconWidgetDrag::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasFormat("application/x-beaconwidget")) {
const QMimeData *mime = event->mimeData();
QByteArray itemData = mime->data("application/x-beaconwidget");
QDataStream dataStream(&itemData, QIODevice::ReadOnly);

QString text;
QPoint offset;
dataStream >> text >> offset;
BeaconWidget * newBeacon = new BeaconWidget(text, BeaconStateDown, this);
newBeacon->move(event->pos() - offset);
newBeacon->show();
newBeacon->setAttribute(Qt::WA_DeleteOnClose);

if (event->source() == this) {
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
event->acceptProposedAction();
}
} else if (event->mimeData()->hasText()) {
QStringList pieces = event->mimeData()->text().split(QRegExp("\\s+"),
QString::SkipEmptyParts);
QPoint position = event->pos();

foreach (QString piece, pieces) {
BeaconWidget * newBeacon = new BeaconWidget(piece, BeaconStateDown, this);
newBeacon->move(position);
newBeacon->show();
newBeacon->setAttribute(Qt::WA_DeleteOnClose);

position += QPoint(newBeacon->width(), 0);
}

event->acceptProposedAction();
} else {
event->ignore();
}
}

void BeaconWidgetDrag::mousePressEvent(QMouseEvent * event)
{
BeaconWidget *child = static_cast<BeaconWidget *>(childAt(event->pos()));
if (!child)
return;

QPoint hotSpot = event->pos() - child->pos();

QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
dataStream << child->labelText() << QPoint(hotSpot);

QMimeData *mimeData = new QMimeData;
mimeData->setData("application/x-beaconwidget", itemData);
mimeData->setText(child->labelText());

QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setPixmap(*child->pixmap());
drag->setHotSpot(hotSpot);

child->hide();

if (drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::CopyAction) == Qt::MoveAction)
child->close();
else
child->show();
}


void BeaconWidgetDrag::Log(QString s)
{
emit LogChanged(s);
}



My drag 'n drop widget is called that way, with ui->frame being a QFrame with setAcceptDrops = true


void BeaconMonitor::on_tabWidget_tabBarDoubleClicked(in t index)
{
BeaconWidgetDrag * beaconWidgetDrag = new BeaconWidgetDrag(ui->frame);
beaconWidgetDrag->show();
}



I hope I have been clear enough.

Thanks for your help;

wysota
19th July 2015, 13:36
Are drag enter and move event handlers being called?

known
2nd August 2015, 13:16
Yes I checked with GDB that drag "enter" and "move" event handlers are called. I still don't have a clue...

known
12th August 2015, 21:46
I found the solution : basically what I was trying to do was to have the widget a parent (ie. QFrame) while calling the constructor. I didn't consider the fact that you could add the BeaconWidgetDrag object directly to a Layout with addWidget.