File indexing completed on 2024-05-12 15:56:45

0001 /*
0002    SPDX-FileCopyrightText: 2006, 2011 Boudewijn Rempt (boud@valdyas.org)
0003    SPDX-FileCopyrightText: 2007, 2010 Thomas Zander <zander@kde.org>
0004    SPDX-FileCopyrightText: 2008 Carlos Licea <carlos.licea@kdemail.net>
0005    SPDX-FileCopyrightText: 2011 Jan Hambrecht <jaham@gmx.net>
0006 
0007    SPDX-License-Identifier: LGPL-2.0-or-later
0008  */
0009 #include "KoResourceManager_p.h"
0010 
0011 #include <QVariant>
0012 #include <FlakeDebug.h>
0013 
0014 #include "KoShape.h"
0015 #include "kis_assert.h"
0016 #include "kis_debug.h"
0017 
0018 void KoResourceManager::slotResourceInternalsChanged(int key)
0019 {
0020     KIS_SAFE_ASSERT_RECOVER_RETURN(m_resources.contains(key));
0021     notifyDerivedResourcesChanged(key, m_resources[key]);
0022     notifyDependenciesAboutTargetChange(key, m_resources[key]);
0023 }
0024 
0025 void KoResourceManager::setResource(int key, const QVariant &value)
0026 {
0027     notifyResourceChangeAttempted(key, value);
0028 
0029     KoDerivedResourceConverterSP converter =
0030         m_derivedResources.value(key, KoDerivedResourceConverterSP());
0031 
0032     if (converter) {
0033         const int sourceKey = converter->sourceKey();
0034         const QVariant oldSourceValue = m_resources.value(sourceKey, QVariant());
0035 
0036         bool valueChanged = false;
0037         const QVariant newSourceValue = converter->writeToSource(value, oldSourceValue, &valueChanged);
0038 
0039         if (valueChanged) {
0040             notifyResourceChanged(key, value);
0041         }
0042 
0043         if (oldSourceValue != newSourceValue) {
0044             m_resources[sourceKey] = newSourceValue;
0045             notifyResourceChanged(sourceKey, newSourceValue);
0046         }
0047     } else if (m_resources.contains(key)) {
0048         const QVariant oldValue = m_resources.value(key, QVariant());
0049         m_resources[key] = value;
0050 
0051         if (m_updateMediators.contains(key)) {
0052             m_updateMediators[key]->connectResource(value);
0053         }
0054 
0055         if (oldValue != value) {
0056             notifyResourceChanged(key, value);
0057         }
0058     } else {
0059         m_resources[key] = value;
0060         if (m_updateMediators.contains(key)) {
0061             m_updateMediators[key]->connectResource(value);
0062         }
0063         notifyResourceChanged(key, value);
0064     }
0065 }
0066 
0067 void KoResourceManager::notifyResourceChanged(int key, const QVariant &value)
0068 {
0069     emit resourceChanged(key, value);
0070     notifyDerivedResourcesChanged(key, value);
0071     notifyDependenciesAboutTargetChange(key, value);
0072 }
0073 
0074 void KoResourceManager::notifyDerivedResourcesChanged(int key, const QVariant &value)
0075 {
0076     QMultiHash<int, KoDerivedResourceConverterSP>::const_iterator it = m_derivedFromSource.constFind(key);
0077     QMultiHash<int, KoDerivedResourceConverterSP>::const_iterator end = m_derivedFromSource.constEnd();
0078 
0079     while (it != end && it.key() == key) {
0080         KoDerivedResourceConverterSP converter = it.value();
0081 
0082         if (converter->notifySourceChanged(value)) {
0083             notifyResourceChanged(converter->key(), converter->readFromSource(value));
0084         }
0085 
0086         it++;
0087     }
0088 }
0089 
0090 void KoResourceManager::notifyResourceChangeAttempted(int key, const QVariant &value)
0091 {
0092     emit resourceChangeAttempted(key, value);
0093     notifyDerivedResourcesChangeAttempted(key, value);
0094 }
0095 
0096 void KoResourceManager::notifyDerivedResourcesChangeAttempted(int key, const QVariant &value)
0097 {
0098     QMultiHash<int, KoDerivedResourceConverterSP>::const_iterator it = m_derivedFromSource.constFind(key);
0099     QMultiHash<int, KoDerivedResourceConverterSP>::const_iterator end = m_derivedFromSource.constEnd();
0100 
0101     while (it != end && it.key() == key) {
0102         KoDerivedResourceConverterSP converter = it.value();
0103         notifyResourceChangeAttempted(converter->key(), converter->readFromSource(value));
0104         it++;
0105     }
0106 }
0107 
0108 void KoResourceManager::notifyDependenciesAboutTargetChange(int targetKey, const QVariant &targetValue)
0109 {
0110     auto it = m_dependencyFromTarget.find(targetKey);
0111     while (it != m_dependencyFromTarget.end() && it.key() == targetKey) {
0112         const int sourceKey = it.value()->sourceKey();
0113 
0114         if (hasResource(sourceKey)) {
0115             QVariant sourceValue = resource(sourceKey);
0116 
0117             notifyResourceChangeAttempted(sourceKey, sourceValue);
0118             if (it.value()->shouldUpdateSource(sourceValue, targetValue)) {
0119                 notifyResourceChanged(sourceKey, sourceValue);
0120             }
0121         }
0122 
0123         ++it;
0124     }
0125 }
0126 
0127 QVariant KoResourceManager::resource(int key) const
0128 {
0129     KoDerivedResourceConverterSP converter =
0130         m_derivedResources.value(key, KoDerivedResourceConverterSP());
0131 
0132     const int realKey = converter ? converter->sourceKey() : key;
0133     QVariant value = m_resources.value(realKey, QVariant());
0134 
0135     return converter ? converter->readFromSource(value) : value;
0136 }
0137 
0138 void KoResourceManager::setResource(int key, const KoColor &color)
0139 {
0140     QVariant v;
0141     v.setValue(color);
0142     setResource(key, v);
0143 }
0144 
0145 void KoResourceManager::setResource(int key, KoShape *shape)
0146 {
0147     QVariant v;
0148     v.setValue(shape);
0149     setResource(key, v);
0150 }
0151 
0152 void KoResourceManager::setResource(int key, const KoUnit &unit)
0153 {
0154     QVariant v;
0155     v.setValue(unit);
0156     setResource(key, v);
0157 }
0158 
0159 KoColor KoResourceManager::koColorResource(int key) const
0160 {
0161     if (! m_resources.contains(key)) {
0162         KoColor empty;
0163         return empty;
0164     }
0165     return resource(key).value<KoColor>();
0166 }
0167 
0168 KoShape *KoResourceManager::koShapeResource(int key) const
0169 {
0170     if (! m_resources.contains(key))
0171         return 0;
0172 
0173     return resource(key).value<KoShape *>();
0174 }
0175 
0176 
0177 KoUnit KoResourceManager::unitResource(int key) const
0178 {
0179     return resource(key).value<KoUnit>();
0180 }
0181 
0182 bool KoResourceManager::boolResource(int key) const
0183 {
0184     if (! m_resources.contains(key))
0185         return false;
0186     return m_resources[key].toBool();
0187 }
0188 
0189 int KoResourceManager::intResource(int key) const
0190 {
0191     if (! m_resources.contains(key))
0192         return 0;
0193     return m_resources[key].toInt();
0194 }
0195 
0196 QString KoResourceManager::stringResource(int key) const
0197 {
0198     if (! m_resources.contains(key)) {
0199         QString empty;
0200         return empty;
0201     }
0202     return qvariant_cast<QString>(resource(key));
0203 }
0204 
0205 QSizeF KoResourceManager::sizeResource(int key) const
0206 {
0207     if (! m_resources.contains(key)) {
0208         QSizeF empty;
0209         return empty;
0210     }
0211     return qvariant_cast<QSizeF>(resource(key));
0212 }
0213 
0214 bool KoResourceManager::hasResource(int key) const
0215 {
0216     KoDerivedResourceConverterSP converter =
0217         m_derivedResources.value(key, KoDerivedResourceConverterSP());
0218 
0219     const int realKey = converter ? converter->sourceKey() : key;
0220     return m_resources.contains(realKey);
0221 }
0222 
0223 void KoResourceManager::clearResource(int key)
0224 {
0225     // we cannot remove a derived resource
0226     if (m_derivedResources.contains(key)) return;
0227 
0228     if (m_resources.contains(key)) {
0229         m_resources.remove(key);
0230         notifyResourceChanged(key, QVariant());
0231     }
0232 }
0233 
0234 void KoResourceManager::addDerivedResourceConverter(KoDerivedResourceConverterSP converter)
0235 {
0236     KIS_SAFE_ASSERT_RECOVER_NOOP(!m_derivedResources.contains(converter->key()));
0237 
0238     m_derivedResources.insert(converter->key(), converter);
0239     m_derivedFromSource.insertMulti(converter->sourceKey(), converter);
0240 }
0241 
0242 bool KoResourceManager::hasDerivedResourceConverter(int key)
0243 {
0244     return m_derivedResources.contains(key);
0245 }
0246 
0247 void KoResourceManager::removeDerivedResourceConverter(int key)
0248 {
0249     Q_ASSERT(m_derivedResources.contains(key));
0250 
0251     KoDerivedResourceConverterSP converter = m_derivedResources.value(key);
0252     m_derivedResources.remove(key);
0253     m_derivedFromSource.remove(converter->sourceKey(), converter);
0254 }
0255 
0256 void KoResourceManager::addResourceUpdateMediator(KoResourceUpdateMediatorSP mediator)
0257 {
0258     KIS_SAFE_ASSERT_RECOVER_NOOP(!m_updateMediators.contains(mediator->key()));
0259     m_updateMediators.insert(mediator->key(), mediator);
0260     connect(mediator.data(), SIGNAL(sigResourceChanged(int)), SLOT(slotResourceInternalsChanged(int)));
0261 }
0262 
0263 bool KoResourceManager::hasResourceUpdateMediator(int key)
0264 {
0265     return m_updateMediators.contains(key);
0266 }
0267 
0268 void KoResourceManager::removeResourceUpdateMediator(int key)
0269 {
0270     KIS_SAFE_ASSERT_RECOVER_RETURN(m_updateMediators.contains(key));
0271     m_updateMediators.remove(key);
0272 }
0273 
0274 void KoResourceManager::addActiveCanvasResourceDependency(KoActiveCanvasResourceDependencySP dep)
0275 {
0276     KIS_SAFE_ASSERT_RECOVER_RETURN(!hasActiveCanvasResourceDependency(dep->sourceKey(), dep->targetKey()));
0277 
0278     m_dependencyFromSource.insertMulti(dep->sourceKey(), dep);
0279     m_dependencyFromTarget.insertMulti(dep->targetKey(), dep);
0280 }
0281 
0282 bool KoResourceManager::hasActiveCanvasResourceDependency(int sourceKey, int targetKey) const
0283 {
0284     auto it = m_dependencyFromSource.find(sourceKey);
0285 
0286     while (it != m_dependencyFromSource.end() && it.key() == sourceKey) {
0287         if (it.value()->targetKey() == targetKey) {
0288             return true;
0289         }
0290         ++it;
0291     }
0292 
0293     return false;
0294 }
0295 
0296 void KoResourceManager::removeActiveCanvasResourceDependency(int sourceKey, int targetKey)
0297 {
0298     KIS_SAFE_ASSERT_RECOVER_RETURN(hasActiveCanvasResourceDependency(sourceKey, targetKey));
0299 
0300     {
0301         auto it = m_dependencyFromSource.find(sourceKey);
0302         while (it != m_dependencyFromSource.end() && it.key() == sourceKey) {
0303             if (it.value()->targetKey() == targetKey) {
0304                 it = m_dependencyFromSource.erase(it);
0305                 break;
0306             } else {
0307                 ++it;
0308             }
0309         }
0310     }
0311 
0312     {
0313         auto it = m_dependencyFromTarget.find(targetKey);
0314         while (it != m_dependencyFromTarget.end() && it.key() == targetKey) {
0315             if (it.value()->sourceKey() == sourceKey) {
0316                 it = m_dependencyFromTarget.erase(it);
0317                 break;
0318             } else {
0319                 ++it;
0320             }
0321         }
0322     }
0323 }