19#include <boost/optional.hpp>
23#ifdef DEBUG_TRANSACTIONS
24# define DEBUG_ACTION(action) dbgKrita << action << "for" << m_d->device->dataManager()
26# define DEBUG_ACTION(action)
32 QScopedPointer<KisTransactionWrapperFactory>
factory;
48 bool defaultPixelChanged =
false;
60 bool suppressUpdates =
false;
79 if (interstrokeDataFactory) {
81 m_d->interstrokeInfo->factory.reset(interstrokeDataFactory);
96 m_d->firstRedo =
true;
97 m_d->transactionFinished =
false;
101 if (
m_d->interstrokeInfo) {
102 m_d->interstrokeInfo->beginTransactionCommand.reset(
m_d->interstrokeInfo->factory->createBeginTransactionCommand(
m_d->device));
103 if (
m_d->interstrokeInfo->beginTransactionCommand) {
104 m_d->interstrokeInfo->beginTransactionCommand->redo();
109 m_d->savedDataManager =
m_d->transactionFrameId >= 0 ?
110 m_d->device->framesInterface()->frameDataManager(
m_d->transactionFrameId) :
111 m_d->device->dataManager();
112 m_d->memento =
m_d->savedDataManager->getMemento();
117 Q_ASSERT(
m_d->memento);
118 m_d->savedDataManager->purgeHistory(
m_d->memento);
123void KisTransactionData::Private::moveDevice(
const QPoint newOffset)
125 if (transactionFrameId >= 0) {
126 device->framesInterface()->setFrameOffset(transactionFrameId, newOffset);
128 device->moveTo(newOffset);
134 if(!
m_d->transactionFinished) {
137 m_d->transactionTime ==
m_d->device->defaultBounds()->currentTime());
140 m_d->transactionFinished =
true;
141 m_d->savedDataManager->commit();
142 m_d->newOffset = QPoint(
m_d->device->x(),
m_d->device->y());
143 m_d->defaultPixelChanged =
m_d->oldDefaultPixel !=
m_d->device->defaultPixel();
145 if (
m_d->interstrokeInfo) {
146 m_d->interstrokeInfo->endTransactionCommand.reset(
m_d->interstrokeInfo->factory->createEndTransactionCommand());
147 if (
m_d->interstrokeInfo->endTransactionCommand) {
148 m_d->interstrokeInfo->endTransactionCommand->redo();
150 m_d->interstrokeInfo->factory.reset();
157 if (
m_d->suppressUpdates)
return;
159 if (
m_d->transactionFrameId == -1 ||
160 m_d->transactionFrameId ==
161 m_d->device->framesInterface()->currentFrameId()) {
164 QRect mementoExtent =
m_d->memento->extent();
166 if (
m_d->newOffset ==
m_d->oldOffset) {
167 rc = mementoExtent.translated(
m_d->device->x(),
m_d->device->y());
170 m_d->savedDataManager->extent() | mementoExtent;
172 rc = totalExtent.translated(
m_d->oldOffset) |
173 totalExtent.translated(
m_d->newOffset);
176 if (
m_d->defaultPixelChanged) {
177 rc |=
m_d->device->defaultBounds()->bounds();
180 m_d->device->setDirty(rc);
182 m_d->device->framesInterface()->invalidateFrameCache(
m_d->transactionFrameId);
192 if (pixelSelection && (selection = pixelSelection->
parentSelection())) {
201 if (
m_d->resetSelectionOutlineCache &&
214 if (pixelSelection) {
217 m_d->flattenUndoCommand.reset(selection->
flatten());
219 if (
m_d->flattenUndoCommand) {
220 m_d->flattenUndoCommand->redo();
231 if (pixelSelection) {
232 if (
m_d->flattenUndoCommand) {
234 m_d->flattenUndoCommand->undo();
236 m_d->flattenUndoCommand->redo();
242void KisTransactionData::Private::possiblySwitchCurrentTime()
244 if (device->defaultBounds()->currentTime() == transactionTime)
return;
246 device->requestTimeSwitch(transactionTime);
252 if (
m_d->firstRedo) {
253 m_d->firstRedo =
false;
268 if (
m_d->interstrokeInfo &&
m_d->interstrokeInfo->beginTransactionCommand) {
269 m_d->interstrokeInfo->beginTransactionCommand->redo();
272 Q_ASSERT(
m_d->memento);
273 m_d->savedDataManager->rollforward(
m_d->memento);
275 if (
m_d->newOffset !=
m_d->oldOffset) {
276 m_d->moveDevice(
m_d->newOffset);
279 if (
m_d->interstrokeInfo &&
m_d->interstrokeInfo->endTransactionCommand) {
280 m_d->interstrokeInfo->endTransactionCommand->redo();
283 m_d->possiblySwitchCurrentTime();
292 if (
m_d->interstrokeInfo &&
m_d->interstrokeInfo->endTransactionCommand) {
293 m_d->interstrokeInfo->endTransactionCommand->undo();
296 Q_ASSERT(
m_d->memento);
297 m_d->savedDataManager->rollback(
m_d->memento);
299 if (
m_d->newOffset !=
m_d->oldOffset) {
300 m_d->moveDevice(
m_d->oldOffset);
303 if (
m_d->interstrokeInfo &&
m_d->interstrokeInfo->beginTransactionCommand) {
304 m_d->interstrokeInfo->beginTransactionCommand->undo();
310 m_d->possiblySwitchCurrentTime();
317 m_d->savedOutlineCacheValid =
false;
322 if (pixelSelection) {
324 if (
m_d->savedOutlineCacheValid) {
338 if (pixelSelection) {
347 if (
m_d->savedOutlineCacheValid) {
354 if (
m_d->savedOutlineCacheValid) {
virtual void setTimedID(int timedID)
virtual int currentTime() const =0
int currentFrameId() const
KisInterstrokeDataSP interstrokeData() const
KisPaintDeviceFramesInterface * framesInterface()
KoColor defaultPixel() const
KisDefaultBoundsBaseSP defaultBounds() const
void doFlattenUndoRedo(bool undo)
void possiblySwitchCurrentTime()
QScopedPointer< KUndo2Command > flattenUndoCommand
~KisTransactionData() override
void init(KisPaintDeviceSP device)
virtual void saveSelectionOutlineCache()
virtual void endTransaction()
QPainterPath savedOutlineCache
KisDataManagerSP savedDataManager
void possiblyFlattenSelection(KisPaintDeviceSP device)
void possiblyResetOutlineCache()
KisDataManagerSP dataManager()
void possiblyNotifySelectionChanged()
void moveDevice(const QPoint newOffset)
virtual void restoreSelectionOutlineCache(bool undo)
bool savedOutlineCacheValid
QScopedPointer< OptionalInterstrokeInfo > interstrokeInfo
KisTransactionData(const KUndo2MagicString &name, KisPaintDeviceSP device, bool resetSelectionOutlineCache, KisTransactionWrapperFactory *interstrokeDataFactory, KUndo2Command *parent, bool suppressUpdates)
bool resetSelectionOutlineCache
#define KIS_ASSERT_RECOVER_RETURN(cond)
#define DEBUG_ACTION(action)
QPainterPath outlineCache
KisSelectionWSP parentSelection
void invalidateOutlineCache()
void setOutlineCache(const QPainterPath &cache)
KUndo2Command * flatten()
flatten creates a new pixel selection component from the shape selection and throws away the shape se...
void notifySelectionChanged()
QScopedPointer< KUndo2Command > beginTransactionCommand
QScopedPointer< KisTransactionWrapperFactory > factory
QScopedPointer< KUndo2Command > endTransactionCommand