10#include <QFileSystemWatcher>
11#include <QRandomGenerator>
12#include <QApplication>
18#include <QTemporaryFile>
103 if (QFileInfo(path).exists()) {
109 if (oldState ==
Lost) {
137 const bool shouldSpitWarning =
138 absenceTimeMSec <= 600000 &&
139 ((absenceTimeMSec >= 60000 && (absenceTimeMSec % 60000 == 0)) ||
140 (absenceTimeMSec >= 10000 && (absenceTimeMSec % 10000 == 0)));
142 if (shouldSpitWarning) {
144 QTextStream log(&message);
147 log <<
"WARNING: couldn't reconnect to a removed file layer's file (" << path <<
"). File is not available for " << absenceTimeMSec / 1000 <<
" seconds";
149 qWarning() << message;
152 if (absenceTimeMSec == 600000) {
156 log <<
"Giving up... :( No more reports about " << path;
158 qWarning() << message;
171 if (it.value().state ==
Lost)
190 return QFileInfo(path).absoluteFilePath();
212 QScopedPointer<KisDocument>
doc;
214 bool isLoading =
false;
215 bool fileChangedFlag =
false;
219 qint64 initialFileSize {0};
222 int failureCount {0};
229 connect(s_fileSystemWatcher, SIGNAL(
fileChanged(QString)),
244 s_fileSystemWatcher->removePath(
m_d->
path);
252 if (path.isEmpty())
return;
255 s_fileSystemWatcher->removePath(
m_d->
path);
259 s_fileSystemWatcher->addPath(
m_d->
path);
289 QFileInfo initialFileInfo(
m_d->
path);
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());
313 QApplication::processEvents();
320 QFileInfo originalInfo(
m_d->
path);
322 bool successfullyLoaded =
false;
330 m_d->
doc->setFileBatchMode(
true);
332 auto loadPathNatively = [&doc =
m_d->
doc](
const QString &path) ->
bool {
334 if (successfullyLoaded) {
337 doc->image()->waitForDone();
339 return successfullyLoaded;
342 if (
m_d->
path.toLower().endsWith(
"ora") ||
m_d->
path.toLower().endsWith(
"kra")) {
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();
359 QByteArray buffer(BUFSIZ, 0);
360 qint64 totalWritten = 0;
361 const qint64 expectedFileSize = store->size();
364 qint64 read = store->read(buffer.data(), buffer.size());
366 warnKrita <<
"Failed to read from mergedimage.png for the file layer's projection";
368 }
else if (read == 0) {
373 qint64 written = temporaryFile.write(buffer.constData(), read);
376 warnKrita <<
"Failed to wirte mergedimage.png into a temporary file for the file layer's projection"
377 << temporaryFile.fileName() <<
":" << temporaryFile.error();
382 totalWritten += written;
386 temporaryFile.close();
389 if (totalWritten == expectedFileSize) {
390 successfullyLoaded = loadPathNatively(temporaryFile.fileName());
392 successfullyLoaded =
false;
396 qWarning() <<
"delayedLoadStart: Could not open mergedimage.png";
400 qWarning() <<
"delayedLoadStart: Store was bad";
407 dbgKrita <<
"File was modified externally. Restarting.";
419 if (!successfullyLoaded) {
434 m_d->
doc->image()->xRes(),
435 m_d->
doc->image()->yRes(),
436 m_d->
doc->image()->size());
442#include "kis_safe_document_loader.moc"
Q_GLOBAL_STATIC(KisStoragePluginRegistry, s_instance)
QHash< QString, int > m_pathCount
static QString unifyFilePath(const QString &path)
QStringList files() const
bool addPath(const QString &file)
QHash< QString, FileEntry > m_fileEntries
KisSignalCompressor m_reattachmentCompressor
void slotFileChanged(const QString &path)
FileSystemWatcherWrapper()
void fileExistsStateChanged(const QString &path, bool exists)
QFileSystemWatcher m_watcher
KisSignalCompressor m_lostCompressor
bool removePath(const QString &file)
void fileChanged(const QString &path)
QHash< QString, int > m_lostFilesAbsenceCounter
void makeCloneFrom(KisPaintDeviceSP src, const QRect &rect)
static KisPart * instance()
~KisSafeDocumentLoader() override
void fileChangedCompressed(bool sync=false)
void fileChanged(QString)
void fileExistsStateChanged(bool fileExists)
void setPath(const QString &path)
void loadingFinished(KisPaintDeviceSP paintDevice, qreal xRes, qreal yRes, const QSize &size)
void slotFileExistsStateChanged(const QString &path, bool fileExists)
KisSafeDocumentLoader(const QString &path="", QObject *parent=0)
static void log(const QString &message)
Logs with date/time.
static KoStore * createStore(const QString &fileName, Mode mode, const QByteArray &appIdentification=QByteArray(), Backend backend=Auto, bool writeMimetype=true)
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
void forceAllDelayedNodesUpdate(KisNodeSP root)
void setUtf8OnStream(QTextStream &stream)
QDateTime initialFileTimeStamp
KisSignalCompressor fileChangedSignalCompressor
QScopedPointer< KisDocument > doc