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

source code of qtbase/src/gui/kernel/qclipboard.cpp