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))
328 , colorHistory(rhs.colorHistory)
330 , preActivatedNode(0)
331 , imageIdleWatcher(2000 )
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;
412 bool isRecovered =
false;
414 bool batchMode {
false };
415 bool decorationsSyncingDisabled =
false;
416 bool wasStorageAdded =
false;
417 bool documentIsClosing =
false;
445 class StrippedSafeSavingLocker;
449void KisDocument::Private::syncDecorationsWrapperLayerState()
451 if (!this->image || this->decorationsSyncingDisabled)
return;
455 KisLayerUtils::findNodeByType<KisDecorationsWrapperLayer>(image->
root());
457 const bool needsDecorationsWrapper =
458 gridConfig.showGrid() || (guidesConfig.showGuides() && guidesConfig.hasGuides()) || !assistants.isEmpty();
461 SyncDecorationsWrapperStroke(
KisDocument *document,
bool needsDecorationsWrapper)
464 m_document(document),
465 m_needsDecorationsWrapper(needsDecorationsWrapper)
474 KisLayerUtils::findNodeByType<KisDecorationsWrapperLayer>(m_document->image()->root());
476 if (m_needsDecorationsWrapper && !decorationsLayer) {
478 }
else if (!m_needsDecorationsWrapper && decorationsLayer) {
479 m_document->image()->removeNode(decorationsLayer);
485 bool m_needsDecorationsWrapper =
false;
499 if (policy == REPLACE) {
504 mimeType = rhs.mimeType;
505 outputMimeType = rhs.outputMimeType;
507 if (policy == REPLACE) {
520 guidesConfig = rhs.guidesConfig;
521 mirrorAxisConfig = rhs.mirrorAxisConfig;
522 modified = rhs.modified;
525 m_storyboardCommentList = rhs.m_storyboardCommentList;
526 audioTracks = rhs.audioTracks;
527 audioLevel = rhs.audioLevel;
528 gridConfig = rhs.gridConfig;
530 imageModifiedWithoutUndo = rhs.imageModifiedWithoutUndo;
531 m_bAutoDetectedMime = rhs.m_bAutoDetectedMime;
534 readwrite = rhs.readwrite;
535 autoSaveActive = rhs.autoSaveActive;
536 firstMod = rhs.firstMod;
537 lastMod = rhs.lastMod;
539 globalAssistantsColor = rhs.globalAssistantsColor;
540 batchMode = rhs.batchMode;
543 if (rhs.linkedResourceStorage) {
544 linkedResourceStorage = rhs.linkedResourceStorage->clone();
547 if (rhs.embeddedResourceStorage) {
548 embeddedResourceStorage = rhs.embeddedResourceStorage->clone();
575 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
598 QMutex *m_savingLock;
599 KisImageReadOnlyBarrierLock m_imageLock;
606 connect(d->undoStack, SIGNAL(cleanChanged(
bool)),
this, SLOT(slotUndoStackCleanChanged(
bool)));
607 connect(d->autoSaveTimer, SIGNAL(timeout()),
this, SLOT(slotAutoSave()));
608 setObjectName(newObjectName());
613 connect(
this, SIGNAL(sigSavingFinished(
const QString&)), bookmarkmngr, SLOT(slotCreateBookmark(
const QString&)));
619 d->linkedResourcesStorageID = QUuid::createUuid().toString();
623 d->embeddedResourcesStorageID = QUuid::createUuid().toString();
624 d->embeddedResourceStorage.reset(
new KisResourceStorage(d->embeddedResourcesStorageID));
627 d->wasStorageAdded =
true;
648 d->wasStorageAdded =
true;
654 d->documentIsClosing =
true;
658 d->imageIdleWatcher.setTrackedImage(0);
666 d->autoSaveTimer->disconnect(
this);
667 d->autoSaveTimer->stop();
669 delete d->importExportManager;
672 delete d->shapeController;
674 delete d->koShapeController;
677 d->image->animationInterface()->blockBackgroundFrameGeneration();
679 d->image->notifyAboutToBeDeleted();
693 d->image->requestStrokeCancellation();
694 d->image->waitForDone();
697 d->undoStack->clear();
698 d->image->waitForDone();
701 Q_UNUSED(sanityCheckPointer);
710 if (
d->wasStorageAdded) {
724 return d->embeddedResourcesStorageID;
729 return d->linkedResourcesStorageID;
739 QFileInfo filePathInfo(job.
filePath);
741 if (filePathInfo.exists() && !filePathInfo.isWritable()) {
743 i18n(
"%1 cannot be written to. Please save under a different name.", job.
filePath),
749 if (cfg.
backupFile() && filePathInfo.exists()) {
753 switch(cfg.
readEntry<
int>(
"backupfilelocation", 0)) {
755 backupDir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
758 backupDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
764 QDir().mkpath(backupDir);
772 QUrl fileUrl = QUrl::fromLocalFile(job.
filePath);
774 backupDir = QDir::tempPath();
783 int numOfBackupsKept = cfg.
readEntry<
int>(
"numberofbackupfiles", 1);
784 QString suffix = cfg.
readEntry<QString>(
"backupfilesuffix",
"~");
786 if (numOfBackupsKept == 1) {
788 qWarning() <<
"Failed to create simple backup file!" << job.
filePath << backupDir << suffix;
790 .arg(job.
filePath, backupDir.isEmpty()
791 ?
"the same location as the file"
798 .arg(job.
filePath, backupDir.isEmpty()
799 ?
"the same location as the file"
803 else if (numOfBackupsKept > 1) {
805 qWarning() <<
"Failed to create numbered backup file!" << job.
filePath << backupDir << suffix;
807 .arg(job.
filePath, backupDir.isEmpty()
808 ?
"the same location as the file"
815 .arg(job.
filePath, backupDir.isEmpty()
816 ?
"the same location as the file"
830 const QString actionName =
832 i18n(
"Exporting Document...") :
833 i18n(
"Saving Document...");
838 job, exportConfiguration, isAdvancedExporting);
841 QString errorShortLog;
847 errorShortLog =
"another save operation is in progress";
848 errorMessage = i18n(
"Could not start saving %1. Wait until the current save operation has finished.", job.
filePath);
852 errorShortLog =
"failed to lock and clone the image";
857 errorShortLog =
"failed to start background saving";
884 SaveFlags flags = SaveIsExporting;
886 flags |= SaveShowWarnings;
889 KisUsageLogger::log(QString(
"Exporting Document: %1 as %2. %3 * %4 pixels, %5 layers, %6 frames, %7 "
890 "framerate. Export configuration: %8")
891 .arg(path, QString::fromLatin1(
mimeType), QString::number(
d->image->width()),
892 QString::number(
d->image->height()), QString::number(
d->image->nlayers()),
893 QString::number(
d->image->animationInterface()->totalLength()),
894 QString::number(
d->image->animationInterface()->framerate()),
895 (exportConfiguration ? exportConfiguration->toXML() :
"No configuration")));
900 exportConfiguration, isAdvancedExporting);
907 KisUsageLogger::log(QString(
"Saving Document %9 as %1 (mime: %2). %3 * %4 pixels, %5 layers. %6 frames, "
908 "%7 framerate. Export configuration: %8")
909 .arg(_path, QString::fromLatin1(
mimeType), QString::number(
d->image->width()),
910 QString::number(
d->image->height()), QString::number(
d->image->nlayers()),
911 QString::number(
d->image->animationInterface()->totalLength()),
912 QString::number(
d->image->animationInterface()->framerate()),
913 (exportConfiguration ? exportConfiguration->toXML() :
"No configuration"),
923 showWarnings ? SaveShowWarnings : SaveNone),
924 exportConfiguration);
937 filter->setBatchMode(
true);
940 Private::StrippedSafeSavingLocker locker(&
d->savingMutex,
d->image);
941 if (!locker.successfullyLocked()) {
942 return buffer.data();
945 d->savingImage =
d->image;
947 if (!filter->convert(
this, &buffer).isOk()) {
948 qWarning() <<
"serializeToByteArray():: Could not export to our native format";
951 return buffer.data();
958 const QString &message,
960 const QString &details = {})
961 : QMessageBox(QMessageBox::Warning, title, message, QMessageBox::Ok, qApp->activeWindow())
963 if (!details.isEmpty()) {
964 setInformativeText(details);
966 if (!warnings.isEmpty()) {
974 QMessageBox::setDetailedText(text.first());
976 QTextEdit *messageBox = findChild<QTextEdit *>();
979 messageBox->setAcceptRichText(
true);
981 QString warning =
"<html><body><ul>";
982 Q_FOREACH (
const QString &i, text) {
983 warning +=
"\n<li>" + i +
"</li>";
985 warning +=
"</ul></body></html>";
987 messageBox->setText(warning);
997 const QString fileName = QFileInfo(job.
filePath).fileName();
999 if (!status.
isOk()) {
1000 Q_EMIT
statusBarMessage(i18nc(
"%1 --- failing file name, %2 --- error message",
1001 "Error during saving %1: %2",
1008 i18n(
"Could not save %1.", job.
filePath),
1022 i18nc(
"@title:window",
"Krita"),
1023 i18nc(
"dialog box shown to the user if there were warnings while saving the document, "
1024 "%1 is the file path",
1025 "%1 has been saved but is incomplete.",
1030 : i18nc(
"dialog box shown to the user if there were warnings while saving the document",
1031 "Some problems were encountered when saving."));
1048 Q_EMIT
statusBarMessage(i18n(
"Finished saving %1", fileName), successMessageTimeout);
1052void KisDocument::Private::updateDocumentMetadataOnSaving(
const QString &filePath,
const QByteArray &mimeType)
1059 QFileInfo fi(filePath);
1062 if (!modifiedWhileSaving) {
1069 if (undoStack->isClean()) {
1072 imageModifiedWithoutUndo =
false;
1073 undoStack->setClean();
1091 return d->batchMode;
1099void KisDocument::Private::uploadLinkedResourcesFromLayersToStorage()
1110 if (KisNodeFilterInterface *layer = dynamic_cast<KisNodeFilterInterface*>(node.data())) {
1111 KisFilterConfigurationSP filterConfig = layer->filter();
1112 if (!filterConfig) return;
1114 QList<KoResourceLoadResult> linkedResources = filterConfig->linkedResources(KisGlobalResourcesInterface::instance());
1116 Q_FOREACH (const KoResourceLoadResult &result, linkedResources) {
1117 KIS_SAFE_ASSERT_RECOVER(result.type() != KoResourceLoadResult::EmbeddedResource) { continue; }
1119 KoResourceSP resource = result.resource();
1122 qWarning() <<
"WARNING: KisDocument::lockAndCloneForSaving failed to fetch a resource" << result.signature();
1127 buf.open(QBuffer::WriteOnly);
1129 KisResourceModel model(resource->resourceType().first);
1130 bool res = model.exportResource(resource, &buf);
1135 qWarning() <<
"WARNING: KisDocument::lockAndCloneForSaving failed to export resource" << result.signature();
1139 buf.open(QBuffer::ReadOnly);
1141 res = doc->d->linkedResourceStorage->importResource(resource->resourceType().first +
"/" + resource->filename(), &buf);
1146 qWarning() <<
"WARNING: KisDocument::lockAndCloneForSaving failed to import resource" << result.signature();
1155KisDocument *KisDocument::Private::lockAndCloneImpl(
bool fetchResourcesFromLayers)
1158 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1170 Private::StrippedSafeSavingLocker locker(&savingMutex, image);
1171 if (!locker.successfullyLocked()) {
1177 if (fetchResourcesFromLayers) {
1178 doc->
d->uploadLinkedResourcesFromLayersToStorage();
1186 return d->lockAndCloneImpl(
true);
1191 return d->lockAndCloneImpl(
false);
1202 d->decorationsSyncingDisabled =
true;
1203 d->copyFrom(*(rhs.
d),
this);
1204 d->decorationsSyncingDisabled =
false;
1206 d->undoStack->clear();
1211 connect(
d->autoSaveTimer, SIGNAL(timeout()),
this, SLOT(
slotAutoSave()));
1217 setObjectName(rhs.objectName());
1223 d->image->barrierLock(
false);
1224 rhs.
d->image->barrierLock(
true);
1225 d->image->copyFromImage(*(rhs.
d->image));
1227 rhs.
d->image->unlock();
1238 d->syncDecorationsWrapperLayerState();
1241 if (rhs.
d->preActivatedNode) {
1242 QQueue<KisNodeSP> linearizedNodes;
1245 linearizedNodes.enqueue(node);
1248 [&linearizedNodes, &rhs,
this](
KisNodeSP node) {
1249 KisNodeSP refNode = linearizedNodes.dequeue();
1250 if (rhs.d->preActivatedNode.data() == refNode.data()) {
1251 d->preActivatedNode = node;
1258 if (referencesLayer) {
1259 d->referenceLayerConnections.clear();
1260 d->referenceLayerConnections.addConnection(
1261 referencesLayer, SIGNAL(sigUpdateCanvas(QRectF)),
1262 this, SIGNAL(sigReferenceImagesChanged()));
1264 Q_EMIT sigReferenceImagesLayerChanged(referencesLayer);
1265 Q_EMIT sigReferenceImagesChanged();
1269 KisLayerUtils::findNodeByType<KisDecorationsWrapperLayer>(
d->image->root());
1270 if (decorationsLayer) {
1271 decorationsLayer->setDocument(
this);
1275 if (policy == REPLACE) {
1289 Private::StrippedSafeSavingLocker locker(&
d->savingMutex,
d->image);
1290 if (!locker.successfullyLocked()) {
1295 d->savingImage =
d->image;
1298 d->importExportManager->
1303 return status.
isOk();
1308 const QObject *receiverObject,
const char *receiverMethod,
1313 job, exportConfiguration, std::unique_ptr<KisDocument>(), isAdvancedExporting);
1317 const QObject *receiverObject,
const char *receiverMethod,
1320 std::unique_ptr<KisDocument> &&optionalClonedDocument,
bool isAdvancedExporting)
1324 QScopedPointer<KisDocument> clonedDocument;
1326 if (!optionalClonedDocument) {
1329 clonedDocument.reset(optionalClonedDocument.release());
1332 if (!
d->savingMutex.tryLock()){
1340 std::unique_lock<QMutex> savingMutexLock(
d->savingMutex, std::adopt_lock);
1342 if (!clonedDocument) {
1359 waitForImage(clonedDocument->image());
1363 if (clonedDocument->image()->hasOverlaySelectionMask()) {
1364 clonedDocument->image()->setOverlaySelectionMask(0);
1365 waitForImage(clonedDocument->image());
1370 clonedDocument->image()->cropImage(clonedDocument->image()->bounds());
1371 clonedDocument->image()->purgeUnusedData(
false);
1372 waitForImage(clonedDocument->image());
1376 waitForImage(clonedDocument->image());
1391 savingMutexLock.release();
1393 d->backgroundSaveDocument.reset(clonedDocument.take());
1394 d->backgroundSaveJob = job;
1395 d->modifiedWhileSaving =
false;
1398 d->backgroundSaveDocument->d->isAutosaving =
true;
1401 connect(
d->backgroundSaveDocument.data(),
1408 receiverObject, receiverMethod, Qt::UniqueConnection);
1411 d->backgroundSaveDocument->startExportInBackground(actionName,
1416 exportConfiguration, isAdvancedExporting);
1417 if (!error.
isOk()) {
1420 d->backgroundSaveDocument.take()->deleteLater();
1421 d->savingMutex.unlock();
1443 std::unique_lock<QMutex> savingMutexLock(
d->savingMutex, std::adopt_lock);
1448 d->backgroundSaveDocument->d->isAutosaving =
false;
1451 d->backgroundSaveDocument.take()->deleteLater();
1459 savingMutexLock.unlock();
1462 KisUsageLogger::log(QString(
"Completed saving %1 (mime: %2). Result: %3. Warning: %4. Size: %5")
1465 QString::number(fi.size())));
1472 if (!
d->modified || !
d->modifiedAfterAutosave)
return;
1475 Q_EMIT
statusBarMessage(i18n(
"Autosaving... %1", autoSaveFileName), successMessageTimeout);
1479 const bool hadClonedDocument = bool(optionalClonedDocument);
1482 if (
d->image->isIdle() || hadClonedDocument) {
1487 std::move(optionalClonedDocument));
1489 Q_EMIT
statusBarMessage(i18n(
"Autosaving postponed: document is busy..."), errorMessageTimeout);
1494 connect(stroke, SIGNAL(sigDocumentCloned(
KisDocument*)),
1496 Qt::BlockingQueuedConnection);
1497 connect(stroke, SIGNAL(sigCloningCancelled()),
1499 Qt::BlockingQueuedConnection);
1502 d->image->endStroke(strokeId);
1509 d->modifiedAfterAutosave =
false;
1517 QStringList pathParts = QFileInfo(path).absolutePath().split(
'/');
1518 if (pathParts.size() > 0) {
1519 QString resourceType = pathParts.last();
1525 QString tempFileName = QDir::tempPath() +
"/" + QFileInfo(path).fileName();
1527 if (QFileInfo(path).exists()) {
1536 d->modifiedWhileSaving =
false;
1538 if (!exportConfiguration) {
1539 QScopedPointer<KisImportExportFilter> filter(
1546 if (exportConfiguration) {
1548 exportConfiguration->setProperty(
"name", res->name());
1552 QFile f2(tempFileName);
1553 f2.open(QFile::ReadOnly);
1555 QByteArray ba = f2.readAll();
1558 buf.open(QBuffer::ReadOnly);
1564 const QString filePath =
1567 d->updateDocumentMetadataOnSaving(filePath,
mimeType);
1576 d->modifiedWhileSaving =
false;
1580 const QString filePath =
1583 d->updateDocumentMetadataOnSaving(filePath,
mimeType);
1612 d->image->explicitRegenerateLevelOfDetail();
1627 const QString fileName = QFileInfo(job.
filePath).fileName();
1629 if (!status.
isOk()) {
1631 Q_EMIT
statusBarMessage(i18nc(
"%1 --- failing file name, %2 --- error message",
1632 "Error during autosaving %1: %2",
1639 if (!
d->modifiedWhileSaving) {
1640 d->autoSaveTimer->stop();
1641 d->autoSaveFailureCount = 0;
1646 Q_EMIT
statusBarMessage(i18n(
"Finished autosaving %1", fileName), successMessageTimeout);
1651 const QString &location,
1652 const QString &realLocation,
1653 const QByteArray &mimeType,
1657 d->savingImage =
d->image;
1663 d->importExportManager->setUpdater(
d->savingUpdater);
1668 d->childSavingFuture =
1669 d->importExportManager->exportDocumentAsync(location,
1672 initializationStatus,
1674 exportConfiguration,
1675 isAdvancedExporting);
1677 if (!initializationStatus.
isOk()) {
1678 if (
d->savingUpdater) {
1679 d->savingUpdater->cancel();
1681 d->savingImage.clear();
1683 return initializationStatus;
1686 typedef QFutureWatcher<KisImportExportErrorCode> StatusWatcher;
1687 StatusWatcher *watcher =
new StatusWatcher();
1688 watcher->setFuture(
d->childSavingFuture);
1691 connect(watcher, SIGNAL(finished()), watcher, SLOT(deleteLater()));
1693 return initializationStatus;
1707 if (!
d->lastErrorMessage.isEmpty()) {
1715 d->savingImage.clear();
1717 d->lastErrorMessage.clear();
1718 d->lastWarningMessage.clear();
1720 if (
d->savingUpdater) {
1721 d->savingUpdater->setProgress(100);
1729 const bool changed =
readwrite !=
d->readwrite;
1751 d->autoSaveTimer->start(delay * 1000);
1753 d->autoSaveTimer->stop();
1760 d->autoSaveFailureCount = 0;
1765 const int emergencyAutoSaveInterval = 10;
1767 d->autoSaveFailureCount++;
1777 return d->autoSaveActive;
1793 if (
d->savingImage)
image =
d->savingImage;
1797 QSize originalSize =
bounds.size();
1799 QSize newSize = originalSize.scaled(size, Qt::KeepAspectRatio).expandedTo({1, 1});
1801 bool pixelArt =
false;
1803 if (originalSize.width() < size.width() && originalSize.height() < size.height()) {
1806 if (newSize.height()%originalSize.height() == 0 && newSize.width()%originalSize.width() == 0) {
1816 QImage scaled = original.scaled(newSize, Qt::KeepAspectRatio, Qt::FastTransformation);
1817 px = QPixmap::fromImage(scaled);
1821 if (px.size() == QSize(0,0)) {
1822 px = QPixmap(newSize);
1825 gc.fillRect(px.rect(), checkBrush);
1830 return QPixmap(size);
1838 const QString extension (
".kra");
1839 QString prefix =
KisConfig(
true).
readEntry<
bool>(
"autosavefileshidden") ? QString(
".") : QString();
1840 QRegularExpression autosavePattern1(
"^\\..+-autosave.kra$");
1841 QRegularExpression autosavePattern2(
"^.+-autosave.kra$");
1844 QString dir = fi.absolutePath();
1848 if (path.startsWith(
"content://")) {
1854 QString filename = fi.fileName();
1856 if (path.isEmpty() || autosavePattern1.match(filename).hasMatch() || autosavePattern2.match(filename).hasMatch() || !fi.isWritable()) {
1858 retval = QString(
"%1%2%3%4-%5-%6-autosave%7")
1863 .arg(qApp->applicationPid())
1869 retval = QString(
"%1%2%3%4-autosave%5").arg(dir).arg(
'/').arg(prefix).arg(filename).arg(extension);
1880 dbgUI <<
"path=" << _path;
1888 dbgUI <<
"success, resetting url";
1898 dbgUI <<
"path=" << _path;
1899 d->lastErrorMessage.clear();
1902 if (_path.isEmpty()) {
1903 d->lastErrorMessage = i18n(
"Malformed Path\n%1", _path);
1907 QString path = _path;
1908 QString original =
"";
1909 bool autosaveOpened =
false;
1911 QString file =
path;
1913 if (QFile::exists(asf)) {
1920 int res = dlg.result();
1926 autosaveOpened =
true;
1955 QFileInfo fi(_path);
1969 QMessageBox::critical(qApp->activeWindow(), i18nc(
"@title:window",
"Krita"), i18n(
"File %1 does not exist.",
localFilePath()));
1976 if (typeName.isEmpty()) {
1981 if (typeName ==
"application/x-trash") {
1982 QString path = filename;
1983 while (path.length() > 0) {
1987 if (!typeName.isEmpty()) {
1999 d->importExportManager->setUpdater(updater);
2004 if (!status.
isOk()) {
2024 i18n(
"There were problems opening %1.",
prettyPath()),
2032 d->syncDecorationsWrapperLayerState();
2042 if (!
d->modified || !
d->modifiedAfterAutosave)
2051 d->modifiedAfterAutosave =
false;
2056 qWarning() <<
"Could not auto-save when paused";
2064 d->outputMimeType =
d->mimeType;
2083 if (
d->isAutosaving ||
d->documentIsClosing)
2089 if (mod && !
d->autoSaveTimer->isActive()) {
2093 d->modifiedAfterAutosave = mod;
2094 d->modifiedWhileSaving = mod;
2097 d->imageModifiedWithoutUndo = mod;
2114 const bool changed =
value !=
d->isRecovered;
2125 return d->isRecovered;
2130 QDateTime now = QDateTime::currentDateTime();
2131 int firstModDelta =
d->firstMod.secsTo(now);
2132 int lastModDelta =
d->lastMod.secsTo(now);
2134 if (lastModDelta > 30) {
2135 d->docInfo->setAboutInfo(
"editing-time", QString::number(
d->docInfo->aboutInfo(
"editing-time").toInt() +
d->firstMod.secsTo(
d->lastMod)));
2137 }
else if (firstModDelta > 60 || forceStoreElapsed) {
2138 d->docInfo->setAboutInfo(
"editing-time", QString::number(
d->docInfo->aboutInfo(
"editing-time").toInt() + firstModDelta));
2147 QString _url(
path());
2149 _url = QDir::toNativeSeparators(_url);
2158 const QString _url(QFileInfo(
path()).fileName());
2161 if (_url.isEmpty()) {
2162 c =
" [" + i18n(
"Not Saved") +
"] ";
2178 QDomImplementation impl;
2179 QString url = QString(
"http://www.calligra.org/DTD/%1-%2.dtd").arg(appName).arg(version);
2180 QDomDocumentType dtype = impl.createDocumentType(tagName,
2181 QString(
"-//KDE//DTD %1 %2//EN").arg(appName).arg(version),
2184 QString namespaceURN = QString(
"http://www.calligra.org/DTD/%1").arg(appName);
2185 QDomDocument doc = impl.createDocument(namespaceURN, tagName, dtype);
2186 doc.insertBefore(doc.createProcessingInstruction(
"xml",
"version=\"1.0\" encoding=\"UTF-8\""), doc.documentElement());
2199 d->lastErrorMessage = errMsg;
2204 return d->lastErrorMessage;
2209 d->lastWarningMessage = warningMsg;
2214 return d->lastWarningMessage;
2222 if (QFile::exists(asf)) {
2228 if (QFile::exists(asf)) {
2235 expressions << QRegularExpression(
"^\\..+-autosave.kra$")
2236 << QRegularExpression(
"^.+-autosave.kra$");
2238 Q_FOREACH(
const QRegularExpression &rex, expressions) {
2240 !autosaveBaseName.isEmpty() &&
2241 rex.match(QFileInfo(autosaveBaseName).fileName()).hasMatch() &&
2242 QFile::exists(autosaveBaseName)) {
2245 QFile::remove(autosaveBaseName);
2257 if (
d->unit !=
unit) {
2265 return d->undoStack;
2270 return d->importExportManager;
2283 if (!
d->undoStack->isClean()) {
2284 d->undoStack->clear();
2300 d->syncDecorationsWrapperLayerState();
2305 d->undoStack->clear();
2310 return d->gridConfig;
2315 if (
d->gridConfig != config) {
2316 d->gridConfig = config;
2317 d->syncDecorationsWrapperLayerState();
2329 if (!
d->linkedResourceStorage) {
2335 while (iter->hasNext()) {
2339 buf.open(QBuffer::WriteOnly);
2340 bool exportSuccessful =
2341 d->linkedResourceStorage->exportResource(iter->url(), &buf);
2343 KoResourceSP resource =
d->linkedResourceStorage->resource(iter->url());
2344 exportSuccessful &= bool(resource);
2346 const QString name = resource ? resource->name() : QString();
2347 const QString fileName = QFileInfo(iter->url()).fileName();
2352 if (exportSuccessful) {
2355 result << signature;
2366 if (
d->linkedResourceStorage) {
2368 while (iter->hasNext()) {
2371 if (resource && resource->valid()) {
2372 oldPaletteList << resource.dynamicCast<
KoColorSet>();
2375 if (oldPaletteList != paletteList) {
2378 if (!paletteList.contains(
palette)) {
2383 if (!oldPaletteList.contains(
palette)) {
2387 palette->setStorageLocation(
d->linkedResourcesStorageID);
2400 return d->m_storyboardItemList;
2405 d->m_storyboardItemList = storyboardItemList;
2413 return d->m_storyboardCommentList;
2418 d->m_storyboardCommentList = storyboardCommentList;
2425 return d->audioTracks;
2436 d->audioLevel = level;
2442 return d->audioLevel;
2447 return d->guidesConfig;
2452 if (
d->guidesConfig == data)
return;
2454 d->guidesConfig = data;
2455 d->syncDecorationsWrapperLayerState();
2462 return d->mirrorAxisConfig;
2467 if (
d->mirrorAxisConfig == config) {
2471 d->mirrorAxisConfig = config;
2474 d->image->bounds()));
2493 return d->readwrite;
2506 if (view && view->
document() ==
this) {
2515 d->mimeType = QByteArray();
2527 const bool changed = path !=
d->m_path;
2549 if ( path.isEmpty() ) {
2553 if (
d->m_bAutoDetectedMime) {
2554 d->mimeType = QByteArray();
2555 d->m_bAutoDetectedMime =
false;
2569 d->m_file =
d->m_path;
2573 if (
d->mimeType.isEmpty()) {
2577 d->mimeType = mime.toLocal8Bit();
2578 d->m_bAutoDetectedMime =
true;
2594 qint32 width, qint32 height,
2598 const QString &description,
const double imageResolution)
2604 if (!cs)
return false;
2606 KisCursorOverrideLock cursorLock(Qt::BusyCursor);
2637 KoColor strippedAlpha = bgColor;
2646 filter_config->setProperty(
"color", strippedAlpha.
toQColor());
2647 filter_config->createLocalResourcesSnapshot();
2653 if (numberOfLayers > 1) {
2663 Q_CHECK_PTR(bgLayer);
2665 bgLayer->
setDirty(QRect(0, 0, width, height));
2668 d->mirrorAxisConfig.setAxisPosition(QRectF(
image->
bounds()).center());
2671 for(
int i = 1; i < numberOfLayers; ++i) {
2675 layer->
setDirty(QRect(0, 0, width, height));
2689 QString(
"Created image \"%1\", %2 * %3 pixels, %4 dpi. Color model: %6 %5 (%7). Layers: %8")
2690 .arg(name, QString::number(width), QString::number(height),
2693 QString::number(numberOfLayers)));
2700 const bool result =
d->savingMutex.tryLock();
2702 d->savingMutex.unlock();
2710 KisAsyncActionFeedback f(i18nc(
"progress dialog message when the user closes the document that is being saved",
"Waiting for saving to complete..."), 0);
2711 f.waitForMutex(
d->savingMutex);
2717 return d->shapeController;
2722 return d->shapeController->shapeForNode(layer);
2727 return d->assistants;
2732 if (
d->assistants !=
value) {
2734 d->syncDecorationsWrapperLayerState();
2744 KisLayerUtils::findNodeByType<KisReferenceImagesLayer>(
d->image->root());
2746 return referencesLayer;
2755 if (currentReferenceLayer == layer && updateImage) {
2759 d->referenceLayerConnections.clear();
2762 if (currentReferenceLayer) {
2763 d->image->removeNode(currentReferenceLayer);
2767 d->image->addNode(layer);
2771 currentReferenceLayer = layer;
2773 if (currentReferenceLayer) {
2774 d->referenceLayerConnections.addConnection(
2775 currentReferenceLayer, SIGNAL(sigUpdateCanvas(QRectF)),
2785 d->preActivatedNode = activatedNode;
2790 return d->preActivatedNode;
2800 return d->savingImage;
2809 d->image->disconnect(
this);
2810 d->shapeController->setImage(0);
2816 if (
d->linkedResourceStorage){
2820 d->setImageAndInitIdleWatcher(
image);
2825 connect(
d->image, SIGNAL(sigImageModified()),
this, SLOT(
setImageModified()), Qt::UniqueConnection);
2829 if (forceInitialUpdate) {
2830 d->image->initialRefreshGraph();
2841 d->shapeController->setImage(
image);
2847 setModified(
d->imageModifiedWithoutUndo || !
d->undoStack->isClean());
2852 d->imageModifiedWithoutUndo =
true;
2864 return d->isAutosaving;
2874 d->globalAssistantsColor = color;
2879 return d->globalAssistantsColor;
2884 return d->colorHistory;
2889 QRectF
bounds =
d->image->bounds();
2893 if (referenceImagesLayer) {
2902 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
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)