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 qint64 totalWritten = 0;
357 const qint64 expectedFileSize = store->size();
358 QTemporaryFile temporaryFile(QDir::tempPath() + QLatin1String(
"/krita_merged_image_XXXXXX.png"));
359 if (temporaryFile.open()) {
360 QByteArray buffer(BUFSIZ, 0);
363 qint64 read = store->read(buffer.data(), buffer.size());
365 warnKrita <<
"Failed to read from mergedimage.png for the file layer's projection";
367 }
else if (read == 0) {
372 qint64 written = temporaryFile.write(buffer.constData(), read);
375 warnKrita <<
"Failed to write mergedimage.png into a temporary file for the file layer's projection"
376 << temporaryFile.fileName() <<
":" << temporaryFile.errorString();
381 totalWritten += written;
385 temporaryFile.close();
387 warnKrita <<
"Failed to open temporary file for mergedimage.png for the file layer's projection"
388 << temporaryFile.fileName() <<
":" << temporaryFile.errorString();
392 if (totalWritten == expectedFileSize) {
393 successfullyLoaded = loadPathNatively(temporaryFile.fileName());
395 successfullyLoaded =
false;
399 qWarning() <<
"delayedLoadStart: Could not open mergedimage.png";
403 qWarning() <<
"delayedLoadStart: Store was bad";
410 dbgKrita <<
"File was modified externally. Restarting.";
422 if (!successfullyLoaded) {
437 m_d->
doc->image()->xRes(),
438 m_d->
doc->image()->yRes(),
439 m_d->
doc->image()->size());
445#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