Changeset 57221 in vbox for trunk/src/VBox/Frontends/VirtualBox
- Timestamp:
- Aug 6, 2015 7:19:19 PM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 101974
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r57112 r57221 118 118 $(if $(VBOX_WITH_DRAG_AND_DROP),VBOX_WITH_DRAG_AND_DROP) \ 119 119 $(if $(VBOX_WITH_DRAG_AND_DROP_GH),VBOX_WITH_DRAG_AND_DROP_GH) \ 120 $(if $(VBOX_WITH_DRAG_AND_DROP_PROMISES),VBOX_WITH_DRAG_AND_DROP_PROMISES) \ 120 121 $(if $(VBOX_WITH_CRHGSMI),VBOX_WITH_CRHGSMI) \ 121 122 $(if $(VBOX_WITH_VIRTIO),VBOX_WITH_VIRTIO) \ … … 807 808 endif 808 809 810 # 811 # Drag and drop support. 812 # 809 813 ifdef VBOX_WITH_DRAG_AND_DROP 810 814 VirtualBox_SOURCES += \ -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.cpp
r56779 r57221 62 62 #include <VBox/log.h> 63 63 64 #if 1 65 # ifdef DEBUG 66 # include <QTextStream> 67 /** Enable this to log debug output of a Qt debug build to a file defined by DEBUG_DND_QT_LOGFILE. */ 68 # define DEBUG_DND_QT 69 /** File to log Qt debug output to. */ 70 # define DEBUG_DND_QT_LOGFILE "/var/tmp/qt.log" 71 # endif /* DEBUG */ 72 #endif 64 73 65 74 UIDnDHandler::UIDnDHandler(UISession *pSession, QWidget *pParent) … … 68 77 , m_enmMode(DNDMODE_UNKNOWN) 69 78 , m_fIsPending(false) 79 , m_fDataRetrieved(false) 70 80 #ifndef RT_OS_WINDOWS 71 81 , m_pMIMEData(NULL) … … 264 274 } 265 275 276 #ifdef DEBUG_DND_QT 277 QTextStream *g_pStrmLogQt = NULL; /* Output stream for Qt debug logging. */ 278 279 /* static */ 280 void UIDnDHandler::debugOutputQt(QtMsgType type, const char *pszMsg) 281 { 282 AssertPtr(pszMsg); 283 284 QString strMsg; 285 switch (type) 286 { 287 case QtWarningMsg: 288 strMsg += "[W]"; 289 break; 290 case QtCriticalMsg: 291 strMsg += "[C]"; 292 break; 293 case QtFatalMsg: 294 strMsg += "[F]"; 295 break; 296 case QtDebugMsg: 297 default: 298 strMsg += "[D]"; 299 break; 300 } 301 302 if (g_pStrmLogQt) 303 (*g_pStrmLogQt) << strMsg << " " << pszMsg << endl; 304 } 305 #endif /* DEBUG_DND_QT */ 306 266 307 /* 267 308 * Source -> Frontend. … … 327 368 } 328 369 329 /* Invoke this handler as data needs to be retrieved. */ 330 connect(m_pMIMEData, SIGNAL(getData(QString, QVariant::Type, QVariant&)), 331 this, SLOT(sltGetData(QString, QVariant::Type, QVariant&))); 370 #ifdef DEBUG_DND_QT 371 QFile *pFileDebugQt = new QFile(DEBUG_DND_QT_LOGFILE); 372 if (pFileDebugQt->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) 373 { 374 g_pStrmLogQt = new QTextStream(pFileDebugQt); 375 376 qInstallMsgHandler(UIDnDHandler::debugOutputQt); 377 qDebug("========================================================================"); 378 } 379 #endif 332 380 333 381 /* Inform the MIME data object of any changes in the current action. */ … … 341 389 pDrag->setMimeData(m_pMIMEData); 342 390 LogFlowFunc(("Executing modal drag'n drop operation ...\n")); 343 Qt::DropAction dropAction = pDrag->exec(actions, defAction); 391 392 Qt::DropAction dropAction; 393 #ifdef RT_OS_DARWIN 394 # ifdef VBOX_WITH_DRAG_AND_DROP_PROMISES 395 dropAction = pDrag->exec(actions, defAction, true /* fUsePromises */); 396 # else 397 /* Without having VBOX_WITH_DRAG_AND_DROP_PROMISES enabled drag and drop 398 * will not work on OS X! It also requires some handcrafted patches within Qt 399 * (which also needs VBOX_WITH_DRAG_AND_DROP_PROMISES set there). */ 400 dropAction = DropAction::IgnoreAction; 401 rc = VERR_NOT_SUPPORTED; 402 # endif 403 #else /* !RT_OS_DARWIN */ 404 dropAction = pDrag->exec(actions, defAction); 405 #endif 344 406 LogRel3(("DnD: Ended with dropAction=%ld\n", UIDnDHandler::toVBoxDnDAction(dropAction))); 345 407 … … 357 419 358 420 #endif 421 422 #ifdef DEBUG_DND_QT 423 if (g_pStrmLogQt) 424 { 425 delete g_pStrmLogQt; 426 g_pStrmLogQt = NULL; 427 } 428 429 if (pFileDebugQt) 430 { 431 pFileDebugQt->close(); 432 delete pFileDebugQt; 433 } 434 #endif 435 436 reset(); 359 437 360 438 LogFlowFuncLeaveRC(rc); … … 405 483 m_dataSource.defaultAction = m_dndSource.DragIsPending(screenID, vecFormats, m_dataSource.vecActions); 406 484 407 LogRel 3(("DnD: Default action is: 0x%x\n", m_dataSource.defaultAction));408 LogRel 3(("DnD: Number of supported guest actions: %d\n", m_dataSource.vecActions.size()));485 LogRelMax3(10, ("DnD: Default action is: 0x%x\n", m_dataSource.defaultAction)); 486 LogRelMax3(10, ("DnD: Number of supported guest actions: %d\n", m_dataSource.vecActions.size())); 409 487 for (int i = 0; i < m_dataSource.vecActions.size(); i++) 410 LogRel 3(("DnD: \tAction %d: 0x%x\n", i, m_dataSource.vecActions.at(i)));411 412 LogRel 3(("DnD: Number of supported guest formats: %d\n", vecFormats.size()));488 LogRelMax3(10, ("DnD: \tAction %d: 0x%x\n", i, m_dataSource.vecActions.at(i))); 489 490 LogRelMax3(10, ("DnD: Number of supported guest formats: %d\n", vecFormats.size())); 413 491 for (int i = 0; i < vecFormats.size(); i++) 414 492 { 415 493 const QString &strFmtGuest = vecFormats.at(i); 416 LogRel 3(("DnD: \tFormat %d: %s\n", i, strFmtGuest.toAscii().constData()));494 LogRelMax3(10, ("DnD: \tFormat %d: %s\n", i, strFmtGuest.toAscii().constData())); 417 495 } 418 496 … … 491 569 NOREF(screenID); 492 570 493 m_fIsPending = false;571 reset(); 494 572 rc = VINF_SUCCESS; 495 573 … … 506 584 } 507 585 586 void UIDnDHandler::reset(void) 587 { 588 LogFlowFuncEnter(); 589 590 m_fDataRetrieved = false; 591 m_fIsPending = false; 592 593 setMode(DNDMODE_UNKNOWN); 594 } 595 596 int UIDnDHandler::retrieveData(Qt::DropAction dropAction, 597 const QString &strMIMEType, 598 QVector<uint8_t> &vecData) 599 { 600 if (!strMIMEType.compare("application/x-qt-mime-type-name", Qt::CaseInsensitive)) 601 return VINF_SUCCESS; 602 603 int rc; 604 if (!m_fDataRetrieved) 605 { 606 /* 607 * Retrieve the actual data from the guest. 608 */ 609 rc = retrieveDataInternal(dropAction, strMIMEType, m_vecData); 610 LogRel3(("DnD: Received data, rc=%Rrc\n", rc)); 611 612 if (RT_SUCCESS(rc)) 613 m_fDataRetrieved = true; 614 } 615 else /* Data already received, supply cached version. */ 616 rc = VINF_SUCCESS; 617 618 if (RT_SUCCESS(rc)) 619 vecData = m_vecData; 620 621 return rc; 622 } 623 508 624 int UIDnDHandler::retrieveData( Qt::DropAction dropAction, 509 const QString &strM imeType,625 const QString &strMIMEType, 510 626 QVariant::Type vaType, 511 627 QVariant &vaData) 512 628 { 513 return retrieveDataInternal(dropAction, strMimeType, vaType, vaData); 514 } 515 516 int UIDnDHandler::retrieveDataInternal( Qt::DropAction dropAction, 517 const QString &strMimeType, 518 QVariant::Type vaType, 519 QVariant &vaData) 520 { 521 LogFlowFunc(("Retrieving data as type=%s (variant type=%RU32)\n", 522 strMimeType.toAscii().constData(), vaType)); 629 QVector<uint8_t> vecData; 630 int rc = retrieveData(dropAction, strMIMEType, vecData); 631 if (RT_SUCCESS(rc)) 632 { 633 /* If no/an invalid variant is set, try to guess the variant type. 634 * This can happen on OS X. */ 635 if (vaType == QVariant::Invalid) 636 vaType = UIDnDMIMEData::getVariantType(strMIMEType); 637 638 rc = UIDnDMIMEData::getDataAsVariant(vecData, strMIMEType, vaType, vaData); 639 } 640 641 LogFlowFuncLeaveRC(rc); 642 return rc; 643 } 644 645 int UIDnDHandler::retrieveDataInternal( Qt::DropAction dropAction, 646 const QString &strMIMEType, 647 QVector<uint8_t> &vecData) 648 { 649 LogFlowFunc(("Retrieving data as '%s', dropAction=%d\n", qPrintable(strMIMEType), dropAction)); 523 650 524 651 int rc = VINF_SUCCESS; … … 527 654 * from the source and display a modal progress dialog while doing this. */ 528 655 Assert(!m_dndSource.isNull()); 529 CProgress progress = m_dndSource.Drop(strM imeType,656 CProgress progress = m_dndSource.Drop(strMIMEType, 530 657 UIDnDHandler::toVBoxDnDAction(dropAction)); 658 659 LogFlowFunc(("Source: isOk=%RTbool\n", m_dndSource.isOk())); 531 660 if (m_dndSource.isOk()) 532 661 { … … 535 664 m_pParent); 536 665 537 LogFlowFunc((" fCanceled=%RTbool, fCompleted=%RTbool, isOk=%RTbool, hrc=%Rhrc\n",666 LogFlowFunc(("Progress: fCanceled=%RTbool, fCompleted=%RTbool, isOk=%RTbool, hrc=%Rhrc\n", 538 667 progress.GetCanceled(), progress.GetCompleted(), progress.isOk(), progress.GetResultCode())); 539 668 … … 547 676 { 548 677 /* After we successfully retrieved data from the source we query it from Main. */ 549 QVector<uint8_t> vecData = m_dndSource.ReceiveData(); 550 if (!vecData.isEmpty()) 551 { 552 switch (vaType) 553 { 554 case QVariant::String: 555 { 556 vaData = QVariant::fromValue(QString(reinterpret_cast<const char *>(vecData.constData()))); 557 Assert(vaData.type() == QVariant::String); 558 break; 559 } 560 561 case QVariant::ByteArray: 562 { 563 QByteArray ba(reinterpret_cast<const char*>(vecData.constData()), vecData.size()); 564 565 vaData = QVariant::fromValue(ba); 566 Assert(vaData.type() == QVariant::ByteArray); 567 break; 568 } 569 570 case QVariant::StringList: 571 { 572 QString strData = QString(reinterpret_cast<const char*>(vecData.constData())); 573 QStringList lstString = strData.split("\r\n", QString::SkipEmptyParts); 574 575 vaData = QVariant::fromValue(lstString); 576 Assert(vaData.type() == QVariant::StringList); 577 break; 578 } 579 580 default: 581 rc = VERR_NOT_SUPPORTED; 582 break; 583 } 584 } 585 else 678 vecData = m_dndSource.ReceiveData(); /** @todo QVector.size() is "int" only!? */ 679 if (vecData.isEmpty()) 586 680 rc = VERR_NO_DATA; 587 681 } … … 609 703 m_enmMode = enmMode; 610 704 LogFlowFunc(("Mode is now: %RU32\n", m_enmMode)); 611 }612 613 int UIDnDHandler::sltGetData(const QString &strMimeType,614 QVariant::Type vaType,615 QVariant &vaData)616 {617 int rc = retrieveDataInternal(Qt::CopyAction, strMimeType, vaType, vaData);618 LogFlowFuncLeaveRC(rc);619 return rc;620 705 } 621 706 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.h
r56555 r57221 76 76 } UIDnDDataSource; 77 77 78 void reset(void); 79 78 80 /* Frontend -> Target. */ 79 81 Qt::DropAction dragEnter(ulong screenId, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData); … … 86 88 int dragStart(ulong screenId); 87 89 int dragStop(ulong screenID); 88 int retrieveData(Qt::DropAction dropAction, const QString &strMimeType, QVariant::Type vaType, QVariant &vaData); 90 91 /* Data access. */ 92 int retrieveData(Qt::DropAction dropAction, const QString &strMIMEType, QVector<uint8_t> &vecData); 93 int retrieveData(Qt::DropAction dropAction, const QString &strMIMEType, QVariant::Type vaType, QVariant &vaData); 89 94 90 95 public: … … 95 100 static Qt::DropActions toQtDnDActions(const QVector<KDnDAction> &vecActions); 96 101 97 p ublic slots:102 protected: 98 103 99 /** 100 * Called by UIDnDMIMEData (Linux, OS X, Solaris) to start retrieving the actual data 101 * from the guest. This function will block and show a modal progress dialog until 102 * the data transfer is complete. 103 * 104 * @return IPRT status code. 105 * @param strMimeType MIME data type. 106 * @param vaType Qt's variant type of the MIME data. 107 * @param vaData Reference to QVariant where to store the retrieved data. 108 */ 109 int sltGetData(const QString &strMimeType, QVariant::Type vaType, QVariant &vaData); 104 #ifdef DEBUG 105 static void debugOutputQt(QtMsgType type, const char *pszMsg); 106 #endif 110 107 111 108 protected: 112 109 113 110 int dragStartInternal(const QStringList &lstFormats, Qt::DropAction defAction, Qt::DropActions actions); 114 int retrieveDataInternal(Qt::DropAction dropAction, const QString &strM imeType, QVariant::Type vaType, QVariant &vaData);111 int retrieveDataInternal(Qt::DropAction dropAction, const QString &strMIMEType, QVector<uint8_t> &vecData); 115 112 void setMode(DNDMODE enmMode); 116 113 … … 133 130 /** Flag indicating if a drag operation is pending currently. */ 134 131 bool m_fIsPending; 132 /** Flag indicating whether data has been retrieved from 133 * the guest already or not. */ 134 bool m_fDataRetrieved; 135 135 QMutex m_ReadLock; 136 136 QMutex m_WriteLock; 137 /** Data received from the guest. */ 138 QVector<uint8_t> m_vecData; 137 139 138 140 #ifndef RT_OS_WINDOWS -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.cpp
r56865 r57221 44 44 , m_actions(actions) 45 45 , m_enmState(Dragging) 46 , m_vaData(QVariant::Invalid)47 #ifdef RT_OS_DARWIN48 , m_fCanDrop(false)49 #endif50 46 { 51 47 LogFlowThisFuncEnter(); 52 53 48 #ifdef DEBUG 54 49 LogFlowFunc(("Number of formats: %d\n", m_lstFormats.size())); … … 56 51 LogFlowFunc(("\tFormat %d: %s\n", i, m_lstFormats.at(i).toAscii().constData())); 57 52 #endif 58 53 } 54 55 QStringList UIDnDMIMEData::formats(void) const 56 { 57 LogFlowFuncEnter(); 58 #ifdef DEBUG 59 for (int i = 0; i < m_lstFormats.size(); i++) 60 LogFlowFunc(("\tFormat %d: %s\n", i, m_lstFormats.at(i).toAscii().constData())); 61 #endif 62 return m_lstFormats; 63 } 64 65 bool UIDnDMIMEData::hasFormat(const QString &strMIMEType) const 66 { 67 bool fRc; 59 68 #ifdef RT_OS_DARWIN 60 connect(this, SIGNAL(notifyDropped()), this, SLOT(sltDropped())); 61 #endif 62 } 63 64 QStringList UIDnDMIMEData::formats(void) const 65 { 66 LogFlowFuncEnter(); 67 return m_lstFormats; 68 } 69 70 bool UIDnDMIMEData::hasFormat(const QString &strMIMEType) const 71 { 72 bool fRc = false; 73 74 #ifdef RT_OS_DARWIN 75 if (strMIMEType.compare("application/x-qt-mime-type-name", Qt::CaseInsensitive) == 0) 76 fRc = true; 77 #endif 78 79 if (!fRc) 80 fRc = m_curAction != Qt::IgnoreAction; 69 fRc = m_lstFormats.contains(strMIMEType); 70 #else 71 fRc = m_curAction != Qt::IgnoreAction; 72 #endif 81 73 82 74 LogFlowFunc(("%s: %RTbool (QtMimeData: %RTbool, curAction=0x%x)\n", 83 75 strMIMEType.toStdString().c_str(), fRc, QMimeData::hasFormat(strMIMEType), m_curAction)); 84 76 85 #ifdef RT_OS_DARWIN86 /*87 * On OS X hasFormat() only seems to get called on a successful88 * drop, that is, if the host knows (and the user accepts) the drop operation.89 *90 * As we can't do here much since this is a const'ed function we're emitting a91 * signal to ourselves in order to let us know that we can start receiving data92 * from the guest within the next retrieveData() call.93 */94 emit notifyDropped();95 #endif96 97 77 return fRc; 98 78 } 99 100 #ifdef RT_OS_DARWIN101 void UIDnDMIMEData::sltDropped(void)102 {103 LogFlowFuncEnter();104 m_fCanDrop = true;105 }106 #endif107 79 108 80 /** … … 120 92 m_enmState, m_curAction, m_defAction, strMIMEType.toStdString().c_str(), vaType, QVariant::typeToName(vaType))); 121 93 122 bool fCanDrop = true; /* Accept by default. */94 int rc = VINF_SUCCESS; 123 95 124 96 #ifdef RT_OS_WINDOWS 125 /* 97 /* 126 98 * On Windows this function will be called several times by Qt's 127 99 * OLE-specific internals to figure out which data formats we have 128 100 * to offer. So just assume we can drop data here for a start. 129 */ 101 */ 130 102 #elif defined(RT_OS_DARWIN) 103 # ifndef VBOX_WITH_DRAG_AND_DROP_PROMISES 131 104 /* 132 * On OS X we rely on an internal flag which gets set in the overriden 133 * hasFormat() function. That function only gets called on a successful drop 134 * so that we can tell if we have to start receiving data the next time 135 * we come by here. 105 * Without VBOX_WITH_DRAG_AND_DROP_PROMISES being set in VBox *and* in our (patched) Qt 106 * libraries there's no reliable way to get this working on OS X. So just deny any dropping. 136 107 */ 137 fCanDrop = m_fCanDrop; 138 #else 139 /* 140 * On non-Windows our state gets updated via an own event filter 141 * (see UIDnDMimeData::eventFilter). This filter will update the current 142 * operation state for us (based on the mouse buttons). 143 */ 108 rc = VERR_NOT_IMPLEMENTED; 109 110 /* Let the user know. */ 111 LogRel(("Drag and drop support for OS X is disabled in this version.")); 112 # endif /* VBOX_WITH_DRAG_AND_DROP_PROMISES */ 113 #else /* !RT_OS_DARWIN */ 114 /* 115 * On Linux/Solaris our state gets updated if the drop target has been 116 * changed. So query the current status if we're at the moment are able 117 * to drop something on the current target. 118 */ 144 119 if (m_curAction == Qt::IgnoreAction) 145 120 { 146 121 LogFlowFunc(("Current drop action is 0x%x, so can't drop yet\n", m_curAction)); 147 fCanDrop = false; 148 } 149 #endif 150 151 if (fCanDrop) 152 { 122 rc = VERR_WRONG_ORDER; 123 } 124 #endif 125 126 if (RT_SUCCESS(rc)) 127 { 128 /* Silently ignore internal Qt types / converters. */ 129 if (!strMIMEType.compare("application/x-qt-mime-type-name", Qt::CaseInsensitive)) 130 { 131 rc = VERR_NOT_FOUND; 132 } 153 133 /* Do we support the requested MIME type? */ 154 if (!m_lstFormats.contains(strMIMEType))134 else if (!m_lstFormats.contains(strMIMEType)) 155 135 { 156 136 LogRel(("DnD: Unsupported MIME type '%s'\n", strMIMEType.toStdString().c_str())); 157 fCanDrop = false; 158 } 159 160 /* Supported types. See below in the switch statement. */ 161 if (!( 162 /* Plain text. */ 163 vaType == QVariant::String 164 /* Binary data. */ 165 || vaType == QVariant::ByteArray 166 /* URI list. */ 167 || vaType == QVariant::List)) 137 rc = VERR_NOT_SUPPORTED; 138 } 139 #ifndef RT_OS_DARWIN /* On OS X QVariant::Invalid can happen for drag and drop "promises" for "lazy requests". */ 140 /* Check supported variant types. */ 141 else if (!( 142 /* Plain text. */ 143 vaType == QVariant::String 144 /* Binary data. */ 145 || vaType == QVariant::ByteArray 146 /* URI list. */ 147 || vaType == QVariant::List 148 || vaType == QVariant::StringList)) 168 149 { 169 150 LogRel(("DnD: Unsupported data type '%s'\n", QVariant::typeToName(vaType))); 170 fCanDrop = false; 171 } 172 } 173 174 LogRel3(("DnD: State=%ld, Action=0x%x, fCanDrop=%RTbool\n", m_enmState, m_curAction, fCanDrop)); 175 176 if (fCanDrop) 151 rc = VERR_NOT_SUPPORTED; 152 } 153 #endif 154 } 155 156 LogRel3(("DnD: Retrieved data state is %ld (action=0x%x), rc=%Rrc\n", m_enmState, m_curAction, rc)); 157 158 if (RT_SUCCESS(rc)) 177 159 { 178 160 QVariant vaData; 179 int rc = emit getData(strMIMEType, vaType, vaData); 180 181 LogRel3(("DnD: Returning data of type=%s (requested MIME type=%s, requested type=%s), rc=%Rrc\n", 182 vaData.typeName() ? vaData.typeName() : "<Invalid>", 183 strMIMEType.toStdString().c_str(), 184 QVariant::typeToName(vaType) ? QVariant::typeToName(vaType) : "<Invalid>", rc)); 185 161 rc = m_pDnDHandler->retrieveData(Qt::CopyAction, strMIMEType, vaType, vaData); 186 162 if (RT_SUCCESS(rc)) 163 { 164 LogRel3(("DnD: Returning data for MIME type=%s, variant type=%s, rc=%Rrc\n", 165 strMIMEType.toStdString().c_str(), QVariant::typeToName(vaData.type()), rc)); 166 187 167 return vaData; 188 } 189 190 #ifdef RT_OS_DARWIN 191 LogFlowFunc(("Returning data for Cocoa\n")); 168 } 169 } 170 else if (rc == VERR_NOT_FOUND) /* Silently skip internal entries. */ 171 rc = VINF_SUCCESS; 172 173 if (RT_FAILURE(rc)) 174 LogRel(("DnD: Retrieving data failed with %Rrc\n", rc)); 175 192 176 return QMimeData::retrieveData(strMIMEType, vaType); 193 #else 194 LogFlowFunc(("Skipping request, state=%RU32 ...\n", m_enmState)); 195 return QVariant(QVariant::Invalid); /* Return a NULL variant. */ 196 #endif 197 } 198 199 int UIDnDMIMEData::setData(const QString &strMIMEType, const QVariant &vaData) 200 { 201 LogFlowFunc(("mimeType=%s, dataType=%s\n", 202 strMIMEType.toAscii().constData(), vaData.typeName())); 177 } 178 179 /* static */ 180 QVariant::Type UIDnDMIMEData::getVariantType(const QString &strMIMEType) 181 { 182 QVariant::Type vaType; 183 184 if ( !strMIMEType.compare("text/html") 185 || !strMIMEType.compare("text/plain;charset=utf-8") 186 || !strMIMEType.compare("text/plain;charset=utf-16") 187 || !strMIMEType.compare("text/plain") 188 || !strMIMEType.compare("text/richtext") 189 || !strMIMEType.compare("UTF8_STRING") 190 || !strMIMEType.compare("TEXT") 191 || !strMIMEType.compare("STRING")) 192 { 193 vaType = QVariant::String; 194 } 195 else if (!strMIMEType.compare("text/uri-list", Qt::CaseInsensitive)) 196 vaType = QVariant::List; 197 else 198 vaType = QVariant::Invalid; 199 200 LogFlowFunc(("strMIMEType=%s -> vaType=%s\n", qPrintable(strMIMEType), QVariant::typeToName(vaType))); 201 return vaType; 202 } 203 204 /* static */ 205 int UIDnDMIMEData::getDataAsVariant(const QVector<uint8_t> &vecData, 206 const QString &strMIMEType, 207 QVariant::Type vaType, 208 QVariant &vaData) 209 { 210 LogFlowFunc(("vecDataSize=%d, strMIMEType=%s vaType=%s\n", 211 vecData.size(), qPrintable(strMIMEType), QVariant::typeToName(vaType))); 203 212 204 213 int rc = VINF_SUCCESS; 205 214 206 switch (m_vaData.type()) 207 { 208 case QVariant::String: /* Plain text. */ 209 { 210 QMimeData::setText(vaData.toString()); 211 break; 212 } 213 214 case QVariant::ByteArray: /* Raw byte data. */ 215 { 216 QMimeData::setData(strMIMEType, vaData.toByteArray()); 217 break; 218 } 219 220 case QVariant::StringList: /* URI. */ 221 { 222 QList<QVariant> lstData = vaData.toList(); 223 QList<QUrl> lstURL; 224 for (int i = 0; i < lstData.size(); i++) 215 switch (vaType) 216 { 217 case QVariant::String: 218 { 219 vaData = QVariant::fromValue(QString(reinterpret_cast<const char *>(vecData.constData()))); 220 Assert(vaData.type() == QVariant::String); 221 break; 222 } 223 224 case QVariant::ByteArray: 225 { 226 QByteArray ba(reinterpret_cast<const char*>(vecData.constData()), vecData.size()); 227 228 vaData = QVariant::fromValue(ba); 229 Assert(vaData.type() == QVariant::ByteArray); 230 break; 231 } 232 233 /* See: https://developer.apple.com/library/ios/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html */ 234 case QVariant::List: /* Used on OS X for representing URI lists. */ 235 { 236 QString strData = QString(reinterpret_cast<const char*>(vecData.constData())); 237 QStringList lstString = strData.split("\r\n", QString::SkipEmptyParts); 238 239 QVariantList lstVariant; 240 241 Q_FOREACH(const QString& strCur, lstString) 225 242 { 226 QFileInfo fileInfo(lstData.at(i).toString()); 227 228 LogFlowFunc(("\tURL: %s (fExists=%RTbool, fIsDir=%RTbool, cb=%RU64)\n", 229 fileInfo.absoluteFilePath().constData(), fileInfo.exists(), 230 fileInfo.isDir(), fileInfo.size())); 231 232 lstURL << QUrl::fromLocalFile(fileInfo.absoluteFilePath()); 243 QVariant vaURL = QVariant::fromValue(QUrl(strCur)); 244 Assert(vaURL.type() == QVariant::Url); 245 lstVariant.append(vaURL); 233 246 } 234 LogFlowFunc(("Number of URLs: %d\n", lstURL.size())); 235 236 if (RT_SUCCESS(rc)) 237 QMimeData::setUrls(lstURL); 247 248 vaData = QVariant::fromValue(lstVariant); 249 Assert(vaData.type() == QVariant::List); 250 break; 251 } 252 253 case QVariant::StringList: 254 { 255 QString strData = QString(reinterpret_cast<const char*>(vecData.constData())); 256 QStringList lstString = strData.split("\r\n", QString::SkipEmptyParts); 257 258 LogFlowFunc(("\tStringList has %d entries\n", lstString.size())); 259 # ifdef DEBUG 260 Q_FOREACH(const QString& strCur, lstString) 261 LogFlowFunc(("\t\tString: %s\n", qPrintable(strCur))); 262 # endif 263 vaData = QVariant::fromValue(lstString); 264 Assert(vaData.type() == QVariant::StringList); 238 265 break; 239 266 } 240 267 241 268 default: 269 { 270 LogRel2(("DnD: Converting data (%d bytes) from guest to variant type '%s' not supported\n", 271 vecData.size(), QVariant::typeToName(vaType) ? QVariant::typeToName(vaType) : "<Invalid>")); 272 242 273 rc = VERR_NOT_SUPPORTED; 243 274 break; 275 } 244 276 } 245 277 … … 258 290 m_curAction = dropAction; 259 291 } 292 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.h
r56865 r57221 65 65 signals: 66 66 67 int getData(const QString &strMIMEType, QVariant::Type vaType, QVariant &vaData) const; 67 /** 68 * Signal which gets emitted if this object is ready to retrieve data 69 * in the specified MIME type. 70 * 71 * @returns IPRT status code. 72 * @param strMIMEType MIME type to retrieve data for. 73 */ 74 int getData(const QString &strMIMEType) const; 68 75 69 76 #ifdef RT_OS_DARWIN 70 77 void notifyDropped(void) const; 71 78 #endif 72 79 … … 74 81 75 82 /** 76 * Slot indicating that the current drop target has been changed. 77 * @note Does not work on OS X. 83 * Slot indicating that the current drop target has been changed. 84 * @note Does not work on OS X. 78 85 */ 79 86 void sltDropActionChanged(Qt::DropAction dropAction); 80 81 #ifdef RT_OS_DARWIN82 /**83 * Slot indicating that the host wants us to drop the84 * data from the guest to the host.85 */86 void sltDropped(void);87 #endif88 87 89 88 protected: … … 97 96 /** @} */ 98 97 99 p rotected:98 public: 100 99 101 100 /** @name Internal helper functions. … … 103 102 104 103 /** 105 * Sets the object's MIME data according to the given 106 * MIME type and data. 104 * Returns the matching variant type of a given MIME type. 105 * 106 * @returns Variant type. 107 * @param strMIMEType MIME type to retrieve variant type for. 108 */ 109 static QVariant::Type getVariantType(const QString &strMIMEType); 110 111 /** 112 * Fills a QVariant with data according to the given type and data. 107 113 * 108 114 * @returns IPRT status code. 109 * @param strMIMEType MIME type to set. 110 * @param vaData Data to set. 111 * @remark 115 * @param vecData Bytes data to set. 116 * @param strMIMEType MIME type to handle. 117 * @param vaType Variant type to set the variant to. 118 * @param vaData Variant holding the transformed result. 119 * Note: The variant's type might be different from the input vaType! 112 120 */ 113 int setData(const QString &strMIMEType, constQVariant &vaData);121 static int getDataAsVariant(const QVector<uint8_t> &vecData, const QString &strMIMEType, QVariant::Type vaType, QVariant &vaData); 114 122 /** @} */ 115 123 116 124 protected: 117 125 126 /** Pointer to the parent. */ 118 127 UIDnDHandler *m_pDnDHandler; 119 128 /** Available formats. */ 120 129 QStringList m_lstFormats; 121 130 /** Default action on successful drop operation. */ … … 123 132 /** Current action, based on QDrag's status. */ 124 133 Qt::DropAction m_curAction; 134 /** Available actions. */ 125 135 Qt::DropActions m_actions; 126 136 /** The current dragging state. */ 127 137 mutable State m_enmState; 128 mutable QVariant m_vaData;129 130 #ifdef RT_OS_DARWIN131 /** Flag indicating whether we can drop data from the132 * guest to the host or not. */133 bool m_fCanDrop;134 #endif135 138 }; 136 139
Note:
See TracChangeset
for help on using the changeset viewer.