dragEnterEvent from external file issue
-
I have a situation like this: http://imgur.com/a/4BpNv
I have a sublclass derived from QTableWidget, modified to accept drag'n drop both internal row and external file. When I drag a file from a Window folder to the TableWidget, the dnd animation stop ath the edge of the TableWidget, preventing me to freely move the mouse inside the TableWidget to select the point where I run the drop. This only happens when I drag file directly from Windows folders, while if I drag files from the Qt API QFileDialog::getOpenFileName() dialog the the dnd works as I would like.This is the subclass:
#include <QtGui> #include <QDrag> #include <QPainter> #include <QDropEvent> #include <QCursor> #include "dtablewidget.h" DTableWidget::DTableWidget(QWidget *parent) : QTableWidget(parent) { //set widget default properties: viewport()->setAcceptDrops(true); //set accept drop on viewport setDragEnabled(true); setDragDropOverwriteMode(false); //set drag drop overwrite to false setDragDropMode(QAbstractItemView::DragDrop); //enable internal drag drop on tablular dispaly setSelectionBehavior(QAbstractItemView::SelectRows); //enable selection of entire row setEditTriggers(QAbstractItemView::NoEditTriggers);//preventing editing setAlternatingRowColors(true); setSelectionBehavior(QAbstractItemView::SelectRows); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); setShowGrid(false); setAcceptDrops(true); setWordWrap(false); setStyleSheet("selection-background-color: yellow;" "selection-color: #002041;" "font-size: 75%;" ); } void DTableWidget::dragEnterEvent(QDragEnterEvent *event) { qDebug() << "dragEnterEvent"; event->accept(); } void DTableWidget::dragMoveEvent(QDragMoveEvent *event) { qDebug() << "dragMoveEvent"; if (event->source() != this) { QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; mimeData->setUrls(event->mimeData()->urls()); drag->setMimeData(mimeData); drag->exec(Qt::LinkAction); } else { event->acceptProposedAction(); event->setDropAction(Qt::LinkAction); } } void DTableWidget::dropEvent(QDropEvent *event) { event->acceptProposedAction(); event->setDropAction(Qt::LinkAction); qDebug() << "dropEvent" << event << event->mimeData()->urls().count(); if (event->mimeData()->urls().count() > 0) { emit dropped(event->mimeData()); qDebug() << "dropEvent" << event->mimeData()->urls().count(); } else { QPoint old_coordinates = QPoint(-1,-1); if(currentItem() != NULL) //Check if user is not accessing empty cell { old_coordinates = QPoint(currentItem()->row(), currentItem()->column()); } if(this->itemAt(event->pos().x(), event->pos().y()) != NULL && old_coordinates != QPoint(-1, -1)) { emit moved(old_coordinates.x(), itemAt( event->pos().x(), event->pos().y())->row()); } } } void DTableWidget::dragLeaveEvent(QDragLeaveEvent *event) { qDebug() << "dragLeaveEvent"; } void DTableWidget::keyPressEvent(QKeyEvent *event) { emit keyboard(event); } void DTableWidget::startDrag(Qt::DropActions supportedActions) { QModelIndexList indexes = selectedIndexes(); if (indexes.count() > 0) { QMimeData *data = model()->mimeData(indexes); if (!data) return; QDrag *drag = new QDrag(this); drag->setMimeData(data); Qt::DropAction defaultDropAction = Qt::IgnoreAction; if (defaultDropAction != Qt::IgnoreAction && (supportedActions & defaultDropAction)) defaultDropAction = defaultDropAction; else if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove) defaultDropAction = Qt::MoveAction; drag->exec(defaultDropAction); } }
Can you help me?
-
I have a situation like this: http://imgur.com/a/4BpNv
I have a sublclass derived from QTableWidget, modified to accept drag'n drop both internal row and external file. When I drag a file from a Window folder to the TableWidget, the dnd animation stop ath the edge of the TableWidget, preventing me to freely move the mouse inside the TableWidget to select the point where I run the drop. This only happens when I drag file directly from Windows folders, while if I drag files from the Qt API QFileDialog::getOpenFileName() dialog the the dnd works as I would like.This is the subclass:
#include <QtGui> #include <QDrag> #include <QPainter> #include <QDropEvent> #include <QCursor> #include "dtablewidget.h" DTableWidget::DTableWidget(QWidget *parent) : QTableWidget(parent) { //set widget default properties: viewport()->setAcceptDrops(true); //set accept drop on viewport setDragEnabled(true); setDragDropOverwriteMode(false); //set drag drop overwrite to false setDragDropMode(QAbstractItemView::DragDrop); //enable internal drag drop on tablular dispaly setSelectionBehavior(QAbstractItemView::SelectRows); //enable selection of entire row setEditTriggers(QAbstractItemView::NoEditTriggers);//preventing editing setAlternatingRowColors(true); setSelectionBehavior(QAbstractItemView::SelectRows); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); setShowGrid(false); setAcceptDrops(true); setWordWrap(false); setStyleSheet("selection-background-color: yellow;" "selection-color: #002041;" "font-size: 75%;" ); } void DTableWidget::dragEnterEvent(QDragEnterEvent *event) { qDebug() << "dragEnterEvent"; event->accept(); } void DTableWidget::dragMoveEvent(QDragMoveEvent *event) { qDebug() << "dragMoveEvent"; if (event->source() != this) { QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; mimeData->setUrls(event->mimeData()->urls()); drag->setMimeData(mimeData); drag->exec(Qt::LinkAction); } else { event->acceptProposedAction(); event->setDropAction(Qt::LinkAction); } } void DTableWidget::dropEvent(QDropEvent *event) { event->acceptProposedAction(); event->setDropAction(Qt::LinkAction); qDebug() << "dropEvent" << event << event->mimeData()->urls().count(); if (event->mimeData()->urls().count() > 0) { emit dropped(event->mimeData()); qDebug() << "dropEvent" << event->mimeData()->urls().count(); } else { QPoint old_coordinates = QPoint(-1,-1); if(currentItem() != NULL) //Check if user is not accessing empty cell { old_coordinates = QPoint(currentItem()->row(), currentItem()->column()); } if(this->itemAt(event->pos().x(), event->pos().y()) != NULL && old_coordinates != QPoint(-1, -1)) { emit moved(old_coordinates.x(), itemAt( event->pos().x(), event->pos().y())->row()); } } } void DTableWidget::dragLeaveEvent(QDragLeaveEvent *event) { qDebug() << "dragLeaveEvent"; } void DTableWidget::keyPressEvent(QKeyEvent *event) { emit keyboard(event); } void DTableWidget::startDrag(Qt::DropActions supportedActions) { QModelIndexList indexes = selectedIndexes(); if (indexes.count() > 0) { QMimeData *data = model()->mimeData(indexes); if (!data) return; QDrag *drag = new QDrag(this); drag->setMimeData(data); Qt::DropAction defaultDropAction = Qt::IgnoreAction; if (defaultDropAction != Qt::IgnoreAction && (supportedActions & defaultDropAction)) defaultDropAction = defaultDropAction; else if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove) defaultDropAction = Qt::MoveAction; drag->exec(defaultDropAction); } }
Can you help me?
@UnitScan said in dragEnterEvent from external file issue:
void DTableWidget::dragMoveEvent
i stopped reading after i saw your implementation of the dragMoveEvent() becasue its so horribly wrong :)
Why do you create a new QDrag there?
When you receive a dragMoveEvent it means that there is already a drag currently happening, otherwise you wouldn't receive the event in the first place.Just remove the whole
if (event->source() != this)
block and it should work.
If you really have to check if the drag origins from inside your application doevent->source()
. If it returns a null-pointer the drag comes from outside your application. -
I created a new QDrag because I wish to change the horrible mouse cursor pixmap that appears during dragMoveEvent, and replace it with a simple Leftarrow, without the preview of the file I'm dragging, with the small symbol of the link at the bottom right of the cursor.
void DTableWidget::dragMoveEvent(QDragMoveEvent *event) { qDebug() << "dragMoveEvent"; if (event->source() != this) { QDrag *drag = new QDrag(this); QCursor cursor; cursor.setShape(Qt::ArrowCursor); drag->setPixmap(cursor.pixmap()); this->cursor().setShape(Qt::ArrowCursor); drag->setDragCursor(this->cursor().pixmap(),Qt::LinkAction); QMimeData *mimeData = new QMimeData; mimeData->setUrls(event->mimeData()->urls()); drag->setMimeData(mimeData); drag->exec(Qt::LinkAction); } else { event->acceptProposedAction(); event->setDropAction(Qt::LinkAction); } }
If there is a better way to do that, what is?
-
I created a new QDrag because I wish to change the horrible mouse cursor pixmap that appears during dragMoveEvent, and replace it with a simple Leftarrow, without the preview of the file I'm dragging, with the small symbol of the link at the bottom right of the cursor.
void DTableWidget::dragMoveEvent(QDragMoveEvent *event) { qDebug() << "dragMoveEvent"; if (event->source() != this) { QDrag *drag = new QDrag(this); QCursor cursor; cursor.setShape(Qt::ArrowCursor); drag->setPixmap(cursor.pixmap()); this->cursor().setShape(Qt::ArrowCursor); drag->setDragCursor(this->cursor().pixmap(),Qt::LinkAction); QMimeData *mimeData = new QMimeData; mimeData->setUrls(event->mimeData()->urls()); drag->setMimeData(mimeData); drag->exec(Qt::LinkAction); } else { event->acceptProposedAction(); event->setDropAction(Qt::LinkAction); } }
If there is a better way to do that, what is?
@UnitScan said in dragEnterEvent from external file issue:
event->setDropAction(Qt::LinkAction);
you mean like you do in the else-block afterwards?
Basically it's only possible to set the cursor during a drag to 4 states:
Copy, Move, Link, NoAction. The operating system decides how to show them.Thus setting it to a "plain" cursor isn't possible.
-
@UnitScan said in dragEnterEvent from external file issue:
event->setDropAction(Qt::LinkAction);
you mean like you do in the else-block afterwards?
Basically it's only possible to set the cursor during a drag to 4 states:
Copy, Move, Link, NoAction. The operating system decides how to show them.Thus setting it to a "plain" cursor isn't possible.
you are already doing it in the else-block (
event->setDropAction()
) like i already said in my previous post!
The "drag image" cannot be removed. Not via Qt API at least. -
I noticed that with Clementine, player made with QT5 libraries, when you drag an external file to the playlist appears only a LeftArrorw with a small square at the bottom right with the "+" symbol, while with me appears, beyond Leftarrow, a gigantic preview of the file I'm dragging and an abnormal word "Link" at the bottom right :'-(
Changing event->setDropAction(Qt::LinkAction) to event->setDropAction(Qt::CopyAction) replace only the abnormal text label from "Link" to "Copy" -
I noticed that with Clementine, player made with QT5 libraries, when you drag an external file to the playlist appears only a LeftArrorw with a small square at the bottom right with the "+" symbol, while with me appears, beyond Leftarrow, a gigantic preview of the file I'm dragging and an abnormal word "Link" at the bottom right :'-(
Changing event->setDropAction(Qt::LinkAction) to event->setDropAction(Qt::CopyAction) replace only the abnormal text label from "Link" to "Copy"@UnitScan
And you are sure they just use the Qt API for Drag-n-Drop handling?!
Anyway you can check the source code how they do it. -
@UnitScan
using the native API directly for exampleBut again to make sure: On the same machine (same OS) the Clementine player doesn't show the drag image while your application does?
-
@raven-worx Yes. on Windows Clementine shows only the small "+" on the bottom right, while my app show the gigantic file preview and the "Link" text