Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_file_layer.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2013 Boudewijn Rempt <boud@valdyas.org>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6#include "kis_file_layer.h"
7
8#include <QFile>
9#include <QFileInfo>
10
12#include "kis_filter_strategy.h"
14#include "kis_node_visitor.h"
15#include "kis_image.h"
16#include "kis_types.h"
18#include "kis_default_bounds.h"
20#include <KisPart.h>
21#include <KisDocument.h>
22#include <QDir>
23
24
25KisFileLayer::KisFileLayer(KisImageWSP image, const QString &name, quint8 opacity)
26 : KisExternalLayer(image, name, opacity)
27{
35
36 connect(&m_loader, SIGNAL(loadingFinished(KisPaintDeviceSP,qreal,qreal,QSize)), SLOT(slotLoadingFinished(KisPaintDeviceSP,qreal,qreal,QSize)));
37 connect(&m_loader, SIGNAL(loadingFailed()), SLOT(slotLoadingFailed()));
38 connect(&m_loader, SIGNAL(fileExistsStateChanged(bool)), SLOT(slotFileExistsStateChanged(bool)));
39 connect(this, SIGNAL(sigRequestOpenFile()), SLOT(openFile()));
40}
41
42KisFileLayer::KisFileLayer(KisImageWSP image, const QString &basePath, const QString &filename, ScalingMethod scaleToImageResolution, QString scalingFilter, const QString &name, quint8 opacity, const KoColorSpace *fallbackColorSpace)
43 : KisExternalLayer(image, name, opacity)
44 , m_basePath(basePath)
45 , m_filename(filename)
46 , m_scalingMethod(scaleToImageResolution)
47 , m_scalingFilter(scalingFilter)
48{
54 m_paintDevice = new KisPaintDevice(fallbackColorSpace ? fallbackColorSpace : image->colorSpace());
56
57 connect(&m_loader, SIGNAL(loadingFinished(KisPaintDeviceSP,qreal,qreal,QSize)), SLOT(slotLoadingFinished(KisPaintDeviceSP,qreal,qreal,QSize)));
58 connect(&m_loader, SIGNAL(loadingFailed()), SLOT(slotLoadingFailed()));
59 connect(&m_loader, SIGNAL(fileExistsStateChanged(bool)), SLOT(slotFileExistsStateChanged(bool)));
60 connect(this, SIGNAL(sigRequestOpenFile()), SLOT(openFile()));
61
62 QFileInfo fi(path());
63 if (fi.exists()) {
66 }
67}
68
72
92
93QIcon KisFileLayer::icon() const
94{
95 return KisIconUtils::loadIcon("fileLayer");
96}
97
99{
100 Q_UNUSED(colorSpace);
102}
103
108
110{
111 return 0;
112}
113
115{
117 Q_FOREACH (const KisBaseNode::Property &property, properties) {
119 if (property.state.toBool() == false) {
120 Q_EMIT sigRequestOpenFile();
121 }
122 }
123 }
124}
125
127{
129 l << KisBaseNode::Property(KoID("sourcefile", i18n("File")), m_filename);
131
132 auto fileNameOrPlaceholder =
133 [this] () {
134 return !m_filename.isEmpty() ? m_filename : i18nc("placeholder test for a warning when not file is set in the file layer", "<No file name is set>");
135 };
136
137 if (m_state == FileNotFound) {
138 l << KisLayerPropertiesIcons::getErrorProperty(i18nc("a tooltip shown when a file layer cannot find its linked file",
139 "Linked file not found: %1", fileNameOrPlaceholder()));
140 } else if (m_state == FileLoadingFailed) {
141 l << KisLayerPropertiesIcons::getErrorProperty(i18nc("a tooltip shown when a file layer cannot load its linked file",
142 "Failed to load linked file: %1", fileNameOrPlaceholder()));
143 }
144
146 KisImageSP image = this->image();
147 if (image && *image->colorSpace() != *cs) {
149 }
150
151 return l;
152}
153
154void KisFileLayer::setFileName(const QString &basePath, const QString &filename)
155{
156 m_basePath = basePath;
157 m_filename = filename;
158 QFileInfo fi(path());
159 if (fi.exists()) {
162 }
163}
164
166{
167 return m_filename;
168}
169
170QString KisFileLayer::path() const
171{
172 if (m_basePath.isEmpty()) {
173 return m_filename;
174 }
175 else {
176#ifndef Q_OS_ANDROID
177 return QDir(m_basePath).filePath(QDir::cleanPath(m_filename));
178#else
179 return m_filename;
180#endif
181 }
182}
183
185{
186 bool fileAlreadyOpen = false;
187 Q_FOREACH (KisDocument *doc, KisPart::instance()->documents()) {
188 if (doc->path()==path()){
189 fileAlreadyOpen = true;
190 }
191 }
192 if (qEnvironmentVariableIsSet("KRITA_ENABLE_ASSERT_TESTS")) {
194 if (m_filename.toLower() == "crash_me_with_safe_assert") {
195 KIS_SAFE_ASSERT_RECOVER_NOOP(0 && "safe assert for testing purposes");
196 }
197 if (m_filename.toLower() == "crash_me_with_normal_assert") {
198 KIS_ASSERT_RECOVER_NOOP(0 && "normal assert for testing purposes");
199 }
200 if (m_filename.toLower() == "crash_me_with_qfatal") {
201 qFatal("Testing fatal message");
202 }
203
204 if (m_filename.toLower() == "crash_me_with_asan") {
205#if defined(__has_feature)
206#if __has_feature(address_sanitizer)
215 int *array = new int[10];
216 qDebug() << "Reading past the end of the allocated array" << array[10];
217 delete[] array;
218#else
219 qDebug() << "ASAN is not enabled for this build!";
220#endif
221#endif
222 }
223 }
224
225 if (!fileAlreadyOpen && QFile::exists(QFileInfo(path()).absoluteFilePath())) {
226 KisPart::instance()->openExistingFile(QFileInfo(path()).absoluteFilePath());
227 }
228}
229
231{
232 const State oldState = m_state;
233 m_state = newState;
234 if (oldState != newState) {
236 }
237}
238
243
248
250{
251 return m_scalingFilter;
252}
253
255{
256 m_scalingFilter = filter;
257}
258
260 qreal xRes, qreal yRes,
261 const QSize &size)
262{
263 qint32 oldX = x();
264 qint32 oldY = y();
265 const QRect oldLayerExtent = m_paintDevice->extent();
266
267
270
281 KisImageWSP image = this->image();
282 if (image) {
284 (!qFuzzyCompare(image->xRes(), xRes) ||
285 !qFuzzyCompare(image->yRes(), yRes))) {
286
287 qreal xscale = image->xRes() / xRes;
288 qreal yscale = image->yRes() / yRes;
289
290 KisTransformWorker worker(m_paintDevice, xscale, yscale, 0.0, 0, 0, 0, 0, 0, KisFilterStrategyRegistry::instance()->get(m_scalingFilter));
291 worker.run();
292 }
293 else if (m_scalingMethod == ToImageSize && size != image->size()) {
294 QSize sz = size;
295 sz.scale(image->size(), Qt::KeepAspectRatio);
296 qreal xscale = (qreal)sz.width() / (qreal)size.width();
297 qreal yscale = (qreal)sz.height() / (qreal)size.height();
298
299 KisTransformWorker worker(m_paintDevice, xscale, yscale, 0.0, 0, 0, 0, 0, 0, KisFilterStrategyRegistry::instance()->get(m_scalingFilter));
300 worker.run();
301 }
302
306 }
307
308 m_paintDevice->setX(oldX);
309 m_paintDevice->setY(oldY);
310
312 setDirty(m_paintDevice->extent() | oldLayerExtent);
313}
314
319
324
326{
327 return KisNodeSP(new KisFileLayer(*this));
328}
329
331{
332 return node->inherits("KisMask");
333}
334
336{
337 return visitor.visit(this);
338}
339
341{
342 return visitor.visit(this, undoAdapter);
343}
344
346{
347 QPoint oldPos(x(), y());
348 QPoint newPos = oldPos - rect.topLeft();
349
350 return new KisNodeMoveCommand2(this, oldPos, newPos);
351}
352
353KUndo2Command* KisFileLayer::transform(const QTransform &/*transform*/)
354{
355 warnKrita << "WARNING: File Layer does not support transformations!" << name();
356 return 0;
357}
358
360{
361 KisImageSP image = this->image();
362 if (!image) return;
363
366 qFuzzyCompare(image->yRes(), m_generatedForYRes)) {
367
369 }
370}
371
373{
374 KisImageSP image = this->image();
375 if (!image) return;
376
379 }
380}
381
383{
384 KisImageWSP oldImage = this->image();
386
389
390 if (image) {
391 m_imageConnections.addUniqueConnection(image, SIGNAL(sigSizeChanged(QPointF,QPointF)), this, SLOT(slotImageSizeChanged()));
392 m_imageConnections.addUniqueConnection(image, SIGNAL(sigResolutionChanged(double, double)), this, SLOT(slotImageResolutionChanged()));
393 }
394
395 if (m_scalingMethod != None && image && oldImage != image) {
396 bool canSkipReloading = false;
397
399 canSkipReloading = true;
400 }
401
402 if (m_scalingMethod == ToImagePPI && image &&
404 qFuzzyCompare(image->yRes(), m_generatedForYRes)) {
405
406 canSkipReloading = true;
407 }
408
409 if (!canSkipReloading) {
411 }
412 }
413}
414
VertexDescriptor get(PredecessorMap const &m, VertexDescriptor v)
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
QString path() const
The KisFileLayer class loads a particular file as a layer into the layer stack.
qreal m_generatedForXRes
bool allowAsChild(KisNodeSP) const override
void slotImageResolutionChanged()
void slotImageSizeChanged()
KisBaseNode::PropertyList sectionModelProperties() const override
ScalingMethod m_scalingMethod
void resetCache(const KoColorSpace *colorSpace=0) override
KisPaintDeviceSP original() const override
void slotFileExistsStateChanged(bool exists)
void sigRequestOpenFile()
QString path() const
void setImage(KisImageWSP image) override
KisPaintDeviceSP m_paintDevice
qreal m_generatedForYRes
KisSafeDocumentLoader m_loader
ScalingMethod scalingMethod() const
QString m_scalingFilter
QString fileName() const
void slotLoadingFinished(KisPaintDeviceSP projection, qreal xRes, qreal yRes, const QSize &size)
QSize m_generatedForImageSize
KisFileLayer(KisImageWSP image, const QString &name, quint8 opacity)
KisNodeSP clone() const override
QString scalingFilter() const
bool accept(KisNodeVisitor &) override
void setScalingFilter(QString method)
void openFile() const
void setFileName(const QString &basePath, const QString &filename)
setFileName replace the existing file with a new one
void setScalingMethod(ScalingMethod method)
KUndo2Command * crop(const QRect &rect) override
KUndo2Command * transform(const QTransform &transform) override
~KisFileLayer() override
void setSectionModelProperties(const KisBaseNode::PropertyList &properties) override
KisSignalAutoConnectionsStore m_imageConnections
KisPaintDeviceSP paintDevice() const override
QIcon icon() const override
void changeState(State newState)
static KisFilterStrategyRegistry * instance()
const KoColorSpace * colorSpace() const
QSize size() const
Definition kis_image.h:547
double xRes() const
double yRes() const
static KisBaseNode::Property getColorSpaceMismatchProperty(const KoColorSpace *cs)
static KisBaseNode::Property getErrorProperty(const QString &message)
static KisBaseNode::Property getProperty(const KoID &id, bool state)
virtual bool visit(KisNode *node)=0
void setX(qint32 x)
void setDefaultBounds(KisDefaultBoundsBaseSP bounds)
QRect extent() const
const KoColorSpace * colorSpace() const
void setY(qint32 y)
void makeCloneFrom(KisPaintDeviceSP src, const QRect &rect)
static KisPart * instance()
Definition KisPart.cpp:131
void openExistingFile(const QString &path)
Definition KisPart.cpp:537
virtual void visit(KisNode *node, KisUndoAdapter *undoAdapter)=0
void setPath(const QString &path)
void addUniqueConnection(Sender sender, Signal signal, Receiver receiver, Method method)
Definition KoID.h:30
QString id() const
Definition KoID.cpp:63
static bool qFuzzyCompare(half p1, half p2)
#define KIS_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:97
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
#define warnKrita
Definition kis_debug.h:87
#define ENTER_FUNCTION()
Definition kis_debug.h:178
#define ppVar(var)
Definition kis_debug.h:155
KisSharedPtr< KisNode > KisNodeSP
Definition kis_types.h:86
QIcon loadIcon(const QString &name)
virtual void setImage(KisImageWSP image)
KoProperties properties
KisImageWSP image
QString name() const
virtual void setSectionModelProperties(const PropertyList &properties)
KisPaintDeviceSP projection() const override
Definition kis_layer.cc:820
qint32 y() const override
Definition kis_layer.cc:978
qint32 x() const override
Definition kis_layer.cc:973
const KoColorSpace * colorSpace() const override
returns the image's colorSpace or null, if there is no image
Definition kis_layer.cc:225
KisBaseNode::PropertyList sectionModelProperties() const override
Definition kis_layer.cc:272
void baseNodeChangedCallback() override
Definition kis_node.cpp:329
virtual void setDirty()
Definition kis_node.cpp:577