PDA

View Full Version : DragDrop problem : QDrag::start doesn't return without mousemove.



Kratzy974
8th August 2006, 11:32
Hi

I'm using Drag'n'Drgop with Qt. The drag is started in MouseMove event in one widget. It end in same or other widget. When I release the mouse the DropEvent is called. But sometimes, the QDrag::start doesn't return, when mouse is not moved. Drop is done, Drag does not end.

This seem to happen, when the mouse moved by 1 pix during releasing the mousebutton.
I'm using a code very similar to the example code from the tutorial.

Could anyone help me out here ?

kind regards

wysota
8th August 2006, 14:25
Can we see the code?

Kratzy974
8th August 2006, 15:09
Here is the code, filled up with some stuff, which isn't needed, but I didn't want to remove stuff, which could be the problem.



//! This is called, when a Drag'n'Drop is commin into this Widget
//!
void CsfDlg_Overview::dragEnterEvent(QDragEnterEvent *qEvent)
{
if(!this->mAllowedDropInto)
qEvent->ignore();
else if (qEvent->mimeData()->hasFormat(kMime_ThumbOverview.c_str())
|| qEvent->mimeData()->hasFormat(sfMime_SystemDragDrop.c_str()))
{
if ((qEvent->source() == this))
{
qEvent->setDropAction(Qt::MoveAction);
qEvent->accept();
}
else
{
qEvent->acceptProposedAction();
}
}
else
qEvent->ignore();
}

//! ..when the Drag'n'Drop is moved in this widget
//!
void CsfDlg_Overview::dragMoveEvent(QDragMoveEvent *qEvent)
{
if(!this->mAllowedDropInto)
qEvent->ignore();
else
emit update();
}

//! Called, when any drag and drop action was ended in this widget
//!
void CsfDlg_Overview::dropEvent(QDropEvent *qEvent)
{
emit update();

if (!qEvent->mimeData()->hasFormat(kMime_ThumbOverview.c_str())
&& !qEvent->mimeData()->hasFormat(sfMime_SystemDragDrop.c_str()))
return;
if(!this->mAllowedDropInto)
return;
if ((qEvent->dropAction() == Qt::MoveAction) || (qEvent->dropAction() == Qt::CopyAction))
qEvent->acceptProposedAction();
else
return;

CsfThumbnailOverview *thumb(0), thumbTemp;
if(qEvent->mimeData()->hasFormat(kMime_ThumbOverview.c_str()))
{
// This seem to be a drag drop event from another thumbnail window
// The thumbnails are complete in the datastream and need to be read

QByteArray itemData(qEvent->mimeData()->data(kMime_ThumbOverview.c_str()));
QDataStream dataStream(&itemData, QIODevice::ReadOnly);
int quant(0);
CsfPoint basePoint, topleftP, curP, hotSpot;

dataStream >> basePoint;
dataStream >> hotSpot;
dataStream >> quant;
if(!this->mReposition)
topleftP = CsfPoint(qEvent->pos())-hotSpot;
while(quant > 0)
{
dataStream >> thumbTemp;

if(!this->mReposition)
{
curP = thumbTemp.getPosition();
curP -= basePoint;
curP += topleftP;
curP += this->mScrollPos;
thumbTemp.setPosition(curP);
}

if((this->getThumbnailFromName(thumbTemp.getImageFile()) == NULL) || (qEvent->source() == this))
{
thumb = this->addThumbnailToList();
*thumb = thumbTemp;
if(!thumb->isThumbnailLowsized())
thumb->setImageFile(thumb->getImageFile(), true);
}
--quant;
}
this->slotChangeSizeAbs(this->mThumbSize);

if ((qEvent->source() == this))
{
qEvent->setDropAction(Qt::MoveAction);
qEvent->accept();
}
else
qEvent->acceptProposedAction();
}
else if(qEvent->mimeData()->hasFormat(sfMime_SystemDragDrop.c_str()))
{
// This event comes from the desktop an includes just the names of the
// files given.

CsfString strg, ext;
QByteArray itemData(qEvent->mimeData()->data(sfMime_SystemDragDrop.c_str()));
std::vector<CsfStringA> filterListIn;

filterListIn = sIMAGEFILELIST.getImageExtensionList();
QList<QUrl> urls = qEvent->mimeData()->urls();
foreach(QUrl url, urls)
{
strg = url.toLocalFile();
if(strg.left(1) == "/")
strg = strg.right(strg.getLength() - 1);
// Sort file out, when the extension is not known
bool allowed(false);
for(std::vector<CsfStringA>::const_iterator iter = filterListIn.begin(); iter != filterListIn.end(); ++iter)
{
ext = strg.right((*iter).getLength());
ext.makeLower();
if(ext == (*iter))
{
allowed = true;
break;
}
}
if(!allowed) continue;
if(this->getThumbnailFromName(strg) == NULL)
{
thumb = this->addThumbnailToList();
thumb->setImageFile(strg);
if(!this->mReposition)
thumb->setPosition(CsfPoint(qEvent->pos())+this->mScrollPos);
}
}

this->slotChangeSizeAbs(this->mThumbSize);

if ((qEvent->source() == this))
{
qEvent->setDropAction(Qt::MoveAction);
qEvent->accept();
}
else
{
qEvent->setDropAction(Qt::CopyAction);
qEvent->accept();
}
}
}

//************************************************** ******************************
// Events commin from using the mouse
//************************************************** ******************************

//! mouseMoveEvent is called everytime, when the mouse cursor is moved over the window
//! This method starts the drag/drop if needed and emit an update, when mouse is still clicked.
//! - Not called after drag/drop started.
void CsfDlg_Overview::mouseMoveEvent(QMouseEvent* qEvent)
{
QPoint pt(qEvent->pos());
std::list<CsfThumbnailOverview*> activeThumb;;

this->mMouseCurrent = CsfPoint(pt);

while((this->mMouseState &= sfMouseState_Dragging) &&
(this->mMouseStart.distance(this->mMouseCurrent) > 15.0)) // distance (pixel) when starting the drag/ drop
{
// We need to drag / drop the current thumbnail.
QDrag *drag = new QDrag(this);
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
QMimeData *mimeData = new QMimeData;
iterator iter, end;
CsfRect rect, thumbRect;
CsfPoint point2, point;

end = this->mThumbList.end();
for(iter = this->mThumbList.begin(); iter != end; ++iter)
{
if(iter->getState() == sfMouseState_Dragging)
{
activeThumb.clear();
break;
}
if(iter->isThumbnailActive())
{
activeThumb.push_back(&(*iter));
iter->setState(sfMouseState_Dragging);
if(rect.empty())
rect = iter->getRect();
else
rect.setUnion(rect, iter->getRect());
}
}

if(activeThumb.size() == 0)
break;

// Painting all thumbnails, wich will be used for drag/drop in an drag/drop image.
QPixmap pixmap(rect.width(), rect.height());
pixmap.fill(QColor(0, 0, 0, 0));
point = this->mMouseStart - (rect.getTopLeft() - this->mScrollPos);
point2 = rect.getTopLeft();
for(std::list<CsfThumbnailOverview*>::iterator iter2 = activeThumb.begin(); iter2 != activeThumb.end(); ++iter2)
{
QPainter painter(&pixmap);
CsfPoint whereTo((*iter2)->getRect().getTopLeft() - point2);

painter.drawPixmap(QPoint(whereTo), (*iter2)->getPreRendered());
}

{ // The thumbnails need an alpha.
QPainter painter(&pixmap);

painter.setCompositionMode(QPainter::CompositionMo de_DestinationIn);
painter.setPen(QColor(255, 255, 255, 120));
painter.setBrush(QColor(255, 255, 255, 120));
painter.drawRect(0, 0, pixmap.width(), pixmap.height());
}

// Now we savin the thumbnail in the drag / drop.
dataStream << point2; // Absolute position, where thumbs were located.
dataStream << point; // Hotspot of the drag.
dataStream << static_cast<int>(activeThumb.size()); // How many thumbnails
for(std::list<CsfThumbnailOverview*>::iterator iter2 = activeThumb.begin(); iter2 != activeThumb.end(); ++iter2)
{
dataStream << *(*iter2);
}
mimeData->setData(kMime_ThumbOverview.c_str(), itemData);

drag->setMimeData(mimeData);
drag->setPixmap(pixmap);
drag->setHotSpot(point);

Qt::DropAction result = drag->start(Qt::CopyAction | (this->mAllowedDropInto ? Qt::MoveAction : Qt::IgnoreAction));

this->mMouseState &= sfMouseState_Nothing;

if(result == Qt::MoveAction && this->mAllowedDropInto)
{
for(std::list<CsfThumbnailOverview*>::iterator iter2 = activeThumb.begin(); iter2 != activeThumb.end(); ++iter2)
{
end = this->mThumbList.end();
for(iter = this->mThumbList.begin(); iter != end; ++iter)
{
if(&(*iter) == (*iter2))
{
this->mThumbList.erase(iter);
break;
}
}
}
this->slotChangeSizeAbs(this->mThumbSize);
}

end = this->mThumbList.end();
for(iter = this->mThumbList.begin(); iter != end; ++iter)
iter->setState(sfMouseState_Nothing);

emit update();
}
if((this->mMouseState & sfMouseState_Clicked))
{
emit update();
}
}