VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.cpp@ 82781

Last change on this file since 82781 was 76606, checked in by vboxsync, 5 years ago

FE/Qt: Cleaning out old precompiled header experiment.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.6 KB
Line 
1/* $Id: UIDnDMIMEData.cpp 76606 2019-01-02 05:40:39Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIDnDMIMEData class implementation.
4 */
5
6/*
7 * Copyright (C) 2011-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#define LOG_GROUP LOG_GROUP_GUEST_DND
19
20/* Qt includes: */
21#include <QFileInfo>
22#include <QMimeData>
23#include <QStringList>
24#include <QUrl>
25
26/* GUI includes: */
27#include "UIDnDMIMEData.h"
28
29/* Other VBox includes: */
30#include <VBox/log.h>
31#include <iprt/errcore.h>
32
33
34UIDnDMIMEData::UIDnDMIMEData(UIDnDHandler *pDnDHandler,
35 QStringList lstFormats, Qt::DropAction defAction, Qt::DropActions actions)
36 : m_pDnDHandler(pDnDHandler)
37 , m_lstFormats(lstFormats)
38 , m_defAction(defAction)
39 , m_curAction(Qt::IgnoreAction)
40 , m_actions(actions)
41 , m_enmState(Dragging)
42{
43 LogFlowThisFuncEnter();
44#ifdef DEBUG
45 LogFlowFunc(("Number of formats: %d\n", m_lstFormats.size()));
46 for (int i = 0; i < m_lstFormats.size(); i++)
47 LogFlowFunc(("\tFormat %d: %s\n", i, m_lstFormats.at(i).toUtf8().constData()));
48#endif
49}
50
51QStringList UIDnDMIMEData::formats(void) const
52{
53 LogFlowFuncEnter();
54#ifdef DEBUG
55 for (int i = 0; i < m_lstFormats.size(); i++)
56 LogFlowFunc(("\tFormat %d: %s\n", i, m_lstFormats.at(i).toUtf8().constData()));
57#endif
58 return m_lstFormats;
59}
60
61bool UIDnDMIMEData::hasFormat(const QString &strMIMEType) const
62{
63 RT_NOREF(strMIMEType);
64
65 bool fRc;
66#ifdef RT_OS_DARWIN
67 fRc = m_lstFormats.contains(strMIMEType);
68#else
69 fRc = m_curAction != Qt::IgnoreAction;
70#endif
71
72 LogFlowFunc(("%s: %RTbool (QtMimeData: %RTbool, curAction=0x%x)\n",
73 strMIMEType.toStdString().c_str(), fRc, QMimeData::hasFormat(strMIMEType), m_curAction));
74
75 return fRc;
76}
77
78/**
79 * Called by Qt's drag'n drop operation (QDrag) for retrieving the actual drag'n drop
80 * data in case of a successful drag'n drop operation.
81 *
82 * @param strMIMEType MIME type string.
83 * @param vaType Variant containing the actual data based on the MIME type.
84 *
85 * @return QVariant
86 */
87QVariant UIDnDMIMEData::retrieveData(const QString &strMIMEType, QVariant::Type vaType) const
88{
89 LogFlowFunc(("state=%RU32, curAction=0x%x, defAction=0x%x, mimeType=%s, type=%d (%s)\n",
90 m_enmState, m_curAction, m_defAction, strMIMEType.toStdString().c_str(), vaType, QVariant::typeToName(vaType)));
91
92 int rc = VINF_SUCCESS;
93
94#ifdef RT_OS_WINDOWS
95 /*
96 * On Windows this function will be called several times by Qt's
97 * OLE-specific internals to figure out which data formats we have
98 * to offer. So just assume we can drop data here for a start.
99 */
100#elif defined(RT_OS_DARWIN)
101# ifndef VBOX_WITH_DRAG_AND_DROP_PROMISES
102 /*
103 * Without VBOX_WITH_DRAG_AND_DROP_PROMISES being set in VBox *and* in our (patched) Qt
104 * libraries there's no reliable way to get this working on OS X. So just deny any dropping.
105 */
106 rc = VERR_NOT_IMPLEMENTED;
107
108 /* Let the user know. */
109 LogRel(("DnD: Drag and drop support for OS X is not available in this version\n"));
110# endif /* VBOX_WITH_DRAG_AND_DROP_PROMISES */
111#else /* !RT_OS_DARWIN */
112 /*
113 * On Linux/Solaris our state gets updated if the drop target has been
114 * changed. So query the current status if we're at the moment are able
115 * to drop something on the current target.
116 */
117 if (m_curAction == Qt::IgnoreAction)
118 {
119 LogFlowFunc(("Current drop action is 0x%x, so can't drop yet\n", m_curAction));
120 rc = VERR_NOT_FOUND;
121 }
122#endif
123
124 if (RT_SUCCESS(rc))
125 {
126 /* Silently ignore internal Qt types / converters. */
127 if (!strMIMEType.compare("application/x-qt-mime-type-name", Qt::CaseInsensitive))
128 {
129 rc = VERR_NOT_FOUND;
130 }
131 /* Do we support the requested MIME type? */
132 else if (!m_lstFormats.contains(strMIMEType))
133 {
134 LogRel(("DnD: Unsupported MIME type '%s'\n", strMIMEType.toStdString().c_str()));
135 rc = VERR_NOT_SUPPORTED;
136 }
137#ifndef RT_OS_DARWIN /* On OS X QVariant::Invalid can happen for drag and drop "promises" for "lazy requests". */
138 /* Check supported variant types. */
139 else if (!(
140 /* Plain text. */
141 vaType == QVariant::String
142 /* Binary data. */
143 || vaType == QVariant::ByteArray
144 /* URI list. */
145 || vaType == QVariant::List
146 || vaType == QVariant::StringList))
147 {
148 LogRel(("DnD: Unsupported data type '%s'\n", QVariant::typeToName(vaType)));
149 rc = VERR_NOT_SUPPORTED;
150 }
151#endif
152 }
153
154 LogRel3(("DnD: Retrieved data state is %ld (action=0x%x), rc=%Rrc\n", m_enmState, m_curAction, rc));
155
156 if (RT_SUCCESS(rc))
157 {
158 QVariant vaData;
159 rc = emit sigGetData(Qt::CopyAction, strMIMEType, vaType, vaData);
160 if (RT_SUCCESS(rc))
161 {
162 LogRel3(("DnD: Returning data for MIME type=%s, variant type=%s, rc=%Rrc\n",
163 strMIMEType.toStdString().c_str(), QVariant::typeToName(vaData.type()), rc));
164
165 return vaData;
166 }
167 }
168 else if (rc == VERR_NOT_FOUND) /* Silently skip internal entries. */
169 rc = VINF_SUCCESS;
170
171 if (RT_FAILURE(rc))
172 LogRel2(("DnD: Retrieving data failed with %Rrc\n", rc));
173
174 return QVariant(QVariant::Invalid);
175}
176
177/* static */
178QVariant::Type UIDnDMIMEData::getVariantType(const QString &strMIMEType)
179{
180 QVariant::Type vaType;
181
182 if ( !strMIMEType.compare("text/html")
183 || !strMIMEType.compare("text/plain;charset=utf-8")
184 || !strMIMEType.compare("text/plain;charset=utf-16")
185 || !strMIMEType.compare("text/plain")
186 || !strMIMEType.compare("text/richtext")
187 || !strMIMEType.compare("UTF8_STRING")
188 || !strMIMEType.compare("TEXT")
189 || !strMIMEType.compare("STRING"))
190 {
191 vaType = QVariant::String;
192 }
193 else if (!strMIMEType.compare("text/uri-list", Qt::CaseInsensitive))
194 vaType = QVariant::List;
195 else
196 vaType = QVariant::Invalid;
197
198 LogFlowFunc(("strMIMEType=%s -> vaType=%s\n", qPrintable(strMIMEType), QVariant::typeToName(vaType)));
199 return vaType;
200}
201
202/* static */
203int UIDnDMIMEData::getDataAsVariant(const QVector<uint8_t> &vecData,
204 const QString &strMIMEType,
205 QVariant::Type vaType,
206 QVariant &vaData)
207{
208 RT_NOREF(strMIMEType);
209 LogFlowFunc(("vecDataSize=%d, strMIMEType=%s vaType=%s\n",
210 vecData.size(), qPrintable(strMIMEType), QVariant::typeToName(vaType)));
211
212 int rc = VINF_SUCCESS;
213
214 switch (vaType)
215 {
216 case QVariant::String:
217 {
218 vaData = QVariant::fromValue(QString(reinterpret_cast<const char *>(vecData.constData())));
219 Assert(vaData.type() == QVariant::String);
220 break;
221 }
222
223 case QVariant::ByteArray:
224 {
225 QByteArray ba(reinterpret_cast<const char*>(vecData.constData()), vecData.size());
226
227 vaData = QVariant::fromValue(ba);
228 Assert(vaData.type() == QVariant::ByteArray);
229 break;
230 }
231
232 /* See: https://developer.apple.com/library/ios/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html */
233 case QVariant::List: /* Used on OS X for representing URI lists. */
234 {
235 QString strData = QString(reinterpret_cast<const char*>(vecData.constData()));
236 QStringList lstString = strData.split("\r\n", QString::SkipEmptyParts);
237
238 QVariantList lstVariant;
239
240 Q_FOREACH(const QString& strCur, lstString)
241 {
242 QVariant vaURL = QVariant::fromValue(QUrl(strCur));
243 Assert(vaURL.type() == QVariant::Url);
244 lstVariant.append(vaURL);
245 }
246
247 vaData = QVariant::fromValue(lstVariant);
248 Assert(vaData.type() == QVariant::List);
249 break;
250 }
251
252 case QVariant::StringList:
253 {
254 QString strData = QString(reinterpret_cast<const char*>(vecData.constData()));
255 QStringList lstString = strData.split("\r\n", QString::SkipEmptyParts);
256
257 LogFlowFunc(("\tStringList has %d entries\n", lstString.size()));
258# ifdef DEBUG
259 Q_FOREACH(const QString& strCur, lstString)
260 LogFlowFunc(("\t\tString: %s\n", qPrintable(strCur)));
261# endif
262 vaData = QVariant::fromValue(lstString);
263 Assert(vaData.type() == QVariant::StringList);
264 break;
265 }
266
267 default:
268 {
269 LogRel2(("DnD: Converting data (%d bytes) from guest to variant type '%s' not supported\n",
270 vecData.size(), QVariant::typeToName(vaType) ? QVariant::typeToName(vaType) : "<Invalid>"));
271
272 rc = VERR_NOT_SUPPORTED;
273 break;
274 }
275 }
276
277 LogFlowFuncLeaveRC(rc);
278 return rc;
279}
280
281/**
282 * Issued by the QDrag object as soon as the current drop action has changed.
283 *
284 * @param dropAction New drop action to use.
285 */
286void UIDnDMIMEData::sltDropActionChanged(Qt::DropAction dropAction)
287{
288 LogFlowFunc(("dropAction=0x%x\n", dropAction));
289 m_curAction = dropAction;
290}
291
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use