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