Coverage Report

Created: 2025-07-16 07:53

/src/qtbase/src/gui/kernel/qclipboard.cpp
Line
Count
Source (jump to first uncovered line)
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
19
QT_BEGIN_NAMESPACE
20
21
using 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
127
QClipboard::QClipboard(QObject *parent)
128
0
    : QObject(parent)
129
0
{
130
    // nothing
131
0
}
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
*/
141
QClipboard::~QClipboard()
142
0
{
143
0
}
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
*/
235
QString QClipboard::text(QString &subtype, Mode mode) const
236
0
{
237
0
    const QMimeData *const data = mimeData(mode);
238
0
    if (!data)
239
0
        return QString();
240
241
0
    const QStringList formats = data->formats();
242
0
    if (subtype.isEmpty()) {
243
0
        if (formats.contains("text/plain"_L1))
244
0
            subtype = "plain"_L1;
245
0
        else {
246
0
            for (const auto &format : formats) {
247
0
                if (format.startsWith("text/"_L1)) {
248
0
                    subtype = format.sliced(5);
249
0
                    break;
250
0
                }
251
0
            }
252
0
            if (subtype.isEmpty())
253
0
                return QString();
254
0
        }
255
0
    } else if (!formats.contains("text/"_L1 + subtype)) {
256
0
        return QString();
257
0
    }
258
259
0
    const QByteArray rawData = data->data("text/"_L1 + subtype);
260
0
    auto encoding = QStringConverter::encodingForData(rawData);
261
0
    if (!encoding)
262
0
        encoding = QStringConverter::Utf8;
263
0
    return QStringDecoder(*encoding).decode(rawData);
264
0
}
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
*/
279
QString QClipboard::text(Mode mode) const
280
0
{
281
0
    const QMimeData *data = mimeData(mode);
282
0
    return data ? data->text() : QString();
283
0
}
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
*/
297
void QClipboard::setText(const QString &text, Mode mode)
298
0
{
299
0
    QMimeData *data = new QMimeData;
300
0
    data->setText(text);
301
0
    setMimeData(data, mode);
302
0
}
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
*/
317
QImage QClipboard::image(Mode mode) const
318
0
{
319
0
    const QMimeData *data = mimeData(mode);
320
0
    if (!data)
321
0
        return QImage();
322
0
    return qvariant_cast<QImage>(data->imageData());
323
0
}
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
*/
340
void QClipboard::setImage(const QImage &image, Mode mode)
341
0
{
342
0
    QMimeData *data = new QMimeData;
343
0
    data->setImageData(image);
344
0
    setMimeData(data, mode);
345
0
}
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
*/
362
QPixmap QClipboard::pixmap(Mode mode) const
363
0
{
364
0
    const QMimeData *data = mimeData(mode);
365
0
    return data ? qvariant_cast<QPixmap>(data->imageData()) : QPixmap();
366
0
}
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
*/
381
void QClipboard::setPixmap(const QPixmap &pixmap, Mode mode)
382
0
{
383
0
    QMimeData *data = new QMimeData;
384
0
    data->setImageData(pixmap);
385
0
    setMimeData(data, mode);
386
0
}
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
*/
412
const QMimeData* QClipboard::mimeData(Mode mode) const
413
0
{
414
0
    QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard();
415
0
    if (!clipboard->supportsMode(mode)) return nullptr;
416
0
    return clipboard->mimeData(mode);
417
0
}
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
*/
438
void QClipboard::setMimeData(QMimeData* src, Mode mode)
439
0
{
440
0
    QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard();
441
0
    if (!clipboard->supportsMode(mode)) {
442
0
        if (src != nullptr) {
443
0
            qDebug("Data set on unsupported clipboard mode. QMimeData object will be deleted.");
444
0
            src->deleteLater();
445
0
        }
446
0
    } else {
447
0
        clipboard->setMimeData(src,mode);
448
0
    }
449
0
}
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
*/
464
void QClipboard::clear(Mode mode)
465
0
{
466
0
    setMimeData(nullptr, mode);
467
0
}
468
469
/*!
470
    Returns \c true if the clipboard supports mouse selection; otherwise
471
    returns \c false.
472
*/
473
bool QClipboard::supportsSelection() const
474
0
{
475
0
    return supportsMode(Selection);
476
0
}
477
478
/*!
479
    Returns \c true if the clipboard supports a separate search buffer; otherwise
480
    returns \c false.
481
*/
482
bool QClipboard::supportsFindBuffer() const
483
0
{
484
0
    return supportsMode(FindBuffer);
485
0
}
486
487
/*!
488
    Returns \c true if this clipboard object owns the clipboard data;
489
    otherwise returns \c false.
490
*/
491
bool QClipboard::ownsClipboard() const
492
0
{
493
0
    return ownsMode(Clipboard);
494
0
}
495
496
/*!
497
    Returns \c true if this clipboard object owns the mouse selection
498
    data; otherwise returns \c false.
499
*/
500
bool QClipboard::ownsSelection() const
501
0
{
502
0
    return ownsMode(Selection);
503
0
}
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
*/
511
bool QClipboard::ownsFindBuffer() const
512
0
{
513
0
    return ownsMode(FindBuffer);
514
0
}
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
*/
522
bool QClipboard::supportsMode(Mode mode) const
523
0
{
524
0
    QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard();
525
0
    return clipboard && clipboard->supportsMode(mode);
526
0
}
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
*/
534
bool QClipboard::ownsMode(Mode mode) const
535
0
{
536
0
    QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard();
537
0
    return clipboard && clipboard->ownsMode(mode);
538
0
}
539
540
/*!
541
    \internal
542
    Emits the appropriate changed signal for \a mode.
543
*/
544
void QClipboard::emitChanged(Mode mode)
545
0
{
546
0
    switch (mode) {
547
0
        case Clipboard:
548
0
            emit dataChanged();
549
0
        break;
550
0
        case Selection:
551
0
            emit selectionChanged();
552
0
        break;
553
0
        case FindBuffer:
554
0
            emit findBufferChanged();
555
0
        break;
556
0
    }
557
558
0
    emit changed(mode);
559
0
}
560
561
QT_END_NAMESPACE
562
563
#include "moc_qclipboard.cpp"
564
565
#endif // QT_NO_CLIPBOARD