Пример #1
0
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;
}
Пример #2
0
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);
}