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";
881 SaveFlags flags = SaveIsExporting;
883 flags |= SaveShowWarnings;
886 KisUsageLogger::log(QString(
"Exporting Document: %1 as %2. %3 * %4 pixels, %5 layers, %6 frames, %7 "
887 "framerate. Export configuration: %8")
888 .arg(path, QString::fromLatin1(
mimeType), QString::number(
d->image->width()),
889 QString::number(
d->image->height()), QString::number(
d->image->nlayers()),
890 QString::number(
d->image->animationInterface()->totalLength()),
891 QString::number(
d->image->animationInterface()->framerate()),
892 (exportConfiguration ? exportConfiguration->toXML() :
"No configuration")));
897 exportConfiguration, isAdvancedExporting);
904 KisUsageLogger::log(QString(
"Saving Document %9 as %1 (mime: %2). %3 * %4 pixels, %5 layers. %6 frames, "
905 "%7 framerate. Export configuration: %8")
906 .arg(_path, QString::fromLatin1(
mimeType), QString::number(
d->image->width()),
907 QString::number(
d->image->height()), QString::number(
d->image->nlayers()),
908 QString::number(
d->image->animationInterface()->totalLength()),
909 QString::number(
d->image->animationInterface()->framerate()),
910 (exportConfiguration ? exportConfiguration->toXML() :
"No configuration"),
920 showWarnings ? SaveShowWarnings : SaveNone),
921 exportConfiguration);
934 filter->setBatchMode(
true);
937 Private::StrippedSafeSavingLocker locker(&
d->savingMutex,
d->image);
938 if (!locker.successfullyLocked()) {
939 return buffer.data();
942 d->savingImage =
d->image;
944 if (!filter->convert(
this, &buffer).isOk()) {
945 qWarning() <<
"serializeToByteArray():: Could not export to our native format";
948 return buffer.data();
955 const QString &message,
957 const QString &details = {})
958 : QMessageBox(QMessageBox::Warning, title, message, QMessageBox::Ok, qApp->activeWindow())
960 if (!details.isEmpty()) {
961 setInformativeText(details);
963 if (!warnings.isEmpty()) {
971 QMessageBox::setDetailedText(text.first());
973 QTextEdit *messageBox = findChild<QTextEdit *>();
976 messageBox->setAcceptRichText(
true);
978 QString warning =
"<html><body><ul>";
979 Q_FOREACH (
const QString &i, text) {
980 warning +=
"\n<li>" + i +
"</li>";
982 warning +=
"</ul></body></html>";
984 messageBox->setText(warning);
994 const QString fileName = QFileInfo(job.
filePath).fileName();
996 if (!status.
isOk()) {
997 Q_EMIT
statusBarMessage(i18nc(
"%1 --- failing file name, %2 --- error message",
998 "Error during saving %1: %2",
1005 i18n(
"Could not save %1.", job.
filePath),
1019 i18nc(
"@title:window",
"Krita"),
1020 i18nc(
"dialog box shown to the user if there were warnings while saving the document, "
1021 "%1 is the file path",
1022 "%1 has been saved but is incomplete.",
1027 : i18nc(
"dialog box shown to the user if there were warnings while saving the document",
1028 "Some problems were encountered when saving."));
1045 Q_EMIT
statusBarMessage(i18n(
"Finished saving %1", fileName), successMessageTimeout);
1049void KisDocument::Private::updateDocumentMetadataOnSaving(
const QString &filePath,
const QByteArray &mimeType)
1056 QFileInfo fi(filePath);
1059 if (!modifiedWhileSaving) {
1066 if (undoStack->isClean()) {
1069 imageModifiedWithoutUndo =
false;
1070 undoStack->setClean();
1088 return d->batchMode;
1096void KisDocument::Private::uploadLinkedResourcesFromLayersToStorage()
1107 if (KisNodeFilterInterface *layer = dynamic_cast<KisNodeFilterInterface*>(node.data())) {
1108 KisFilterConfigurationSP filterConfig = layer->filter();
1109 if (!filterConfig) return;
1111 QList<KoResourceLoadResult> linkedResources = filterConfig->linkedResources(KisGlobalResourcesInterface::instance());
1113 Q_FOREACH (const KoResourceLoadResult &result, linkedResources) {
1114 KIS_SAFE_ASSERT_RECOVER(result.type() != KoResourceLoadResult::EmbeddedResource) { continue; }
1116 KoResourceSP resource = result.resource();
1119 qWarning() <<
"WARNING: KisDocument::lockAndCloneForSaving failed to fetch a resource" << result.signature();
1124 buf.open(QBuffer::WriteOnly);
1126 KisResourceModel model(resource->resourceType().first);
1127 bool res = model.exportResource(resource, &buf);
1132 qWarning() <<
"WARNING: KisDocument::lockAndCloneForSaving failed to export resource" << result.signature();
1136 buf.open(QBuffer::ReadOnly);
1138 res = doc->d->linkedResourceStorage->importResource(resource->resourceType().first +
"/" + resource->filename(), &buf);
1143 qWarning() <<
"WARNING: KisDocument::lockAndCloneForSaving failed to import resource" << result.signature();
1152KisDocument *KisDocument::Private::lockAndCloneImpl(
bool fetchResourcesFromLayers)
1155 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1167 Private::StrippedSafeSavingLocker locker(&savingMutex, image);
1168 if (!locker.successfullyLocked()) {
1174 if (fetchResourcesFromLayers) {
1175 doc->
d->uploadLinkedResourcesFromLayersToStorage();
1183 return d->lockAndCloneImpl(
true);
1188 return d->lockAndCloneImpl(
false);
1199 d->decorationsSyncingDisabled =
true;
1200 d->copyFrom(*(rhs.
d),
this);
1201 d->decorationsSyncingDisabled =
false;
1203 d->undoStack->clear();
1214 setObjectName(rhs.objectName());
1220 d->image->barrierLock(
false);
1221 rhs.
d->image->barrierLock(
true);
1222 d->image->copyFromImage(*(rhs.
d->image));
1224 rhs.
d->image->unlock();
1235 d->syncDecorationsWrapperLayerState();
1238 if (rhs.
d->preActivatedNode) {
1239 QQueue<KisNodeSP> linearizedNodes;
1242 linearizedNodes.enqueue(node);
1245 [&linearizedNodes, &rhs,
this](
KisNodeSP node) {
1246 KisNodeSP refNode = linearizedNodes.dequeue();
1247 if (rhs.d->preActivatedNode.data() == refNode.data()) {
1248 d->preActivatedNode = node;
1255 if (referencesLayer) {
1256 d->referenceLayerConnections.clear();
1257 d->referenceLayerConnections.addConnection(
1258 referencesLayer, SIGNAL(sigUpdateCanvas(QRectF)),
1259 this, SIGNAL(sigReferenceImagesChanged()));
1261 Q_EMIT sigReferenceImagesLayerChanged(referencesLayer);
1262 Q_EMIT sigReferenceImagesChanged();
1266 KisLayerUtils::findNodeByType<KisDecorationsWrapperLayer>(
d->image->root());
1267 if (decorationsLayer) {
1268 decorationsLayer->setDocument(
this);
1272 if (policy == REPLACE) {
1286 Private::StrippedSafeSavingLocker locker(&
d->savingMutex,
d->image);
1287 if (!locker.successfullyLocked()) {
1292 d->savingImage =
d->image;
1295 d->importExportManager->
1300 return status.
isOk();
1305 const QObject *receiverObject,
const char *receiverMethod,
1310 job, exportConfiguration, std::unique_ptr<KisDocument>(), isAdvancedExporting);
1314 const QObject *receiverObject,
const char *receiverMethod,
1317 std::unique_ptr<KisDocument> &&optionalClonedDocument,
bool isAdvancedExporting)
1321 QScopedPointer<KisDocument> clonedDocument;
1323 if (!optionalClonedDocument) {
1326 clonedDocument.reset(optionalClonedDocument.release());
1329 if (!
d->savingMutex.tryLock()){
1337 std::unique_lock<QMutex> savingMutexLock(
d->savingMutex, std::adopt_lock);
1339 if (!clonedDocument) {
1356 waitForImage(clonedDocument->image());
1360 if (clonedDocument->image()->hasOverlaySelectionMask()) {
1361 clonedDocument->image()->setOverlaySelectionMask(0);
1362 waitForImage(clonedDocument->image());
1367 clonedDocument->image()->cropImage(clonedDocument->image()->bounds());
1368 clonedDocument->image()->purgeUnusedData(
false);
1369 waitForImage(clonedDocument->image());
1373 waitForImage(clonedDocument->image());
1388 savingMutexLock.release();
1390 d->backgroundSaveDocument.reset(clonedDocument.take());
1391 d->backgroundSaveJob = job;
1392 d->modifiedWhileSaving =
false;
1395 d->backgroundSaveDocument->d->isAutosaving =
true;
1398 connect(
d->backgroundSaveDocument.data(),
1405 receiverObject, receiverMethod, Qt::UniqueConnection);
1408 d->backgroundSaveDocument->startExportInBackground(actionName,
1413 exportConfiguration, isAdvancedExporting);
1418 d->backgroundSaveDocument.take()->deleteLater();
1419 d->savingMutex.unlock();
1438 std::unique_lock<QMutex> savingMutexLock(
d->savingMutex, std::adopt_lock);
1443 d->backgroundSaveDocument->d->isAutosaving =
false;
1446 d->backgroundSaveDocument.take()->deleteLater();
1454 savingMutexLock.unlock();
1457 KisUsageLogger::log(QString(
"Completed saving %1 (mime: %2). Result: %3. Warning: %4. Size: %5")
1460 QString::number(fi.size())));
1467 if (!
d->modified || !
d->modifiedAfterAutosave)
return;
1470 Q_EMIT
statusBarMessage(i18n(
"Autosaving... %1", autoSaveFileName), successMessageTimeout);
1474 const bool hadClonedDocument = bool(optionalClonedDocument);
1477 if (
d->image->isIdle() || hadClonedDocument) {
1482 std::move(optionalClonedDocument));
1484 Q_EMIT
statusBarMessage(i18n(
"Autosaving postponed: document is busy..."), errorMessageTimeout);
1491 Qt::BlockingQueuedConnection);
1492 connect(stroke, SIGNAL(sigCloningCancelled()),
1494 Qt::BlockingQueuedConnection);
1497 d->image->endStroke(strokeId);
1504 d->modifiedAfterAutosave =
false;
1512 QStringList pathParts = QFileInfo(path).absolutePath().split(
'/');
1513 if (pathParts.size() > 0) {
1514 QString resourceType = pathParts.last();
1520 QString tempFileName = QDir::tempPath() +
"/" + QFileInfo(path).fileName();
1522 if (QFileInfo(path).exists()) {
1531 d->modifiedWhileSaving =
false;
1533 if (!exportConfiguration) {
1534 QScopedPointer<KisImportExportFilter> filter(
1541 if (exportConfiguration) {
1543 exportConfiguration->setProperty(
"name", res->name());
1547 QFile f2(tempFileName);
1548 f2.open(QFile::ReadOnly);
1550 QByteArray ba = f2.readAll();
1553 buf.open(QBuffer::ReadOnly);
1559 const QString filePath =
1562 d->updateDocumentMetadataOnSaving(filePath,
mimeType);
1571 d->modifiedWhileSaving =
false;
1575 const QString filePath =
1578 d->updateDocumentMetadataOnSaving(filePath,
mimeType);
1607 d->image->explicitRegenerateLevelOfDetail();
1622 const QString fileName = QFileInfo(job.
filePath).fileName();
1624 if (!status.
isOk()) {
1626 Q_EMIT
statusBarMessage(i18nc(
"%1 --- failing file name, %2 --- error message",
1627 "Error during autosaving %1: %2",
1634 if (!
d->modifiedWhileSaving) {
1635 d->autoSaveTimer->stop();
1636 d->autoSaveFailureCount = 0;
1641 Q_EMIT
statusBarMessage(i18n(
"Finished autosaving %1", fileName), successMessageTimeout);
1646 const QString &location,
1647 const QString &realLocation,
1648 const QByteArray &mimeType,
1652 d->savingImage =
d->image;
1658 d->importExportManager->setUpdater(
d->savingUpdater);
1663 d->childSavingFuture =
1664 d->importExportManager->exportDocumentAsync(location,
1667 initializationStatus,
1669 exportConfiguration,
1670 isAdvancedExporting);
1672 if (!initializationStatus.
isOk()) {
1673 if (
d->savingUpdater) {
1674 d->savingUpdater->cancel();
1676 d->savingImage.clear();
1681 typedef QFutureWatcher<KisImportExportErrorCode> StatusWatcher;
1682 StatusWatcher *watcher =
new StatusWatcher();
1683 watcher->setFuture(
d->childSavingFuture);
1686 connect(watcher, SIGNAL(finished()), watcher, SLOT(deleteLater()));
1702 if (!
d->lastErrorMessage.isEmpty()) {
1710 d->savingImage.clear();
1712 d->lastErrorMessage.clear();
1713 d->lastWarningMessage.clear();
1715 if (
d->savingUpdater) {
1716 d->savingUpdater->setProgress(100);
1724 const bool changed =
readwrite !=
d->readwrite;
1746 d->autoSaveTimer->start(delay * 1000);
1748 d->autoSaveTimer->stop();
1755 d->autoSaveFailureCount = 0;
1760 const int emergencyAutoSaveInterval = 10;
1762 d->autoSaveFailureCount++;
1772 return d->autoSaveActive;
1788 if (
d->savingImage)
image =
d->savingImage;
1792 QSize originalSize =
bounds.size();
1794 QSize newSize = originalSize.scaled(size, Qt::KeepAspectRatio).expandedTo({1, 1});
1796 bool pixelArt =
false;
1798 if (originalSize.width() < size.width() && originalSize.height() < size.height()) {
1801 if (newSize.height()%originalSize.height() == 0 && newSize.width()%originalSize.width() == 0) {
1811 QImage scaled = original.scaled(newSize, Qt::KeepAspectRatio, Qt::FastTransformation);
1812 px = QPixmap::fromImage(scaled);
1816 if (px.size() == QSize(0,0)) {
1817 px = QPixmap(newSize);
1820 gc.fillRect(px.rect(), checkBrush);
1825 return QPixmap(size);
1833 const QString extension (
".kra");
1834 QString prefix =
KisConfig(
true).
readEntry<
bool>(
"autosavefileshidden") ? QString(
".") : QString();
1835 QRegularExpression autosavePattern1(
"^\\..+-autosave.kra$");
1836 QRegularExpression autosavePattern2(
"^.+-autosave.kra$");
1839 QString dir = fi.absolutePath();
1843 if (path.startsWith(
"content://")) {
1849 QString filename = fi.fileName();
1851 if (path.isEmpty() || autosavePattern1.match(filename).hasMatch() || autosavePattern2.match(filename).hasMatch() || !fi.isWritable()) {
1853 retval = QString(
"%1%2%3%4-%5-%6-autosave%7")
1858 .arg(qApp->applicationPid())
1864 retval = QString(
"%1%2%3%4-autosave%5").arg(dir).arg(
'/').arg(prefix).arg(filename).arg(extension);
1875 dbgUI <<
"path=" << _path;
1883 dbgUI <<
"success, resetting url";
1893 dbgUI <<
"path=" << _path;
1894 d->lastErrorMessage.clear();
1897 if (_path.isEmpty()) {
1898 d->lastErrorMessage = i18n(
"Malformed Path\n%1", _path);
1902 QString path = _path;
1903 QString original =
"";
1904 bool autosaveOpened =
false;
1906 QString file =
path;
1908 if (QFile::exists(asf)) {
1915 int res = dlg.result();
1921 autosaveOpened =
true;
1950 QFileInfo fi(_path);
1964 QMessageBox::critical(qApp->activeWindow(), i18nc(
"@title:window",
"Krita"), i18n(
"File %1 does not exist.",
localFilePath()));
1971 if (typeName.isEmpty()) {
1976 if (typeName ==
"application/x-trash") {
1977 QString path = filename;
1978 while (path.length() > 0) {
1982 if (!typeName.isEmpty()) {
1994 d->importExportManager->setUpdater(updater);
1999 if (!status.
isOk()) {
2019 i18n(
"There were problems opening %1.",
prettyPath()),
2027 d->syncDecorationsWrapperLayerState();
2037 if (!
d->modified || !
d->modifiedAfterAutosave)
2046 d->modifiedAfterAutosave =
false;
2051 qWarning() <<
"Could not auto-save when paused";
2059 d->outputMimeType =
d->mimeType;
2078 if (
d->isAutosaving ||
d->documentIsClosing)
2084 if (mod && !
d->autoSaveTimer->isActive()) {
2088 d->modifiedAfterAutosave = mod;
2089 d->modifiedWhileSaving = mod;
2092 d->imageModifiedWithoutUndo = mod;
2109 const bool changed =
value !=
d->isRecovered;
2120 return d->isRecovered;
2125 QDateTime now = QDateTime::currentDateTime();
2126 int firstModDelta =
d->firstMod.secsTo(now);
2127 int lastModDelta =
d->lastMod.secsTo(now);
2129 if (lastModDelta > 30) {
2130 d->docInfo->setAboutInfo(
"editing-time", QString::number(
d->docInfo->aboutInfo(
"editing-time").toInt() +
d->firstMod.secsTo(
d->lastMod)));
2132 }
else if (firstModDelta > 60 || forceStoreElapsed) {
2133 d->docInfo->setAboutInfo(
"editing-time", QString::number(
d->docInfo->aboutInfo(
"editing-time").toInt() + firstModDelta));
2142 QString _url(
path());
2144 _url = QDir::toNativeSeparators(_url);
2153 const QString _url(QFileInfo(
path()).fileName());
2156 if (_url.isEmpty()) {
2157 c =
" [" + i18n(
"Not Saved") +
"] ";
2173 QDomImplementation impl;
2174 QString url = QString(
"http://www.calligra.org/DTD/%1-%2.dtd").arg(appName).arg(version);
2175 QDomDocumentType dtype = impl.createDocumentType(tagName,
2176 QString(
"-//KDE//DTD %1 %2//EN").arg(appName).arg(version),
2179 QString namespaceURN = QString(
"http://www.calligra.org/DTD/%1").arg(appName);
2180 QDomDocument doc = impl.createDocument(namespaceURN, tagName, dtype);
2181 doc.insertBefore(doc.createProcessingInstruction(
"xml",
"version=\"1.0\" encoding=\"UTF-8\""), doc.documentElement());
2194 d->lastErrorMessage = errMsg;
2199 return d->lastErrorMessage;
2204 d->lastWarningMessage = warningMsg;
2209 return d->lastWarningMessage;
2217 if (QFile::exists(asf)) {
2223 if (QFile::exists(asf)) {
2230 expressions << QRegularExpression(
"^\\..+-autosave.kra$")
2231 << QRegularExpression(
"^.+-autosave.kra$");
2233 Q_FOREACH(
const QRegularExpression &rex, expressions) {
2235 !autosaveBaseName.isEmpty() &&
2236 rex.match(QFileInfo(autosaveBaseName).fileName()).hasMatch() &&
2237 QFile::exists(autosaveBaseName)) {
2240 QFile::remove(autosaveBaseName);
2252 if (
d->unit !=
unit) {
2260 return d->undoStack;
2265 return d->importExportManager;
2278 if (!
d->undoStack->isClean()) {
2279 d->undoStack->clear();
2295 d->syncDecorationsWrapperLayerState();
2300 d->undoStack->clear();
2305 return d->gridConfig;
2310 if (
d->gridConfig != config) {
2311 d->gridConfig = config;
2312 d->syncDecorationsWrapperLayerState();
2324 if (!
d->linkedResourceStorage) {
2330 while (iter->hasNext()) {
2334 buf.open(QBuffer::WriteOnly);
2335 bool exportSuccessful =
2336 d->linkedResourceStorage->exportResource(iter->url(), &buf);
2338 KoResourceSP resource =
d->linkedResourceStorage->resource(iter->url());
2339 exportSuccessful &= bool(resource);
2341 const QString name = resource ? resource->name() : QString();
2342 const QString fileName = QFileInfo(iter->url()).fileName();
2347 if (exportSuccessful) {
2350 result << signature;
2361 if (
d->linkedResourceStorage) {
2363 while (iter->hasNext()) {
2366 if (resource && resource->valid()) {
2367 oldPaletteList << resource.dynamicCast<
KoColorSet>();
2370 if (oldPaletteList != paletteList) {
2373 if (!paletteList.contains(
palette)) {
2378 if (!oldPaletteList.contains(
palette)) {
2382 palette->setStorageLocation(
d->linkedResourcesStorageID);
2395 return d->m_storyboardItemList;
2400 d->m_storyboardItemList = storyboardItemList;
2408 return d->m_storyboardCommentList;
2413 d->m_storyboardCommentList = storyboardCommentList;
2420 return d->audioTracks;
2431 d->audioLevel = level;
2437 return d->audioLevel;
2442 return d->guidesConfig;
2447 if (
d->guidesConfig == data)
return;
2449 d->guidesConfig = data;
2450 d->syncDecorationsWrapperLayerState();
2457 return d->mirrorAxisConfig;
2462 if (
d->mirrorAxisConfig == config) {
2466 d->mirrorAxisConfig = config;
2469 d->image->bounds()));
2488 return d->readwrite;
2501 if (view && view->
document() ==
this) {
2510 d->mimeType = QByteArray();
2522 const bool changed = path !=
d->m_path;
2544 if ( path.isEmpty() ) {
2548 if (
d->m_bAutoDetectedMime) {
2549 d->mimeType = QByteArray();
2550 d->m_bAutoDetectedMime =
false;
2564 d->m_file =
d->m_path;
2568 if (
d->mimeType.isEmpty()) {
2572 d->mimeType = mime.toLocal8Bit();
2573 d->m_bAutoDetectedMime =
true;
2589 qint32 width, qint32 height,
2593 const QString &description,
const double imageResolution)
2599 if (!cs)
return false;
2601 KisCursorOverrideLock cursorLock(Qt::BusyCursor);
2632 KoColor strippedAlpha = bgColor;
2641 filter_config->setProperty(
"color", strippedAlpha.
toQColor());
2642 filter_config->createLocalResourcesSnapshot();
2648 if (numberOfLayers > 1) {
2658 Q_CHECK_PTR(bgLayer);
2660 bgLayer->
setDirty(QRect(0, 0, width, height));
2663 d->mirrorAxisConfig.setAxisPosition(QRectF(
image->
bounds()).center());
2666 for(
int i = 1; i < numberOfLayers; ++i) {
2670 layer->
setDirty(QRect(0, 0, width, height));
2684 QString(
"Created image \"%1\", %2 * %3 pixels, %4 dpi. Color model: %6 %5 (%7). Layers: %8")
2685 .arg(name, QString::number(width), QString::number(height),
2688 QString::number(numberOfLayers)));
2695 const bool result =
d->savingMutex.tryLock();
2697 d->savingMutex.unlock();
2705 KisAsyncActionFeedback f(i18nc(
"progress dialog message when the user closes the document that is being saved",
"Waiting for saving to complete..."), 0);
2706 f.waitForMutex(
d->savingMutex);
2712 return d->shapeController;
2717 return d->shapeController->shapeForNode(layer);
2722 return d->assistants;
2727 if (
d->assistants !=
value) {
2729 d->syncDecorationsWrapperLayerState();
2739 KisLayerUtils::findNodeByType<KisReferenceImagesLayer>(
d->image->root());
2741 return referencesLayer;
2750 if (currentReferenceLayer == layer && updateImage) {
2754 d->referenceLayerConnections.clear();
2757 if (currentReferenceLayer) {
2758 d->image->removeNode(currentReferenceLayer);
2762 d->image->addNode(layer);
2766 currentReferenceLayer = layer;
2768 if (currentReferenceLayer) {
2769 d->referenceLayerConnections.addConnection(
2770 currentReferenceLayer, SIGNAL(sigUpdateCanvas(QRectF)),
2780 d->preActivatedNode = activatedNode;
2785 return d->preActivatedNode;
2795 return d->savingImage;
2804 d->image->disconnect(
this);
2805 d->shapeController->setImage(0);
2811 if (
d->linkedResourceStorage){
2815 d->setImageAndInitIdleWatcher(
image);
2824 if (forceInitialUpdate) {
2825 d->image->initialRefreshGraph();
2836 d->shapeController->setImage(
image);
2842 setModified(
d->imageModifiedWithoutUndo || !
d->undoStack->isClean());
2847 d->imageModifiedWithoutUndo =
true;
2859 return d->isAutosaving;
2869 d->globalAssistantsColor = color;
2874 return d->globalAssistantsColor;
2879 return d->colorHistory;
2884 QRectF
bounds =
d->image->bounds();
2888 if (referenceImagesLayer) {
2897 d->colorHistory = colors;
float value(const T *src, size_t ch)
KisSharedPtr< KisReferenceImagesLayer > KisReferenceImagesLayerSP
const quint8 OPACITY_OPAQUE_U8
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
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()
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)
bool startExportInBackground(const QString &actionName, const QString &location, const QString &realLocation, const QByteArray &mimeType, bool showWarnings, KisPropertiesConfigurationSP exportConfiguration, bool isAdvancedExporting=false)
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)