Commit 5b5eb973 authored by Tusooa Zhu's avatar Tusooa Zhu 🔼

Implement replacing the current KisDocument with another snapshot

parent 2f964c32
......@@ -274,6 +274,80 @@ KisImage *KisImage::clone(bool exactCopy)
return new KisImage(*this, 0, exactCopy);
}
void KisImage::copyFromImage(const KisImage &rhs)
{
m_d->width = rhs.width();
m_d->height = rhs.height();
if (m_d->colorSpace != rhs.colorSpace()) {
m_d->colorSpace = rhs.colorSpace();
emit sigColorSpaceChanged(m_d->colorSpace);
}
// from KisImage::KisImage(const KisImage &, KisUndoStore *, bool)
setObjectName(rhs.objectName());
if (m_d->xres != rhs.m_d->xres || m_d->yres != rhs.m_d->yres) {
m_d->xres = rhs.m_d->xres;
m_d->yres = rhs.m_d->yres;
emit sigResolutionChanged(m_d->xres, m_d->yres);
}
m_d->allowMasksOnRootNode = rhs.m_d->allowMasksOnRootNode;
KisNodeSP newRoot = rhs.root()->clone();
newRoot->setGraphListener(this);
newRoot->setImage(this);
m_d->rootLayer = dynamic_cast<KisGroupLayer*>(newRoot.data());
setRoot(newRoot);
if (rhs.m_d->isolatedRootNode) {
QQueue<KisNodeSP> linearizedNodes;
KisLayerUtils::recursiveApplyNodes(rhs.root(),
[&linearizedNodes](KisNodeSP node) {
linearizedNodes.enqueue(node);
});
KisLayerUtils::recursiveApplyNodes(newRoot,
[&linearizedNodes, &rhs, this](KisNodeSP node) {
KisNodeSP refNode = linearizedNodes.dequeue();
if (rhs.m_d->isolatedRootNode == refNode) {
m_d->isolatedRootNode = node;
}
});
}
KisLayerUtils::recursiveApplyNodes(newRoot,
[](KisNodeSP node) {
dbgImage << "Node: " << (void *)node.data();
});
Q_FOREACH (KisLayerCompositionSP comp, rhs.m_d->compositions) {
m_d->compositions << toQShared(new KisLayerComposition(*comp, this));
}
emit sigLayersChangedAsync();
m_d->nserver = rhs.m_d->nserver;
vKisAnnotationSP newAnnotations;
Q_FOREACH (KisAnnotationSP annotation, rhs.m_d->annotations) {
newAnnotations << annotation->clone();
}
m_d->annotations = newAnnotations;
KIS_ASSERT_RECOVER_NOOP(!rhs.m_d->projectionUpdatesFilter);
KIS_ASSERT_RECOVER_NOOP(!rhs.m_d->disableUIUpdateSignals);
KIS_ASSERT_RECOVER_NOOP(!rhs.m_d->disableDirtyRequests);
m_d->blockLevelOfDetail = rhs.m_d->blockLevelOfDetail;
/**
* The overlay device is not inherited when cloning the image!
*/
if (rhs.m_d->overlaySelectionMask) {
const QRect dirtyRect = rhs.m_d->overlaySelectionMask->extent();
m_d->rootLayer->setDirty(dirtyRect);
}
}
KisImage::KisImage(const KisImage& rhs, KisUndoStore *undoStore, bool exactCopy)
: KisNodeFacade(),
KisNodeGraphListener(),
......
......@@ -122,6 +122,8 @@ public:
*/
KisImage *clone(bool exactCopy = false);
void copyFromImage(const KisImage &rhs);
/**
* Render the projection onto a QImage.
*/
......
......@@ -367,9 +367,40 @@ public:
}
}
void copyFrom(const Private &rhs, KisDocument *q);
class StrippedSafeSavingLocker;
};
void KisDocument::Private::copyFrom(const Private &rhs, KisDocument *q)
{
delete docInfo;
docInfo = (new KoDocumentInfo(*rhs.docInfo, q));
unit = rhs.unit;
// , importExportManager(new KisImportExportManager(q))
mimeType = rhs.mimeType;
outputMimeType = rhs.outputMimeType;
// TODO: undo stacks may store pointers to the document and/or image
// we *have* to destroy the original one
//delete undoStack;
//undoStack = new UndoStack(q);
q->setGuidesConfig(rhs.guidesConfig);
q->setMirrorAxisConfig(rhs.mirrorAxisConfig);
m_bAutoDetectedMime = rhs.m_bAutoDetectedMime;
m_url = rhs.m_url;
m_file = rhs.m_file;
q->setModified(rhs.modified);
readwrite = rhs.readwrite;
firstMod = rhs.firstMod;
lastMod = rhs.lastMod;
// TODO clone assistants
assistants = (rhs.assistants); // WARNING: assistants should not store pointers to the document!
globalAssistantsColor = rhs.globalAssistantsColor;
paletteList = rhs.paletteList;
gridConfig = rhs.gridConfig;
batchMode = rhs.batchMode;
}
class KisDocument::Private::StrippedSafeSavingLocker {
public:
StrippedSafeSavingLocker(QMutex *savingMutex, KisImageSP image)
......@@ -458,7 +489,7 @@ KisDocument::KisDocument(const KisDocument &rhs)
// since we clone uuid's, we can use them for lacating new
// nodes. Otherwise we would need to use findSymmetricClone()
d->preActivatedNode =
KisLayerUtils::findNodeByUuid(d->image->root(), rhs.d->preActivatedNode->uuid());
KisLayerUtils::findNodeByUuid(d->image->root(), rhs.d->preActivatedNode->uuid());
}
}
......@@ -578,14 +609,14 @@ bool KisDocument::exportDocumentImpl(const KritaUtils::ExportFileJob &job, KisPr
}
const QString actionName =
job.flags & KritaUtils::SaveIsExporting ?
i18n("Exporting Document...") :
i18n("Saving Document...");
job.flags & KritaUtils::SaveIsExporting ?
i18n("Exporting Document...") :
i18n("Saving Document...");
bool started =
initiateSavingInBackground(actionName,
this, SLOT(slotCompleteSavingDocument(KritaUtils::ExportFileJob, KisImportExportErrorCode ,QString)),
job, exportConfiguration);
initiateSavingInBackground(actionName,
this, SLOT(slotCompleteSavingDocument(KritaUtils::ExportFileJob, KisImportExportErrorCode ,QString)),
job, exportConfiguration);
if (!started) {
emit canceled(QString());
}
......@@ -763,6 +794,39 @@ KisDocument* KisDocument::lockAndCloneForSaving()
return new KisDocument(*this);
}
void KisDocument::copyFromDocument(const KisDocument &rhs)
{
d->copyFrom(*(rhs.d), this);
connect(d->undoStack, SIGNAL(cleanChanged(bool)), this, SLOT(slotUndoStackCleanChanged(bool)));
setObjectName(rhs.objectName());
slotConfigChanged();
if (rhs.d->image) {
d->image->barrierLock(/* readOnly = */ false);
rhs.d->image->barrierLock(/* readOnly = */ true);
d->image->copyFromImage(*(rhs.d->image));
d->image->unlock();
rhs.d->image->unlock();
setCurrentImage(d->image, /* forceInitialUpdate = */ true);
}
if (rhs.d->preActivatedNode) {
QQueue<KisNodeSP> linearizedNodes;
KisLayerUtils::recursiveApplyNodes(rhs.d->image->root(),
[&linearizedNodes](KisNodeSP node) {
linearizedNodes.enqueue(node);
});
KisLayerUtils::recursiveApplyNodes(d->image->root(),
[&linearizedNodes, &rhs, this](KisNodeSP node) {
KisNodeSP refNode = linearizedNodes.dequeue();
if (rhs.d->preActivatedNode.data() == refNode.data()) {
d->preActivatedNode = node;
}
});
}
}
bool KisDocument::exportDocumentSync(const QUrl &url, const QByteArray &mimeType, KisPropertiesConfigurationSP exportConfiguration)
{
{
......
......@@ -648,6 +648,8 @@ public:
*/
KisDocument *lockAndCloneForSaving();
void copyFromDocument(const KisDocument &rhs);
private:
QString exportErrorToUserMessage(KisImportExportErrorCode status, const QString &errorMessage);
......
......@@ -26,6 +26,7 @@
#include <KisDocument.h>
#include <KisView.h>
#include <KisViewManager.h>
struct KisSnapshotModel::Private
{
......@@ -39,7 +40,7 @@ struct KisSnapshotModel::Private
DocPList curDocList;
QList<DocPList> documentGroups;
QMap<QPointer<KisDocument>, DocPList> documentGroups;
QPointer<KisCanvas2> curCanvas;
};
......@@ -63,7 +64,10 @@ bool KisSnapshotModel::Private::switchToDocument(QPointer<KisDocument> doc)
{
if (curCanvas && curCanvas->imageView()) {
KisView *view = curCanvas->imageView();
view->setDocument(doc);
KisDocument *curDoc = curDocument();
if (curDoc && doc) {
curDoc->copyFromDocument(*doc);
}
// FIXME: more things need to be done
return true;
}
......@@ -116,17 +120,8 @@ void KisSnapshotModel::setCanvas(QPointer<KisCanvas2> canvas)
}
if (m_d->curCanvas) {
// if any one doc in the group is no longer valid (is closed)
// destroy all other snapshots
bool docValid = true;
Q_FOREACH (auto const &i, m_d->curDocList) {
if (! i.second) {
docValid = false;
break;
}
}
if (docValid) {
m_d->documentGroups << m_d->curDocList;
if (m_d->curDocument()) {
m_d->documentGroups.insert(m_d->curDocument(), m_d->curDocList);
} else {
Q_FOREACH (auto const &i, m_d->curDocList) {
delete i.second.data();
......@@ -142,19 +137,14 @@ void KisSnapshotModel::setCanvas(QPointer<KisCanvas2> canvas)
QPointer<KisDocument> curDoc = m_d->curDocument();
if (curDoc) {
for (int i = 0; i < m_d->documentGroups.size(); ++i) {
const Private::DocPList &docList = m_d->documentGroups[i];
Q_FOREACH (auto const &j, docList) {
if (j.second == curDoc) {
m_d->curDocList = m_d->documentGroups.takeAt(i);
return;
}
}
QMap<QPointer<KisDocument>, Private::DocPList>::const_iterator i = m_d->documentGroups.constFind(curDoc);
if (i != m_d->documentGroups.constEnd()) {
Private::DocPList docList = i.value();
beginInsertRows(QModelIndex(), docList.size(), docList.size());
m_d->curDocList = docList;
endInsertRows();
}
// we have not found any existing group containing the current document
beginInsertRows(QModelIndex(), m_d->curDocList.size(), m_d->curDocList.size());
m_d->curDocList << qMakePair(i18n("Original Document"), curDoc); /// XXX: a better title for it?
endInsertRows();
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment