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 }