Contact

If you like a new Web or Desktop
application, update a existing one
or add new modifications. Your at
the right place and hit the
hire me button

Follow

If your intersted you can follow
me on Twitter by clicking here

Web and Apps Building Refernce World Wild Web UNIX Apps AND Tips Programming languages

Drag and drop

Valuable drag and drop examples for beginner are not present in Qt distribution, so let's have a closer look at it.

Please read customing widgets and have a look at Qt documentation about drag&drop before reading this.

Adjust the form from previous tutorial, place QLineEdit, QTreeWidget and QListWidget on it.

Promote QLineEdit, QTreeWidget and QListWidget to promote widgets and create appropriate .h and .cpp files like we did in previous tutorial.

Make sure acceptDrops property is set to true on each of them.

Add drop capability to customized QLineEdit

We will implement drop capability to QLineEdit (now myLineEdit). When file is dropped (but not directory), path will appear in myLineEdit.

Define the following methods in mylineedit.h

void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);

and implement in mylineedit.cpp

void myLineEdit::dragEnterEvent(QDragEnterEvent *event)
{
// accept just text/uri-list mime format
if (event->mimeData()->hasFormat("text/uri-list"))
{
event->acceptProposedAction();
}
}


void myLineEdit::dropEvent(QDropEvent *event)
{
QList<QUrl> urlList;
QString fName;
QFileInfo info;

if (event->mimeData()->hasUrls())
{
urlList = event->mimeData()->urls(); // returns list of QUrls

// if just text was dropped, urlList is empty (size == 0)
if ( urlList.size() > 0) // if at least one QUrl is present in list
{
fName = urlList[0].toLocalFile(); // convert first QUrl to local path
info.setFile( fName ); // information about file
if ( info.isFile() ) setText( fName ); // if is file, setText
}
}

event->acceptProposedAction();
}

Recompile and try to drop file (from explorer) into customized QLineEdit.

Drop to customized QTreeWidget

You may think we will do the same as with QLineEdit, but setup is little different.

If you look at Protected Functions of QTreeWidget you'll see some virtual functions responsible for drag/drop.

To actually implement drop on QTreeWidget, define following methods in mytreewidget.h

virtual bool dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action);    
QStringList mimeTypes() const;
Qt::DropActions supportedDropActions () const;

mytreewidget.cpp

bool myTreeWidget::dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action)
{
QList<QUrl> urlList;
QTreeWidgetItem *item;

urlList = data->urls(); // retrieve list of urls

foreach(QUrl url, urlList) // iterate over list
{
// make new QTreeWidgetItem and set its text
// if parent is null - add top level item (this parent)
if (parent == NULL) item = new QTreeWidgetItem(this);
else
// else add QTreeWidgetItem with parent and expand parent
{
item = new QTreeWidgetItem(parent);
parent->setExpanded( true );
}

// set item text
item->setText( 0, url.toLocalFile() );
}

return true;
}


QStringList myTreeWidget::mimeTypes () const
{
QStringList qstrList;
// list of accepted mime types for drop
qstrList.append("text/uri-list");
return qstrList;
}


Qt::DropActions myTreeWidget::supportedDropActions () const
{
// returns what actions are supported when dropping
return Qt::CopyAction | Qt::MoveAction;
}

DragDropOverwriteMode property can be enabled to enhance visual effect when dropping.

Drop to customized QListWidget

This is pretty much same as with QTreeWidget. The only difference is different parameters list in function dropMimeData.

mylistwidget.h

virtual bool dropMimeData(int index, const QMimeData *data, Qt::DropAction action);    
QStringList mimeTypes() const;
Qt::DropActions supportedDropActions () const;

mylistwidget.cpp

bool myListWidget::dropMimeData(int index, const QMimeData *data, Qt::DropAction action)
{
QList <QUrl> urlList;
QListWidgetItem *item;
QFileInfo info;
QString fName;

urlList = data->urls(); // retrieve list of urls

foreach(QUrl url, urlList) // iterate over list
{
fName = url.toLocalFile();
info.setFile( fName );

item = new QListWidgetItem(info.fileName());
insertItem(index, item);
++
index; // increment index to preserve drop order
}

return true;
}


QStringList myListWidget::mimeTypes () const
{
// same as with QTreeWidget
}


Qt::DropActions myListWidget::supportedDropActions () const
{
// same as with QTreeWidget
}

Drag from customized QListWidget

To implement drag operation, override mouseMoveEvent(QMouseEvent *event) method.

mylistwidget.h

void mouseMoveEvent(QMouseEvent *event);

mylistwidget.cpp

void myListWidget::mouseMoveEvent(QMouseEvent *event)
{
// if not left button - return
if (!(event->buttons() & Qt::LeftButton)) return;

// if no item selected, return (else it would crash)
if (currentItem() == NULL) return;

QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;

// construct list of QUrls
// other widgets accept this mime type, we can drop to them
QList<QUrl> list;
list.append(QUrl(currentItem()->text())); // only QUrl in list will be text of actual item

// mime stuff
mimeData->setUrls(list);
drag->setMimeData(mimeData);

// start drag
drag->start(Qt::CopyAction | Qt::MoveAction);
}

Project ready: drag_and_drop.zip