45#include <klocalizedstring.h>
50#include <kdesktopfile.h>
51#include <kconfiggroup.h>
55#include <QTextBrowser>
56#include <QApplication>
58#include <QStandardPaths>
60#include <QDomDocument>
68#include <QScopedPointer>
75#include <QFutureWatcher>
132#define STORE_PROTOCOL "tar"
134#define INTERNAL_PROTOCOL "intern"
135#define INTERNAL_PREFIX "intern:/"
147constexpr int errorMessageTimeout = 5000;
148constexpr int successMessageTimeout = 1000;
161 static int s_docIFNumber = 0;
162 QString name; name.setNum(s_docIFNumber++); name.prepend(
"document_");
191 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
209 Q_ASSERT(currentImage);
301 , autoSaveTimer(new QTimer(_q))
303 , m_bAutoDetectedMime(false)
306 , autoSaveActive(true)
307 , firstMod(QDateTime::currentDateTime())
310 , imageIdleWatcher(2000 )
311 , globalAssistantsColor(
KisConfig(true).defaultAssistantsColor())
314 if (QLocale().measurementSystem() == QLocale::ImperialSystem) {
319 connect(&imageIdleWatcher, SIGNAL(startedIdleMode()), q, SLOT(slotPerformIdleRoutines()));
326 , autoSaveTimer(new QTimer(_q))
329 , preActivatedNode(0)
330 , imageIdleWatcher(2000 )
331 , colorHistory(rhs.colorHistory)
333 copyFromImpl(rhs, _q, CONSTRUCT);
334 connect(&imageIdleWatcher, SIGNAL(startedIdleMode()), q, SLOT(slotPerformIdleRoutines()));
356 int autoSaveDelay = 300;
357 bool modifiedAfterAutosave =
false;
358 bool isAutosaving =
false;
359 bool disregardAutosaveFailure =
false;
360 int autoSaveFailureCount = 0;
367 bool m_bAutoDetectedMime =
false;
373 bool modified =
false;
374 bool readwrite =
false;
375 bool autoSaveActive =
true;
397 qreal audioLevel = 1.0;
404 bool imageModifiedWithoutUndo =
false;
405 bool modifiedWhileSaving =
false;
413 bool isRecovered =
false;
415 bool batchMode {
false };
416 bool decorationsSyncingDisabled =
false;
417 bool wasStorageAdded =
false;
418 bool documentIsClosing =
false;
446 class StrippedSafeSavingLocker;
450void KisDocument::Private::syncDecorationsWrapperLayerState()
452 if (!this->image || this->decorationsSyncingDisabled)
return;
456 KisLayerUtils::findNodeByType<KisDecorationsWrapperLayer>(image->
root());
458 const bool needsDecorationsWrapper =
459 gridConfig.showGrid() || (guidesConfig.showGuides() && guidesConfig.hasGuides()) || !assistants.isEmpty();
462 SyncDecorationsWrapperStroke(
KisDocument *document,
bool needsDecorationsWrapper)
465 m_document(document),
466 m_needsDecorationsWrapper(needsDecorationsWrapper)
475 KisLayerUtils::findNodeByType<KisDecorationsWrapperLayer>(m_document->image()->root());
477 if (m_needsDecorationsWrapper && !decorationsLayer) {
479 }
else if (!m_needsDecorationsWrapper && decorationsLayer) {
480 m_document->image()->removeNode(decorationsLayer);
486 bool m_needsDecorationsWrapper =
false;
500 if (policy == REPLACE) {
505 mimeType = rhs.mimeType;
506 outputMimeType = rhs.outputMimeType;
508 if (policy == REPLACE) {
521 guidesConfig = rhs.guidesConfig;
522 mirrorAxisConfig = rhs.mirrorAxisConfig;
523 modified = rhs.modified;
526 m_storyboardCommentList = rhs.m_storyboardCommentList;
527 audioTracks = rhs.audioTracks;
528 audioLevel = rhs.audioLevel;
529 gridConfig = rhs.gridConfig;
531 imageModifiedWithoutUndo = rhs.imageModifiedWithoutUndo;
532 m_bAutoDetectedMime = rhs.m_bAutoDetectedMime;
535 readwrite = rhs.readwrite;
536 autoSaveActive = rhs.autoSaveActive;
537 firstMod = rhs.firstMod;
538 lastMod = rhs.lastMod;
540 globalAssistantsColor = rhs.globalAssistantsColor;
541 batchMode = rhs.batchMode;
544 if (rhs.linkedResourceStorage) {
545 linkedResourceStorage = rhs.linkedResourceStorage->clone();
548 if (rhs.embeddedResourceStorage) {
549 embeddedResourceStorage = rhs.embeddedResourceStorage->clone();
576 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
599 QMutex *m_savingLock;
600 KisImageReadOnlyBarrierLock m_imageLock;
607 connect(d->undoStack, SIGNAL(cleanChanged(
bool)),
this, SLOT(slotUndoStackCleanChanged(
bool)));
608 connect(d->autoSaveTimer, SIGNAL(timeout()),
this, SLOT(slotAutoSave()));
609 setObjectName(newObjectName());
614 connect(
this, SIGNAL(sigSavingFinished(
const QString&)), bookmarkmngr, SLOT(slotCreateBookmark(
const QString&)));
620 d->linkedResourcesStorageID = QUuid::createUuid().toString();
624 d->embeddedResourcesStorageID = QUuid::createUuid().toString();
625 d->embeddedResourceStorage.reset(
new KisResourceStorage(d->embeddedResourcesStorageID));
628 d->wasStorageAdded =
true;
649 d->wasStorageAdded =
true;
655 d->documentIsClosing =
true;
659 d->imageIdleWatcher.setTrackedImage(0);
667 d->autoSaveTimer->disconnect(
this);
668 d->autoSaveTimer->stop();
670 delete d->importExportManager;
673 delete d->shapeController;
675 delete d->koShapeController;
678 d->image->animationInterface()->blockBackgroundFrameGeneration();
680 d->image->notifyAboutToBeDeleted();
694 d->image->requestStrokeCancellation();
695 d->image->waitForDone();
698 d->undoStack->clear();
699 d->image->waitForDone();
702 Q_UNUSED(sanityCheckPointer);
711 if (
d->wasStorageAdded) {
725 return d->embeddedResourcesStorageID;
730 return d->linkedResourcesStorageID;
781 QFileInfo filePathInfo(job.
filePath);
782 bool fileExists = filePathInfo.exists();
785 fileExists = filePathInfo.size() > 0;
788 if (fileExists && !filePathInfo.isWritable()) {
790 i18n(
"%1 cannot be written to. Please save under a different name.", job.
filePath),
801 switch(cfg.
readEntry<
int>(
"backupfilelocation", 0)) {
803 backupDir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
806 backupDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
812 QDir().mkpath(backupDir);
820 QUrl fileUrl = QUrl::fromLocalFile(job.
filePath);
822 backupDir = QDir::tempPath();
831 int numOfBackupsKept = cfg.
readEntry<
int>(
"numberofbackupfiles", 1);
832 QString suffix = cfg.
readEntry<QString>(
"backupfilesuffix",
"~");
834 if (numOfBackupsKept == 1) {
836 qWarning() <<
"Failed to create simple backup file!" << job.
filePath << backupDir << suffix;
838 .arg(job.
filePath, backupDir.isEmpty()
839 ?
"the same location as the file"
846 .arg(job.
filePath, backupDir.isEmpty()
847 ?
"the same location as the file"
851 else if (numOfBackupsKept > 1) {
853 qWarning() <<
"Failed to create numbered backup file!" << job.
filePath << backupDir << suffix;
855 .arg(job.
filePath, backupDir.isEmpty()
856 ?
"the same location as the file"
863 .arg(job.
filePath, backupDir.isEmpty()
864 ?
"the same location as the file"
878 const QString actionName =
880 i18n(
"Exporting Document...") :
881 i18n(
"Saving Document...");
886 job, exportConfiguration, isAdvancedExporting);
889 QString errorShortLog;
895 errorShortLog =
"another save operation is in progress";
896 errorMessage = i18n(
"Could not start saving %1. Wait until the current save operation has finished.", job.
filePath);
900 errorShortLog =
"failed to lock and clone the image";
905 errorShortLog =
"failed to start background saving";
932 SaveFlags flags = SaveIsExporting;
934 flags |= SaveShowWarnings;
937 KisUsageLogger::log(QString(
"Exporting Document: %1 as %2. %3 * %4 pixels, %5 layers, %6 frames, %7 "
938 "framerate. Export configuration: %8")
939 .arg(path, QString::fromLatin1(
mimeType), QString::number(
d->image->width()),
940 QString::number(
d->image->height()), QString::number(
d->image->nlayers()),
941 QString::number(
d->image->animationInterface()->totalLength()),
942 QString::number(
d->image->animationInterface()->framerate()),
943 (exportConfiguration ? exportConfiguration->toXML() :
"No configuration")));
948 exportConfiguration, isAdvancedExporting);
955 KisUsageLogger::log(QString(
"Saving Document %9 as %1 (mime: %2). %3 * %4 pixels, %5 layers. %6 frames, "
956 "%7 framerate. Export configuration: %8")
957 .arg(_path, QString::fromLatin1(
mimeType), QString::number(
d->image->width()),
958 QString::number(
d->image->height()), QString::number(
d->image->nlayers()),
959 QString::number(
d->image->animationInterface()->totalLength()),
960 QString::number(
d->image->animationInterface()->framerate()),
961 (exportConfiguration ? exportConfiguration->toXML() :
"No configuration"),
971 showWarnings ? SaveShowWarnings : SaveNone),
972 exportConfiguration);
985 filter->setBatchMode(
true);
988 Private::StrippedSafeSavingLocker locker(&
d->savingMutex,
d->image);
989 if (!locker.successfullyLocked()) {
990 return buffer.data();
993 d->savingImage =
d->image;
995 if (!filter->convert(
this, &buffer).isOk()) {
996 qWarning() <<
"serializeToByteArray():: Could not export to our native format";
999 return buffer.data();
1006 const QString &message,
1008 const QString &details = {})
1009 : QMessageBox(QMessageBox::Warning, title, message, QMessageBox::Ok, qApp->activeWindow())
1011 if (!details.isEmpty()) {
1012 setInformativeText(details);
1014 if (!warnings.isEmpty()) {
1022 QMessageBox::setDetailedText(text.first());
1024 QTextEdit *messageBox = findChild<QTextEdit *>();
1027 messageBox->setAcceptRichText(
true);
1029 QString warning =
"<html><body><ul>";
1030 Q_FOREACH (
const QString &i, text) {
1031 warning +=
"\n<li>" + i +
"</li>";
1033 warning +=
"</ul></body></html>";
1035 messageBox->setText(warning);
1045 const QString fileName = QFileInfo(job.
filePath).fileName();
1047 if (!status.
isOk()) {
1048 Q_EMIT
statusBarMessage(i18nc(
"%1 --- failing file name, %2 --- error message",
1049 "Error during saving %1: %2",
1056 i18n(
"Could not save %1.", job.
filePath),
1070 i18nc(
"@title:window",
"Krita"),
1071 i18nc(
"dialog box shown to the user if there were warnings while saving the document, "
1072 "%1 is the file path",
1073 "%1 has been saved but is incomplete.",
1078 : i18nc(
"dialog box shown to the user if there were warnings while saving the document",
1079 "Some problems were encountered when saving."));
1096 Q_EMIT
statusBarMessage(i18n(
"Finished saving %1", fileName), successMessageTimeout);
1100void KisDocument::Private::updateDocumentMetadataOnSaving(
const QString &filePath,
const QByteArray &mimeType)
1112 QFileInfo fi(filePath);
1116 if (!modifiedWhileSaving) {
1123 if (undoStack->isClean()) {
1126 imageModifiedWithoutUndo =
false;
1127 undoStack->setClean();
1145 return d->batchMode;
1153void KisDocument::Private::uploadLinkedResourcesFromLayersToStorage()
1164 if (KisNodeFilterInterface *layer = dynamic_cast<KisNodeFilterInterface*>(node.data())) {
1165 KisFilterConfigurationSP filterConfig = layer->filter();
1166 if (!filterConfig) return;
1168 QList<KoResourceLoadResult> linkedResources = filterConfig->linkedResources(KisGlobalResourcesInterface::instance());
1170 Q_FOREACH (const KoResourceLoadResult &result, linkedResources) {
1171 KIS_SAFE_ASSERT_RECOVER(result.type() != KoResourceLoadResult::EmbeddedResource) { continue; }
1173 KoResourceSP resource = result.resource();
1176 qWarning() <<
"WARNING: KisDocument::lockAndCloneForSaving failed to fetch a resource" << result.signature();
1181 buf.open(QBuffer::WriteOnly);
1183 KisResourceModel model(resource->resourceType().first);
1184 bool res = model.exportResource(resource, &buf);
1189 qWarning() <<
"WARNING: KisDocument::lockAndCloneForSaving failed to export resource" << result.signature();
1193 buf.open(QBuffer::ReadOnly);
1195 res = doc->d->linkedResourceStorage->importResource(resource->resourceType().first +
"/" + resource->filename(), &buf);
1200 qWarning() <<
"WARNING: KisDocument::lockAndCloneForSaving failed to import resource" << result.signature();
1209KisDocument *KisDocument::Private::lockAndCloneImpl(
bool fetchResourcesFromLayers)
1212 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1224 Private::StrippedSafeSavingLocker locker(&savingMutex, image);
1225 if (!locker.successfullyLocked()) {
1231 if (fetchResourcesFromLayers) {
1232 doc->
d->uploadLinkedResourcesFromLayersToStorage();
1240 return d->lockAndCloneImpl(
true);
1245 return d->lockAndCloneImpl(
false);
1256 d->decorationsSyncingDisabled =
true;
1257 d->copyFrom(*(rhs.
d),
this);
1258 d->decorationsSyncingDisabled =
false;
1260 d->undoStack->clear();
1265 connect(
d->autoSaveTimer, SIGNAL(timeout()),
this, SLOT(
slotAutoSave()));
1271 setObjectName(rhs.objectName());
1277 d->image->barrierLock(
false);
1278 rhs.
d->image->barrierLock(
true);
1279 d->image->copyFromImage(*(rhs.
d->image));
1281 rhs.
d->image->unlock();
1292 d->syncDecorationsWrapperLayerState();
1295 if (rhs.
d->preActivatedNode) {
1296 QQueue<KisNodeSP> linearizedNodes;
1299 linearizedNodes.enqueue(node);
1302 [&linearizedNodes, &rhs,
this](
KisNodeSP node) {
1303 KisNodeSP refNode = linearizedNodes.dequeue();
1304 if (rhs.d->preActivatedNode.data() == refNode.data()) {
1305 d->preActivatedNode = node;
1312 if (referencesLayer) {
1313 d->referenceLayerConnections.clear();
1314 d->referenceLayerConnections.addConnection(
1315 referencesLayer, SIGNAL(sigUpdateCanvas(QRectF)),
1316 this, SIGNAL(sigReferenceImagesChanged()));
1318 Q_EMIT sigReferenceImagesLayerChanged(referencesLayer);
1319 Q_EMIT sigReferenceImagesChanged();
1323 KisLayerUtils::findNodeByType<KisDecorationsWrapperLayer>(
d->image->root());
1324 if (decorationsLayer) {
1325 decorationsLayer->setDocument(
this);
1329 if (policy == REPLACE) {
1343 Private::StrippedSafeSavingLocker locker(&
d->savingMutex,
d->image);
1344 if (!locker.successfullyLocked()) {
1349 d->savingImage =
d->image;
1352 d->importExportManager->
1357 return status.
isOk();
1362 const QObject *receiverObject,
const char *receiverMethod,
1367 job, exportConfiguration, std::unique_ptr<KisDocument>(), isAdvancedExporting);
1371 const QObject *receiverObject,
const char *receiverMethod,
1374 std::unique_ptr<KisDocument> &&optionalClonedDocument,
bool isAdvancedExporting)
1378 QScopedPointer<KisDocument> clonedDocument;
1380 if (!optionalClonedDocument) {
1383 clonedDocument.reset(optionalClonedDocument.release());
1386 if (!
d->savingMutex.tryLock()){
1394 std::unique_lock<QMutex> savingMutexLock(
d->savingMutex, std::adopt_lock);
1396 if (!clonedDocument) {
1413 waitForImage(clonedDocument->image());
1417 if (clonedDocument->image()->hasOverlaySelectionMask()) {
1418 clonedDocument->image()->setOverlaySelectionMask(0);
1419 waitForImage(clonedDocument->image());
1424 clonedDocument->image()->cropImage(clonedDocument->image()->bounds());
1425 clonedDocument->image()->purgeUnusedData(
false);
1426 waitForImage(clonedDocument->image());
1430 waitForImage(clonedDocument->image());
1445 savingMutexLock.release();
1447 d->backgroundSaveDocument.reset(clonedDocument.take());
1448 d->backgroundSaveJob = job;
1449 d->modifiedWhileSaving =
false;
1452 d->backgroundSaveDocument->d->isAutosaving =
true;
1455 connect(
d->backgroundSaveDocument.data(),
1461 if (
d->completeSavingConnection) {
1462 disconnect(
d->completeSavingConnection);
1464 d->completeSavingConnection = connect(
1466 receiverObject, receiverMethod);
1469 d->backgroundSaveDocument->startExportInBackground(actionName,
1474 exportConfiguration, isAdvancedExporting);
1475 if (!error.
isOk()) {
1478 d->backgroundSaveDocument.take()->deleteLater();
1479 d->savingMutex.unlock();
1501 std::unique_lock<QMutex> savingMutexLock(
d->savingMutex, std::adopt_lock);
1506 d->backgroundSaveDocument->d->isAutosaving =
false;
1509 d->backgroundSaveDocument.take()->deleteLater();
1517 savingMutexLock.unlock();
1520 KisUsageLogger::log(QString(
"Completed saving %1 (mime: %2). Result: %3. Warning: %4. Size: %5")
1523 QString::number(fi.size())));
1528 disconnect(
d->completeSavingConnection);
1529 d->completeSavingConnection = {};
1534 if (!
d->modified || !
d->modifiedAfterAutosave)
return;
1537 Q_EMIT
statusBarMessage(i18n(
"Autosaving... %1", autoSaveFileName), successMessageTimeout);
1541 const bool hadClonedDocument = bool(optionalClonedDocument);
1544 if (
d->image->isIdle() || hadClonedDocument) {
1549 std::move(optionalClonedDocument));
1551 Q_EMIT
statusBarMessage(i18n(
"Autosaving postponed: document is busy..."), errorMessageTimeout);
1556 connect(stroke, SIGNAL(sigDocumentCloned(
KisDocument*)),
1558 Qt::BlockingQueuedConnection);
1559 connect(stroke, SIGNAL(sigCloningCancelled()),
1561 Qt::BlockingQueuedConnection);
1564 d->image->endStroke(strokeId);
1571 d->modifiedAfterAutosave =
false;
1579 QStringList pathParts = QFileInfo(path).absolutePath().split(
'/');
1580 if (pathParts.size() > 0) {
1581 QString resourceType = pathParts.last();
1587 QString tempFileName = QDir::tempPath() +
"/" + QFileInfo(path).fileName();
1589 if (QFileInfo(path).exists()) {
1598 d->modifiedWhileSaving =
false;
1600 if (!exportConfiguration) {
1601 QScopedPointer<KisImportExportFilter> filter(
1608 if (exportConfiguration) {
1610 exportConfiguration->setProperty(
"name", res->name());
1614 QFile f2(tempFileName);
1615 f2.open(QFile::ReadOnly);
1617 QByteArray ba = f2.readAll();
1620 buf.open(QBuffer::ReadOnly);
1626 const QString filePath =
1629 d->updateDocumentMetadataOnSaving(filePath,
mimeType);
1638 d->modifiedWhileSaving =
false;
1642 const QString filePath =
1645 d->updateDocumentMetadataOnSaving(filePath,
mimeType);
1674 d->image->explicitRegenerateLevelOfDetail();
1689 const QString fileName = QFileInfo(job.
filePath).fileName();
1691 if (!status.
isOk()) {
1693 Q_EMIT
statusBarMessage(i18nc(
"%1 --- failing file name, %2 --- error message",
1694 "Error during autosaving %1: %2",
1701 if (!
d->modifiedWhileSaving) {
1702 d->autoSaveTimer->stop();
1703 d->autoSaveFailureCount = 0;
1708 Q_EMIT
statusBarMessage(i18n(
"Finished autosaving %1", fileName), successMessageTimeout);
1713 const QString &location,
1714 const QString &realLocation,
1715 const QByteArray &mimeType,
1719 d->savingImage =
d->image;
1725 d->importExportManager->setUpdater(
d->savingUpdater);
1730 d->childSavingFuture =
1731 d->importExportManager->exportDocumentAsync(location,
1734 initializationStatus,
1736 exportConfiguration,
1737 isAdvancedExporting);
1739 if (!initializationStatus.
isOk()) {
1740 if (
d->savingUpdater) {
1741 d->savingUpdater->cancel();
1743 d->savingImage.clear();
1745 return initializationStatus;
1748 typedef QFutureWatcher<KisImportExportErrorCode> StatusWatcher;
1749 StatusWatcher *watcher =
new StatusWatcher();
1750 watcher->setFuture(
d->childSavingFuture);
1753 connect(watcher, SIGNAL(finished()), watcher, SLOT(deleteLater()));
1755 return initializationStatus;
1769 if (!
d->lastErrorMessage.isEmpty()) {
1777 d->savingImage.clear();
1779 d->lastErrorMessage.clear();
1780 d->lastWarningMessage.clear();
1782 if (
d->savingUpdater) {
1783 d->savingUpdater->setProgress(100);
1791 const bool changed =
readwrite !=
d->readwrite;
1813 d->autoSaveTimer->start(delay * 1000);
1815 d->autoSaveTimer->stop();
1822 d->autoSaveFailureCount = 0;
1827 const int emergencyAutoSaveInterval = 10;
1829 d->autoSaveFailureCount++;
1839 return d->autoSaveActive;
1855 if (
d->savingImage)
image =
d->savingImage;
1859 QSize originalSize =
bounds.size();
1861 QSize newSize = originalSize.scaled(size, Qt::KeepAspectRatio).expandedTo({1, 1});
1863 bool pixelArt =
false;
1865 if (originalSize.width() < size.width() && originalSize.height() < size.height()) {
1868 if (newSize.height()%originalSize.height() == 0 && newSize.width()%originalSize.width() == 0) {
1878 QImage scaled = original.scaled(newSize, Qt::KeepAspectRatio, Qt::FastTransformation);
1879 px = QPixmap::fromImage(scaled);
1883 if (px.size() == QSize(0,0)) {
1884 px = QPixmap(newSize);
1887 gc.fillRect(px.rect(), checkBrush);
1892 return QPixmap(size);
1900 const QString extension (
".kra");
1901 QString prefix =
KisConfig(
true).
readEntry<
bool>(
"autosavefileshidden") ? QString(
".") : QString();
1902 QRegularExpression autosavePattern1(
"^\\..+-autosave.kra$");
1903 QRegularExpression autosavePattern2(
"^.+-autosave.kra$");
1906 QString dir = fi.absolutePath();
1910 if (path.startsWith(
"content://")) {
1916 QString filename = fi.fileName();
1918 if (path.isEmpty() || autosavePattern1.match(filename).hasMatch() || autosavePattern2.match(filename).hasMatch() || !fi.isWritable()) {
1920 retval = QString(
"%1%2%3%4-%5-%6-autosave%7")
1925 .arg(qApp->applicationPid())
1931 retval = QString(
"%1%2%3%4-autosave%5").arg(dir).arg(
'/').arg(prefix).arg(filename).arg(extension);
1942 dbgUI <<
"path=" << _path;
1950 dbgUI <<
"success, resetting url";
1960 dbgUI <<
"path=" << _path;
1961 d->lastErrorMessage.clear();
1964 if (_path.isEmpty()) {
1965 d->lastErrorMessage = i18n(
"Malformed Path\n%1", _path);
1969 QString path = _path;
1970 QString original =
"";
1971 bool autosaveOpened =
false;
1973 QString file =
path;
1975 if (QFile::exists(asf)) {
1982 int res = dlg.result();
1988 autosaveOpened =
true;
2022 QFileInfo fi(_path);
2037 QMessageBox::critical(qApp->activeWindow(), i18nc(
"@title:window",
"Krita"), i18n(
"File %1 does not exist.",
localFilePath()));
2044 if (typeName.isEmpty()) {
2049 if (typeName ==
"application/x-trash") {
2050 QString path = filename;
2051 while (path.length() > 0) {
2055 if (!typeName.isEmpty()) {
2067 d->importExportManager->setUpdater(updater);
2072 if (!status.
isOk()) {
2092 i18n(
"There were problems opening %1.",
prettyPath()),
2100 d->syncDecorationsWrapperLayerState();
2110 if (!
d->modified || !
d->modifiedAfterAutosave)
2119 d->modifiedAfterAutosave =
false;
2124 qWarning() <<
"Could not auto-save when paused";
2132 d->outputMimeType =
d->mimeType;
2151 if (
d->isAutosaving ||
d->documentIsClosing)
2157 if (mod && !
d->autoSaveTimer->isActive()) {
2161 d->modifiedAfterAutosave = mod;
2162 d->modifiedWhileSaving = mod;
2165 d->imageModifiedWithoutUndo = mod;
2182 const bool changed =
value !=
d->isRecovered;
2193 return d->isRecovered;
2198 QDateTime now = QDateTime::currentDateTime();
2199 int firstModDelta =
d->firstMod.secsTo(now);
2200 int lastModDelta =
d->lastMod.secsTo(now);
2202 if (lastModDelta > 30) {
2203 d->docInfo->setAboutInfo(
"editing-time", QString::number(
d->docInfo->aboutInfo(
"editing-time").toInt() +
d->firstMod.secsTo(
d->lastMod)));
2205 }
else if (firstModDelta > 60 || forceStoreElapsed) {
2206 d->docInfo->setAboutInfo(
"editing-time", QString::number(
d->docInfo->aboutInfo(
"editing-time").toInt() + firstModDelta));
2215 QString _url(
path());
2217 _url = QDir::toNativeSeparators(_url);
2226 const QString _url(QFileInfo(
path()).fileName());
2229 if (_url.isEmpty()) {
2230 c =
" [" + i18n(
"Not Saved") +
"] ";
2246 QDomImplementation impl;
2247 QString url = QString(
"http://www.calligra.org/DTD/%1-%2.dtd").arg(appName).arg(version);
2248 QDomDocumentType dtype = impl.createDocumentType(tagName,
2249 QString(
"-//KDE//DTD %1 %2//EN").arg(appName).arg(version),
2252 QString namespaceURN = QString(
"http://www.calligra.org/DTD/%1").arg(appName);
2253 QDomDocument doc = impl.createDocument(namespaceURN, tagName, dtype);
2254 doc.insertBefore(doc.createProcessingInstruction(
"xml",
"version=\"1.0\" encoding=\"UTF-8\""), doc.documentElement());
2267 d->lastErrorMessage = errMsg;
2272 return d->lastErrorMessage;
2277 d->lastWarningMessage = warningMsg;
2282 return d->lastWarningMessage;
2290 if (QFile::exists(asf)) {
2296 if (QFile::exists(asf)) {
2303 expressions << QRegularExpression(
"^\\..+-autosave.kra$")
2304 << QRegularExpression(
"^.+-autosave.kra$");
2306 Q_FOREACH(
const QRegularExpression &rex, expressions) {
2308 !autosaveBaseName.isEmpty() &&
2309 rex.match(QFileInfo(autosaveBaseName).fileName()).hasMatch() &&
2310 QFile::exists(autosaveBaseName)) {
2313 QFile::remove(autosaveBaseName);
2325 if (
d->unit !=
unit) {
2333 return d->undoStack;
2338 return d->importExportManager;
2351 if (!
d->undoStack->isClean()) {
2352 d->undoStack->clear();
2368 d->syncDecorationsWrapperLayerState();
2373 d->undoStack->clear();
2378 return d->gridConfig;
2383 if (
d->gridConfig != config) {
2384 d->gridConfig = config;
2385 d->syncDecorationsWrapperLayerState();
2397 if (!
d->linkedResourceStorage) {
2403 while (iter->hasNext()) {
2407 buf.open(QBuffer::WriteOnly);
2408 bool exportSuccessful =
2409 d->linkedResourceStorage->exportResource(iter->url(), &buf);
2411 KoResourceSP resource =
d->linkedResourceStorage->resource(iter->url());
2412 exportSuccessful &= bool(resource);
2414 const QString name = resource ? resource->name() : QString();
2415 const QString fileName = QFileInfo(iter->url()).fileName();
2420 if (exportSuccessful) {
2423 result << signature;
2434 if (
d->linkedResourceStorage) {
2436 while (iter->hasNext()) {
2439 if (resource && resource->valid()) {
2440 oldPaletteList << resource.dynamicCast<
KoColorSet>();
2443 if (oldPaletteList != paletteList) {
2446 if (!paletteList.contains(
palette)) {
2451 if (!oldPaletteList.contains(
palette)) {
2455 palette->setStorageLocation(
d->linkedResourcesStorageID);
2468 return d->m_storyboardItemList;
2473 d->m_storyboardItemList = storyboardItemList;
2481 return d->m_storyboardCommentList;
2486 d->m_storyboardCommentList = storyboardCommentList;
2493 return d->audioTracks;
2504 d->audioLevel = level;
2510 return d->audioLevel;
2515 return d->guidesConfig;
2520 if (
d->guidesConfig == data)
return;
2522 d->guidesConfig = data;
2523 d->syncDecorationsWrapperLayerState();
2530 return d->mirrorAxisConfig;
2535 if (
d->mirrorAxisConfig == config) {
2539 d->mirrorAxisConfig = config;
2542 d->image->bounds()));
2561 return d->readwrite;
2574 if (view && view->
document() ==
this) {
2583 d->mimeType = QByteArray();
2595 const bool changed = path !=
d->m_path;
2617 if ( path.isEmpty() ) {
2621 if (
d->m_bAutoDetectedMime) {
2622 d->mimeType = QByteArray();
2623 d->m_bAutoDetectedMime =
false;
2637 d->m_file =
d->m_path;
2641 if (
d->mimeType.isEmpty()) {
2645 d->mimeType = mime.toLocal8Bit();
2646 d->m_bAutoDetectedMime =
true;
2662 qint32 width, qint32 height,
2666 const QString &description,
const double imageResolution)
2672 if (!cs)
return false;
2674 KisCursorOverrideLock cursorLock(Qt::BusyCursor);
2705 KoColor strippedAlpha = bgColor;
2714 filter_config->setProperty(
"color", strippedAlpha.
toQColor());
2715 filter_config->createLocalResourcesSnapshot();
2721 if (numberOfLayers > 1) {
2731 Q_CHECK_PTR(bgLayer);
2733 bgLayer->
setDirty(QRect(0, 0, width, height));
2736 d->mirrorAxisConfig.setAxisPosition(QRectF(
image->
bounds()).center());
2739 for(
int i = 1; i < numberOfLayers; ++i) {
2743 layer->
setDirty(QRect(0, 0, width, height));
2757 QString(
"Created image \"%1\", %2 * %3 pixels, %4 dpi. Color model: %6 %5 (%7). Layers: %8")
2758 .arg(name, QString::number(width), QString::number(height),
2761 QString::number(numberOfLayers)));
2768 const bool result =
d->savingMutex.tryLock();
2770 d->savingMutex.unlock();
2778 KisAsyncActionFeedback f(i18nc(
"progress dialog message when the user closes the document that is being saved",
"Waiting for saving to complete..."), 0);
2779 f.waitForMutex(
d->savingMutex);
2785 return d->shapeController;
2790 return d->shapeController->shapeForNode(layer);
2795 return d->assistants;
2800 if (
d->assistants !=
value) {
2802 d->syncDecorationsWrapperLayerState();
2812 KisLayerUtils::findNodeByType<KisReferenceImagesLayer>(
d->image->root());
2814 return referencesLayer;
2823 if (currentReferenceLayer == layer && updateImage) {
2827 d->referenceLayerConnections.clear();
2830 if (currentReferenceLayer) {
2831 d->image->removeNode(currentReferenceLayer);
2835 d->image->addNode(layer);
2839 currentReferenceLayer = layer;
2841 if (currentReferenceLayer) {
2842 d->referenceLayerConnections.addConnection(
2843 currentReferenceLayer, SIGNAL(sigUpdateCanvas(QRectF)),
2853 d->preActivatedNode = activatedNode;
2858 return d->preActivatedNode;
2868 return d->savingImage;
2877 d->image->disconnect(
this);
2878 d->shapeController->setImage(0);
2884 if (
d->linkedResourceStorage){
2888 d->setImageAndInitIdleWatcher(
image);
2893 connect(
d->image, SIGNAL(sigImageModified()),
this, SLOT(
setImageModified()), Qt::UniqueConnection);
2897 if (forceInitialUpdate) {
2898 d->image->initialRefreshGraph();
2909 d->shapeController->setImage(
image);
2915 setModified(
d->imageModifiedWithoutUndo || !
d->undoStack->isClean());
2920 d->imageModifiedWithoutUndo =
true;
2932 return d->isAutosaving;
2942 d->globalAssistantsColor = color;
2947 return d->globalAssistantsColor;
2952 return d->colorHistory;
2957 QRectF
bounds =
d->image->bounds();
2961 if (referenceImagesLayer) {
2970 d->colorHistory = colors;
float value(const T *src, size_t ch)
KisSharedPtr< KisReferenceImagesLayer > KisReferenceImagesLayerSP
const quint8 OPACITY_OPAQUE_U8
void setDetailedText(const QStringList &text)
DlgLoadMessages(const QString &title, const QString &message, const QStringList &warnings={}, const QString &details={})
virtual void setIndex(int idx)
bool setResourceInactive(const QModelIndex &index)
Base class for the Krita app.
static QString autoSaveLocation()
static bool simpleBackupFile(const QString &filename, const QString &backupDir=QString(), const QString &backupExtension=QStringLiteral("~"))
static bool numberedBackupFile(const QString &filename, const QString &backupDir=QString(), const QString &backupExtension=QStringLiteral("~"), const uint maxBackups=10)
QList< KoColor > colorHistory() const
static KisConfigNotifier * instance()
bool backupFile(bool defaultValue=false) const
qint32 defImageHeight(bool defaultValue=false) const
qint32 defImageWidth(bool defaultValue=false) const
bool useDefaultColorSpace(bool defaultvalue=false) const
void setDefaultColorDepth(const QString &depth) const
void setDefaultGridSpacing(QPoint gridSpacing)
qreal defImageResolution(bool defaultValue=false) const
bool useCumulativeUndoRedo(bool defaultValue=false) const
QString defColorProfile(bool defaultValue=false) const
KisCumulativeUndoData cumulativeUndoData(bool defaultValue=false) const
bool autoPinLayersToTimeline(bool defaultValue=false) const
bool trimKra(bool defaultValue=false) const
T readEntry(const QString &name, const T &defaultValue=T())
int autoSaveInterval(bool defaultValue=false) const
QString defColorModel(bool defaultValue=false) const
int undoStackLimit(bool defaultValue=false) const
~StrippedSafeSavingLocker()
StrippedSafeSavingLocker(QMutex *savingMutex, KisImageSP image)
KisImageReadOnlyBarrierLock m_imageLock
bool successfullyLocked() const
QScopedPointer< KisSignalAutoConnection > imageIdleConnection
void slotImageRootChanged()
void setAssistants(const QList< KisPaintingAssistantSP > &value)
@replace the current list of assistants with
void waitForSavingToComplete()
QRectF documentBounds() const
QString warningMessage() const
void copyFrom(const Private &rhs, KisDocument *q)
void removeAutoSaveFiles(const QString &autosaveBaseName, bool wasRecovered)
KisUndoStore * createUndoStore()
void slotInitiateAsyncAutosaving(KisDocument *clonedDocument)
void updateDocumentMetadataOnSaving(const QString &filePath, const QByteArray &mimeType)
QList< KoColor > colorHistory
void sigStoryboardCommentListChanged()
QFuture< KisImportExportErrorCode > childSavingFuture
void setEmergencyAutoSaveInterval()
void setFileBatchMode(const bool batchMode)
KisMirrorAxisConfig mirrorAxisConfig
KisSharedPtr< KisReferenceImagesLayer > referenceImagesLayer() const
bool exportDocument(const QString &path, const QByteArray &mimeType, bool isAdvancedExporting=false, bool showWarnings=false, KisPropertiesConfigurationSP exportConfiguration=0)
KoDocumentInfo * documentInfo() const
void syncDecorationsWrapperLayerState()
void hackPreliminarySetImage(KisImageSP image)
void sigBackgroundSavingFinished(KisImportExportErrorCode status, const QString &errorMessage, const QString &warningMessage)
QString linkedResourcesStorageId() const
void copyFromImpl(const Private &rhs, KisDocument *q, KisDocument::CopyPolicy policy)
QPixmap generatePreview(const QSize &size)
Generates a preview picture of the document.
KisShapeController * shapeController
static QStringList extraNativeMimeTypes()
KisSignalAutoConnectionsStore referenceLayerConnections
KritaUtils::BackgroudSavingStartResult initiateSavingInBackground(const QString actionName, const QObject *receiverObject, const char *receiverMethod, const KritaUtils::ExportFileJob &job, KisPropertiesConfigurationSP exportConfiguration, std::unique_ptr< KisDocument > &&optionalClonedDocument, bool isAdvancedExporting=false)
bool save(bool showWarnings, KisPropertiesConfigurationSP exportConfiguration)
KisImportExportManager * importExportManager
void statusBarMessage(const QString &text, int timeout=0)
bool isNativeFormat(const QByteArray &mimeType) const
Checks whether a given mimeType can be handled natively.
void setAudioTracks(QVector< QFileInfo > f)
void sigAudioLevelChanged(qreal level)
KisDocument * lockAndCloneImpl(bool fetchResourcesFromLayers)
void uploadLinkedResourcesFromLayersToStorage()
void slotUndoStackCleanChanged(bool value)
QString localFilePath() const
void sigAssistantsChanged()
void setErrorMessage(const QString &errMsg)
void setMirrorAxisConfig(const KisMirrorAxisConfig &config)
KoDocumentInfoDlg * createDocumentInfoDialog(QWidget *parent, KoDocumentInfo *docInfo) const
void sigStoryboardItemListChanged()
KisImportExportErrorCode startExportInBackground(const QString &actionName, const QString &location, const QString &realLocation, const QByteArray &mimeType, bool showWarnings, KisPropertiesConfigurationSP exportConfiguration, bool isAdvancedExporting=false)
QString exportErrorToUserMessage(KisImportExportErrorCode status, const QString &errorMessage)
void setAssistantsGlobalColor(QColor color)
bool loadNativeFormat(const QString &file)
void updateEditingTime(bool forceStoreElapsed)
void sigPaletteListChanged(const QList< KoColorSetSP > &oldPaletteList, const QList< KoColorSetSP > &newPaletteList)
void setModified(bool _mod)
void setMimeType(const QByteArray &mimeType)
Sets the mime type for the document.
QDomDocument createDomDocument(const QString &tagName, const QString &version) const
void sigLoadingFinished()
KisDocument * lockAndCloneForSaving()
try to clone the image. This method handles all the locking for you. If locking has failed,...
void sigReadWriteChanged(bool value)
void finishExportInBackground()
void copyFromDocument(const KisDocument &rhs)
void slotDocumentCloningCancelled()
void setWarningMessage(const QString &warningMsg)
void setUnit(const KoUnit &unit)
void setPath(const QString &path)
bool saveAs(const QString &path, const QByteArray &mimeType, bool showWarnings, KisPropertiesConfigurationSP exportConfiguration=0)
bool newImage(const QString &name, qint32 width, qint32 height, const KoColorSpace *cs, const KoColor &bgColor, KisConfig::BackgroundStyle bgStyle, int numberOfLayers, const QString &imageDescription, const double imageResolution)
void setLocalFilePath(const QString &localFilePath)
QList< KoResourceLoadResult > linkedDocumentResources()
linkedDocumentResources List returns all the resources linked to the document, such as palettes
KisDocument * lockAndCreateSnapshot()
void setAutoSaveDelay(int delay)
void setPreActivatedNode(KisNodeSP activatedNode)
QString lastWarningMessage
void sigGuidesConfigChanged(const KisGuidesConfig &config)
void setRecovered(bool value)
void slotChildCompletedSavingInBackground(KisImportExportErrorCode status, const QString &errorMessage, const QString &warningMessage)
Private(const Private &rhs, KisDocument *_q)
bool importDocument(const QString &path)
QString errorMessage() const
KritaUtils::ExportFileJob backgroundSaveJob
QColor globalAssistantsColor
KisResourceStorageSP embeddedResourceStorage
static QByteArray nativeFormatMimeType()
void sigAudioTracksChanged()
void setReferenceImagesLayer(KisSharedPtr< KisReferenceImagesLayer > layer, bool updateImage)
bool resourceSavingFilter(const QString &path, const QByteArray &mimeType, KisPropertiesConfigurationSP exportConfiguration)
KisDocument(bool addStorage=true)
void canceled(const QString &)
void setReadWrite(bool readwrite=true)
Sets whether the document can be edited or is read only.
void setImageModifiedWithoutUndo()
void sigGridConfigChanged(const KisGridConfig &config)
QColor assistantsGlobalColor()
QPointer< KoUpdater > savingUpdater
void autoSaveOnPause()
Start saving when android activity is pushed to the background.
StoryboardItemList getStoryboardItemList()
returns the list of pointers to storyboard Items for the document
QString embeddedResourcesStorageId() const
QString linkedResourcesStorageID
void sigSavingFinished(const QString &filePath)
QString generateAutoSaveFileName(const QString &path) const
KisResourceStorageSP linkedResourceStorage
QMetaObject::Connection completeSavingConnection
KisNodeWSP preActivatedNode
void setNormalAutoSaveInterval()
void slotCompleteSavingDocument(const KritaUtils::ExportFileJob &job, KisImportExportErrorCode status, const QString &errorMessage, const QString &warningMessage)
void unitChanged(const KoUnit &unit)
KoShapeLayer * shapeForNode(KisNodeSP layer) const
bool exportDocumentSync(const QString &path, const QByteArray &mimeType, KisPropertiesConfigurationSP exportConfiguration=0)
void setGridConfig(const KisGridConfig &config)
bool closePath(bool promptToSave=true)
void sigPathChanged(const QString &path)
QByteArray serializeToNativeByteArray()
serializeToNativeByteArray daves the document into a .kra file written to a memory-based byte-array
QList< KisPaintingAssistantSP > assistants
void setImageAndInitIdleWatcher(KisImageSP _image)
void setAudioVolume(qreal level)
void setAutoSaveActive(bool autoSaveIsActive)
@ CONSTRUCT
we are copy-constructing a new KisDocument
@ REPLACE
we are replacing the current KisDocument with another
void setGuidesConfig(const KisGuidesConfig &data)
bool openPathInternal(const QString &path)
KisIdleWatcher imageIdleWatcher
bool fileBatchMode() const
QByteArray outputMimeType
QVector< StoryboardComment > getStoryboardCommentsList()
returns the list of comments for the storyboard docker in the document
void setMimeTypeAfterLoading(const QString &mimeType)
void sigCompleteBackgroundSaving(const KritaUtils::ExportFileJob &job, KisImportExportErrorCode status, const QString &errorMessage, const QString &warningMessage)
void copyFromDocumentImpl(const KisDocument &rhs, CopyPolicy policy)
QScopedPointer< KisDocument > backgroundSaveDocument
void sigReferenceImagesLayerChanged(KisSharedPtr< KisReferenceImagesLayer > layer)
void slotPerformIdleRoutines()
StoryboardItemList m_storyboardItemList
void slotAutoSaveImpl(std::unique_ptr< KisDocument > &&optionalClonedDocument)
void setCurrentImage(KisImageSP image, bool forceInitialUpdate=true, KisNodeSP preActivatedNode=nullptr)
void sigRecoveredChanged(bool value)
QVector< StoryboardComment > m_storyboardCommentList
QVector< QFileInfo > getAudioTracks() const
bool exportDocumentImpl(const KritaUtils::ExportFileJob &job, KisPropertiesConfigurationSP exportConfiguration, bool isAdvancedExporting=false)
void setStoryboardCommentList(const QVector< StoryboardComment > &storyboardCommentList, bool emitSignal=false)
sets the list of comments for the storyboard docker in the document, emits empty signal if emitSignal...
void setPaletteList(const QList< KoColorSetSP > &paletteList, bool emitSignal=false)
setPaletteList replaces the palettes in the document's local resource storage with the list of palett...
void slotCompleteAutoSaving(const KritaUtils::ExportFileJob &job, KisImportExportErrorCode status, const QString &errorMessage, const QString &warningMessage)
KisDocument * clone(bool addStorage=false)
creates a clone of the document and returns it. Please make sure that you hold all the necessary lock...
void setInfiniteAutoSaveInterval()
void sigReferenceImagesChanged()
QString embeddedResourcesStorageID
void setStoryboardItemList(const StoryboardItemList &storyboardItemList, bool emitSignal=false)
sets the storyboardItemList in the document, emits empty signal if emitSignal is true.
bool openPath(const QString &path, OpenFlags flags=None)
openPath Open a Path
KisGuidesConfig guidesConfig
void setColorHistory(const QList< KoColor > &colors)
QVector< QFileInfo > audioTracks
void sigMirrorAxisConfigChanged()
QString prettyPath() const
The KisDumbUndoStore class doesn't actually save commands, so you cannot undo or redo!
static KisGeneratorRegistry * instance()
static KisResourcesInterfaceSP instance()
void setTrackedImage(KisImageSP image)
QImage convertToQImage(qint32 x1, qint32 y1, qint32 width, qint32 height, const KoColorProfile *profile)
KisGroupLayerSP rootLayer() const
UndoResult tryUndoUnfinishedLod0Stroke()
const KoColorSpace * colorSpace() const
void requestUndoDuringStroke()
QString nextLayerName(const QString &baseName="") const
bool assignImageProfile(const KoColorProfile *profile, bool blockAllUpdates=false)
KisImage * clone(bool exactCopy=false)
void setDefaultProjectionColor(const KoColor &color)
void requestStrokeCancellation()
KisStrokeId startStroke(KisStrokeStrategy *strokeStrategy) override
KisSelectionSP globalSelection() const
QRect bounds() const override
bool tryBarrierLock(bool readOnly=false)
Tries to lock the image without waiting for the jobs to finish.
void endStroke(KisStrokeId id) override
void requestRedoDuringStroke()
void setResolution(double xres, double yres)
QString errorMessage() const
The class managing all the filters.
static KisImportExportFilter * filterForMimeType(const QString &mimetype, Direction direction)
filterForMimeType loads the relevant import/export plugin and returns it. The caller is responsible f...
static KisMacosSecurityBookmarkManager * instance()
bool parentDirHasPermissions(const QString &path)
KisViewManager * viewManager
static QString mimeTypeForFile(const QString &file, bool checkExistingFiles=true)
Find the mimetype for the given filename. The filename must include a suffix.
The KisMirrorAxisConfig class stores configuration for the KisMirrorAxis canvas decoration....
void setDefaultPixel(const KoColor &defPixel)
static MemoryReleaseObject * createMemoryReleaseObject()
static QList< KisPaintingAssistantSP > cloneAssistantList(const QList< KisPaintingAssistantSP > &list)
void addRecentURLToAllMainWindows(QUrl url, QUrl oldUrl=QUrl())
static KisPart * instance()
KisMainWindow * currentMainwindow() const
The KisRecoverNamedAutosaveDialog class is a dialog to recover already existing files from autosave.
QRectF boundingImageRect() const
static bool getResourceIdFromVersionedFilename(QString filename, QString resourceType, QString storageLocation, int &outResourceId)
Note that here you can put even the original filename - any filename from the versioned_resources - a...
static KisResourceLoaderRegistry * instance()
bool removeStorage(const QString &storageLocation)
removeStorage removes the temporary storage from the database
bool addStorage(const QString &storageLocation, KisResourceStorageSP storage)
addStorage Adds a new resource storage to the database. The storage is will be marked as not pre-inst...
QString filePathForResource(KoResourceSP resource)
static KisResourceLocator * instance()
The KisResourceModel class provides the main access to resources. It is possible to filter the resour...
KoResourceSP resourceForId(int id) const
KoResourceSP importResourceFile(const QString &filename, const bool allowOverwrite, const QString &storageId=QString("")) override
importResourceFile
bool updateResource(KoResourceSP resource) override
updateResource creates a new version of the resource in the storage and in the database....
bool addResource(KoResourceSP resource, const QString &storageId=QString("")) override
addResource adds the given resource to the database and storage. If the resource already exists in th...
void setResourceFilter(ResourceFilter filter) override
QModelIndex indexForResource(KoResourceSP resource) const override
indexFromResource
static KisResourceServerProvider * instance()
static const QString s_meta_name
void enableJob(JobType type, bool enable=true, KisStrokeJobData::Sequentiality sequentiality=KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity=KisStrokeJobData::NORMAL)
virtual void initStrokeCallback()
void setClearsRedoOnStart(bool value)
void setRequestsOtherStrokesToEnd(bool value)
static void log(const QString &message)
Logs with date/time.
bool blockUntilOperationsFinished(KisImageSP image)
blockUntilOperationsFinished blocks the GUI of the application until execution of actions on image is...
QPointer< KoUpdater > createThreadedUpdater(const QString &name)
void blockUntilOperationsFinishedForced(KisImageSP image)
blockUntilOperationsFinished blocks the GUI of the application until execution of actions on image is...
QPointer< KoUpdater > createUnthreadedUpdater(const QString &name)
create a new progress updater
KisCanvasResourceProvider * canvasResourceProvider()
QPointer< KisDocument > document
virtual KoID colorModelId() const =0
virtual KoID colorDepthId() const =0
virtual const KoColorProfile * profile() const =0
void setOpacity(quint8 alpha)
void toQColor(QColor *c) const
a convenience method for the above.
The dialog that shows information about the document.
The class containing all meta information about a document.
void setAboutInfo(const QString &info, const QString &data)
T get(const QString &id) const
static QString generateHash(const QString &filename)
generateHash reads the given file and generates a hex-encoded md5sum for the file.
A simple wrapper object for the main information about the resource.
static StoryboardItemList cloneStoryboardItemList(const StoryboardItemList &list)
QQueue< PostponedJob > m_postponedJobs
void notifySetIndexChangedOneCommand() override
UndoStack(KisDocument *doc)
void processPostponedJobs()
void setIndex(int idx) override
void setIndexImpl(int idx)
#define KIS_ASSERT_RECOVER_RETURN_VALUE(cond, val)
#define KIS_SAFE_ASSERT_RECOVER(cond)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
#define KIS_ASSERT_RECOVER_RETURN(cond)
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
KUndo2MagicString kundo2_noi18n(const QString &text)
QPointF absoluteToRelative(const QPointF &pt, const QRectF &rc)
bool hasDelayedNodeWithUpdates(KisNodeSP root)
void recursiveApplyNodes(NodePointer node, Functor func)
void forceAllDelayedNodesUpdate(KisNodeSP root)
BackgroudSavingStartResult
@ AnotherSavingInProgress
rgba palette[MAX_PALETTE]
void setPinnedToTimeline(bool pinned)
virtual void setUserLocked(bool l)
void setOpacity(quint8 val)
virtual KisPaintDeviceSP paintDevice() const =0
virtual KisFilterConfigurationSP defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) const
bool addNode(KisNodeSP node, KisNodeSP parent=KisNodeSP(), KisNodeAdditionFlags flags=KisNodeAdditionFlag::None)