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
220 const QByteArray mimeType = QByteArrayLiteral(
"application/x-krita-selection");
228 if (cbData->hasFormat(mimeType)) {
229 QByteArray encodedData = cbData->data(mimeType);
230 QBuffer buffer(&encodedData);
235 QString csDepth, csModel;
238 if (store->hasFile(
"colormodel")) {
239 store->open(
"colormodel");
240 csModel = QString(store->read(store->size()));
244 if (store->hasFile(
"colordepth")) {
245 store->open(
"colordepth");
246 csDepth = QString(store->read(store->size()));
250 if (store->hasFile(
"profile.icc")) {
252 store->open(
"profile.icc");
253 data = store->read(store->size());
262 if (store->hasFile(
"layerdata")) {
263 store->open(
"layerdata");
264 if (!
clip->read(store->device())) {
270 if (
clip && !imageBounds.isEmpty()) {
272 if (store->hasFile(
"topLeft")) {
273 store->open(
"topLeft");
274 QString str = store->read(store->size());
277 if (list.size() == 2) {
278 QPoint topLeft(list[0].toInt(), list[1].toInt());
279 clip->setX(topLeft.x());
280 clip->setY(topLeft.y());
284 QRect clipBounds =
clip->exactBounds();
286 if (!imageBounds.contains(clipBounds) && !imageBounds.intersects(clipBounds)) {
287 QPoint diff = imageBounds.center() - clipBounds.center();
292 if (store->hasFile(
"timeRange") && clipRange) {
293 store->open(
"timeRange");
294 QString str = store->read(store->size());
297 if (list.size() == 2) {
300 dbgUI <<
"Pasted time range" << range;
318 const KisMimeData *mimedata = qobject_cast<const KisMimeData *>(data);
319 if (!mimedata)
return 0;
323 if (nodes.size() > 1) {
326 QRect
bounds = QRect(0, 0, 1, 1);
344 }
else if (!nodes.isEmpty()) {
345 return nodes.first()->projection();
351QPair<bool, KisClipboard::PasteFormatBehaviour>
353 bool useClipboardFallback)
const
361 bool saveSourceSetting =
false;
365 const QImage qimage = [&]() {
368 if (qimage.isNull() && useClipboardFallback) {
375 if (!qimage.isNull() || cbData->hasUrls()) {
376 const auto &urls = cbData->urls();
382 std::for_each(urls.constBegin(), urls.constEnd(), [&](
const QUrl &url) {
383 local |= url.isLocalFile();
384 remote |= !url.isLocalFile();
385 isURI |= url.scheme() ==
"data";
388 const bool hasMultipleFormatsAvailable = (remote && local)
389 || (remote && !qimage.isNull()) || (local && !qimage.isNull());
391 const bool defaultOptionUnavailable =
396 dbgUI <<
"Incoming paste event:";
397 dbgUI <<
"\tHas attached bitmap:" << cbData->hasImage();
398 dbgUI <<
"\tHas local images:" << local;
399 dbgUI <<
"\tHas remote images:" << remote;
400 dbgUI <<
"\tHas multiple formats:" << hasMultipleFormatsAvailable;
401 dbgUI <<
"\tDefault source preference" << choice;
402 dbgUI <<
"\tDefault source available:" << !defaultOptionUnavailable;
403 dbgUI <<
"\tIs data URI:" << isURI;
412 if (dlg.exec() != KoDialog::Accepted) {
424 }
else if (!qimage.isNull()) {
434 if (saveSourceSetting) {
438 dbgUI <<
"Selected source for the paste:" << choice;
440 return {
true, choice};
444 const QRect &imageBounds,
446 int pasteBehaviourOverride,
447 bool useClipboardFallback,
448 QPair<bool, PasteFormatBehaviour>
source)
const
465 const QImage qimage = [&]() {
468 if (qimage.isNull() && useClipboardFallback) {
477 warnKrita <<
"Clipboard was cleared before loading image";
481 int behaviour = pasteBehaviourOverride;
482 bool saveColorSetting =
false;
486 if (pasteBehaviourOverride == -1) {
490 if (behaviour ==
PASTE_ASK && showPopup) {
494 if (dlg.exec() != QDialog::Accepted) {
516 clip->convertFromQImage(qimage, profile);
519 if (saveColorSetting) {
523 const auto &urls = cbData->urls();
524 const auto url = std::find_if(urls.constBegin(), urls.constEnd(), [&](
const QUrl &url) {
525 if (choice == PASTE_FORMAT_DOWNLOAD) {
526 return !url.isLocalFile();
528 return url.isLocalFile();
534 if (url != urls.constEnd()) {
539 if (clip && !imageBounds.isEmpty()) {
540 QRect clipBounds = clip->exactBounds();
541 QPoint diff = imageBounds.center() - clipBounds.center();
542 clip->setX(diff.x());
543 clip->setY(diff.y());
552 const QMimeData *cbData =
d->
clipboard->mimeData();
554 || (cbData && cbData->hasFormat(
"application/x-krita-selection"));
567 const auto mimeType = QByteArrayLiteral(
"application/x-krita-selection");
568 const QMimeData *cbData =
d->
clipboard->mimeData();
572 if (cbData && cbData->hasFormat(mimeType)) {
573 QByteArray encodedData = cbData->data(mimeType);
574 QBuffer buffer(&encodedData);
577 QString csDepth, csModel;
580 if (store->hasFile(
"colormodel")) {
581 store->open(
"colormodel");
582 csModel = QString(store->read(store->size()));
586 if (store->hasFile(
"colordepth")) {
587 store->open(
"colordepth");
588 csDepth = QString(store->read(store->size()));
592 if (store->hasFile(
"profile.icc")) {
594 store->open(
"profile.icc");
595 data = store->read(store->size());
606 if (store->hasFile(
"layerdata")) {
607 store->open(
"layerdata");
608 clip->read(store->device());
612 return clip->exactBounds().size();
616 return qimage.size();
636 const QByteArray mimeType = QByteArrayLiteral(
"application/x-krita-node-internal-pointer");
637 return d->
clipboard->mimeData()->hasFormat(mimeType);
646 return d->
clipboard->mimeData()->hasFormat(
"application/x-krita-layer-style");
651 const QMimeData *cbData =
d->
clipboard->mimeData();
652 return cbData->hasFormat(
"application/x-krita-node-internal-pointer") ? cbData : 0;
663 {{
"image/png"},
"PNG"},
664 {{
"image/tiff"},
"TIFF"},
665 {{
"image/bmp",
"image/x-bmp",
"image/x-MS-bmp",
"image/x-win-bitmap"},
"BMP"}};
668 QSet<QString> clipboardMimeTypes;
670 Q_FOREACH (
const QString &format, cbData->formats()) {
671 clipboardMimeTypes << format;
675 const QSet<QString> &intersection = item.
mimeTypes & clipboardMimeTypes;
676 if (intersection.isEmpty()) {
680 const QString &format = *intersection.constBegin();
681 const QByteArray &imageData = cbData->data(format);
682 if (imageData.isEmpty()) {
686 if (image.loadFromData(imageData, item.
format.toLatin1())) {
691 if (image.isNull() && cbData->hasImage()) {
692 image = qvariant_cast<QImage>(cbData->imageData());
701 QUrl url(originalUrl);
702 QScopedPointer<QTemporaryFile>
tmp;
704 if (!originalUrl.isLocalFile()) {
705 tmp.reset(
new QTemporaryFile());
706 tmp->setAutoRemove(
true);
712 qWarning() <<
"Fetching" << originalUrl <<
"failed";
715 url = QUrl::fromLocalFile(
tmp->fileName());
718 if (url.isLocalFile()) {
719 QFileInfo fileInfo(url.toLocalFile());
724 if (!mimes.contains(type)) {
727 i18nc(
"@title:window",
"Krita"),
728 i18n(
"Could not open %2.\nReason: %1.", msg, url.toDisplayString()));
737 doc->image()->waitForDone();
740 qWarning() <<
"Failed to import file" << url.toLocalFile();
KisMagneticGraph::vertex_descriptor source(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
Q_GLOBAL_STATIC(KisStoragePluginRegistry, s_instance)
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
A data extension mechanism for Krita.
void setLayers(KisNodeList nodes, KisImageSP image, bool forceCopy=false)
void clipboardDataChanged()
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
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 refreshHiddenAreaAsync(KisImageSP image, KisNodeSP rootNode, const QRect &preparedArea)
void forceAllDelayedNodesUpdate(KisNodeSP root)
virtual QRect exactBounds() const
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)