File indexing completed on 2024-05-12 15:58:51

0001 /*
0002  *  SPDX-FileCopyrightText: 2021 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "KisInterstrokeDataTransactionWrapperFactory.h"
0008 
0009 #include <kundo2command.h>
0010 
0011 #include "KisInterstrokeData.h"
0012 #include "KisInterstrokeDataFactory.h"
0013 
0014 #include <kis_paint_device.h>
0015 #include <kis_pointer_utils.h>
0016 #include <kis_command_utils.h>
0017 
0018 
0019 namespace {
0020 struct BeginInterstrokeDataTransactionCommand : public KUndo2Command
0021 {
0022     BeginInterstrokeDataTransactionCommand(KisPaintDeviceSP device, KisInterstrokeDataSP newData)
0023         : m_device(device),
0024           m_interstrokeData(newData)
0025     {
0026     }
0027 
0028     void redo() override {
0029         if (m_firstRedo) {
0030             if (m_device->interstrokeData() != m_interstrokeData) {
0031                 m_dataSwapCommand.reset(m_device->createChangeInterstrokeDataCommand(m_interstrokeData));
0032                 m_dataSwapCommand->redo();
0033             }
0034 
0035             if (m_interstrokeData) {
0036                 m_interstrokeData->beginTransaction();
0037             }
0038 
0039             m_firstRedo = false;
0040         } else if (m_dataSwapCommand) {
0041             m_dataSwapCommand->redo();
0042 
0043         }
0044     }
0045 
0046     void undo() override {
0047         if (m_dataSwapCommand) {
0048             m_dataSwapCommand->undo();
0049         }
0050     }
0051 
0052 private:
0053     bool m_firstRedo {true};
0054     KisPaintDeviceSP m_device;
0055     KisInterstrokeDataSP m_interstrokeData;
0056     QScopedPointer<KUndo2Command> m_dataSwapCommand;
0057 };
0058 
0059 struct EndInterstrokeDataTransactionCommand : public KUndo2Command
0060 {
0061     EndInterstrokeDataTransactionCommand(KisPaintDeviceSP device)
0062         : m_device(device)
0063     {
0064     }
0065 
0066     void redo() override {
0067         KisInterstrokeDataSP data = m_device->interstrokeData();
0068 
0069         if (!m_transactionCommand && data) {
0070             m_transactionCommand.reset(data->endTransaction());
0071         }
0072 
0073         if (m_transactionCommand) {
0074             m_transactionCommand->redo();
0075         }
0076     }
0077 
0078     void undo() override {
0079         if (m_transactionCommand) {
0080             m_transactionCommand->undo();
0081         }
0082     }
0083 
0084 private:
0085     KisPaintDeviceSP m_device;
0086     QScopedPointer<KUndo2Command> m_transactionCommand;
0087 };
0088 
0089 }
0090 
0091 
0092 struct KisInterstrokeDataTransactionWrapperFactory::Private
0093 {
0094     QScopedPointer<KisInterstrokeDataFactory> factory;
0095     KisPaintDeviceSP device;
0096     bool supportsContinuedInterstrokeData = true;
0097 };
0098 
0099 KisInterstrokeDataTransactionWrapperFactory::KisInterstrokeDataTransactionWrapperFactory(KisInterstrokeDataFactory *factory, bool supportsContinuedInterstrokeData)
0100     : m_d(new Private())
0101 {
0102     m_d->factory.reset(factory);
0103     m_d->supportsContinuedInterstrokeData = supportsContinuedInterstrokeData;
0104 }
0105 
0106 KisInterstrokeDataTransactionWrapperFactory::~KisInterstrokeDataTransactionWrapperFactory()
0107 {
0108 }
0109 
0110 KUndo2Command *KisInterstrokeDataTransactionWrapperFactory::createBeginTransactionCommand(KisPaintDeviceSP device)
0111 {
0112     KisInterstrokeDataSP data = device->interstrokeData();
0113     if (m_d->factory) {
0114         if (!m_d->supportsContinuedInterstrokeData ||
0115             !data ||
0116             !data->isStillCompatible() ||
0117             !m_d->factory->isCompatible(data.data())) {
0118 
0119             data = toQShared(m_d->factory->create(device));
0120         }
0121     } else {
0122         data.clear();
0123     }
0124 
0125     KUndo2Command *cmd = 0;
0126 
0127     if (device->interstrokeData() || data) {
0128         m_d->device = device;
0129         cmd = new BeginInterstrokeDataTransactionCommand(device, data);
0130     }
0131 
0132     return cmd;
0133 }
0134 
0135 KUndo2Command *KisInterstrokeDataTransactionWrapperFactory::createEndTransactionCommand()
0136 {
0137     KUndo2Command *result = 0;
0138 
0139     if (m_d->device) {
0140         if (m_d->supportsContinuedInterstrokeData) {
0141             result = new EndInterstrokeDataTransactionCommand(m_d->device);
0142         } else {
0143             KisCommandUtils::CompositeCommand *composite
0144                 = new KisCommandUtils::CompositeCommand();
0145 
0146             composite->addCommand(new EndInterstrokeDataTransactionCommand(m_d->device));
0147             composite->addCommand(new BeginInterstrokeDataTransactionCommand(m_d->device, 0));
0148 
0149             result = composite;
0150         }
0151     }
0152 
0153     return result;
0154 }