PDA

View Full Version : Drag and drop revisited



Big Duck
29th June 2006, 18:30
Hi, hoping some people could help me with some drag and drop of mime data

I have a treeview and a standardItemModel I have subclassed.
I'd like to drag and drop within the view to sort the items.
And a line to indicate where would be perfect.

I've looked at this thread and I've picked up lots of ideas.
http://www.qtcentre.org/forum/f-qt-programming-2/t-can-i-get-a-dragdrop-tobe-displayed-as-a-line-instead-of-the-big-floating-icon-2304.html

However I cant make it work..:( spent a few days trying

If I implement only these :



void MyTreeView::dragMoveEvent (QDragMoveEvent *event)
{

dropSite = event->answerRect ( );
model_->emit_layoutChanged();
}

void MyModel::emit_layoutChanged ( )
{
emit layoutChanged ( );
}

void MyTreeView::paintEvent ( QPaintEvent* event )
{
QTreeView::paintEvent (event);
QPainter painter ( viewport() );
int x, y, w, h;
dropSite.getRect ( &x, &y, &w, &h );
painter.drawLine ( 0, y, width(), y );
event->accept();
}


I get a line drawn although it doesnt stick to between items and draws behind at all pixel positions. However Its not a mime data drag and drop and so its a floating icon type which I want to avoid.

Now, if I implement :




void MyTreeView::mousePressEvent(QMouseEvent *event)
{
QTreeView::mousePressEvent ( event );
if (event->button() == Qt::LeftButton) {
dragStartPosition = event->pos();
}
repaint();
}

void MyTreeView::mouseMoveEvent(QMouseEvent *event)
{
if (!(event->buttons() & Qt::LeftButton))
return;
if ((event->pos() - dragStartPosition).manhattanLength()
< QApplication::startDragDistance())
return;

QByteArray encodedData;
mimeData = new QMimeData;
// Sample text type mime data - I will use mybe row index to pass data instead
mimeData->setData("application/vnd.text.list", encodedData);

drag = new QDrag(this);
drag->setMimeData(mimeData);
dropAction = drag->start ( Qt::CopyAction | Qt::MoveAction );
repaint();
}


I get a mime type drag and drop which I want but I cannot drop it on the Treeview anywhere. I get the no entry sign :)

I have these turned on:

treeView->setDragEnabled(true);
treeView->setDropIndicatorShown(true);
treeView->setAcceptDrops(true);

I guess I need to implement something in here :


bool MyModel::dropMimeData ( const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent )
{
qDebug("dropMimeData");
if (action == Qt::CopyAction) {
return true;
}
else {
return false;
}
}


but this never gets called when I drop.

What am I missing and any tips ? Mybe someone else find this useful.
Thanks,

wysota
29th June 2006, 21:58
It doesn't get called probably because you reimplemented the other methods. According to my belief, you should reimplement dropMimeData(), mimeData() and mimeTypes() from in model class.

Big Duck
30th June 2006, 16:41
Hi, I made some great progress. I've a line drawn where the item is placed. And I can pass the row index of the item to be moved.

May be useful for to someone, very similiar to Amarok(music player) playlist drag and drop.
Without the actual moving of items yet.

I guess a custom mime type would be best to stop unwanted drops and drags



QStringList MyModel::mimeTypes () const
{
QStringList list;
list << "text/plain";
return list;
}

void MyModel::emit_layoutChanged ( )
{
emit layoutChanged();
}

void MyTreeView::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
QTreeView::mousePressEvent(event);
QModelIndex index = currentIndex();
QString plainText = lexical_cast<std::string>(index.row()).c_str();
mimeData = new QMimeData;
mimeData->setText(plainText);
drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setHotSpot(event->pos() - rect().topLeft());
dropAction = drag->start(Qt::CopyAction | Qt::MoveAction);
}
}

void MyTreeView::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasText())
event->acceptProposedAction();
else
event->ignore();
}

void MyTreeView::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasText()) {
event->setDropAction(Qt::MoveAction);
std::string text = (event->mimeData()->text()).toStdString();
std::cout << text << std::endl;
}
else {
event->ignore();
}
}

void MyTreeView::dragMoveEvent (QDragMoveEvent *event)
{
dropSite = event->answerRect();
model_->emit_layoutChanged(); // public function in model subclass
}

void MyTreeView::paintEvent ( QPaintEvent* event )
{
QTreeView::paintEvent (event);
QPainter painter ( viewport() );
int x, y, w, h;
dropSite.getRect ( &x, &y, &w, &h );
QPoint point(x,y);
QModelIndex modidx = indexAt ( point );
QRect arect = visualRect ( modidx );
int b = arect.y();
QBrush brush(Qt::black, Qt::Dense4Pattern);
QPen pen;
pen.setWidth(2);
pen.setBrush(brush);
painter.setPen(pen);
painter.drawLine ( 0, b, width(), b );
event->accept();
}