int UIDnDHandler::retrieveDataInternal( Qt::DropAction dropAction, const QString &strMIMEType, QVector<uint8_t> &vecData) { LogFlowFunc(("Retrieving data as '%s', dropAction=%d\n", qPrintable(strMIMEType), dropAction)); int rc = VINF_SUCCESS; /* Indicate to the guest that we have dropped the data on the host. * The guest then will initiate the actual "drop" operation into our proxy on the guest. */ Assert(!m_dndSource.isNull()); CProgress progress = m_dndSource.Drop(strMIMEType, UIDnDHandler::toVBoxDnDAction(dropAction)); LogFlowFunc(("Source: isOk=%RTbool\n", m_dndSource.isOk())); if (m_dndSource.isOk()) { /* Send a mouse event with released mouse buttons into the guest that triggers * the "drop" event in our proxy window on the guest. */ AssertPtr(m_pSession); m_pSession->mouse().PutMouseEvent(0, 0, 0, 0, 0); msgCenter().showModalProgressDialog(progress, tr("Retrieving data ..."), ":/progress_dnd_gh_90px.png", m_pParent); LogFlowFunc(("Progress: fCanceled=%RTbool, fCompleted=%RTbool, isOk=%RTbool, hrc=%Rhrc\n", progress.GetCanceled(), progress.GetCompleted(), progress.isOk(), progress.GetResultCode())); if (!progress.GetCanceled()) { rc = ( progress.isOk() && progress.GetResultCode() == 0) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /** @todo Fudge; do a GetResultCode() to rc translation. */ if (RT_SUCCESS(rc)) { /* After we successfully retrieved data from the source we query it from Main. */ vecData = m_dndSource.ReceiveData(); /** @todo QVector.size() is "int" only!? */ if (vecData.isEmpty()) rc = VERR_NO_DATA; } else msgCenter().cannotDropDataToHost(progress, m_pParent); } else /* Don't pop up a message. */ rc = VERR_CANCELLED; } else { msgCenter().cannotDropDataToHost(m_dndSource, m_pParent); rc = VERR_GENERAL_FAILURE; /** @todo Fudge; do a GetResultCode() to rc translation. */ } setMode(DNDMODE_UNKNOWN); LogFlowFuncLeaveRC(rc); return rc; }
Qt::DropAction UIDnDHandler::dragDrop(ulong screenID, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData) { LogFlowFunc(("enmOpMode=%RU32, screenID=%RU32, x=%d, y=%d, action=%ld\n", m_enmOpMode, screenID, x, y, toVBoxDnDAction(proposedAction))); if (m_enmOpMode != DNDMODE_HOSTTOGUEST) return Qt::IgnoreAction; /* The format the guest requests. */ QString strFormat; /* Ask the guest for dropping data. */ KDnDAction enmResult = m_dndTarget.Drop(screenID, x, y, toVBoxDnDAction(proposedAction), toVBoxDnDActions(possibleActions), pMimeData->formats().toVector(), strFormat); /* Has the guest accepted the drop event? */ if ( m_dndTarget.isOk() && enmResult != KDnDAction_Ignore) { LogFlowFunc(("strFormat=%s ...\n", strFormat.toUtf8().constData())); QByteArray arrBytes; /* * Does the host support the format requested by the guest? * Lookup the format in the MIME data object. */ AssertPtr(pMimeData); if (pMimeData->formats().indexOf(strFormat) >= 0) { arrBytes = pMimeData->data(strFormat); Assert(!arrBytes.isEmpty()); } /* * The host does not support the format requested by the guest. * This can happen if the host wants to send plan text, for example, but * the guest requested something else, e.g. an URI list. * * In that case dictate the guest to use a fixed format from the host, * so instead returning the requested URI list, return the original * data format from the host. The guest has to try to deal with that then. **/ else { LogRel3(("DnD: Guest requested a different format '%s'\n", strFormat.toUtf8().constData())); LogRel3(("DnD: The host offered:\n")); #if 0 for (QStringList::iterator itFmt = pMimeData->formats().begin(); itFmt != pMimeData->formats().end(); itFmt++) { QString strTemp = *itFmt; LogRel3(("DnD: \t%s\n", strTemp.toUtf8().constData())); } #endif if (pMimeData->hasText()) { LogRel3(("DnD: Converting data to text ...\n")); arrBytes = pMimeData->text().toUtf8(); strFormat = "text/plain;charset=utf-8"; } else { LogRel(("DnD: Error: Could not convert host format to guest format\n")); enmResult = KDnDAction_Ignore; } } if (arrBytes.size()) /* Anything to send? */ { /* Convert data to a vector. */ QVector<uint8_t> vecData(arrBytes.size()); /** @todo Can this throw or anything? */ AssertReleaseMsg(vecData.size() == arrBytes.size(), ("Drag and drop format buffer size does not match")); memcpy(vecData.data(), arrBytes.constData(), arrBytes.size()); /* Send data to the guest. */ LogRel3(("DnD: Host is sending %d bytes of data as '%s'\n", vecData.size(), strFormat.toUtf8().constData())); CProgress progress = m_dndTarget.SendData(screenID, strFormat, vecData); if (m_dndTarget.isOk()) { msgCenter().showModalProgressDialog(progress, tr("Dropping data ..."), ":/progress_dnd_hg_90px.png", m_pParent); LogFlowFunc(("Transfer fCompleted=%RTbool, fCanceled=%RTbool, hr=%Rhrc\n", progress.GetCompleted(), progress.GetCanceled(), progress.GetResultCode())); BOOL fCanceled = progress.GetCanceled(); if ( !fCanceled && ( !progress.isOk() || progress.GetResultCode() != 0)) { msgCenter().cannotDropDataToGuest(progress, m_pParent); enmResult = KDnDAction_Ignore; } } else { msgCenter().cannotDropDataToGuest(m_dndTarget, m_pParent); enmResult = KDnDAction_Ignore; } } else /* Error. */ enmResult = KDnDAction_Ignore; } /* * Since the mouse button has been release this in any case marks * the end of the current transfer direction. So reset the current * mode as well here. */ setOpMode(DNDMODE_UNKNOWN); return toQtDnDAction(enmResult); }