File indexing completed on 2024-05-12 16:01:53

0001 /*
0002  *  SPDX-FileCopyrightText: 2021 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "KisPresetShadowUpdater.h"
0008 
0009 #include <KisViewManager.h>
0010 
0011 #include <KoCanvasResourcesIds.h>
0012 
0013 #include <kis_paintop_preset.h>
0014 #include <KisPaintOpPresetUpdateProxy.h>
0015 #include <kis_signal_auto_connection.h>
0016 #include <kis_signal_compressor.h>
0017 
0018 #include <kis_image.h>
0019 #include <kis_spontaneous_job.h>
0020 
0021 #include <KisGlobalResourcesInterface.h>
0022 #include <kis_canvas_resource_provider.h>
0023 #include <KoCanvasResourceProvider.h>
0024 #include <KoCanvasResourcesInterface.h>
0025 #include <KoResourceCacheStorage.h>
0026 
0027 
0028 class ShadowUpdatePresetJob : public QObject, public KisSpontaneousJob
0029 {
0030     Q_OBJECT
0031 public:
0032 
0033     ShadowUpdatePresetJob(KisPaintOpPresetSP preset, int sequenceNumber)
0034         : m_preset(preset),
0035           m_sequenceNumber(sequenceNumber)
0036     {
0037     }
0038 
0039     void run() override {
0040         KIS_SAFE_ASSERT_RECOVER_RETURN(m_preset);
0041 
0042         KoResourceCacheInterfaceSP cacheInterface =
0043             toQShared(new KoResourceCacheStorage());
0044 
0045         m_preset->regenerateResourceCache(cacheInterface);
0046 
0047         Q_EMIT sigCacheGenerationFinished(m_sequenceNumber, cacheInterface);
0048     }
0049 
0050     bool overrides(const KisSpontaneousJob *_otherJob) override {
0051         const ShadowUpdatePresetJob *otherJob =
0052             dynamic_cast<const ShadowUpdatePresetJob*>(_otherJob);
0053 
0054         return otherJob;
0055     }
0056 
0057     int levelOfDetail() const override {
0058         return 0;
0059     }
0060 
0061     QString debugName() const override {
0062         QString result;
0063         QDebug dbg(&result);
0064         dbg << "ShadowUpdatePresetJob" << m_preset;
0065         return result;
0066     }
0067 
0068 Q_SIGNALS:
0069     void sigCacheGenerationFinished(int sequenceNumber,
0070                                     KoResourceCacheInterfaceSP cacheInterface);
0071 private:
0072     KisPaintOpPresetSP m_preset;
0073     const int m_sequenceNumber;
0074 };
0075 
0076 struct KisPresetShadowUpdater::Private
0077 {
0078     Private()
0079         : updateStartCompressor(1500, KisSignalCompressor::POSTPONE)
0080     {
0081     }
0082 
0083     KisViewManager *view {nullptr};
0084 
0085     KisPaintOpPresetSP currentPreset;
0086     QPointer<KisPaintOpPresetUpdateProxy> currentUpdateProxy;
0087 
0088     KisSignalAutoConnectionsStore proxyConnections;
0089     KisSignalCompressor updateStartCompressor;
0090 
0091     int sequenceNumber {0};
0092 
0093 };
0094 
0095 KisPresetShadowUpdater::KisPresetShadowUpdater(KisViewManager *view)
0096     : m_d(new Private)
0097 {
0098     m_d->view = view;
0099     connect(&m_d->updateStartCompressor, SIGNAL(timeout()),
0100             this, SLOT(slotStartPresetPreparation()));
0101 }
0102 
0103 KisPresetShadowUpdater::~KisPresetShadowUpdater()
0104 {
0105 }
0106 
0107 void KisPresetShadowUpdater::slotCanvasResourceChanged(int key, const QVariant &value)
0108 {
0109     if (key == KoCanvasResource::CurrentPaintOpPreset) {
0110         m_d->currentPreset = value.value<KisPaintOpPresetSP>();
0111 
0112         m_d->proxyConnections.clear();
0113 
0114         if (m_d->currentPreset) {
0115             m_d->currentUpdateProxy = m_d->currentPreset->updateProxy();
0116             m_d->proxyConnections.addConnection(
0117                 m_d->currentUpdateProxy, SIGNAL(sigSettingsChangedUncompressedEarlyWarning()),
0118                 this, SLOT(slotPresetChanged()));
0119             slotPresetChanged();
0120         } else {
0121             m_d->view->canvasResourceProvider()->resourceManager()->
0122                     setResource(KoCanvasResource::CurrentPaintOpPresetCache,
0123                                 QVariant::fromValue(KoResourceCacheInterfaceSP()));
0124         }
0125     } else if (m_d->currentPreset) {
0126         /// if the current preset depends on the canvas resources,
0127         /// we should reset its cache and restart cache generation
0128 
0129         if (m_d->currentPreset->requiredCanvasResources().contains(key)) {
0130             slotPresetChanged();
0131         }
0132     }
0133 }
0134 
0135 void KisPresetShadowUpdater::slotPresetChanged()
0136 {
0137     m_d->sequenceNumber++;
0138     m_d->updateStartCompressor.start();
0139 
0140     m_d->view->canvasResourceProvider()->resourceManager()->
0141             setResource(KoCanvasResource::CurrentPaintOpPresetCache,
0142                         QVariant::fromValue(KoResourceCacheInterfaceSP()));
0143 
0144 }
0145 
0146 void KisPresetShadowUpdater::slotStartPresetPreparation()
0147 {
0148     if (m_d->currentPreset) {
0149         KisImageSP image = m_d->view->image();
0150         if (image) {
0151             KisPaintOpPresetSP preset =
0152                     m_d->currentPreset->cloneWithResourcesSnapshot(
0153                         KisGlobalResourcesInterface::instance(),
0154                         m_d->view->canvasResourceProvider()->resourceManager()->canvasResourcesInterface(),
0155                         nullptr);
0156 
0157             ShadowUpdatePresetJob *job = new ShadowUpdatePresetJob(preset, m_d->sequenceNumber);
0158 
0159             connect(job, SIGNAL(sigCacheGenerationFinished(int, KoResourceCacheInterfaceSP)),
0160                     this, SLOT(slotCacheGenerationFinished(int, KoResourceCacheInterfaceSP)));
0161 
0162             image->addSpontaneousJob(job);
0163         } else {
0164             /// a fallback solution when a preset is selected on
0165             /// Krita loading, when there is no image present
0166 
0167             KoResourceCacheInterfaceSP cacheInterface =
0168                 toQShared(new KoResourceCacheStorage());
0169 
0170             m_d->currentPreset->regenerateResourceCache(cacheInterface);
0171             slotCacheGenerationFinished(m_d->sequenceNumber, cacheInterface);
0172         }
0173     }
0174 }
0175 
0176 void KisPresetShadowUpdater::slotCacheGenerationFinished(int sequenceNumber, KoResourceCacheInterfaceSP cacheInterface)
0177 {
0178     if (sequenceNumber == m_d->sequenceNumber) {
0179         m_d->view->canvasResourceProvider()->resourceManager()->
0180                 setResource(KoCanvasResource::CurrentPaintOpPresetCache,
0181                             QVariant::fromValue(cacheInterface));
0182     }
0183 }
0184 
0185 #include "KisPresetShadowUpdater.moc"