diff --git a/libs/image/kis_annotation.h b/libs/image/kis_annotation.h --- a/libs/image/kis_annotation.h +++ b/libs/image/kis_annotation.h @@ -67,6 +67,10 @@ virtual ~KisAnnotation() {} + virtual KisAnnotation* clone() const { + return new KisAnnotation(*this); + } + /** * gets a non-localized string identifying the type of the * annotation. @@ -103,6 +107,15 @@ } protected: + KisAnnotation(const KisAnnotation &rhs) + : KisShared(), + m_type(rhs.m_type), + m_description(rhs.m_description), + m_annotation(rhs.m_annotation) + { + } + +protected: QString m_type; QString m_description; diff --git a/libs/image/kis_image.h b/libs/image/kis_image.h --- a/libs/image/kis_image.h +++ b/libs/image/kis_image.h @@ -102,6 +102,18 @@ public: /** + * Makes a copy of the image with all the layers. If possible, shallow + * copies of the layers are made. + * + * \p exactCopy shows if the copied image should look *exactly* the same as + * the other one (according to it's .kra xml representation). It means that + * the layers will have the same UUID keys and, therefore, you are not + * expected to use the copied image anywhere except for saving. Don't use + * this option if you plan to work with the copied image later. + */ + KisImage* clone(bool exactCopy = false); + + /** * Render the projection onto a QImage. */ QImage convertToQImage(qint32 x1, @@ -912,7 +924,7 @@ private: - KisImage(const KisImage& rhs); + KisImage(const KisImage& rhs, KisUndoStore *undoStore, bool exactCopy); KisImage& operator=(const KisImage& rhs); void emitSizeChanged(); diff --git a/libs/image/kis_image.cc b/libs/image/kis_image.cc --- a/libs/image/kis_image.cc +++ b/libs/image/kis_image.cc @@ -137,10 +137,43 @@ , postExecutionUndoAdapter(u, _q) , recorder(_q) , signalRouter(_q) - , animationInterface(0) + , animationInterface(new KisImageAnimationInterface(q)) , scheduler(_q) , axesCenter(QPointF(0.5, 0.5)) - {} + { + { + KisImageConfig cfg; + if (cfg.enableProgressReporting()) { + scheduler.setProgressProxy(&compositeProgressProxy); + } + + // Each of these lambdas defines a new factory function. + scheduler.setLod0ToNStrokeStrategyFactory( + [=](bool forgettable) { + return KisLodSyncPair( + new KisSyncLodCacheStrokeStrategy(KisImageWSP(q), forgettable), + KisSyncLodCacheStrokeStrategy::createJobsData(KisImageWSP(q))); + }); + + scheduler.setSuspendUpdatesStrokeStrategyFactory( + [=]() { + return KisSuspendResumePair( + new KisSuspendProjectionUpdatesStrokeStrategy(KisImageWSP(q), true), + KisSuspendProjectionUpdatesStrokeStrategy::createSuspendJobsData(KisImageWSP(q))); + }); + + scheduler.setResumeUpdatesStrokeStrategyFactory( + [=]() { + return KisSuspendResumePair( + new KisSuspendProjectionUpdatesStrokeStrategy(KisImageWSP(q), false), + KisSuspendProjectionUpdatesStrokeStrategy::createResumeJobsData(KisImageWSP(q))); + }); + } + + connect(q, SIGNAL(sigImageModified()), KisMemoryStatisticsServer::instance(), SLOT(notifyImageChanged())); + } + + KisImage *q; @@ -158,7 +191,6 @@ KisSelectionSP deselectedGlobalSelection; KisGroupLayerSP rootLayer; // The layers are contained in here - QList dirtyLayers; // for thumbnails QList compositions; KisNodeSP isolatedRootNode; bool wrapAroundModePermitted = false; @@ -210,41 +242,7 @@ } m_d = new KisImagePrivate(this, width, height, c, undoStore); - - { - KisImageConfig cfg; - if (cfg.enableProgressReporting()) { - m_d->scheduler.setProgressProxy(&m_d->compositeProgressProxy); - } - - // Each of these lambdas defines a new factory function. - m_d->scheduler.setLod0ToNStrokeStrategyFactory( - [=](bool forgettable) { - return KisLodSyncPair( - new KisSyncLodCacheStrokeStrategy(KisImageWSP(this), forgettable), - KisSyncLodCacheStrokeStrategy::createJobsData(KisImageWSP(this))); - }); - - m_d->scheduler.setSuspendUpdatesStrokeStrategyFactory( - [=]() { - return KisSuspendResumePair( - new KisSuspendProjectionUpdatesStrokeStrategy(KisImageWSP(this), true), - KisSuspendProjectionUpdatesStrokeStrategy::createSuspendJobsData(KisImageWSP(this))); - }); - - m_d->scheduler.setResumeUpdatesStrokeStrategyFactory( - [=]() { - return KisSuspendResumePair( - new KisSuspendProjectionUpdatesStrokeStrategy(KisImageWSP(this), false), - KisSuspendProjectionUpdatesStrokeStrategy::createResumeJobsData(KisImageWSP(this))); - }); - } - setRootLayer(new KisGroupLayer(this, "root", OPACITY_OPAQUE_U8)); - - m_d->animationInterface = new KisImageAnimationInterface(this); - - connect(this, SIGNAL(sigImageModified()), KisMemoryStatisticsServer::instance(), SLOT(notifyImageChanged())); } KisImage::~KisImage() @@ -272,6 +270,63 @@ disconnect(); // in case Qt gets confused } +KisImage *KisImage::clone(bool exactCopy) +{ + return new KisImage(*this, 0, exactCopy); +} + +KisImage::KisImage(const KisImage& rhs, KisUndoStore *undoStore, bool exactCopy) + : KisNodeFacade(), + KisNodeGraphListener(), + KisShared(), + m_d(new KisImagePrivate(this, + rhs.width(), rhs.height(), + rhs.colorSpace(), + undoStore ? undoStore : new KisDumbUndoStore())) +{ + setObjectName(rhs.objectName()); + + m_d->xres = rhs.m_d->xres; + m_d->yres = rhs.m_d->yres; + + + if (rhs.m_d->proofingConfig) { + m_d->proofingConfig = toQShared(new KisProofingConfiguration(*rhs.m_d->proofingConfig)); + } + + KisNodeSP newRoot = rhs.root()->clone(); + newRoot->setGraphListener(this); + newRoot->setImage(this); + m_d->rootLayer = dynamic_cast(newRoot.data()); + setRoot(newRoot); + + if (exactCopy) { + QQueue linearizedNodes; + KisLayerUtils::recursiveApplyNodes(rhs.root(), + [&linearizedNodes](KisNodeSP node) { + linearizedNodes.enqueue(node); + }); + KisLayerUtils::recursiveApplyNodes(newRoot, + [&linearizedNodes](KisNodeSP node) { + KisNodeSP refNode = linearizedNodes.dequeue(); + node->setUuid(refNode->uuid()); + }); + } + + Q_FOREACH (KisLayerCompositionSP comp, rhs.m_d->compositions) { + m_d->compositions << toQShared(new KisLayerComposition(*comp, this)); + } + + rhs.m_d->nserver = KisNameServer(rhs.m_d->nserver); + + vKisAnnotationSP newAnnotations; + Q_FOREACH (KisAnnotationSP annotation, rhs.m_d->annotations) { + newAnnotations << annotation->clone(); + } + m_d->annotations = newAnnotations; + m_d->blockLevelOfDetail = rhs.m_d->blockLevelOfDetail; +} + void KisImage::aboutToAddANode(KisNode *parent, int index) { KisNodeGraphListener::aboutToAddANode(parent, index); @@ -1484,12 +1539,16 @@ void KisImage::invalidateFrames(const KisTimeRange &range, const QRect &rect) { - m_d->animationInterface->invalidateFrames(range, rect); + if (m_d->animationInterface) { + m_d->animationInterface->invalidateFrames(range, rect); + } } void KisImage::requestTimeSwitch(int time) { - m_d->animationInterface->requestTimeSwitchNonGUI(time); + if (m_d->animationInterface) { + m_d->animationInterface->requestTimeSwitchNonGUI(time); + } } QList KisImage::compositions() diff --git a/libs/image/kis_layer_composition.h b/libs/image/kis_layer_composition.h --- a/libs/image/kis_layer_composition.h +++ b/libs/image/kis_layer_composition.h @@ -38,6 +38,8 @@ KisLayerComposition(KisImageWSP image, const QString& name); ~KisLayerComposition(); + KisLayerComposition(const KisLayerComposition &rhs, KisImageWSP otherImage = 0); + /** * Sets name of the composition */ diff --git a/libs/image/kis_layer_composition.cpp b/libs/image/kis_layer_composition.cpp --- a/libs/image/kis_layer_composition.cpp +++ b/libs/image/kis_layer_composition.cpp @@ -29,6 +29,8 @@ #include "kis_transparency_mask.h" #include "kis_selection_mask.h" #include "lazybrush/kis_colorize_mask.h" +#include "kis_layer_utils.h" +#include "kis_node_query_path.h" #include @@ -98,6 +100,42 @@ } +KisLayerComposition::KisLayerComposition(const KisLayerComposition &rhs, KisImageWSP otherImage) + : m_image(otherImage ? otherImage : rhs.m_image), + m_name(rhs.m_name), + m_exportEnabled(rhs.m_exportEnabled) +{ + { + auto it = rhs.m_visibilityMap.constBegin(); + for (; it != rhs.m_visibilityMap.constEnd(); ++it) { + QUuid nodeUuid = it.key(); + KisNodeSP node = KisLayerUtils::findNodeByUuid(rhs.m_image->root(), nodeUuid); + if (node) { + KisNodeQueryPath path = KisNodeQueryPath::absolutePath(node); + KisNodeSP newNode = path.queryUniqueNode(m_image); + KIS_ASSERT_RECOVER(newNode) { continue; } + + m_visibilityMap.insert(newNode->uuid(), it.value()); + } + } + } + + { + auto it = rhs.m_collapsedMap.constBegin(); + for (; it != rhs.m_collapsedMap.constEnd(); ++it) { + QUuid nodeUuid = it.key(); + KisNodeSP node = KisLayerUtils::findNodeByUuid(rhs.m_image->root(), nodeUuid); + if (node) { + KisNodeQueryPath path = KisNodeQueryPath::absolutePath(node); + KisNodeSP newNode = path.queryUniqueNode(m_image); + KIS_ASSERT_RECOVER(newNode) { continue; } + + m_collapsedMap.insert(newNode->uuid(), it.value()); + } + } + } +} + void KisLayerComposition::setName(const QString& name) { m_name = name; diff --git a/libs/image/kis_layer_utils.h b/libs/image/kis_layer_utils.h --- a/libs/image/kis_layer_utils.h +++ b/libs/image/kis_layer_utils.h @@ -28,6 +28,7 @@ class KoProperties; class KoColor; +class QUuid; namespace KisMetaData { @@ -193,6 +194,11 @@ * node is returned to the caller. */ KisNodeSP KRITAIMAGE_EXPORT recursiveFindNode(KisNodeSP node, std::function func); + + /** + * Recursively searches for a node with specified Uuid + */ + KisNodeSP KRITAIMAGE_EXPORT findNodeByUuid(KisNodeSP root, const QUuid &uuid); }; #endif /* __KIS_LAYER_UTILS_H */ diff --git a/libs/image/kis_layer_utils.cpp b/libs/image/kis_layer_utils.cpp --- a/libs/image/kis_layer_utils.cpp +++ b/libs/image/kis_layer_utils.cpp @@ -20,6 +20,7 @@ #include +#include #include #include "kis_painter.h" @@ -1263,4 +1264,13 @@ return 0; } + + KisNodeSP findNodeByUuid(KisNodeSP root, const QUuid &uuid) + { + return recursiveFindNode(root, + [uuid] (KisNodeSP node) { + return node->uuid() == uuid; + }); + } + } diff --git a/libs/image/kis_name_server.h b/libs/image/kis_name_server.h --- a/libs/image/kis_name_server.h +++ b/libs/image/kis_name_server.h @@ -33,7 +33,6 @@ private: qint32 m_generator; - QString m_prefix; }; #endif // KIS_NAMESERVER_H_ diff --git a/libs/image/kis_node_facade.h b/libs/image/kis_node_facade.h --- a/libs/image/kis_node_facade.h +++ b/libs/image/kis_node_facade.h @@ -18,6 +18,8 @@ #ifndef _KIS_NODE_FACADE_H #define _KIS_NODE_FACADE_H +#include + #include "kis_types.h" #include "kis_node.h" #include "kritaimage_export.h" @@ -135,6 +137,6 @@ private: struct Private; - Private * const m_d; + QScopedPointer m_d; }; #endif diff --git a/libs/image/kis_node_facade.cpp b/libs/image/kis_node_facade.cpp --- a/libs/image/kis_node_facade.cpp +++ b/libs/image/kis_node_facade.cpp @@ -39,7 +39,6 @@ KisNodeFacade::~KisNodeFacade() { - delete m_d; } void KisNodeFacade::setRoot(KisNodeSP root) diff --git a/libs/image/kis_node_graph_listener.h b/libs/image/kis_node_graph_listener.h --- a/libs/image/kis_node_graph_listener.h +++ b/libs/image/kis_node_graph_listener.h @@ -19,6 +19,9 @@ #define KIS_NODE_GRAPH_LISTENER_H_ #include "kritaimage_export.h" + +#include + class KisTimeRange; class KisNode; class QRect; @@ -114,7 +117,7 @@ private: struct Private; - Private * const m_d; + QScopedPointer m_d; }; #endif diff --git a/libs/image/kis_node_graph_listener.cpp b/libs/image/kis_node_graph_listener.cpp --- a/libs/image/kis_node_graph_listener.cpp +++ b/libs/image/kis_node_graph_listener.cpp @@ -37,7 +37,6 @@ KisNodeGraphListener::~KisNodeGraphListener() { - delete m_d; } void KisNodeGraphListener::aboutToAddANode(KisNode */*parent*/, int /*index*/) diff --git a/libs/image/recorder/kis_node_query_path.h b/libs/image/recorder/kis_node_query_path.h --- a/libs/image/recorder/kis_node_query_path.h +++ b/libs/image/recorder/kis_node_query_path.h @@ -33,6 +33,7 @@ KisNodeQueryPath(const KisNodeQueryPath&); KisNodeQueryPath& operator=(const KisNodeQueryPath&); QList queryNodes(KisImageWSP image, KisNodeSP currentNode) const; + KisNodeSP queryUniqueNode(KisImageWSP image, KisNodeSP currentNode = 0) const; bool isRelative() const; // Use "///" style because of the needed "/*" /// This function return a string representing this path. Which is a list separated by '\' of: diff --git a/libs/image/recorder/kis_node_query_path.cc b/libs/image/recorder/kis_node_query_path.cc --- a/libs/image/recorder/kis_node_query_path.cc +++ b/libs/image/recorder/kis_node_query_path.cc @@ -142,6 +142,14 @@ return result; } +KisNodeSP KisNodeQueryPath::queryUniqueNode(KisImageWSP image, KisNodeSP currentNode) const +{ + QList result = queryNodes(image, currentNode); + KIS_ASSERT_RECOVER_NOOP(result.size() <= 1); + + return !result.isEmpty() ? result.first() : 0; +} + QString KisNodeQueryPath::toString() const { QString str; diff --git a/libs/image/tests/kis_image_test.h b/libs/image/tests/kis_image_test.h --- a/libs/image/tests/kis_image_test.h +++ b/libs/image/tests/kis_image_test.h @@ -33,6 +33,7 @@ void testBlockLevelOfDetail(); void testConvertImageColorSpace(); void testGlobalSelection(); + void testCloneImage(); void testLayerComposition(); void testFlattenLayer(); diff --git a/libs/image/tests/kis_image_test.cpp b/libs/image/tests/kis_image_test.cpp --- a/libs/image/tests/kis_image_test.cpp +++ b/libs/image/tests/kis_image_test.cpp @@ -38,6 +38,8 @@ #include "kis_keyframe_channel.h" #include "kis_selection_mask.h" #include "kis_layer_utils.h" +#include "kis_annotation.h" +#include "KisProofingConfiguration.h" #include "kis_undo_stores.h" @@ -239,15 +241,84 @@ QCOMPARE(image->root()->childCount(), 1U); } +void KisImageTest::testCloneImage() +{ + KisImageSP image = new KisImage(0, IMAGE_WIDTH, IMAGE_WIDTH, 0, "layer tests"); + QVERIFY(image->rootLayer() != 0); + QVERIFY(image->rootLayer()->firstChild() == 0); + + KisAnnotationSP annotation = new KisAnnotation("mytype", "mydescription", QByteArray()); + image->addAnnotation(annotation); + QVERIFY(image->annotation("mytype")); + + KisProofingConfigurationSP proofing = toQShared(new KisProofingConfiguration()); + image->setProofingConfiguration(proofing); + QVERIFY(image->proofingConfiguration()); + + const KoColor defaultColor(Qt::green, image->colorSpace()); + image->setDefaultProjectionColor(defaultColor); + QCOMPARE(image->defaultProjectionColor(), defaultColor); + + KisLayerSP layer = new KisPaintLayer(image, "layer1", OPACITY_OPAQUE_U8); + image->addNode(layer); + KisLayerSP layer2 = new KisPaintLayer(image, "layer2", OPACITY_OPAQUE_U8); + image->addNode(layer2); + + QVERIFY(layer->visible()); + QVERIFY(layer2->visible()); + + QVERIFY(TestUtil::findNode(image->root(), "layer1")); + QVERIFY(TestUtil::findNode(image->root(), "layer2")); + + QUuid uuid1 = layer->uuid(); + QUuid uuid2 = layer2->uuid(); + + { + KisImageSP newImage = image->clone(); + + KisNodeSP newLayer1 = TestUtil::findNode(newImage->root(), "layer1"); + KisNodeSP newLayer2 = TestUtil::findNode(newImage->root(), "layer2"); + + QVERIFY(newLayer1); + QVERIFY(newLayer2); + + QVERIFY(newLayer1->uuid() != uuid1); + QVERIFY(newLayer2->uuid() != uuid2); + + KisAnnotationSP newAnnotation = newImage->annotation("mytype"); + QVERIFY(newAnnotation); + QVERIFY(newAnnotation != annotation); + + KisProofingConfigurationSP newProofing = newImage->proofingConfiguration(); + QVERIFY(newProofing); + QVERIFY(newProofing != proofing); + + QCOMPARE(newImage->defaultProjectionColor(), defaultColor); + } + + { + KisImageSP newImage = image->clone(true); + + KisNodeSP newLayer1 = TestUtil::findNode(newImage->root(), "layer1"); + KisNodeSP newLayer2 = TestUtil::findNode(newImage->root(), "layer2"); + + QVERIFY(newLayer1); + QVERIFY(newLayer2); + + QVERIFY(newLayer1->uuid() == uuid1); + QVERIFY(newLayer2->uuid() == uuid2); + } +} + void KisImageTest::testLayerComposition() { KisImageSP image = new KisImage(0, IMAGE_WIDTH, IMAGE_WIDTH, 0, "layer tests"); QVERIFY(image->rootLayer() != 0); QVERIFY(image->rootLayer()->firstChild() == 0); - KisLayerSP layer = new KisPaintLayer(image, "layer 1", OPACITY_OPAQUE_U8); + KisLayerSP layer = new KisPaintLayer(image, "layer1", OPACITY_OPAQUE_U8); image->addNode(layer); - KisLayerSP layer2 = new KisPaintLayer(image, "layer 2", OPACITY_OPAQUE_U8); + KisLayerSP layer2 = new KisPaintLayer(image, "layer2", OPACITY_OPAQUE_U8); image->addNode(layer2); QVERIFY(layer->visible()); @@ -264,6 +335,10 @@ KisLayerComposition comp2(image, "comp 2"); comp2.store(); + KisLayerCompositionSP comp3 = toQShared(new KisLayerComposition(image, "comp 3")); + comp3->store(); + image->addComposition(comp3); + comp.apply(); QVERIFY(layer->visible()); @@ -273,6 +348,42 @@ QVERIFY(layer->visible()); QVERIFY(!layer2->visible()); + + comp.apply(); + + QVERIFY(layer->visible()); + QVERIFY(layer2->visible()); + + KisImageSP newImage = image->clone(); + + KisNodeSP newLayer1 = TestUtil::findNode(newImage->root(), "layer1"); + KisNodeSP newLayer2 = TestUtil::findNode(newImage->root(), "layer2"); + + QVERIFY(newLayer1); + QVERIFY(newLayer2); + + QVERIFY(newLayer1->visible()); + QVERIFY(newLayer2->visible()); + + KisLayerComposition newComp1(comp, newImage); + newComp1.apply(); + QVERIFY(newLayer1->visible()); + QVERIFY(newLayer2->visible()); + + KisLayerComposition newComp2(comp2, newImage); + newComp2.apply(); + QVERIFY(newLayer1->visible()); + QVERIFY(!newLayer2->visible()); + + newComp1.apply(); + QVERIFY(newLayer1->visible()); + QVERIFY(newLayer2->visible()); + + QVERIFY(!newImage->compositions().isEmpty()); + KisLayerCompositionSP newComp3 = newImage->compositions().first(); + newComp3->apply(); + QVERIFY(newLayer1->visible()); + QVERIFY(!newLayer2->visible()); } #include "testutil.h" diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt --- a/libs/ui/CMakeLists.txt +++ b/libs/ui/CMakeLists.txt @@ -59,7 +59,6 @@ dialogs/kis_dlg_layer_style.cpp dialogs/kis_dlg_png_import.cpp dialogs/kis_dlg_import_image_sequence.cpp - dialogs/kis_delayed_save_dialog.cpp dialogs/kis_dlg_internal_color_selector.cpp flake/kis_node_dummies_graph.cpp flake/kis_dummies_facade_base.cpp @@ -459,7 +458,6 @@ forms/wdgstopgradienteditor.ui brushhud/kis_dlg_brush_hud_config.ui forms/wdgdlginternalcolorselector.ui - dialogs/kis_delayed_save_dialog.ui input/config/kis_input_configuration_page.ui input/config/kis_edit_profiles_dialog.ui input/config/kis_input_configuration_page_item.ui diff --git a/libs/ui/KisDocument.h b/libs/ui/KisDocument.h --- a/libs/ui/KisDocument.h +++ b/libs/ui/KisDocument.h @@ -744,9 +744,19 @@ */ KisImageWSP newImage(const QString& name, qint32 width, qint32 height, const KoColorSpace * colorspace); + KisImageWSP image() const; /** + * @brief savingImage provides a detached, shallow copy of the original image that must be used when saving. + * Any strokes in progress will not be applied to this image, so the result might be missing some data. On + * the other hand, it won't block. + * + * @return a shallow copy of the original image, or 0 is saving is not in progress + */ + KisImageSP savingImage() const; + + /** * Makes an otherwise empty document ready for import/export */ void prepareForImport(); diff --git a/libs/ui/KisDocument.cpp b/libs/ui/KisDocument.cpp --- a/libs/ui/KisDocument.cpp +++ b/libs/ui/KisDocument.cpp @@ -360,6 +360,8 @@ qint32 macroNestDepth; KisImageSP image; + KisImageSP savingImage; + KisNodeSP preActivatedNode; KisShapeController* shapeController; KoShapeController* koShapeController; @@ -437,70 +439,6 @@ class SafeSavingLocker; }; -class KisDocument::Private::SafeSavingLocker { -public: - SafeSavingLocker(KisDocument::Private *_d) - : d(_d), - m_locked(false), - m_imageLock(d->image, true), - m_savingLock(&d->savingMutex) - { - const int realAutoSaveInterval = KisConfig().autoSaveInterval(); - const int emergencyAutoSaveInterval = 10; // sec - - /** - * Initial try to lock both objects. Locking the image guards - * us from any image composition threads running in the - * background, while savingMutex guards us from entering the - * saving code twice by autosave and main threads. - * - * Since we are trying to lock multiple objects, so we should - * do it in a safe manner. - */ - m_locked = std::try_lock(m_imageLock, m_savingLock) < 0; - - if (!m_locked) { - if (d->isAutosaving) { - d->disregardAutosaveFailure = true; - if (realAutoSaveInterval) { - d->document->setAutoSave(emergencyAutoSaveInterval); - } - } else { - d->image->requestStrokeEnd(); - QApplication::processEvents(); - - // one more try... - m_locked = std::try_lock(m_imageLock, m_savingLock) < 0; - } - } - - if (m_locked) { - d->disregardAutosaveFailure = false; - } - } - - ~SafeSavingLocker() { - if (m_locked) { - m_imageLock.unlock(); - m_savingLock.unlock(); - - const int realAutoSaveInterval = KisConfig().autoSaveInterval(); - d->document->setAutoSave(realAutoSaveInterval); - } - } - - bool successfullyLocked() const { - return m_locked; - } - -private: - KisDocument::Private *d; - bool m_locked; - - KisImageBarrierLockAdapter m_imageLock; - StdLockableWrapper m_savingLock; -}; - KisDocument::KisDocument() : d(new Private(this)) { @@ -528,7 +466,6 @@ d->firstMod = QDateTime::currentDateTime(); d->lastMod = QDateTime::currentDateTime(); - // preload the krita resources KisResourceServerProvider::instance(); @@ -698,12 +635,10 @@ Q_ASSERT(!tempororaryFileName.isEmpty()); if (!isNativeFormat(outputMimeType)) { - Private::SafeSavingLocker locker(d); - if (locker.successfullyLocked()) { - status = d->importExportManager->exportDocument(tempororaryFileName, outputMimeType, exportConfiguration); - } else { - status = KisImportExportFilter::UsageError; - } + + d->savingImage = d->image->clone(true); + status = d->importExportManager->exportDocument(tempororaryFileName, outputMimeType, exportConfiguration); + d->savingImage.clear(); ret = status == KisImportExportFilter::OK; suppressErrorDialog = (status == KisImportExportFilter::UserCancelled || status == KisImportExportFilter::BadConversionGraph); @@ -882,7 +817,7 @@ void KisDocument::slotAutoSave() { - if (d->modified && d->modifiedAfterAutosave && !d->isLoading) { + if (!d->isAutosaving && d->modified && d->modifiedAfterAutosave && !d->isLoading) { // Give a warning when trying to autosave an encrypted file when no password is known (should not happen) if (d->specialOutputFlag == SaveEncrypted && d->password.isNull()) { // That advice should also fix this error from occurring again @@ -939,9 +874,7 @@ bool KisDocument::saveNativeFormat(const QString & file) { - Private::SafeSavingLocker locker(d); - if (!locker.successfullyLocked()) return false; - + d->savingImage = d->image->clone(true); d->lastErrorMessage.clear(); //dbgUI <<"Saving to store"; @@ -956,9 +889,12 @@ if (f.open(QIODevice::WriteOnly | QIODevice::Text)) { bool success = saveToStream(&f); f.close(); + d->savingImage = 0; return success; - } else + } else { + d->savingImage = 0; return false; + } } dbgUI << "KisDocument::saveNativeFormat nativeFormatMimeType=" << nativeFormatMimeType(); @@ -971,6 +907,7 @@ } if (store->bad()) { d->lastErrorMessage = i18n("Could not create the file for saving"); // more details needed? + d->savingImage = 0; delete store; return false; } @@ -983,6 +920,7 @@ } else { result = saveNativeFormatCalligra(store); } + d->savingImage = 0; return result; } @@ -1784,8 +1722,9 @@ bool KisDocument::completeSaving(KoStore* store) { + Q_ASSERT(!d->savingImage.isNull()); d->kraSaver->saveKeyframes(store, url().url(), isStoredExtern()); - d->kraSaver->saveBinaryData(store, d->image, url().url(), isStoredExtern(), d->isAutosaving); + d->kraSaver->saveBinaryData(store, d->savingImage, url().url(), isStoredExtern(), d->isAutosaving); bool retval = true; if (!d->kraSaver->errorMessages().isEmpty()) { setErrorMessage(d->kraSaver->errorMessages().join(".\n")); @@ -1899,7 +1838,9 @@ if (d->kraSaver) delete d->kraSaver; d->kraSaver = new KisKraSaver(this); - root.appendChild(d->kraSaver->saveXML(doc, d->image)); + Q_ASSERT(!d->savingImage.isNull()); + + root.appendChild(d->kraSaver->saveXML(doc, d->savingImage)); if (!d->kraSaver->errorMessages().isEmpty()) { setErrorMessage(d->kraSaver->errorMessages().join(".\n")); } @@ -2478,6 +2419,11 @@ return d->image; } +KisImageSP KisDocument::savingImage() const +{ + return d->savingImage; +} + void KisDocument::setCurrentImage(KisImageSP image) { diff --git a/libs/ui/KisMainWindow.cpp b/libs/ui/KisMainWindow.cpp --- a/libs/ui/KisMainWindow.cpp +++ b/libs/ui/KisMainWindow.cpp @@ -98,7 +98,6 @@ #include #include #include "dialogs/kis_about_application.h" -#include "dialogs/kis_delayed_save_dialog.h" #include "dialogs/kis_dlg_preferences.h" #include "kis_action.h" #include "kis_action_manager.h" @@ -882,11 +881,8 @@ std::unique_lock> l(wrapper, std::try_to_lock); if (!l.owns_lock()) return false; - KisDelayedSaveDialog dlg(document->image(), this); - dlg.blockIfImageIsBusy(); - - if (dlg.result() != QDialog::Accepted) { - return false; + if (!document->image()->isIdle()) { + QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("Krita is still rendering the last strokes. Those strokes will not be saved.")); } bool reset_url; diff --git a/libs/ui/dialogs/kis_delayed_save_dialog.h b/libs/ui/dialogs/kis_delayed_save_dialog.h deleted file mode 100644 --- a/libs/ui/dialogs/kis_delayed_save_dialog.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2016 Dmitry Kazakov - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef KIS_DELAYED_SAVE_DIALOG_H -#define KIS_DELAYED_SAVE_DIALOG_H - -#include -#include -#include "kis_types.h" - -namespace Ui { -class KisDelayedSaveDialog; -} - -class KisDelayedSaveDialog : public QDialog -{ - Q_OBJECT - -public: - explicit KisDelayedSaveDialog(KisImageSP image, QWidget *parent = 0); - ~KisDelayedSaveDialog(); - - void blockIfImageIsBusy(); - -private Q_SLOTS: - void slotTimerTimeout(); - void slotCancelRequested(); - -private: - Ui::KisDelayedSaveDialog *ui; - -private: - struct Private; - const QScopedPointer m_d; -}; - -#endif // KIS_DELAYED_SAVE_DIALOG_H diff --git a/libs/ui/dialogs/kis_delayed_save_dialog.cpp b/libs/ui/dialogs/kis_delayed_save_dialog.cpp deleted file mode 100644 --- a/libs/ui/dialogs/kis_delayed_save_dialog.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2016 Dmitry Kazakov - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "kis_delayed_save_dialog.h" -#include "ui_kis_delayed_save_dialog.h" - -#include - -#include "kis_debug.h" -#include "kis_image.h" -#include "kis_composite_progress_proxy.h" - - -struct KisDelayedSaveDialog::Private -{ - Private(KisImageSP _image) : image(_image) {} - - KisImageSP image; - QTimer updateTimer; -}; - -KisDelayedSaveDialog::KisDelayedSaveDialog(KisImageSP image, QWidget *parent) - : QDialog(parent), - ui(new Ui::KisDelayedSaveDialog), - m_d(new Private(image)) -{ - KIS_ASSERT_RECOVER_NOOP(image); - - ui->setupUi(this); - - connect(ui->btnCancel, SIGNAL(clicked()), SLOT(slotCancelRequested())); - connect(&m_d->updateTimer, SIGNAL(timeout()), SLOT(slotTimerTimeout())); - - m_d->image->compositeProgressProxy()->addProxy(ui->progressBar); -} - -KisDelayedSaveDialog::~KisDelayedSaveDialog() -{ - m_d->image->compositeProgressProxy()->removeProxy(ui->progressBar); - delete ui; -} - -void KisDelayedSaveDialog::blockIfImageIsBusy() -{ - if (m_d->image->isIdle()) { - setResult(Accepted); - return; - } - - m_d->image->requestStrokeEnd(); - - m_d->updateTimer.start(200); - exec(); - m_d->updateTimer.stop(); -} - -void KisDelayedSaveDialog::slotTimerTimeout() -{ - if (m_d->image->isIdle()) { - accept(); - } -} - -void KisDelayedSaveDialog::slotCancelRequested() -{ - m_d->image->requestStrokeCancellation(); -} diff --git a/libs/ui/dialogs/kis_delayed_save_dialog.ui b/libs/ui/dialogs/kis_delayed_save_dialog.ui deleted file mode 100644 --- a/libs/ui/dialogs/kis_delayed_save_dialog.ui +++ /dev/null @@ -1,74 +0,0 @@ - - - KisDelayedSaveDialog - - - Qt::WindowModal - - - - 0 - 0 - 374 - 157 - - - - Krita - - - true - - - - - - Waiting for image operation to complete... - - - - - - - 0 - - - -1 - - - - - - - Qt::Vertical - - - QSizePolicy::MinimumExpanding - - - - 20 - 40 - - - - - - - - Cancel Operation and Save - - - - - - - - KoProgressBar - QProgressBar -
KoProgressBar.h
-
-
- - -
diff --git a/libs/ui/kra/kis_kra_save_visitor.cpp b/libs/ui/kra/kis_kra_save_visitor.cpp --- a/libs/ui/kra/kis_kra_save_visitor.cpp +++ b/libs/ui/kra/kis_kra_save_visitor.cpp @@ -77,6 +77,7 @@ { } + KisKraSaveVisitor::~KisKraSaveVisitor() { delete m_writer; @@ -406,7 +407,8 @@ if (annotation) { // save layer profile - if (m_store->open(getLocation(layer, DOT_ICC))) { + QString location = getLocation(layer, DOT_ICC); + if (m_store->open(location)) { m_store->write(annotation->annotation()); m_store->close(); } else { diff --git a/plugins/impex/bmp/kis_bmp_export.cpp b/plugins/impex/bmp/kis_bmp_export.cpp --- a/plugins/impex/bmp/kis_bmp_export.cpp +++ b/plugins/impex/bmp/kis_bmp_export.cpp @@ -60,10 +60,8 @@ if (from != "application/x-krita") return KisImportExportFilter::NotImplemented; - QRect rc = input->image()->bounds(); - // the image must be locked at the higher levels - KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); - QImage image = input->image()->projection()->convertToQImage(0, 0, 0, rc.width(), rc.height(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); + QRect rc = input->savingImage()->bounds(); + QImage image = input->savingImage()->projection()->convertToQImage(0, 0, 0, rc.width(), rc.height(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); image.save(filename); return KisImportExportFilter::OK; } diff --git a/plugins/impex/brush/KisAnimatedBrushAnnotation.h b/plugins/impex/brush/KisAnimatedBrushAnnotation.h --- a/plugins/impex/brush/KisAnimatedBrushAnnotation.h +++ b/plugins/impex/brush/KisAnimatedBrushAnnotation.h @@ -28,6 +28,9 @@ { public: KisAnimatedBrushAnnotation(const KisPipeBrushParasite ¶site); + virtual KisAnnotation* clone() const Q_DECL_OVERRIDE { + return new KisAnimatedBrushAnnotation(*this); + } }; #endif // KISANIMATEDBRUSHANNOTATION_H diff --git a/plugins/impex/brush/kis_brush_export.cpp b/plugins/impex/brush/kis_brush_export.cpp --- a/plugins/impex/brush/kis_brush_export.cpp +++ b/plugins/impex/brush/kis_brush_export.cpp @@ -77,25 +77,25 @@ if (from != "application/x-krita") return KisImportExportFilter::NotImplemented; - KisAnnotationSP annotation = input->image()->annotation("ImagePipe Parasite"); - KisPipeBrushParasite parasite; - if (annotation) { - QBuffer buf(const_cast(&annotation->annotation())); - buf.open(QBuffer::ReadOnly); - //parasite.loadFromDevice(&buf); - buf.close(); - } +// KisAnnotationSP annotation = input->savingImage()->annotation("ImagePipe Parasite"); +// KisPipeBrushParasite parasite; +// if (annotation) { +// QBuffer buf(const_cast(&annotation->annotation())); +// buf.open(QBuffer::ReadOnly); +// //parasite.loadFromDevice(&buf); +// buf.close(); +// } KisBrushExportOptions exportOptions; exportOptions.spacing = 1.0; - exportOptions.name = input->image()->objectName(); + exportOptions.name = input->savingImage()->objectName(); exportOptions.mask = true; exportOptions.selectionMode = 0; exportOptions.brushStyle = 0; - if (input->image()->dynamicPropertyNames().contains("brushspacing")) { - exportOptions.spacing = input->image()->property("brushspacing").toFloat(); + if (input->savingImage()->dynamicPropertyNames().contains("brushspacing")) { + exportOptions.spacing = input->savingImage()->property("brushspacing").toFloat(); } KisGbrBrush *brush = 0; @@ -143,17 +143,14 @@ qApp->processEvents(); // For vector layers to be updated } - // the image must be locked at the higher levels - KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); - - QRect rc = input->image()->bounds(); + QRect rc = input->savingImage()->bounds(); brush->setName(exportOptions.name); brush->setSpacing(exportOptions.spacing); brush->setUseColorAsMask(exportOptions.mask); - int w = input->image()->width(); - int h = input->image()->height(); + int w = input->savingImage()->width(); + int h = input->savingImage()->height(); KisImagePipeBrush *pipeBrush = dynamic_cast(brush); if (pipeBrush) { @@ -163,7 +160,7 @@ KoProperties properties; properties.setProperty("visible", true); - QList layers = input->image()->root()->childNodes(QStringList("KisLayer"), properties); + QList layers = input->savingImage()->root()->childNodes(QStringList("KisLayer"), properties); KisNodeSP node; Q_FOREACH (KisNodeSP node, layers) { devices[0].push_back(node->projection().data()); @@ -194,7 +191,7 @@ pipeBrush->setDevices(devices, w, h); } else { - QImage image = input->image()->projection()->convertToQImage(0, 0, 0, rc.width(), rc.height(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); + QImage image = input->savingImage()->projection()->convertToQImage(0, 0, 0, rc.width(), rc.height(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); brush->setImage(image); } diff --git a/plugins/impex/csv/kis_csv_export.cpp b/plugins/impex/csv/kis_csv_export.cpp --- a/plugins/impex/csv/kis_csv_export.cpp +++ b/plugins/impex/csv/kis_csv_export.cpp @@ -79,7 +79,7 @@ if (!input) return KisImportExportFilter::NoDocumentCreated; - if (!checkHomogenity(input->image()->rootLayer())) { + if (!checkHomogenity(input->savingImage()->rootLayer())) { if (!getBatchMode()) { QMessageBox::critical(0, i18nc("@title:window", "CSV Export Error"), diff --git a/plugins/impex/exr/exr_export.cc b/plugins/impex/exr/exr_export.cc --- a/plugins/impex/exr/exr_export.cc +++ b/plugins/impex/exr/exr_export.cc @@ -84,7 +84,7 @@ KisDocument *input = inputDocument(); if (!input) return KisImportExportFilter::NoDocumentCreated; - KisImageWSP image = input->image(); + KisImageWSP image = input->savingImage(); Q_CHECK_PTR(image); KoDialog kdb; @@ -121,17 +121,12 @@ KisImageBuilder_Result res; if (cfg->getBool("flatten")) { - // the image must be locked at the higher levels - KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); - KisPaintDeviceSP pd = new KisPaintDevice(*image->projection()); KisPaintLayerSP l = new KisPaintLayer(image, "projection", OPACITY_OPAQUE_U8, pd); res = kpc.buildFile(filename, l); } else { - // the image must be locked at the higher levels - KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); res = kpc.buildFile(filename, image->rootLayer()); } diff --git a/plugins/impex/heightmap/kis_heightmap_export.cpp b/plugins/impex/heightmap/kis_heightmap_export.cpp --- a/plugins/impex/heightmap/kis_heightmap_export.cpp +++ b/plugins/impex/heightmap/kis_heightmap_export.cpp @@ -82,24 +82,24 @@ if (from != "application/x-krita") return KisImportExportFilter::NotImplemented; - KisDocument *inputDoc = inputDocument(); + KisDocument *input = inputDocument(); QString filename = outputFile(); - if (!inputDoc) + if (!input) return KisImportExportFilter::NoDocumentCreated; if (filename.isEmpty()) return KisImportExportFilter::FileNotFound; - KisImageWSP image = inputDoc->image(); + KisImageWSP image = input->savingImage(); Q_CHECK_PTR(image); - if (inputDoc->image()->width() != inputDoc->image()->height()) { - inputDoc->setErrorMessage(i18n("Cannot export this image to a heightmap: it is not square")); + if (input->savingImage()->width() != input->savingImage()->height()) { + input->setErrorMessage(i18n("Cannot export this image to a heightmap: it is not square")); return KisImportExportFilter::WrongFormat; } - if (inputDoc->image()->colorSpace()->colorModelId() != GrayAColorModelID) { - inputDoc->setErrorMessage(i18n("Cannot export this image to a heightmap: it is not grayscale")); + if (input->savingImage()->colorSpace()->colorModelId() != GrayAColorModelID) { + input->setErrorMessage(i18n("Cannot export this image to a heightmap: it is not grayscale")); return KisImportExportFilter::WrongFormat; } @@ -143,8 +143,6 @@ } - // the image must be locked at the higher levels - KIS_SAFE_ASSERT_RECOVER_NOOP(image->locked()); KisPaintDeviceSP pd = new KisPaintDevice(*image->projection()); QFile f(filename); diff --git a/plugins/impex/jpeg/kis_jpeg_export.cc b/plugins/impex/jpeg/kis_jpeg_export.cc --- a/plugins/impex/jpeg/kis_jpeg_export.cc +++ b/plugins/impex/jpeg/kis_jpeg_export.cc @@ -76,7 +76,7 @@ if (!input) return KisImportExportFilter::NoDocumentCreated; - KisImageWSP image = input->image(); + KisImageWSP image = input->savingImage(); Q_CHECK_PTR(image); KoDialog kdb; @@ -135,8 +135,6 @@ if (filename.isEmpty()) return KisImportExportFilter::FileNotFound; - // the image must be locked at the higher levels - KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); KisPaintDeviceSP pd = new KisPaintDevice(*image->projection()); KisJPEGConverter kpc(input, getBatchMode()); diff --git a/plugins/impex/ora/ora_export.cc b/plugins/impex/ora/ora_export.cc --- a/plugins/impex/ora/ora_export.cc +++ b/plugins/impex/ora/ora_export.cc @@ -90,7 +90,7 @@ if (filename.isEmpty()) return KisImportExportFilter::FileNotFound; - KisImageWSP image = input->image(); + KisImageWSP image = input->savingImage(); Q_CHECK_PTR(image); KisPaintDeviceSP pd = image->projection(); diff --git a/plugins/impex/png/kis_png_export.cc b/plugins/impex/png/kis_png_export.cc --- a/plugins/impex/png/kis_png_export.cc +++ b/plugins/impex/png/kis_png_export.cc @@ -86,12 +86,8 @@ if (from != "application/x-krita") return KisImportExportFilter::NotImplemented; + KisImageWSP image = input->savingImage(); - - KisImageWSP image = input->image(); - - // the image must be locked at the higher levels - KIS_SAFE_ASSERT_RECOVER_NOOP(image->locked()); KisPaintDeviceSP pd; pd = new KisPaintDevice(*image->projection()); KisPaintLayerSP l = new KisPaintLayer(image, "projection", OPACITY_OPAQUE_U8, pd); diff --git a/plugins/impex/ppm/kis_ppm_export.cpp b/plugins/impex/ppm/kis_ppm_export.cpp --- a/plugins/impex/ppm/kis_ppm_export.cpp +++ b/plugins/impex/ppm/kis_ppm_export.cpp @@ -180,10 +180,8 @@ bool bitmap = (to == "image/x-portable-bitmap"); - KisImageWSP image = input->image(); + KisImageWSP image = input->savingImage(); Q_CHECK_PTR(image); - // the image must be locked at the higher levels - KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); KisPaintDeviceSP pd = new KisPaintDevice(*image->projection()); // Test color space diff --git a/plugins/impex/psd/psd_export.cc b/plugins/impex/psd/psd_export.cc --- a/plugins/impex/psd/psd_export.cc +++ b/plugins/impex/psd/psd_export.cc @@ -87,7 +87,7 @@ return KisImportExportFilter::NoDocumentCreated; - if (input->image()->width() > 30000 || input->image()->height() > 30000) { + if (input->savingImage()->width() > 30000 || input->savingImage()->height() > 30000) { if (!getBatchMode()) { QMessageBox::critical(0, i18nc("@title:window", "Photoshop Export Error"), @@ -98,7 +98,7 @@ } - if (!checkHomogenity(input->image()->rootLayer(), input->image()->colorSpace())) { + if (!checkHomogenity(input->savingImage()->rootLayer(), input->savingImage()->colorSpace())) { if (!getBatchMode()) { QMessageBox::critical(0, i18nc("@title:window", "Photoshop Export Error"), diff --git a/plugins/impex/psd/psd_resource_block.h b/plugins/impex/psd/psd_resource_block.h --- a/plugins/impex/psd/psd_resource_block.h +++ b/plugins/impex/psd/psd_resource_block.h @@ -75,6 +75,18 @@ delete resource; } + KisAnnotation* clone() const Q_DECL_OVERRIDE { + // HACK ALERT: we are evil! use notmal copying instead! + + PSDResourceBlock *copied = new PSDResourceBlock(); + + QBuffer buffer; + write(&buffer); + copied->read(&buffer); + + return copied; + } + QString displayText() const { if (resource) { return resource->displayText(); @@ -83,7 +95,7 @@ } bool read(QIODevice* io); - bool write(QIODevice* io); + bool write(QIODevice* io) const; bool valid(); quint16 identifier; @@ -93,7 +105,7 @@ PSDInterpretedResource *resource; - QString error; + mutable QString error; }; diff --git a/plugins/impex/psd/psd_resource_block.cpp b/plugins/impex/psd/psd_resource_block.cpp --- a/plugins/impex/psd/psd_resource_block.cpp +++ b/plugins/impex/psd/psd_resource_block.cpp @@ -258,7 +258,7 @@ return valid(); } -bool PSDResourceBlock::write(QIODevice* io) +bool PSDResourceBlock::write(QIODevice* io) const { dbgFile << "Writing Resource Block" << PSDImageResourceSection::idToString((PSDImageResourceSection::PSDResourceID)identifier) << identifier; diff --git a/plugins/impex/psd/psd_saver.cpp b/plugins/impex/psd/psd_saver.cpp --- a/plugins/impex/psd/psd_saver.cpp +++ b/plugins/impex/psd/psd_saver.cpp @@ -85,7 +85,7 @@ PSDSaver::PSDSaver(KisDocument *doc) - : m_image(doc->image()) + : m_image(doc->savingImage()) , m_doc(doc) , m_stop(false) { diff --git a/plugins/impex/qml/qml_export.cc b/plugins/impex/qml/qml_export.cc --- a/plugins/impex/qml/qml_export.cc +++ b/plugins/impex/qml/qml_export.cc @@ -64,7 +64,7 @@ return KisImportExportFilter::FileNotFound; } - KisImageWSP image = input->image(); + KisImageWSP image = input->savingImage(); Q_CHECK_PTR(image); QMLConverter converter; diff --git a/plugins/impex/spriter/kis_spriter_export.cpp b/plugins/impex/spriter/kis_spriter_export.cpp --- a/plugins/impex/spriter/kis_spriter_export.cpp +++ b/plugins/impex/spriter/kis_spriter_export.cpp @@ -486,13 +486,13 @@ QFileInfo fi(filename); //qDebug() << "filename" << filename << fi.absolutePath() << fi.baseName(); - m_image = input->image(); + m_image = input->savingImage(); if (m_image->rootLayer()->childCount() == 0) { return KisImportExportFilter::UsageError; } - KisGroupLayerSP root = input->image()->rootLayer(); + KisGroupLayerSP root = input->savingImage()->rootLayer(); m_boneLayer = qobject_cast(root->findChildByName("bone").data()); //qDebug() << "Found boneLayer" << m_boneLayer; @@ -500,7 +500,7 @@ m_rootLayer= qobject_cast(root->findChildByName("root").data()); //qDebug() << "Fond rootLayer" << m_rootLayer; - parseFolder(input->image()->rootLayer(), "", fi.absolutePath()); + parseFolder(input->savingImage()->rootLayer(), "", fi.absolutePath()); m_rootBone = 0; diff --git a/plugins/impex/tga/kis_tga_export.cpp b/plugins/impex/tga/kis_tga_export.cpp --- a/plugins/impex/tga/kis_tga_export.cpp +++ b/plugins/impex/tga/kis_tga_export.cpp @@ -62,11 +62,8 @@ if (from != "application/x-krita") return KisImportExportFilter::NotImplemented; - // the image must be locked at the higher levels - KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); - - QRect rc = input->image()->bounds(); - QImage image = input->image()->projection()->convertToQImage(0, 0, 0, rc.width(), rc.height(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); + QRect rc = input->savingImage()->bounds(); + QImage image = input->savingImage()->projection()->convertToQImage(0, 0, 0, rc.width(), rc.height(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); QFile f(filename); f.open(QIODevice::WriteOnly); diff --git a/plugins/impex/tiff/kis_tiff_export.cc b/plugins/impex/tiff/kis_tiff_export.cc --- a/plugins/impex/tiff/kis_tiff_export.cc +++ b/plugins/impex/tiff/kis_tiff_export.cc @@ -81,7 +81,7 @@ cfg = lastSavedConfiguration(from, to); } - const KoColorSpace* cs = input->image()->colorSpace(); + const KoColorSpace* cs = input->savingImage()->colorSpace(); cfg->setProperty("type", (int)cs->channels()[0]->channelValueType()); cfg->setProperty("isCMYK", (cs->colorModelId() == CMYKAColorModelID)); @@ -112,18 +112,15 @@ KisImageSP image; if (options.flatten) { - image = new KisImage(0, input->image()->width(), input->image()->height(), input->image()->colorSpace(), ""); - image->setResolution(input->image()->xRes(), input->image()->yRes()); - KisPaintDeviceSP pd = KisPaintDeviceSP(new KisPaintDevice(*input->image()->projection())); + image = new KisImage(0, input->savingImage()->width(), input->savingImage()->height(), input->savingImage()->colorSpace(), ""); + image->setResolution(input->savingImage()->xRes(), input->savingImage()->yRes()); + KisPaintDeviceSP pd = KisPaintDeviceSP(new KisPaintDevice(*input->savingImage()->projection())); KisPaintLayerSP l = KisPaintLayerSP(new KisPaintLayer(image.data(), "projection", OPACITY_OPAQUE_U8, pd)); image->addNode(KisNodeSP(l.data()), image->rootLayer().data()); } else { - image = input->image(); + image = input->savingImage(); } - // the image must be locked at the higher levels - KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); - KisTIFFConverter ktc(input); KisImageBuilder_Result res; if ((res = ktc.buildFile(filename, image, options)) == KisImageBuilder_RESULT_OK) {