Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_clipboard.cc
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2004 Boudewijn Rempt <boud@valdyas.org>
3 * SPDX-FileCopyrightText: 2021 L. E. Segovia <amy@amyspark.me>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8#include "kis_clipboard.h"
9
10#include <QApplication>
11#include <QBuffer>
12#include <QClipboard>
13#include <QScreen>
14#include <QFileInfo>
15#include <QMessageBox>
16#include <QMimeData>
17#include <QScopedPointer>
18#include <QTemporaryFile>
19
20// kritaglobal
21#include <algorithm>
22#include <kis_assert.h>
23#include <kis_debug.h>
24
25// kritastore
26#include <KoStore.h>
27
28// kritaimage
29#include <kis_annotation.h>
30#include <kis_layer_utils.h>
31#include <kis_paint_device.h>
32#include <kis_time_span.h>
33
34// local
35#include "KisDocument.h"
37#include "KisMainWindow.h"
38#include "KisMimeDatabase.h"
39#include "KisPart.h"
43#include "kis_mimedata.h"
45#include "KisDisplayConfig.h"
46
48
50 QSet<QString> mimeTypes;
51 QString format;
52};
53
54class Q_DECL_HIDDEN KisClipboardPrivate
55{
56public:
58 : clipboard(QApplication::clipboard())
59 {
60 }
61
62 bool hasClip{};
63 bool pushedClipboard{};
64 QClipboard *clipboard;
65};
66
68 : d(new KisClipboardPrivate)
69{
70 // Check that we don't already have a clip ready
72
73 // Make sure we are notified when clipboard changes
74 connect(d->clipboard, &QClipboard::dataChanged, this, &KisClipboard::clipboardDataChanged, Qt::UniqueConnection);
75}
76
78{
79 dbgRegistry << "deleting KisClipBoard";
80 delete d;
81}
82
84{
85 return s_instance;
86}
87
88void KisClipboard::setClip(KisPaintDeviceSP dev, const QPoint &topLeft, const KisTimeSpan &range)
89{
90 if (!dev)
91 return;
92
93 d->hasClip = true;
94
95 // We'll create a store (ZIP format) in memory
96 QBuffer buffer;
97 const auto mimeType = QByteArrayLiteral("application/x-krita-selection");
98 QScopedPointer<KoStore> store(KoStore::createStore(&buffer, KoStore::Write, mimeType));
99 KisStorePaintDeviceWriter writer(store.data());
100 Q_ASSERT(store);
101 Q_ASSERT(!store->bad());
102
103 // Layer data
104 if (store->open("layerdata")) {
105 if (!dev->write(writer)) {
106 dev->disconnect();
107 store->close();
108 return;
109 }
110 store->close();
111 }
112
113 // copied frame time limits
114 if (range.isValid() && store->open("timeRange")) {
115 store->write(QString("%1 %2").arg(range.start()).arg(range.end()).toLatin1());
116 store->close();
117 }
118
119 // Coordinates
120 if (store->open("topLeft")) {
121 store->write(QString("%1 %2").arg(topLeft.x()).arg(topLeft.y()).toLatin1());
122 store->close();
123 }
124 // ColorSpace id of layer data
125 if (store->open("colormodel")) {
126 QString csName = dev->colorSpace()->colorModelId().id();
127 store->write(csName.toLatin1());
128 store->close();
129 }
130 if (store->open("colordepth")) {
131 QString csName = dev->colorSpace()->colorDepthId().id();
132 store->write(csName.toLatin1());
133 store->close();
134 }
135
136 if (dev->colorSpace()->profile()) {
137 const KoColorProfile *profile = dev->colorSpace()->profile();
138 KisAnnotationSP annotation;
139
140 if (profile && profile->type() == "icc" && !profile->rawData().isEmpty()) {
141 annotation = new KisAnnotation("icc", profile->name(), profile->rawData());
142
143 if (annotation) {
144 // save layer profile
145 if (store->open("profile.icc")) {
146 store->write(annotation->annotation());
147 store->close();
148 }
149 }
150 }
151 }
152
153 QMimeData *mimeData = new QMimeData;
154 Q_CHECK_PTR(mimeData);
155
156 if (mimeData) {
157 mimeData->setData(mimeType, buffer.buffer());
158 }
159
160 // We also create a QImage so we can interchange with other applications
161 QImage qimage;
163
164 qimage = dev->convertToQImage(displayConfig.profile,
165 displayConfig.intent,
166 displayConfig.conversionFlags);
167 if (!qimage.isNull() && mimeData) {
168 mimeData->setImageData(qimage);
169 }
170
171 if (mimeData) {
172 d->pushedClipboard = true;
173 d->clipboard->setMimeData(mimeData);
174 }
175}
176
177void KisClipboard::setClip(KisPaintDeviceSP dev, const QPoint &topLeft)
178{
179 setClip(dev, topLeft, KisTimeSpan());
180}
181
182KisPaintDeviceSP KisClipboard::clip(const QRect &imageBounds, bool showPopup, int overridePasteBehaviour, KisTimeSpan *clipRange) const
183{
184 const QMimeData *cbData = d->clipboard->mimeData();
185
186 if (!cbData) {
187 return nullptr;
188 }
189
190 dbgUI << Q_FUNC_INFO;
191 dbgUI << "\tFormats: " << cbData->formats();
192 dbgUI << "\tUrls: " << cbData->urls();
193 dbgUI << "\tHas images: " << cbData->hasImage();
194
195 return clipFromMimeData(cbData, imageBounds, showPopup, overridePasteBehaviour, clipRange, true);
196}
197
199 const QRect &imageBounds,
200 bool showPopup,
201 int overridePasteBehaviour,
202 KisTimeSpan *clipRange,
203 bool useClipboardFallback) const
204{
205 if (clipRange) {
206 *clipRange = KisTimeSpan();
207 }
208
209 KisPaintDeviceSP clip = clipFromKritaSelection(cbData, imageBounds, clipRange);
210
211 if (!clip) {
212 clip = clipFromKritaLayers(nullptr);
213 }
214
215 if (!clip) {
216 clip = clipFromBoardContents(cbData, imageBounds, showPopup, overridePasteBehaviour, useClipboardFallback);
217 }
218
219 return clip;
220}
221
222KisPaintDeviceSP KisClipboard::clipFromKritaSelection(const QMimeData *cbData, const QRect &imageBounds, KisTimeSpan *clipRange) const
223{
224 const QByteArray mimeType = QByteArrayLiteral("application/x-krita-selection");
225
227
228 if (!cbData) {
229 return nullptr;
230 }
231
232 if (cbData->hasFormat(mimeType)) {
233 QByteArray encodedData = cbData->data(mimeType);
234 QBuffer buffer(&encodedData);
235 QScopedPointer<KoStore> store(KoStore::createStore(&buffer, KoStore::Read, mimeType));
236
237 const KoColorProfile *profile = 0;
238
239 QString csDepth, csModel;
240
241 // ColorSpace id of layer data
242 if (store->hasFile("colormodel")) {
243 store->open("colormodel");
244 csModel = QString(store->read(store->size()));
245 store->close();
246 }
247
248 if (store->hasFile("colordepth")) {
249 store->open("colordepth");
250 csDepth = QString(store->read(store->size()));
251 store->close();
252 }
253
254 if (store->hasFile("profile.icc")) {
255 QByteArray data;
256 store->open("profile.icc");
257 data = store->read(store->size());
258 store->close();
259 profile = KoColorSpaceRegistry::instance()->createColorProfile(csModel, csDepth, data);
260 }
261
262 const KoColorSpace *cs = KoColorSpaceRegistry::instance()->colorSpace(csModel, csDepth, profile);
263 if (cs) {
264 clip = new KisPaintDevice(cs);
265
266 if (store->hasFile("layerdata")) {
267 store->open("layerdata");
268 if (!clip->read(store->device())) {
269 clip = 0;
270 }
271 store->close();
272 }
273
274 if (clip && !imageBounds.isEmpty()) {
275 // load topLeft
276 if (store->hasFile("topLeft")) {
277 store->open("topLeft");
278 QString str = store->read(store->size());
279 store->close();
280 QStringList list = str.split(' ');
281 if (list.size() == 2) {
282 QPoint topLeft(list[0].toInt(), list[1].toInt());
283 clip->setX(topLeft.x());
284 clip->setY(topLeft.y());
285 }
286 }
287
288 QRect clipBounds = clip->exactBounds();
289
290 if (!imageBounds.contains(clipBounds) && !imageBounds.intersects(clipBounds)) {
291 QPoint diff = imageBounds.center() - clipBounds.center();
292 clip->setX(clip->x() + diff.x());
293 clip->setY(clip->y() + diff.y());
294 }
295
296 if (store->hasFile("timeRange") && clipRange) {
297 store->open("timeRange");
298 QString str = store->read(store->size());
299 store->close();
300 QStringList list = str.split(' ');
301 if (list.size() == 2) {
302 KisTimeSpan range = KisTimeSpan::fromTimeToTime(list[0].toInt(), list[1].toInt());
303 *clipRange = range;
304 dbgUI << "Pasted time range" << range;
305 }
306 }
307 }
308 }
309 }
310
311 return clip;
312}
313
315{
316 const QMimeData *data = KisClipboard::instance()->layersMimeData();
317
318 if (!data) {
319 return nullptr;
320 }
321
322 const KisMimeData *mimedata = qobject_cast<const KisMimeData *>(data);
323 if (!mimedata) return 0;
324
325 KisNodeList nodes = mimedata->nodes();
326
327 if (nodes.size() > 1) {
328 // we explicitly include point (0,0) into the bounds since that
329 // is a requirement for the image
330 const QRect bounds =
331 std::accumulate(nodes.begin(), nodes.end(), QRect(0, 0, 1, 1),
333
334 // if no color space provided choose the most used one in the layer data
335 if (cs == nullptr) {
336 QHash<const KoColorSpace *, int> colorSpacesCount;
337
338 Q_FOREACH (KisNodeSP node, nodes) {
339 const KoColorSpace *colorSpace = node->colorSpace();
340 if (colorSpace != nullptr) {
341 colorSpacesCount.insert(colorSpace, colorSpacesCount.value(colorSpace) + 1);
342 }
343 }
344
345 int max = 0;
346 for (auto it = colorSpacesCount.begin(); it != colorSpacesCount.end(); ++it) {
347 if (it.value() > max) {
348 max = it.value();
349 cs = it.key();
350 }
351 }
352
353 // fallback to rgb8 if no color space found
354 // It is likely that this will never be triggered, but it's probably best to handle this just in case
355 if (cs == nullptr) {
357 }
358 }
359
360 KisImageSP tempImage = new KisImage(nullptr,
361 bounds.width(),
362 bounds.height(),
363 cs,
364 "ClipImage");
365
367 for (KisNodeSP node : nodes) {
368 tempImage->addNode(node, tempImage->root());
369 }
370 tempImage->refreshGraphAsync();
371 KisLayerUtils::refreshHiddenAreaAsync(tempImage, tempImage->root(), bounds);
372 tempImage->waitForDone();
373
374 return tempImage->projection();
375 } else if (!nodes.isEmpty()) {
376 return nodes.first()->projection();
377 }
378
379 return nullptr;
380}
381
382QPair<bool, KisClipboard::PasteFormatBehaviour>
383KisClipboard::askUserForSource(const QMimeData *cbData, bool useClipboardFallback) const
384{
385 if (!cbData) {
386 return {false, PASTE_FORMAT_ASK};
387 }
388 const QImage qimage = getImageWithFallback(cbData, useClipboardFallback);
389 QList<QUrl> urls = cbData->urls();
390
391 return askUserForSourceWithData(qimage, urls, useClipboardFallback);
392}
393
394QPair<bool, KisClipboard::PasteFormatBehaviour>
395KisClipboard::askUserForSourceWithData(QImage qimage, const QList<QUrl> urls, bool useClipboardFallback) const
396{
397 KisConfig cfg(true);
398
399 bool saveSourceSetting = false;
400
401 auto choice = (PasteFormatBehaviour)cfg.pasteFormat(false);
402
403 if (!qimage.isNull() || !urls.isEmpty()) {
404 bool local = false;
405 bool remote = false;
406 bool isURI = false;
407
408 std::for_each(urls.constBegin(), urls.constEnd(), [&](const QUrl &url) {
409 local |= url.isLocalFile();
410 remote |= !url.isLocalFile();
411 isURI |= url.scheme() == "data";
412 });
413
414 const bool hasMultipleFormatsAvailable = (remote && local)
415 || (remote && !qimage.isNull()) || (local && !qimage.isNull());
416
417 const bool defaultOptionUnavailable =
418 (!remote && choice == PASTE_FORMAT_DOWNLOAD)
419 || (!local && choice == PASTE_FORMAT_LOCAL)
420 || (qimage.isNull() && choice == PASTE_FORMAT_CLIP);
421
422 dbgUI << "Incoming paste event:";
423 dbgUI << "\tHas attached bitmap:" << !qimage.isNull();
424 dbgUI << "\tHas local images:" << local;
425 dbgUI << "\tHas remote images:" << remote;
426 dbgUI << "\tHas multiple formats:" << hasMultipleFormatsAvailable;
427 dbgUI << "\tDefault source preference" << choice;
428 dbgUI << "\tDefault source available:" << !defaultOptionUnavailable;
429 dbgUI << "\tIs data URI:" << isURI;
430
431 if (hasMultipleFormatsAvailable && choice == PASTE_FORMAT_ASK && !isURI) {
432 KisDlgPasteFormat dlg(qApp->activeWindow());
433
436 dlg.setSourceAvailable(PASTE_FORMAT_CLIP, !qimage.isNull());
437
438 if (dlg.exec() != KoDialog::Accepted) {
439 return {false, PASTE_FORMAT_ASK};
440 };
441
442 choice = dlg.source();
443
444 saveSourceSetting = dlg.remember();
445 } else if (defaultOptionUnavailable || choice == PASTE_FORMAT_ASK) {
446 if (remote) {
447 choice = PASTE_FORMAT_DOWNLOAD;
448 } else if (local) {
449 choice = PASTE_FORMAT_LOCAL;
450 } else if (!qimage.isNull()) {
451 choice = PASTE_FORMAT_CLIP;
452 } else {
453 return {false, PASTE_FORMAT_ASK};
454 }
455 } else if (isURI) {
456 choice = PASTE_FORMAT_DOWNLOAD;
457 }
458 }
459
460 if (saveSourceSetting) {
461 cfg.setPasteFormat(choice);
462 }
463
464 dbgUI << "Selected source for the paste:" << choice;
465
466 return {true, choice};
467}
468
470 const QRect &imageBounds,
471 bool showPopup,
472 int pasteBehaviourOverride,
473 bool useClipboardFallback,
474 QPair<bool, PasteFormatBehaviour> source) const
475{
476 if (!cbData) {
477 return nullptr;
478 }
479
480 // On wayland opening a dialog invalidates the clipboard data so we cache all the data beforehand
481 const auto &urls = cbData->urls();
482 const QImage qimage = getImageWithFallback(cbData, useClipboardFallback);
483
484 return clipFromBoardContentsWithData(qimage,
485 urls,
486 imageBounds,
487 showPopup,
488 pasteBehaviourOverride,
489 useClipboardFallback,
490 source);
491}
492
494 const QList<QUrl> urls,
495 const QRect &imageBounds,
496 bool showPopup,
497 int pasteBehaviourOverride,
498 bool useClipboardFallback,
499 QPair<bool, PasteFormatBehaviour> source) const
500{
503
504 if (!source.first) {
505 choice = askUserForSourceWithData(qimage , urls).second;
506 } else {
507 choice = source.second;
508 }
509
510 if (choice == PASTE_FORMAT_CLIP) {
511 KIS_SAFE_ASSERT_RECOVER(!qimage.isNull())
512 {
513 warnKrita << "Clipboard was cleared before loading image";
514 return nullptr;
515 }
516
517 int behaviour = pasteBehaviourOverride;
518 bool saveColorSetting = false;
519
520 KisConfig cfg(true);
521
522 if (pasteBehaviourOverride == -1) {
523 behaviour = cfg.pasteBehaviour();
524 }
525
526 if (behaviour == PASTE_ASK && showPopup) {
527 // Ask user each time.
528 KisDlgMissingColorProfile dlg(qApp->activeWindow());
529
530 if (dlg.exec() != QDialog::Accepted) {
531 return nullptr;
532 }
533
534 behaviour = dlg.source();
535
536 saveColorSetting = dlg.remember(); // should we save this option to the config for next time?
537 }
538
539 const KoColorSpace *cs = nullptr;
540 const KoColorProfile *profile = nullptr;
541 if (!profile && behaviour == PASTE_ASSUME_MONITOR)
543
544 cs = KoColorSpaceRegistry::instance()->rgb8(profile);
545 if (!cs) {
547 profile = cs->profile();
548 }
549
550 clip = new KisPaintDevice(cs);
551 Q_CHECK_PTR(clip);
552 clip->convertFromQImage(qimage, profile);
553
554 // save the user's selection to the configuration if the option is checked
555 if (saveColorSetting) {
556 cfg.setPasteBehaviour(behaviour);
557 }
558 } else {
559 const auto url = std::find_if(urls.constBegin(), urls.constEnd(), [&](const QUrl &url) {
560 if (choice == PASTE_FORMAT_DOWNLOAD) {
561 return !url.isLocalFile();
562 } else if (choice == PASTE_FORMAT_LOCAL) {
563 return url.isLocalFile();
564 } else {
565 return false;
566 }
567 });
568
569 if (url != urls.constEnd()) {
570 clip = fetchImageByURL(*url);
571 }
572 }
573
574 if (clip && !imageBounds.isEmpty()) {
575 QRect clipBounds = clip->exactBounds();
576 QPoint diff = imageBounds.center() - clipBounds.center();
577 clip->setX(diff.x());
578 clip->setY(diff.y());
579 }
580
581 return clip;
582}
583
585{
586 if (!d->pushedClipboard) {
587 const QMimeData *cbData = d->clipboard->mimeData();
588 d->hasClip = d->clipboard->mimeData()->hasImage()
589 || (cbData && cbData->hasFormat("application/x-krita-selection"));
590 }
591 d->pushedClipboard = false;
592 Q_EMIT clipChanged();
593}
594
595QImage KisClipboard::getImageWithFallback(const QMimeData *cbData, bool useClipboardFallback) const
596{
597 QImage qimage = getImageFromMimeData(cbData);
598
599 if (qimage.isNull() && useClipboardFallback) {
600 qimage = d->clipboard->image();
601 }
602
603 return qimage;
604}
605
607{
608 return d->hasClip;
609}
610
612{
613 const auto mimeType = QByteArrayLiteral("application/x-krita-selection");
614 const QMimeData *cbData = d->clipboard->mimeData();
615
617
618 if (cbData && cbData->hasFormat(mimeType)) {
619 QByteArray encodedData = cbData->data(mimeType);
620 QBuffer buffer(&encodedData);
621 QScopedPointer<KoStore> store(KoStore::createStore(&buffer, KoStore::Read, mimeType));
622 const KoColorProfile *profile = 0;
623 QString csDepth, csModel;
624
625 // ColorSpace id of layer data
626 if (store->hasFile("colormodel")) {
627 store->open("colormodel");
628 csModel = QString(store->read(store->size()));
629 store->close();
630 }
631
632 if (store->hasFile("colordepth")) {
633 store->open("colordepth");
634 csDepth = QString(store->read(store->size()));
635 store->close();
636 }
637
638 if (store->hasFile("profile.icc")) {
639 QByteArray data;
640 store->open("profile.icc");
641 data = store->read(store->size());
642 store->close();
643 profile = KoColorSpaceRegistry::instance()->createColorProfile(csModel, csDepth, data);
644 }
645
646 const KoColorSpace *cs = KoColorSpaceRegistry::instance()->colorSpace(csModel, csDepth, profile);
647 if (!cs) {
649 }
650 clip = new KisPaintDevice(cs);
651
652 if (store->hasFile("layerdata")) {
653 store->open("layerdata");
654 clip->read(store->device());
655 store->close();
656 }
657
658 return clip->exactBounds().size();
659 } else {
660 if (d->clipboard->mimeData()->hasImage()) {
661 QImage qimage = d->clipboard->image();
662 return qimage.size();
663 }
664 }
665 return QSize();
666}
667
668void KisClipboard::setLayers(KisNodeList nodes, KisImageSP image, bool forceCopy)
669{
673 QMimeData *data = KisMimeData::mimeForLayersDeepCopy(nodes, image, forceCopy);
674 if (!data)
675 return;
676
677 d->clipboard->setMimeData(data);
678}
679
681{
682 const QByteArray mimeType = QByteArrayLiteral("application/x-krita-node-internal-pointer");
683 return d->clipboard->mimeData()->hasFormat(mimeType);
684}
685
687{
688 // NOTE: please don't disable the paste action based on the
689 // result of this function, because we allow pasting
690 // of the layer styles as 'text/plain'
691
692 return d->clipboard->mimeData()->hasFormat("application/x-krita-layer-style");
693}
694
695const QMimeData *KisClipboard::layersMimeData() const
696{
697 const QMimeData *cbData = d->clipboard->mimeData();
698 return cbData->hasFormat("application/x-krita-node-internal-pointer") ? cbData : 0;
699}
700
702{
703 return d->clipboard->mimeData()->hasUrls();
704}
705
706
708{
709 return d->clipboard->mimeData()->hasImage();
710}
711
712QImage KisClipboard::getImageFromMimeData(const QMimeData *cbData) const
713{
714 static const QList<ClipboardImageFormat> supportedFormats = {
715 {{"image/png"}, "PNG"},
716 {{"image/tiff"}, "TIFF"},
717 {{"image/bmp", "image/x-bmp", "image/x-MS-bmp", "image/x-win-bitmap"}, "BMP"}};
718
719 QImage image;
720 QSet<QString> clipboardMimeTypes;
721
722 Q_FOREACH (const QString &format, cbData->formats()) {
723 clipboardMimeTypes << format;
724 }
725
726 Q_FOREACH (const ClipboardImageFormat &item, supportedFormats) {
727 const QSet<QString> &intersection = item.mimeTypes & clipboardMimeTypes;
728 if (intersection.isEmpty()) {
729 continue;
730 }
731
732 const QString &format = *intersection.constBegin();
733 const QByteArray &imageData = cbData->data(format);
734 if (imageData.isEmpty()) {
735 continue;
736 }
737
738 if (image.loadFromData(imageData, item.format.toLatin1())) {
739 break;
740 }
741 }
742
743 if (image.isNull() && cbData->hasImage()) {
744 image = qvariant_cast<QImage>(cbData->imageData());
745 }
746
747 return image;
748}
749
751{
752 KisPaintDeviceSP result;
753 QUrl url(originalUrl);
754 QScopedPointer<QTemporaryFile> tmp;
755
756 if (!originalUrl.isLocalFile()) {
757 tmp.reset(new QTemporaryFile());
758 tmp->setAutoRemove(true);
759
760 // download the file and substitute the url
761 KisRemoteFileFetcher fetcher;
762
763 if (!fetcher.fetchFile(originalUrl, tmp.data())) {
764 qWarning() << "Fetching" << originalUrl << "failed";
765 return result;
766 }
767 url = QUrl::fromLocalFile(tmp->fileName());
768 }
769
770 if (url.isLocalFile()) {
771 QFileInfo fileInfo(url.toLocalFile());
772
773 QString type = KisMimeDatabase::mimeTypeForFile(url.toLocalFile());
775
776 if (!mimes.contains(type)) {
778 QMessageBox::warning(KisPart::instance()->currentMainwindow(),
779 i18nc("@title:window", "Krita"),
780 i18n("Could not open %2.\nReason: %1.", msg, url.toDisplayString()));
781 return result;
782 }
783
784 QScopedPointer<KisDocument> doc(KisPart::instance()->createDocument());
785
786 if (doc->openPath(url.toLocalFile(), KisDocument::DontAddToRecent)) {
787 // Wait for required updates, if any. BUG: 448256
788 KisLayerUtils::forceAllDelayedNodesUpdate(doc->image()->root());
789 doc->image()->waitForDone();
790 result = new KisPaintDevice(*doc->image()->projection());
791 } else {
792 qWarning() << "Failed to import file" << url.toLocalFile();
793 }
794 }
795
796 return result;
797}
KisMagneticGraph::vertex_descriptor source(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
Q_GLOBAL_STATIC(KisStoragePluginRegistry, s_instance)
A data extension mechanism for Krita.
QClipboard * clipboard
void setLayers(KisNodeList nodes, KisImageSP image, bool forceCopy=false)
void clipboardDataChanged()
KisPaintDeviceSP clipFromBoardContentsWithData(QImage image, const QList< QUrl > urls, const QRect &imageBounds, bool showPopup, int overridePasteBehaviour=-1, bool useClipboardFallback=false, QPair< bool, PasteFormatBehaviour > source={false, PasteFormatBehaviour::PASTE_FORMAT_ASK}) const
QPair< bool, PasteFormatBehaviour > askUserForSourceWithData(QImage qimage, const QList< QUrl > urls, bool useClipboardFallback=false) const
static KisClipboard * instance()
bool hasClip() const
void clipChanged()
QPair< bool, PasteFormatBehaviour > askUserForSource(const QMimeData *data, bool useClipboardFallback=false) const
KisPaintDeviceSP clipFromKritaSelection(const QMimeData *data, const QRect &imageBounds, KisTimeSpan *clipRange) const
KisPaintDeviceSP clipFromMimeData(const QMimeData *data, const QRect &imageBounds, bool showPopup, int overridePasteBehaviour=-1, KisTimeSpan *clipRange=nullptr, bool useClipboardFallback=false) const
QImage getImageWithFallback(const QMimeData *cbData, bool useClipboardFallback=false) const
void setClip(KisPaintDeviceSP dev, const QPoint &topLeft)
const QMimeData * layersMimeData() const
QImage getImageFromMimeData(const QMimeData *cbData) const
bool hasLayerStyles() const
KisPaintDeviceSP clipFromKritaLayers(const KoColorSpace *cs) const
bool hasLayers() const
bool hasImage() const
KisPaintDeviceSP fetchImageByURL(const QUrl &originalUrl) const
QSize clipSize() const
KisPaintDeviceSP clipFromBoardContents(const QMimeData *data, const QRect &imageBounds, bool showPopup, int overridePasteBehaviour=-1, bool useClipboardFallback=false, QPair< bool, PasteFormatBehaviour > source={ false, PasteFormatBehaviour::PASTE_FORMAT_ASK}) const
KisClipboardPrivate *const d
~KisClipboard() override
bool hasUrls() const
void setPasteFormat(qint32 format)
qint32 pasteFormat(bool defaultValue) const
qint32 pasteBehaviour(bool defaultValue=false) const
void setPasteBehaviour(qint32 behaviour) const
KisDisplayConfig This class keeps track of the color management configuration for image to display....
KoColorConversionTransformation::ConversionFlags conversionFlags
const KoColorProfile * profile
KoColorConversionTransformation::Intent intent
KisClipboard::PasteBehaviour source() const
KisClipboard::PasteFormatBehaviour source() const
void setSourceAvailable(KisClipboard::PasteFormatBehaviour id, bool value)
void waitForDone()
void refreshGraphAsync(KisNodeSP root, const QVector< QRect > &rects, const QRect &cropRect, KisProjectionUpdateFlags flags=KisProjectionUpdateFlag::None) override
KisPaintDeviceSP projection() const
static QStringList supportedMimeTypes(Direction direction)
static KisDisplayConfig displayConfigForMimePastes()
QList< KisNodeSP > nodes() const
return the node set on this mimedata object – for internal use
static QMimeData * mimeForLayersDeepCopy(const KisNodeList &nodes, KisImageSP image, bool forceCopy)
static QString mimeTypeForFile(const QString &file, bool checkExistingFiles=true)
Find the mimetype for the given filename. The filename must include a suffix.
bool write(KisPaintDeviceWriter &store)
const KoColorSpace * colorSpace() const
QImage convertToQImage(const KoColorProfile *dstProfile, qint32 x, qint32 y, qint32 w, qint32 h, KoColorConversionTransformation::Intent renderingIntent=KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags=KoColorConversionTransformation::internalConversionFlags()) const
static KisPart * instance()
Definition KisPart.cpp:131
The KisRemoteFileFetcher class can fetch a remote file and blocks until the file is downloaded.
bool fetchFile(const QUrl &remote, QIODevice *io)
fetch the image. Shows a progress dialog
int start() const
int end() const
static KisTimeSpan fromTimeToTime(int start, int end)
bool isValid() const
virtual KoID colorModelId() const =0
virtual KoID colorDepthId() const =0
virtual const KoColorProfile * profile() const =0
QString id() const
Definition KoID.cpp:63
@ Read
Definition KoStore.h:29
@ Write
Definition KoStore.h:29
static KoStore * createStore(const QString &fileName, Mode mode, const QByteArray &appIdentification=QByteArray(), Backend backend=Auto, bool writeMimetype=true)
Definition KoStore.cpp:39
This file is part of the Krita application in calligra.
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
#define bounds(x, a, b)
#define warnKrita
Definition kis_debug.h:87
#define dbgUI
Definition kis_debug.h:52
#define dbgRegistry
Definition kis_debug.h:47
KisDocument * createDocument(QList< KisNodeSP > nodes, KisImageSP srcImage, const QRect &copiedBounds)
void filterMergeableNodes(KisNodeList &nodes, bool allowMasks)
void refreshHiddenAreaAsync(KisImageSP image, KisNodeSP rootNode, const QRect &preparedArea)
void forceAllDelayedNodesUpdate(KisNodeSP root)
auto mem_bit_or(MemType Class::*ptr)
mem_bit_or is a binary functor that applies a bitwise-or operator to member of an object and a given ...
Definition KisMpl.h:589
QSet< QString > mimeTypes
virtual QRect exactBounds() const
virtual const KoColorSpace * colorSpace() const =0
bool addNode(KisNodeSP node, KisNodeSP parent=KisNodeSP(), KisNodeAdditionFlags flags=KisNodeAdditionFlag::None)
virtual QByteArray rawData() const
virtual QString type() const
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()
const KoColorSpace * rgb8(const QString &profileName=QString())
const KoColorProfile * createColorProfile(const QString &colorModelId, const QString &colorDepthId, const QByteArray &rawData)