QtBase  v6.3.1
qmimedata.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qmimedata.h"
41 
42 #include "private/qobject_p.h"
43 #include "qurl.h"
44 #include "qstringlist.h"
45 #include "qstringconverter.h"
46 
48 
49 static inline QString textUriListLiteral() { return QStringLiteral("text/uri-list"); }
50 static inline QString textHtmlLiteral() { return QStringLiteral("text/html"); }
51 static inline QString textPlainLiteral() { return QStringLiteral("text/plain"); }
52 static inline QString textPlainUtf8Literal() { return QStringLiteral("text/plain;charset=utf-8"); }
53 static inline QString applicationXColorLiteral() { return QStringLiteral("application/x-color"); }
54 static inline QString applicationXQtImageLiteral() { return QStringLiteral("application/x-qt-image"); }
55 
57 {
60 };
62 
64 {
65  Q_DECLARE_PUBLIC(QMimeData)
66 public:
67  void removeData(const QString &format);
68  void setData(const QString &format, const QVariant &data);
69  QVariant getData(const QString &format) const;
70 
72 
74  const auto formatEquals = [](const QString &format) {
75  return [&format](const QMimeDataStruct &s) { return s.format == format; };
76  };
77  return std::find_if(dataList.begin(), dataList.end(), formatEquals(format));
78  }
79 
81  return const_cast<QMimeDataPrivate*>(this)->find(format);
82  }
83 
84  std::vector<QMimeDataStruct> dataList;
85 };
86 
88 {
89  const auto it = find(format);
90  if (it != dataList.end())
91  dataList.erase(it);
92 }
93 
95 {
96  const auto it = find(format);
97  if (it == dataList.end())
98  dataList.push_back({format, data});
99  else
100  it->data = data;
101 }
102 
103 
105 {
106  const auto it = find(format);
107  if (it == dataList.cend())
108  return {};
109  else
110  return it->data;
111 }
112 
114 {
115  Q_Q(const QMimeData);
116  int typeId = type.id();
117 
118  QVariant data = q->retrieveData(format, type);
119 
120  // Text data requested: fallback to URL data if available
121  if (format == QLatin1String("text/plain") && !data.isValid()) {
122  data = retrieveTypedData(textUriListLiteral(), QMetaType(QMetaType::QVariantList));
123  if (data.metaType().id() == QMetaType::QUrl) {
124  data = QVariant(data.toUrl().toDisplayString());
125  } else if (data.metaType().id() == QMetaType::QVariantList) {
126  QString text;
127  int numUrls = 0;
128  const QList<QVariant> list = data.toList();
129  for (int i = 0; i < list.size(); ++i) {
130  if (list.at(i).metaType().id() == QMetaType::QUrl) {
131  text += list.at(i).toUrl().toDisplayString() + QLatin1Char('\n');
132  ++numUrls;
133  }
134  }
135  if (numUrls == 1)
136  text.chop(1); // no final '\n' if there's only one URL
137  data = QVariant(text);
138  }
139  }
140 
141  if (data.metaType() == type || !data.isValid())
142  return data;
143 
144  // provide more conversion possibilities than just what QVariant provides
145 
146  // URLs can be lists as well...
147  if ((typeId == QMetaType::QUrl && data.metaType().id() == QMetaType::QVariantList)
148  || (typeId == QMetaType::QVariantList && data.metaType().id() == QMetaType::QUrl))
149  return data;
150 
151  // images and pixmaps are interchangeable
152  if ((typeId == QMetaType::QPixmap && data.metaType().id() == QMetaType::QImage)
153  || (typeId == QMetaType::QImage && data.metaType().id() == QMetaType::QPixmap))
154  return data;
155 
156  if (data.metaType().id() == QMetaType::QByteArray) {
157  // see if we can convert to the requested type
158  switch (typeId) {
159  case QMetaType::QString: {
160  const QByteArray ba = data.toByteArray();
161  if (ba.isNull())
162  return QVariant();
163  if (format == QLatin1String("text/html")) {
164  auto encoding = QStringConverter::encodingForHtml(ba);
165  if (encoding) {
166  QStringDecoder toUtf16(*encoding);
167  return QString(toUtf16(ba));
168  }
169  // fall back to utf8
170  }
171  return QString::fromUtf8(ba);
172  }
173  case QMetaType::QColor: {
174  QVariant newData = data;
176  newData.convert(QMetaType::QColor);
178  return newData;
179  }
181  if (format != QLatin1String("text/uri-list"))
182  break;
183  Q_FALLTHROUGH();
184  }
185  case QMetaType::QUrl: {
186  QByteArray ba = data.toByteArray();
187  // Qt 3.x will send text/uri-list with a trailing
188  // null-terminator (that is *not* sent for any other
189  // text/* mime-type), so chop it off
190  if (ba.endsWith('\0'))
191  ba.chop(1);
192 
193  QList<QByteArray> urls = ba.split('\n');
195  for (int i = 0; i < urls.size(); ++i) {
196  QByteArray ba = urls.at(i).trimmed();
197  if (!ba.isEmpty())
198  list.append(QUrl::fromEncoded(ba));
199  }
200  return list;
201  }
202  default:
203  break;
204  }
205 
206  } else if (typeId == QMetaType::QByteArray) {
207 
208  // try to convert to bytearray
209  switch (data.metaType().id()) {
211  case QMetaType::QColor:
212  return data.toByteArray();
213  case QMetaType::QString:
214  return data.toString().toUtf8();
215  case QMetaType::QUrl:
216  return data.toUrl().toEncoded();
218  // has to be list of URLs
220  QList<QVariant> list = data.toList();
221  for (int i = 0; i < list.size(); ++i) {
222  if (list.at(i).metaType().id() == QMetaType::QUrl) {
223  result += list.at(i).toUrl().toEncoded();
224  result += "\r\n";
225  }
226  }
227  if (!result.isEmpty())
228  return result;
229  break;
230  }
231  default:
232  break;
233  }
234  }
235  return data;
236 }
237 
333 {
334 }
335 
340 {
341 }
342 
351 {
352  Q_D(const QMimeData);
353  QVariant data = d->retrieveTypedData(textUriListLiteral(), QMetaType(QMetaType::QVariantList));
355  if (data.metaType().id() == QMetaType::QUrl)
356  urls.append(data.toUrl());
357  else if (data.metaType().id() == QMetaType::QVariantList) {
358  QList<QVariant> list = data.toList();
359  for (int i = 0; i < list.size(); ++i) {
360  if (list.at(i).metaType().id() == QMetaType::QUrl)
361  urls.append(list.at(i).toUrl());
362  }
363  }
364  return urls;
365 }
366 
379 {
380  Q_D(QMimeData);
382  const int numUrls = urls.size();
383  list.reserve(numUrls);
384  for (int i = 0; i < numUrls; ++i)
385  list.append(urls.at(i));
386 
387  d->setData(textUriListLiteral(), list);
388 }
389 
398 bool QMimeData::hasUrls() const
399 {
400  return hasFormat(textUriListLiteral());
401 }
402 
403 
411 {
412  Q_D(const QMimeData);
413  QVariant utf8Text = d->retrieveTypedData(textPlainUtf8Literal(), QMetaType(QMetaType::QString));
414  if (!utf8Text.isNull())
415  return utf8Text.toString();
416 
417  QVariant data = d->retrieveTypedData(textPlainLiteral(), QMetaType(QMetaType::QString));
418  return data.toString();
419 }
420 
428 {
429  Q_D(QMimeData);
430  d->setData(textPlainLiteral(), text);
431 }
432 
439 bool QMimeData::hasText() const
440 {
441  return hasFormat(textPlainLiteral()) || hasUrls();
442 }
443 
451 {
452  Q_D(const QMimeData);
453  QVariant data = d->retrieveTypedData(textHtmlLiteral(), QMetaType(QMetaType::QString));
454  return data.toString();
455 }
456 
464 {
465  Q_D(QMimeData);
466  d->setData(textHtmlLiteral(), html);
467 }
468 
475 bool QMimeData::hasHtml() const
476 {
477  return hasFormat(textHtmlLiteral());
478 }
479 
493 {
494  Q_D(const QMimeData);
495  return d->retrieveTypedData(applicationXQtImageLiteral(), QMetaType(QMetaType::QImage));
496 }
497 
510 {
511  Q_D(QMimeData);
512  d->setData(applicationXQtImageLiteral(), image);
513 }
514 
522 {
523  return hasFormat(applicationXQtImageLiteral());
524 }
525 
540 {
541  Q_D(const QMimeData);
542  return d->retrieveTypedData(applicationXColorLiteral(), QMetaType(QMetaType::QColor));
543 }
544 
553 {
554  Q_D(QMimeData);
555  d->setData(applicationXColorLiteral(), color);
556 }
557 
558 
566 {
567  return hasFormat(applicationXColorLiteral());
568 }
569 
574 QByteArray QMimeData::data(const QString &mimeType) const
575 {
576  Q_D(const QMimeData);
577  QVariant data = d->retrieveTypedData(mimeType, QMetaType(QMetaType::QByteArray));
578  return data.toByteArray();
579 }
580 
595 void QMimeData::setData(const QString &mimeType, const QByteArray &data)
596 {
597  Q_D(QMimeData);
598 
599  if (mimeType == QLatin1String("text/uri-list")) {
600  QByteArray ba = data;
601  if (ba.endsWith('\0'))
602  ba.chop(1);
603  QList<QByteArray> urls = ba.split('\n');
605  for (int i = 0; i < urls.size(); ++i) {
606  QByteArray ba = urls.at(i).trimmed();
607  if (!ba.isEmpty())
608  list.append(QUrl::fromEncoded(ba));
609  }
610  d->setData(mimeType, list);
611  } else {
612  d->setData(mimeType, QVariant(data));
613  }
614 }
615 
626 bool QMimeData::hasFormat(const QString &mimeType) const
627 {
628  return formats().contains(mimeType);
629 }
630 
643 {
644  Q_D(const QMimeData);
646  list.reserve(static_cast<int>(d->dataList.size()));
647  for (auto &e : d->dataList)
648  list += e.format;
649  return list;
650 }
651 
668 {
669  Q_UNUSED(type);
670  Q_D(const QMimeData);
671  return d->getData(mimeType);
672 }
673 
678 {
679  Q_D(QMimeData);
680  d->dataList.clear();
681 }
682 
688 void QMimeData::removeFormat(const QString &mimeType)
689 {
690  Q_D(QMimeData);
691  d->removeData(mimeType);
692 }
693 
695 
696 #include "moc_qmimedata.cpp"
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
QByteArray trimmed() const &
Definition: qbytearray.h:220
bool endsWith(char c) const
Definition: qbytearray.h:196
QList< QByteArray > split(char sep) const
void chop(qsizetype n)
bool isEmpty() const noexcept
Definition: qbytearray.h:129
bool isNull() const noexcept
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal.
Definition: qstring.h:84
qsizetype size() const noexcept
Definition: qlist.h:414
const_reference at(qsizetype i) const noexcept
Definition: qlist.h:457
void append(parameter_type t)
Definition: qlist.h:469
The QMetaType class manages named types in the meta-object system.
Definition: qmetatype.h:328
The QMimeData class provides a container for data that records information about its MIME type.
Definition: qmimedata.h:52
bool hasUrls() const
Definition: qmimedata.cpp:398
void setHtml(const QString &html)
Definition: qmimedata.cpp:463
QVariant colorData() const
Definition: qmimedata.cpp:539
void setData(const QString &mimetype, const QByteArray &data)
Definition: qmimedata.cpp:595
QVariant imageData() const
Definition: qmimedata.cpp:492
bool hasHtml() const
Definition: qmimedata.cpp:475
bool hasImage() const
Definition: qmimedata.cpp:521
bool hasText() const
Definition: qmimedata.cpp:439
void setText(const QString &text)
Definition: qmimedata.cpp:427
void setImageData(const QVariant &image)
Definition: qmimedata.cpp:509
virtual bool hasFormat(const QString &mimetype) const
Definition: qmimedata.cpp:626
void setColorData(const QVariant &color)
Definition: qmimedata.cpp:552
virtual QVariant retrieveData(const QString &mimetype, QMetaType preferredType) const
Definition: qmimedata.cpp:667
QString html() const
Definition: qmimedata.cpp:450
QList< QUrl > urls() const
Definition: qmimedata.cpp:350
bool hasColor() const
Definition: qmimedata.cpp:565
QByteArray data(const QString &mimetype) const
Definition: qmimedata.cpp:574
void clear()
Definition: qmimedata.cpp:677
virtual QStringList formats() const
Definition: qmimedata.cpp:642
void setUrls(const QList< QUrl > &urls)
Definition: qmimedata.cpp:378
void removeFormat(const QString &mimetype)
Definition: qmimedata.cpp:688
QString text() const
Definition: qmimedata.cpp:410
std::vector< QMimeDataStruct >::iterator find(const QString &format) noexcept
Definition: qmimedata.cpp:73
std::vector< QMimeDataStruct > dataList
Definition: qmimedata.cpp:84
QVariant getData(const QString &format) const
Definition: qmimedata.cpp:104
std::vector< QMimeDataStruct >::const_iterator find(const QString &format) const noexcept
Definition: qmimedata.cpp:80
QVariant retrieveTypedData(const QString &format, QMetaType type) const
Definition: qmimedata.cpp:113
void setData(const QString &format, const QVariant &data)
Definition: qmimedata.cpp:94
void removeData(const QString &format)
Definition: qmimedata.cpp:87
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
static Q_CORE_EXPORT std::optional< Encoding > encodingForHtml(QByteArrayView data)
The QStringDecoder class provides a state-based decoder for text. \reentrant.
The QString class provides a Unicode character string.
Definition: qstring.h:388
static QString fromUtf8(QByteArrayView utf8)
Definition: qstring.cpp:5632
The QStringList class provides a list of strings.
static QUrl fromEncoded(const QByteArray &url, ParsingMode mode=TolerantMode)
Definition: qurl.cpp:3004
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:95
bool convert(QMetaType type)
Definition: qvariant.cpp:2049
QString toString() const
Definition: qvariant.cpp:1416
bool isNull() const
Definition: qvariant.cpp:2483
QString text
[meta data]
double e
typename C::const_iterator const_iterator
typename C::iterator iterator
Definition: image.cpp:51
#define QString()
Definition: parse-defines.h:51
#define Q_FALLTHROUGH()
#define QT_WARNING_POP
#define QT_WARNING_DISABLE_DEPRECATED
#define QT_WARNING_PUSH
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
@ text
QList< QVariant > QVariantList
Definition: qjsonarray.h:50
Q_DECLARE_TYPEINFO(QMimeDataStruct, Q_RELOCATABLE_TYPE)
GLenum type
Definition: qopengl.h:270
GLuint color
[2]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLsizei GLsizei GLenum format
GLdouble GLdouble GLdouble GLdouble q
Definition: qopenglext.h:259
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
GLdouble s
[6]
Definition: qopenglext.h:235
#define QStringLiteral(str)
@ Q_RELOCATABLE_TYPE
Definition: qtypeinfo.h:156
Q_UNUSED(salary)
[21]
QByteArray ba
[0]
QObject::connect nullptr
content text html
QStringList::Iterator it
QStringList list
[0]
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:53
QString format
Definition: qmimedata.cpp:58
QVariant data
Definition: qmimedata.cpp:59