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"