/src/qtbase/src/gui/kernel/qclipboard.cpp
Line | Count | Source |
1 | | // Copyright (C) 2016 The Qt Company Ltd. |
2 | | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | | // Qt-Security score:significant reason:default |
4 | | |
5 | | #include "qclipboard.h" |
6 | | |
7 | | #ifndef QT_NO_CLIPBOARD |
8 | | |
9 | | #include "qmimedata.h" |
10 | | #include "qpixmap.h" |
11 | | #include "qvariant.h" |
12 | | #include "qbuffer.h" |
13 | | #include "qimage.h" |
14 | | #include "private/qstringconverter_p.h" |
15 | | |
16 | | #include "private/qguiapplication_p.h" |
17 | | #include <qpa/qplatformintegration.h> |
18 | | #include <qpa/qplatformclipboard.h> |
19 | | |
20 | | QT_BEGIN_NAMESPACE |
21 | | |
22 | | using namespace Qt::StringLiterals; |
23 | | |
24 | | /*! |
25 | | \class QClipboard |
26 | | \brief The QClipboard class provides access to the window system clipboard. |
27 | | \inmodule QtGui |
28 | | |
29 | | The clipboard offers a simple mechanism to copy and paste data |
30 | | between applications. |
31 | | |
32 | | QClipboard supports the same data types that QDrag does, and uses |
33 | | similar mechanisms. For advanced clipboard usage read \l{Drag and |
34 | | Drop}. |
35 | | |
36 | | There is a single QClipboard object in an application, accessible |
37 | | as QGuiApplication::clipboard(). |
38 | | |
39 | | Example: |
40 | | \snippet code/src_gui_kernel_qclipboard.cpp 0 |
41 | | |
42 | | QClipboard features some convenience functions to access common |
43 | | data types: setText() allows the exchange of Unicode text and |
44 | | setPixmap() and setImage() allows the exchange of QPixmaps and |
45 | | QImages between applications. The setMimeData() function is the |
46 | | ultimate in flexibility: it allows you to add any QMimeData into |
47 | | the clipboard. There are corresponding getters for each of these, |
48 | | e.g. text(), image() and pixmap(). You can clear the clipboard by |
49 | | calling clear(). |
50 | | |
51 | | A typical example of the use of these functions follows: |
52 | | |
53 | | \snippet droparea/droparea.cpp 0 |
54 | | |
55 | | \section1 Notes for X11 Users |
56 | | |
57 | | \list |
58 | | |
59 | | \li The X11 Window System has the concept of a separate selection |
60 | | and clipboard. When text is selected, it is immediately available |
61 | | as the global mouse selection. The global mouse selection may |
62 | | later be copied to the clipboard. By convention, the middle mouse |
63 | | button is used to paste the global mouse selection. |
64 | | |
65 | | \li X11 also has the concept of ownership; if you change the |
66 | | selection within a window, X11 will only notify the owner and the |
67 | | previous owner of the change, i.e. it will not notify all |
68 | | applications that the selection or clipboard data changed. |
69 | | |
70 | | \li Lastly, the X11 clipboard is event driven, i.e. the clipboard |
71 | | will not function properly if the event loop is not running. |
72 | | Similarly, it is recommended that the contents of the clipboard |
73 | | are stored or retrieved in direct response to user-input events, |
74 | | e.g. mouse button or key presses and releases. You should not |
75 | | store or retrieve the clipboard contents in response to timer or |
76 | | non-user-input events. |
77 | | |
78 | | \li Since there is no standard way to copy and paste files between |
79 | | applications on X11, various MIME types and conventions are currently |
80 | | in use. For instance, Nautilus expects files to be supplied with a |
81 | | \c{x-special/gnome-copied-files} MIME type with data beginning with |
82 | | the cut/copy action, a newline character, and the URL of the file. |
83 | | |
84 | | \endlist |
85 | | |
86 | | \section1 Notes for \macos Users |
87 | | |
88 | | \macos supports a separate find buffer that holds the current |
89 | | search string in Find operations. This find clipboard can be accessed |
90 | | by specifying the FindBuffer mode. |
91 | | |
92 | | \section1 Notes for Windows and \macos Users |
93 | | |
94 | | \list |
95 | | |
96 | | \li Windows and \macos do not support the global mouse |
97 | | selection; they only supports the global clipboard, i.e. they |
98 | | only add text to the clipboard when an explicit copy or cut is |
99 | | made. |
100 | | |
101 | | \li Windows and \macos does not have the concept of ownership; |
102 | | the clipboard is a fully global resource so all applications are |
103 | | notified of changes. |
104 | | |
105 | | \endlist |
106 | | |
107 | | \section1 Notes for Android Users |
108 | | |
109 | | On Android only these mime types are supported: text/plain, text/html, and text/uri-list. |
110 | | |
111 | | \sa QGuiApplication |
112 | | */ |
113 | | |
114 | | /*! |
115 | | \internal |
116 | | |
117 | | Constructs a clipboard object. |
118 | | |
119 | | Do not call this function. |
120 | | |
121 | | Call QGuiApplication::clipboard() instead to get a pointer to the |
122 | | application's global clipboard object. |
123 | | |
124 | | There is only one clipboard in the window system, and creating |
125 | | more than one object to represent it is almost certainly an error. |
126 | | */ |
127 | | |
128 | | QClipboard::QClipboard(QObject *parent) |
129 | 0 | : QObject(parent) |
130 | 0 | { |
131 | | // nothing |
132 | 0 | } |
133 | | |
134 | | /*! |
135 | | \internal |
136 | | |
137 | | Destroys the clipboard. |
138 | | |
139 | | You should never delete the clipboard. QGuiApplication will do this |
140 | | when the application terminates. |
141 | | */ |
142 | | QClipboard::~QClipboard() |
143 | 0 | { |
144 | 0 | } |
145 | | |
146 | | /*! |
147 | | \fn void QClipboard::changed(QClipboard::Mode mode) |
148 | | \since 4.2 |
149 | | |
150 | | This signal is emitted when the data for the given clipboard \a |
151 | | mode is changed. |
152 | | |
153 | | \sa dataChanged(), selectionChanged(), findBufferChanged() |
154 | | */ |
155 | | |
156 | | /*! |
157 | | \fn void QClipboard::dataChanged() |
158 | | |
159 | | This signal is emitted when the clipboard data is changed. |
160 | | |
161 | | On \macos and with Qt version 4.3 or higher, clipboard |
162 | | changes made by other applications will only be detected |
163 | | when the application is activated. |
164 | | |
165 | | \sa findBufferChanged(), selectionChanged(), changed() |
166 | | */ |
167 | | |
168 | | /*! |
169 | | \fn void QClipboard::selectionChanged() |
170 | | |
171 | | This signal is emitted when the selection is changed. This only |
172 | | applies to windowing systems that support selections, e.g. X11. |
173 | | Windows and \macos don't support selections. |
174 | | |
175 | | \sa dataChanged(), findBufferChanged(), changed() |
176 | | */ |
177 | | |
178 | | /*! |
179 | | \fn void QClipboard::findBufferChanged() |
180 | | \since 4.2 |
181 | | |
182 | | This signal is emitted when the find buffer is changed. This only |
183 | | applies to \macos. |
184 | | |
185 | | With Qt version 4.3 or higher, clipboard changes made by other |
186 | | applications will only be detected when the application is activated. |
187 | | |
188 | | \sa dataChanged(), selectionChanged(), changed() |
189 | | */ |
190 | | |
191 | | |
192 | | /*! \enum QClipboard::Mode |
193 | | \keyword clipboard mode |
194 | | |
195 | | This enum type is used to control which part of the system clipboard is |
196 | | used by QClipboard::mimeData(), QClipboard::setMimeData() and related functions. |
197 | | |
198 | | \value Clipboard indicates that data should be stored and retrieved from |
199 | | the global clipboard. |
200 | | |
201 | | \value Selection indicates that data should be stored and retrieved from |
202 | | the global mouse selection. Support for \c Selection is provided only on |
203 | | systems with a global mouse selection (e.g. X11). |
204 | | |
205 | | \value FindBuffer indicates that data should be stored and retrieved from |
206 | | the Find buffer. This mode is used for holding search strings on \macos. |
207 | | |
208 | | \omitvalue LastMode |
209 | | |
210 | | \sa QClipboard::supportsSelection() |
211 | | */ |
212 | | |
213 | | |
214 | | /*! |
215 | | \overload |
216 | | |
217 | | Returns the clipboard text in subtype \a subtype, or an empty string |
218 | | if the clipboard does not contain any text. If \a subtype is null, |
219 | | any subtype is acceptable, and \a subtype is set to the chosen |
220 | | subtype. |
221 | | |
222 | | The \a mode argument is used to control which part of the system |
223 | | clipboard is used. If \a mode is QClipboard::Clipboard, the |
224 | | text is retrieved from the global clipboard. If \a mode is |
225 | | QClipboard::Selection, the text is retrieved from the global |
226 | | mouse selection. |
227 | | |
228 | | Common values for \a subtype are "plain" and "html". |
229 | | |
230 | | Note that calling this function repeatedly, for instance from a |
231 | | key event handler, may be slow. In such cases, you should use the |
232 | | \c dataChanged() signal instead. |
233 | | |
234 | | \sa setText(), mimeData() |
235 | | */ |
236 | | QString QClipboard::text(QString &subtype, Mode mode) const |
237 | 0 | { |
238 | 0 | const QMimeData *const data = mimeData(mode); |
239 | 0 | if (!data) |
240 | 0 | return QString(); |
241 | | |
242 | 0 | const QStringList formats = data->formats(); |
243 | 0 | if (subtype.isEmpty()) { |
244 | 0 | if (formats.contains("text/plain"_L1)) |
245 | 0 | subtype = "plain"_L1; |
246 | 0 | else { |
247 | 0 | for (const auto &format : formats) { |
248 | 0 | if (format.startsWith("text/"_L1)) { |
249 | 0 | subtype = format.sliced(5); |
250 | 0 | break; |
251 | 0 | } |
252 | 0 | } |
253 | 0 | if (subtype.isEmpty()) |
254 | 0 | return QString(); |
255 | 0 | } |
256 | 0 | } else if (!formats.contains("text/"_L1 + subtype)) { |
257 | 0 | return QString(); |
258 | 0 | } |
259 | | |
260 | 0 | const QByteArray rawData = data->data("text/"_L1 + subtype); |
261 | 0 | auto encoding = QStringConverter::encodingForData(rawData); |
262 | 0 | if (!encoding) |
263 | 0 | encoding = QStringConverter::Utf8; |
264 | 0 | return QStringDecoder(*encoding).decode(rawData); |
265 | 0 | } |
266 | | |
267 | | /*! |
268 | | Returns the clipboard text as plain text, or an empty string if the |
269 | | clipboard does not contain any text. |
270 | | |
271 | | The \a mode argument is used to control which part of the system |
272 | | clipboard is used. If \a mode is QClipboard::Clipboard, the |
273 | | text is retrieved from the global clipboard. If \a mode is |
274 | | QClipboard::Selection, the text is retrieved from the global |
275 | | mouse selection. If \a mode is QClipboard::FindBuffer, the |
276 | | text is retrieved from the search string buffer. |
277 | | |
278 | | \sa setText(), mimeData() |
279 | | */ |
280 | | QString QClipboard::text(Mode mode) const |
281 | 0 | { |
282 | 0 | const QMimeData *data = mimeData(mode); |
283 | 0 | return data ? data->text() : QString(); |
284 | 0 | } |
285 | | |
286 | | /*! |
287 | | Copies \a text into the clipboard as plain text. |
288 | | |
289 | | The \a mode argument is used to control which part of the system |
290 | | clipboard is used. If \a mode is QClipboard::Clipboard, the |
291 | | text is stored in the global clipboard. If \a mode is |
292 | | QClipboard::Selection, the text is stored in the global |
293 | | mouse selection. If \a mode is QClipboard::FindBuffer, the |
294 | | text is stored in the search string buffer. |
295 | | |
296 | | \sa text(), setMimeData() |
297 | | */ |
298 | | void QClipboard::setText(const QString &text, Mode mode) |
299 | 0 | { |
300 | 0 | QMimeData *data = new QMimeData; |
301 | 0 | data->setText(text); |
302 | 0 | setMimeData(data, mode); |
303 | 0 | } |
304 | | |
305 | | /*! |
306 | | Returns the clipboard image, or returns a null image if the |
307 | | clipboard does not contain an image or if it contains an image in |
308 | | an unsupported image format. |
309 | | |
310 | | The \a mode argument is used to control which part of the system |
311 | | clipboard is used. If \a mode is QClipboard::Clipboard, the |
312 | | image is retrieved from the global clipboard. If \a mode is |
313 | | QClipboard::Selection, the image is retrieved from the global |
314 | | mouse selection. |
315 | | |
316 | | \sa setImage(), pixmap(), mimeData(), QImage::isNull() |
317 | | */ |
318 | | QImage QClipboard::image(Mode mode) const |
319 | 0 | { |
320 | 0 | const QMimeData *data = mimeData(mode); |
321 | 0 | if (!data) |
322 | 0 | return QImage(); |
323 | 0 | return qvariant_cast<QImage>(data->imageData()); |
324 | 0 | } |
325 | | |
326 | | /*! |
327 | | Copies the \a image into the clipboard. |
328 | | |
329 | | The \a mode argument is used to control which part of the system |
330 | | clipboard is used. If \a mode is QClipboard::Clipboard, the |
331 | | image is stored in the global clipboard. If \a mode is |
332 | | QClipboard::Selection, the data is stored in the global |
333 | | mouse selection. |
334 | | |
335 | | This is shorthand for: |
336 | | |
337 | | \snippet code/src_gui_kernel_qclipboard.cpp 1 |
338 | | |
339 | | \sa image(), setPixmap(), setMimeData() |
340 | | */ |
341 | | void QClipboard::setImage(const QImage &image, Mode mode) |
342 | 0 | { |
343 | 0 | QMimeData *data = new QMimeData; |
344 | 0 | data->setImageData(image); |
345 | 0 | setMimeData(data, mode); |
346 | 0 | } |
347 | | |
348 | | /*! |
349 | | Returns the clipboard pixmap, or null if the clipboard does not |
350 | | contain a pixmap. Note that this can lose information. For |
351 | | example, if the image is 24-bit and the display is 8-bit, the |
352 | | result is converted to 8 bits, and if the image has an alpha |
353 | | channel, the result just has a mask. |
354 | | |
355 | | The \a mode argument is used to control which part of the system |
356 | | clipboard is used. If \a mode is QClipboard::Clipboard, the |
357 | | pixmap is retrieved from the global clipboard. If \a mode is |
358 | | QClipboard::Selection, the pixmap is retrieved from the global |
359 | | mouse selection. |
360 | | |
361 | | \sa setPixmap(), image(), mimeData(), QPixmap::convertFromImage() |
362 | | */ |
363 | | QPixmap QClipboard::pixmap(Mode mode) const |
364 | 0 | { |
365 | 0 | const QMimeData *data = mimeData(mode); |
366 | 0 | return data ? qvariant_cast<QPixmap>(data->imageData()) : QPixmap(); |
367 | 0 | } |
368 | | |
369 | | /*! |
370 | | Copies \a pixmap into the clipboard. Note that this is slower |
371 | | than setImage() because it needs to convert the QPixmap to a |
372 | | QImage first. |
373 | | |
374 | | The \a mode argument is used to control which part of the system |
375 | | clipboard is used. If \a mode is QClipboard::Clipboard, the |
376 | | pixmap is stored in the global clipboard. If \a mode is |
377 | | QClipboard::Selection, the pixmap is stored in the global |
378 | | mouse selection. |
379 | | |
380 | | \sa pixmap(), setImage(), setMimeData() |
381 | | */ |
382 | | void QClipboard::setPixmap(const QPixmap &pixmap, Mode mode) |
383 | 0 | { |
384 | 0 | QMimeData *data = new QMimeData; |
385 | 0 | data->setImageData(pixmap); |
386 | 0 | setMimeData(data, mode); |
387 | 0 | } |
388 | | |
389 | | |
390 | | /*! |
391 | | \fn QMimeData *QClipboard::mimeData(Mode mode) const |
392 | | |
393 | | Returns a pointer to a QMimeData representation of the current |
394 | | clipboard data (can be \nullptr if the given \a mode is not |
395 | | supported by the platform). |
396 | | |
397 | | The \a mode argument is used to control which part of the system |
398 | | clipboard is used. If \a mode is QClipboard::Clipboard, the |
399 | | data is retrieved from the global clipboard. If \a mode is |
400 | | QClipboard::Selection, the data is retrieved from the global |
401 | | mouse selection. If \a mode is QClipboard::FindBuffer, the |
402 | | data is retrieved from the search string buffer. |
403 | | |
404 | | The text(), image(), and pixmap() functions are simpler |
405 | | wrappers for retrieving text, image, and pixmap data. |
406 | | |
407 | | \note The pointer returned might become invalidated when the contents |
408 | | of the clipboard changes; either by calling one of the setter functions |
409 | | or externally by the system clipboard changing. |
410 | | |
411 | | \sa setMimeData() |
412 | | */ |
413 | | const QMimeData* QClipboard::mimeData(Mode mode) const |
414 | 0 | { |
415 | 0 | QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard(); |
416 | 0 | if (!clipboard->supportsMode(mode)) return nullptr; |
417 | 0 | return clipboard->mimeData(mode); |
418 | 0 | } |
419 | | |
420 | | /*! |
421 | | \fn void QClipboard::setMimeData(QMimeData *src, Mode mode) |
422 | | |
423 | | Sets the clipboard data to \a src. Ownership of the data is |
424 | | transferred to the clipboard. If you want to remove the data |
425 | | either call clear() or call setMimeData() again with new data. |
426 | | |
427 | | The \a mode argument is used to control which part of the system |
428 | | clipboard is used. If \a mode is QClipboard::Clipboard, the |
429 | | data is stored in the global clipboard. If \a mode is |
430 | | QClipboard::Selection, the data is stored in the global |
431 | | mouse selection. If \a mode is QClipboard::FindBuffer, the |
432 | | data is stored in the search string buffer. |
433 | | |
434 | | The setText(), setImage() and setPixmap() functions are simpler |
435 | | wrappers for setting text, image and pixmap data respectively. |
436 | | |
437 | | \sa mimeData() |
438 | | */ |
439 | | void QClipboard::setMimeData(QMimeData* src, Mode mode) |
440 | 0 | { |
441 | 0 | QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard(); |
442 | 0 | if (!clipboard->supportsMode(mode)) { |
443 | 0 | if (src != nullptr) { |
444 | 0 | qDebug("Data set on unsupported clipboard mode. QMimeData object will be deleted."); |
445 | 0 | src->deleteLater(); |
446 | 0 | } |
447 | 0 | } else { |
448 | 0 | clipboard->setMimeData(src,mode); |
449 | 0 | } |
450 | 0 | } |
451 | | |
452 | | /*! |
453 | | \fn void QClipboard::clear(Mode mode) |
454 | | Clear the clipboard contents. |
455 | | |
456 | | The \a mode argument is used to control which part of the system |
457 | | clipboard is used. If \a mode is QClipboard::Clipboard, this |
458 | | function clears the global clipboard contents. If \a mode is |
459 | | QClipboard::Selection, this function clears the global mouse |
460 | | selection contents. If \a mode is QClipboard::FindBuffer, this |
461 | | function clears the search string buffer. |
462 | | |
463 | | \sa QClipboard::Mode, supportsSelection() |
464 | | */ |
465 | | void QClipboard::clear(Mode mode) |
466 | 0 | { |
467 | 0 | setMimeData(nullptr, mode); |
468 | 0 | } |
469 | | |
470 | | /*! |
471 | | Returns \c true if the clipboard supports mouse selection; otherwise |
472 | | returns \c false. |
473 | | */ |
474 | | bool QClipboard::supportsSelection() const |
475 | 0 | { |
476 | 0 | return supportsMode(Selection); |
477 | 0 | } |
478 | | |
479 | | /*! |
480 | | Returns \c true if the clipboard supports a separate search buffer; otherwise |
481 | | returns \c false. |
482 | | */ |
483 | | bool QClipboard::supportsFindBuffer() const |
484 | 0 | { |
485 | 0 | return supportsMode(FindBuffer); |
486 | 0 | } |
487 | | |
488 | | /*! |
489 | | Returns \c true if this clipboard object owns the clipboard data; |
490 | | otherwise returns \c false. |
491 | | */ |
492 | | bool QClipboard::ownsClipboard() const |
493 | 0 | { |
494 | 0 | return ownsMode(Clipboard); |
495 | 0 | } |
496 | | |
497 | | /*! |
498 | | Returns \c true if this clipboard object owns the mouse selection |
499 | | data; otherwise returns \c false. |
500 | | */ |
501 | | bool QClipboard::ownsSelection() const |
502 | 0 | { |
503 | 0 | return ownsMode(Selection); |
504 | 0 | } |
505 | | |
506 | | /*! |
507 | | \since 4.2 |
508 | | |
509 | | Returns \c true if this clipboard object owns the find buffer data; |
510 | | otherwise returns \c false. |
511 | | */ |
512 | | bool QClipboard::ownsFindBuffer() const |
513 | 0 | { |
514 | 0 | return ownsMode(FindBuffer); |
515 | 0 | } |
516 | | |
517 | | /*! |
518 | | \internal |
519 | | \fn bool QClipboard::supportsMode(Mode mode) const; |
520 | | Returns \c true if the clipboard supports the clipboard mode speacified by \a mode; |
521 | | otherwise returns \c false. |
522 | | */ |
523 | | bool QClipboard::supportsMode(Mode mode) const |
524 | 0 | { |
525 | 0 | QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard(); |
526 | 0 | return clipboard && clipboard->supportsMode(mode); |
527 | 0 | } |
528 | | |
529 | | /*! |
530 | | \internal |
531 | | \fn bool QClipboard::ownsMode(Mode mode) const; |
532 | | Returns \c true if the clipboard supports the clipboard data speacified by \a mode; |
533 | | otherwise returns \c false. |
534 | | */ |
535 | | bool QClipboard::ownsMode(Mode mode) const |
536 | 0 | { |
537 | 0 | QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard(); |
538 | 0 | return clipboard && clipboard->ownsMode(mode); |
539 | 0 | } |
540 | | |
541 | | /*! |
542 | | \internal |
543 | | Emits the appropriate changed signal for \a mode. |
544 | | */ |
545 | | void QClipboard::emitChanged(Mode mode) |
546 | 0 | { |
547 | 0 | switch (mode) { |
548 | 0 | case Clipboard: |
549 | 0 | emit dataChanged(); |
550 | 0 | break; |
551 | 0 | case Selection: |
552 | 0 | emit selectionChanged(); |
553 | 0 | break; |
554 | 0 | case FindBuffer: |
555 | 0 | emit findBufferChanged(); |
556 | 0 | break; |
557 | 0 | } |
558 | | |
559 | 0 | emit changed(mode); |
560 | 0 | } |
561 | | |
562 | | QT_END_NAMESPACE |
563 | | |
564 | | #include "moc_qclipboard.cpp" |
565 | | |
566 | | #endif // QT_NO_CLIPBOARD |