10#include <QApplication>
17#include <QScopedPointer>
18#include <QTemporaryFile>
58 : clipboard(QApplication::clipboard())
63 bool pushedClipboard{};
97 const auto mimeType = QByteArrayLiteral(
"application/x-krita-selection");
101 Q_ASSERT(!store->bad());
104 if (store->open(
"layerdata")) {
105 if (!dev->
write(writer)) {
114 if (range.
isValid() && store->open(
"timeRange")) {
115 store->
write(QString(
"%1 %2").arg(range.
start()).arg(range.
end()).toLatin1());
120 if (store->open(
"topLeft")) {
121 store->write(QString(
"%1 %2").arg(topLeft.x()).arg(topLeft.y()).toLatin1());
125 if (store->open(
"colormodel")) {
127 store->write(csName.toLatin1());
130 if (store->open(
"colordepth")) {
132 store->write(csName.toLatin1());
140 if (profile && profile->
type() ==
"icc" && !profile->
rawData().isEmpty()) {
145 if (store->open(
"profile.icc")) {
146 store->write(annotation->annotation());
153 QMimeData *mimeData =
new QMimeData;
154 Q_CHECK_PTR(mimeData);
157 mimeData->setData(mimeType, buffer.buffer());
167 if (!qimage.isNull() && mimeData) {
168 mimeData->setImageData(qimage);
184 const QMimeData *cbData =
d->
clipboard->mimeData();
190 dbgUI << Q_FUNC_INFO;
191 dbgUI <<
"\tFormats: " << cbData->formats();
192 dbgUI <<
"\tUrls: " << cbData->urls();
193 dbgUI <<
"\tHas images: " << cbData->hasImage();
195 return clipFromMimeData(cbData, imageBounds, showPopup, overridePasteBehaviour, clipRange,
true);
199 const QRect &imageBounds,
201 int overridePasteBehaviour,
203 bool useClipboardFallback)
const
224 const QByteArray mimeType = QByteArrayLiteral(
"application/x-krita-selection");
232 if (cbData->hasFormat(mimeType)) {
233 QByteArray encodedData = cbData->data(mimeType);
234 QBuffer buffer(&encodedData);
239 QString csDepth, csModel;
242 if (store->hasFile(
"colormodel")) {
243 store->open(
"colormodel");
244 csModel = QString(store->read(store->size()));
248 if (store->hasFile(
"colordepth")) {
249 store->open(
"colordepth");
250 csDepth = QString(store->read(store->size()));
254 if (store->hasFile(
"profile.icc")) {
256 store->open(
"profile.icc");
257 data = store->read(store->size());
266 if (store->hasFile(
"layerdata")) {
267 store->open(
"layerdata");
268 if (!
clip->read(store->device())) {
274 if (
clip && !imageBounds.isEmpty()) {
276 if (store->hasFile(
"topLeft")) {
277 store->open(
"topLeft");
278 QString str = store->read(store->size());
281 if (list.size() == 2) {
282 QPoint topLeft(list[0].toInt(), list[1].toInt());
283 clip->setX(topLeft.x());
284 clip->setY(topLeft.y());
288 QRect clipBounds =
clip->exactBounds();
290 if (!imageBounds.contains(clipBounds) && !imageBounds.intersects(clipBounds)) {
291 QPoint diff = imageBounds.center() - clipBounds.center();
296 if (store->hasFile(
"timeRange") && clipRange) {
297 store->open(
"timeRange");
298 QString str = store->read(store->size());
301 if (list.size() == 2) {
304 dbgUI <<
"Pasted time range" << range;
322 const KisMimeData *mimedata = qobject_cast<const KisMimeData *>(data);
323 if (!mimedata)
return 0;
327 if (nodes.size() > 1) {
331 std::accumulate(nodes.begin(), nodes.end(), QRect(0, 0, 1, 1),
336 QHash<const KoColorSpace *, int> colorSpacesCount;
340 if (colorSpace !=
nullptr) {
341 colorSpacesCount.insert(colorSpace, colorSpacesCount.value(colorSpace) + 1);
346 for (
auto it = colorSpacesCount.begin(); it != colorSpacesCount.end(); ++it) {
347 if (it.value() > max) {
375 }
else if (!nodes.isEmpty()) {
376 return nodes.first()->projection();
382QPair<bool, KisClipboard::PasteFormatBehaviour>
394QPair<bool, KisClipboard::PasteFormatBehaviour>
399 bool saveSourceSetting =
false;
403 if (!qimage.isNull() || !urls.isEmpty()) {
408 std::for_each(urls.constBegin(), urls.constEnd(), [&](
const QUrl &url) {
409 local |= url.isLocalFile();
410 remote |= !url.isLocalFile();
411 isURI |= url.scheme() ==
"data";
414 const bool hasMultipleFormatsAvailable = (remote && local)
415 || (remote && !qimage.isNull()) || (local && !qimage.isNull());
417 const bool defaultOptionUnavailable =
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;
438 if (dlg.exec() != KoDialog::Accepted) {
450 }
else if (!qimage.isNull()) {
460 if (saveSourceSetting) {
464 dbgUI <<
"Selected source for the paste:" << choice;
466 return {
true, choice};
470 const QRect &imageBounds,
472 int pasteBehaviourOverride,
473 bool useClipboardFallback,
474 QPair<bool, PasteFormatBehaviour>
source)
const
481 const auto &urls = cbData->urls();
488 pasteBehaviourOverride,
489 useClipboardFallback,
495 const QRect &imageBounds,
497 int pasteBehaviourOverride,
498 bool useClipboardFallback,
499 QPair<bool, PasteFormatBehaviour>
source)
const
513 warnKrita <<
"Clipboard was cleared before loading image";
517 int behaviour = pasteBehaviourOverride;
518 bool saveColorSetting =
false;
522 if (pasteBehaviourOverride == -1) {
526 if (behaviour ==
PASTE_ASK && showPopup) {
530 if (dlg.exec() != QDialog::Accepted) {
552 clip->convertFromQImage(qimage, profile);
555 if (saveColorSetting) {
559 const auto url = std::find_if(urls.constBegin(), urls.constEnd(), [&](
const QUrl &url) {
560 if (choice == PASTE_FORMAT_DOWNLOAD) {
561 return !url.isLocalFile();
563 return url.isLocalFile();
569 if (url != urls.constEnd()) {
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());
587 const QMimeData *cbData =
d->
clipboard->mimeData();
589 || (cbData && cbData->hasFormat(
"application/x-krita-selection"));
599 if (qimage.isNull() && useClipboardFallback) {
613 const auto mimeType = QByteArrayLiteral(
"application/x-krita-selection");
614 const QMimeData *cbData =
d->
clipboard->mimeData();
618 if (cbData && cbData->hasFormat(mimeType)) {
619 QByteArray encodedData = cbData->data(mimeType);
620 QBuffer buffer(&encodedData);
623 QString csDepth, csModel;
626 if (store->hasFile(
"colormodel")) {
627 store->open(
"colormodel");
628 csModel = QString(store->read(store->size()));
632 if (store->hasFile(
"colordepth")) {
633 store->open(
"colordepth");
634 csDepth = QString(store->read(store->size()));
638 if (store->hasFile(
"profile.icc")) {
640 store->open(
"profile.icc");
641 data = store->read(store->size());
652 if (store->hasFile(
"layerdata")) {
653 store->open(
"layerdata");
654 clip->read(store->device());
658 return clip->exactBounds().size();
662 return qimage.size();
682 const QByteArray mimeType = QByteArrayLiteral(
"application/x-krita-node-internal-pointer");
683 return d->
clipboard->mimeData()->hasFormat(mimeType);
692 return d->
clipboard->mimeData()->hasFormat(
"application/x-krita-layer-style");
697 const QMimeData *cbData =
d->
clipboard->mimeData();
698 return cbData->hasFormat(
"application/x-krita-node-internal-pointer") ? cbData : 0;
715 {{
"image/png"},
"PNG"},
716 {{
"image/tiff"},
"TIFF"},
717 {{
"image/bmp",
"image/x-bmp",
"image/x-MS-bmp",
"image/x-win-bitmap"},
"BMP"}};
720 QSet<QString> clipboardMimeTypes;
722 Q_FOREACH (
const QString &format, cbData->formats()) {
723 clipboardMimeTypes << format;
727 const QSet<QString> &intersection = item.
mimeTypes & clipboardMimeTypes;
728 if (intersection.isEmpty()) {
732 const QString &format = *intersection.constBegin();
733 const QByteArray &imageData = cbData->data(format);
734 if (imageData.isEmpty()) {
738 if (image.loadFromData(imageData, item.
format.toLatin1())) {
743 if (image.isNull() && cbData->hasImage()) {
744 image = qvariant_cast<QImage>(cbData->imageData());
753 QUrl url(originalUrl);
754 QScopedPointer<QTemporaryFile>
tmp;
756 if (!originalUrl.isLocalFile()) {
757 tmp.reset(
new QTemporaryFile());
758 tmp->setAutoRemove(
true);
764 qWarning() <<
"Fetching" << originalUrl <<
"failed";
767 url = QUrl::fromLocalFile(
tmp->fileName());
770 if (url.isLocalFile()) {
771 QFileInfo fileInfo(url.toLocalFile());
776 if (!mimes.contains(type)) {
779 i18nc(
"@title:window",
"Krita"),
780 i18n(
"Could not open %2.\nReason: %1.", msg, url.toDisplayString()));
789 doc->image()->waitForDone();
792 qWarning() <<
"Failed to import file" << url.toLocalFile();
KisMagneticGraph::vertex_descriptor source(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
Q_GLOBAL_STATIC(KisStoragePluginRegistry, s_instance)
A data extension mechanism for Krita.
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()
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
KisPaintDeviceSP fetchImageByURL(const QUrl &originalUrl) 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
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
void refreshGraphAsync(KisNodeSP root, const QVector< QRect > &rects, const QRect &cropRect, KisProjectionUpdateFlags flags=KisProjectionUpdateFlag::None) override
KisPaintDeviceSP projection() const
QString errorMessage() 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()
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
static KisTimeSpan fromTimeToTime(int start, int end)
virtual KoID colorModelId() const =0
virtual KoID colorDepthId() const =0
virtual const KoColorProfile * profile() const =0
static KoStore * createStore(const QString &fileName, Mode mode, const QByteArray &appIdentification=QByteArray(), Backend backend=Auto, bool writeMimetype=true)
This file is part of the Krita application in calligra.
#define KIS_SAFE_ASSERT_RECOVER(cond)
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 ...
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)