PDA

View Full Version : <SOLVED > Treeview select draged Item or set mime data from draged item



0backbone0
30th August 2015, 13:54
Hi,

I have a custom Treeview with a QFilemodel attached to it.
The reason for making it custom is to be able to handel drag and drop myself.
All I wanted to archiev is to get rid of the Pixmap that is taken from the draged Treeview Item.
setPixmap does work if I set the mimeData myself.
The Problem is to get the right Index for the mime Data.

I tired:


QModelIndexList tempindexlist;
tempindexlist.append(selectedIndexes());

Drag.setMimeData(model()->mimeData(tempindexlist));


wich woks if I select the Item to be draged first. So I have to explicitly click on an Item first befor draging it.
If I just drag it out of the treevie without clicking it previously, the indexlist contains the last selected index (or nothing if there is no selection).

then I tried it this way:


QModelIndexList tempindexlist;
tempindexlist.append(currentIndex());

but this behaves exactly the same way.

If I don't set the mimeData it works, but then the Pixmap is set automatically and i can't change it.
Is there an equivalent of selectedIndexes for draged indexes?
Any other way to solve this?

anda_skoa
30th August 2015, 14:15
tired:


QModelIndexList tempindexlist;
tempindexlist.append(selectedIndexes());

Drag.setMimeData(model()->mimeData(tempindexlist));


wich woks if I select the Item to be draged first. So I have to explicitly click on an Item first befor draging it.
If I just drag it out of the treevie without clicking it previously, the indexlist contains the last selected index (or nothing if there is no selection).

Interesting, because the default implementation also does this:
http://code.woboq.org/qt5/qtbase/src/widgets/itemviews/qabstractitemview.cpp.html#_ZN17QAbstractItemView9 startDragE6QFlagsIN2Qt10DropActionEE

The selectedDraggableIndexes() are just the selectedIndexes() without those which are not draggable according to their item flags.

Cheers,
_

0backbone0
30th August 2015, 15:07
I got it working.
The solution was to use IndexAt() with the event->pos() from mousePressEvent.
Then I had to create a pointer to the attached model in order to use fileinfo on it.
I then insert the resulting filename into an Urllist and set the mimeData with it.



QFileSystemModel *tempmodel = qobject_cast<QFileSystemModel *>(model());
QModelIndex tempindex = indexAt(event->pos());
QMimeData *mimeData = new QMimeData;
QList<QUrl>urllist;
QString filename=tempmodel->filePath(tempindex);
urllist.append(QString("file:"+filename));
mimeData->setUrls(urllist);


Now setPixmap is working as expected and mimeData contains allways the currently dragged Item.

anda_skoa
30th August 2015, 15:58
You should be able to get the filename from the model without casting, no?

Regarding the difference in the default behavior and your workaround:
are you trying to initiate the draw in a mouse event handler instead of in startDrag()?

Cheers,
_

0backbone0
30th August 2015, 16:14
Yes, thats what I am doing right now;


#include "customtreeview.h"

customtreeview::customtreeview(QWidget * parent)
{
}

void customtreeview::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
QDrag Drag( this );
QFileSystemModel *tempmodel = qobject_cast<QFileSystemModel *>(model());
QModelIndex tempindex = indexAt(event->pos());

QPixmap tempmap(1,1);
QMimeData *mimeData = new QMimeData;
QList<QUrl>urllist;
QString filename=tempmodel->filePath(tempindex);

emit setpreview(filename);

urllist.append(QString("file:"+filename));
mimeData->setUrls(urllist);
tempmap.fill(Qt::white);
Drag.setPixmap(tempmap);
Drag.setMimeData(mimeData);
Drag.exec( Qt::IgnoreAction );
}
QTreeView::mousePressEvent(event);
}

I left everything else untouched.

I still struggle to understand how to set drag and drop behaviour correctly.

anda_skoa
30th August 2015, 22:12
Is this a good idea?
Won't that start a drag even when you are just clicking to select?

My understanding is that the startDrag() method is where you should be starting drag operations, since it not only takes care of the mouse event handling, it also respects the "drag distance", i.e. the minimum mouse move while the button is down to start a drag.

As a side note: that setUrls() call doesn't make much sense, you are not filling the list anywhere, right?

Also, you can just use model()->data() or tempindex.data() to get the filename, no need for casting.

Cheers,
_

0backbone0
31st August 2015, 10:53
Is this a good idea?
As a side note: that setUrls() call doesn't make much sense, you are not filling the list anywhere, right?


I append the filename to it. Or is there a way to set just one Url directly?

urllist.append(QString("file:"+filename));

How do you reimplement startDrag() ?

I tried it this way?



void customtreeview::startDrag()
{

}

and put a qDebug in it, but it's never called.
Otherwise what you say make perfect sense, but out of ignorance I am still stuck with my workaround.

And model()->Data() just returns the filename without path. So it isn't much use to me either.

anda_skoa
31st August 2015, 11:10
I append the filename to it. Or is there a way to set just one Url directly?

urllist.append(QString("file:"+filename));

Right, sorry, missed that line.
Better use QUrl::fromLocalFile() instead of string concatentation though.



How do you reimplement startDrag() ?

I tried it this way?



void customtreeview::startDrag()

and put a qDebug in it, but it's never called.

This is not the correct signature, you are missing the argument.




And model()->Data() just returns the filename without path. So it isn't much use to me either.
Ah, but you can also retrieve the path, QFileSystemModel::FilePathRole.
Anyway, casting should be fine, but you might want to check the result of the cast for null pointer.

Cheers,
_

0backbone0
31st August 2015, 11:56
The documentation sais:


void QAbstractItemView::startDrag(Qt::DropActions supportedActions) [virtual protected]
Starts a drag by calling drag->exec() using the given supportedActions.

If I use Qt::DropActions as an Argument I get the Error:

variable or field 'startDrag' declared void
void customtreeview::startDrag(Qt::IgnoreAction)

What now? Any link to an example perhaps?

anda_skoa
31st August 2015, 16:00
The documentation sais:


void QAbstractItemView::startDrag(Qt::DropActions supportedActions) [virtual protected]
Starts a drag by calling drag->exec() using the given supportedActions.


Exactly!



If I use Qt::DropActions as an Argument I get the Error:

variable or field 'startDrag' declared void
void customtreeview::startDrag(Qt::IgnoreAction)

That looks wrong, almost like you had written exactly that instead of the actual method signature.

Cheers,
_