Krita Source Code Documentation
Loading...
Searching...
No Matches
KisSafeDocumentLoader Class Reference

#include <kis_safe_document_loader.h>

+ Inheritance diagram for KisSafeDocumentLoader:

Classes

struct  Private
 

Signals

void fileExistsStateChanged (bool fileExists)
 
void loadingFailed ()
 
void loadingFinished (KisPaintDeviceSP paintDevice, qreal xRes, qreal yRes, const QSize &size)
 

Public Member Functions

 KisSafeDocumentLoader (const QString &path="", QObject *parent=0)
 
void reloadImage ()
 
void setPath (const QString &path)
 
 ~KisSafeDocumentLoader () override
 

Private Slots

void delayedLoadStart ()
 
void fileChanged (QString)
 
void fileChangedCompressed (bool sync=false)
 
void slotFileExistsStateChanged (const QString &path, bool fileExists)
 

Private Attributes

Private *const m_d
 

Detailed Description

Definition at line 14 of file kis_safe_document_loader.h.

Constructor & Destructor Documentation

◆ KisSafeDocumentLoader()

KisSafeDocumentLoader::KisSafeDocumentLoader ( const QString & path = "",
QObject * parent = 0 )

Definition at line 225 of file kis_safe_document_loader.cpp.

226 : QObject(parent),
227 m_d(new Private())
228{
229 connect(s_fileSystemWatcher, SIGNAL(fileChanged(QString)),
230 SLOT(fileChanged(QString)));
231
232 connect(s_fileSystemWatcher, SIGNAL(fileExistsStateChanged(QString, bool)),
233 SLOT(slotFileExistsStateChanged(QString, bool)));
234
235 connect(&m_d->fileChangedSignalCompressor, SIGNAL(timeout()),
236 SLOT(fileChangedCompressed()));
237
238 setPath(path);
239}
void fileChangedCompressed(bool sync=false)
void fileExistsStateChanged(bool fileExists)
void setPath(const QString &path)
void slotFileExistsStateChanged(const QString &path, bool fileExists)

References fileChanged(), fileChangedCompressed(), KisSafeDocumentLoader::Private::fileChangedSignalCompressor, fileExistsStateChanged(), m_d, setPath(), and slotFileExistsStateChanged().

◆ ~KisSafeDocumentLoader()

KisSafeDocumentLoader::~KisSafeDocumentLoader ( )
override

Definition at line 241 of file kis_safe_document_loader.cpp.

242{
243 if (!m_d->path.isEmpty()) {
244 s_fileSystemWatcher->removePath(m_d->path);
245 }
246
247 delete m_d;
248}

References m_d, and KisSafeDocumentLoader::Private::path.

Member Function Documentation

◆ delayedLoadStart

void KisSafeDocumentLoader::delayedLoadStart ( )
privateslot

TODO: Ideally we should modify our KisDocument code to allow loading from a QIODevice, but currently it supports loading from a local file only. That is why we just extract the PNG into a temporary file and load it separately.

NOTE: we cannot use QImage for loading, since it strips the color profile attached to the PNG file

Definition at line 318 of file kis_safe_document_loader.cpp.

319{
320 QFileInfo originalInfo(m_d->path);
321 QFileInfo tempInfo(m_d->temporaryPath);
322 bool successfullyLoaded = false;
323
324 if (!m_d->fileChangedFlag &&
325 originalInfo.size() == m_d->initialFileSize &&
326 originalInfo.lastModified() == m_d->initialFileTimeStamp &&
327 tempInfo.size() == m_d->initialFileSize) {
328
329 m_d->doc.reset(KisPart::instance()->createTemporaryDocument());
330 m_d->doc->setFileBatchMode(true);
331
332 auto loadPathNatively = [&doc = m_d->doc](const QString &path) -> bool {
333 const bool successfullyLoaded = doc->openPath(path, KisDocument::DontAddToRecent);
334 if (successfullyLoaded) {
335 // Wait for required updates, if any. BUG: 448256
336 KisLayerUtils::forceAllDelayedNodesUpdate(doc->image()->root());
337 doc->image()->waitForDone();
338 }
339 return successfullyLoaded;
340 };
341
342 if (m_d->path.toLower().endsWith("ora") || m_d->path.toLower().endsWith("kra")) {
343 QScopedPointer<KoStore> store(KoStore::createStore(m_d->temporaryPath, KoStore::Read));
344 if (store && !store->bad()) {
345 if (store->open(QString("mergedimage.png"))) {
356 QTemporaryFile temporaryFile(QDir::tempPath() + QLatin1String("/krita_merged_image_XXXXXX.png"));
357 temporaryFile.open();
358
359 QByteArray buffer(BUFSIZ, 0);
360 qint64 totalWritten = 0;
361 const qint64 expectedFileSize = store->size();
362
363 while (true) {
364 qint64 read = store->read(buffer.data(), buffer.size());
365 if (read < 0) {
366 warnKrita << "Failed to read from mergedimage.png for the file layer's projection";
367 break;
368 } else if (read == 0) {
369 // End of file
370 break;
371 } else {
372 // Successful read, try to write it.
373 qint64 written = temporaryFile.write(buffer.constData(), read);
374 if (written < 0) {
375 // Write error.
376 warnKrita << "Failed to wirte mergedimage.png into a temporary file for the file layer's projection"
377 << temporaryFile.fileName() << ":" << temporaryFile.error();
378 break;
379 }
380 // We may not have written as much as we read, but we handle
381 // that at the end.
382 totalWritten += written;
383 }
384 }
385
386 temporaryFile.close();
387 store->close();
388
389 if (totalWritten == expectedFileSize) {
390 successfullyLoaded = loadPathNatively(temporaryFile.fileName());
391 } else {
392 successfullyLoaded = false;
393 }
394 }
395 else {
396 qWarning() << "delayedLoadStart: Could not open mergedimage.png";
397 }
398 }
399 else {
400 qWarning() << "delayedLoadStart: Store was bad";
401 }
402 }
403 else {
404 successfullyLoaded = loadPathNatively(m_d->temporaryPath);
405 }
406 } else {
407 dbgKrita << "File was modified externally. Restarting.";
411 dbgKrita << ppVar(originalInfo.size());
412 dbgKrita << ppVar(originalInfo.lastModified());
413 dbgKrita << ppVar(tempInfo.size());
414 }
415
416 QFile::remove(m_d->temporaryPath);
417 m_d->isLoading = false;
418
419 if (!successfullyLoaded) {
420 // Restart the attempt
421 m_d->failureCount++;
422 if (m_d->failureCount >= 3) {
423 Q_EMIT loadingFailed();
424 }
425 else {
427 }
428 }
429 else {
430 KisPaintDeviceSP paintDevice = new KisPaintDevice(m_d->doc->image()->colorSpace());
431 KisPaintDeviceSP projection = m_d->doc->image()->projection();
432 paintDevice->makeCloneFrom(projection, projection->extent());
433 Q_EMIT loadingFinished(paintDevice,
434 m_d->doc->image()->xRes(),
435 m_d->doc->image()->yRes(),
436 m_d->doc->image()->size());
437 }
438
439 m_d->doc.reset();
440}
QRect extent() const
void makeCloneFrom(KisPaintDeviceSP src, const QRect &rect)
static KisPart * instance()
Definition KisPart.cpp:131
void loadingFinished(KisPaintDeviceSP paintDevice, qreal xRes, qreal yRes, const QSize &size)
@ Read
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
#define dbgKrita
Definition kis_debug.h:45
#define warnKrita
Definition kis_debug.h:87
#define ppVar(var)
Definition kis_debug.h:155
void forceAllDelayedNodesUpdate(KisNodeSP root)

References KoStore::createStore(), dbgKrita, KisSafeDocumentLoader::Private::doc, KisDocument::DontAddToRecent, KisPaintDevice::extent(), KisSafeDocumentLoader::Private::failureCount, KisSafeDocumentLoader::Private::fileChangedFlag, KisSafeDocumentLoader::Private::fileChangedSignalCompressor, KisLayerUtils::forceAllDelayedNodesUpdate(), KisSafeDocumentLoader::Private::initialFileSize, KisSafeDocumentLoader::Private::initialFileTimeStamp, KisPart::instance(), KisSafeDocumentLoader::Private::isLoading, loadingFailed(), loadingFinished(), m_d, KisPaintDevice::makeCloneFrom(), KisSafeDocumentLoader::Private::path, ppVar, KoStore::Read, KisSignalCompressor::start(), KisSafeDocumentLoader::Private::temporaryPath, and warnKrita.

◆ fileChanged

◆ fileChangedCompressed

void KisSafeDocumentLoader::fileChangedCompressed ( bool sync = false)
privateslot

Definition at line 285 of file kis_safe_document_loader.cpp.

286{
287 if (m_d->isLoading) return;
288
289 QFileInfo initialFileInfo(m_d->path);
290 m_d->initialFileSize = initialFileInfo.size();
291 m_d->initialFileTimeStamp = initialFileInfo.lastModified();
292
293 // it may happen when the file is flushed by
294 // so other application
295 if (!m_d->initialFileSize) return;
296
297 m_d->isLoading = true;
298 m_d->fileChangedFlag = false;
299
301 QDir::tempPath() + '/' +
302 QString("krita_file_layer_copy_%1_%2.%3")
303 .arg(QApplication::applicationPid())
304 .arg(QRandomGenerator::global()->generate())
305 .arg(initialFileInfo.suffix());
306
307 QFile::copy(m_d->path, m_d->temporaryPath);
308
309
310 if (!sync) {
311 QTimer::singleShot(100, Qt::CoarseTimer, this, SLOT(delayedLoadStart()));
312 } else {
313 QApplication::processEvents();
315 }
316}

References delayedLoadStart(), KisSafeDocumentLoader::Private::fileChangedFlag, KisSafeDocumentLoader::Private::initialFileSize, KisSafeDocumentLoader::Private::initialFileTimeStamp, KisSafeDocumentLoader::Private::isLoading, m_d, KisSafeDocumentLoader::Private::path, and KisSafeDocumentLoader::Private::temporaryPath.

◆ fileExistsStateChanged

void KisSafeDocumentLoader::fileExistsStateChanged ( bool fileExists)
signal

◆ loadingFailed

void KisSafeDocumentLoader::loadingFailed ( )
signal

◆ loadingFinished

void KisSafeDocumentLoader::loadingFinished ( KisPaintDeviceSP paintDevice,
qreal xRes,
qreal yRes,
const QSize & size )
signal

◆ reloadImage()

void KisSafeDocumentLoader::reloadImage ( )

Definition at line 262 of file kis_safe_document_loader.cpp.

263{
265}

References fileChangedCompressed().

◆ setPath()

void KisSafeDocumentLoader::setPath ( const QString & path)

Definition at line 250 of file kis_safe_document_loader.cpp.

251{
252 if (path.isEmpty()) return;
253
254 if (!m_d->path.isEmpty()) {
255 s_fileSystemWatcher->removePath(m_d->path);
256 }
257
258 m_d->path = path;
259 s_fileSystemWatcher->addPath(m_d->path);
260}

References m_d, and KisSafeDocumentLoader::Private::path.

◆ slotFileExistsStateChanged

void KisSafeDocumentLoader::slotFileExistsStateChanged ( const QString & path,
bool fileExists )
privateslot

Definition at line 275 of file kis_safe_document_loader.cpp.

276{
278 Q_EMIT fileExistsStateChanged(fileExists);
279 if (fileExists) {
280 fileChanged(path);
281 }
282 }
283}

References fileChanged(), fileExistsStateChanged(), m_d, KisSafeDocumentLoader::Private::path, and FileSystemWatcherWrapper::unifyFilePath().

Member Data Documentation

◆ m_d

Private* const KisSafeDocumentLoader::m_d
private

Definition at line 37 of file kis_safe_document_loader.h.


The documentation for this class was generated from the following files: