File indexing completed on 2024-05-19 04:26:41
0001 /* 0002 * SPDX-FileCopyrightText: 2018 Boudewijn Rempt <boud@valdyas.org> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "KisAslStorage.h" 0008 #include <KisResourceStorage.h> 0009 #include <kis_psd_layer_style.h> 0010 0011 #include <QFileInfo> 0012 #include <KisStaticInitializer.h> 0013 0014 KIS_DECLARE_STATIC_INITIALIZER { 0015 KisStoragePluginRegistry::instance()->addStoragePluginFactory(KisResourceStorage::StorageType::AdobeStyleLibrary, new KisStoragePluginFactory<KisAslStorage>()); 0016 } 0017 0018 0019 class AslTagIterator : public KisResourceStorage::TagIterator 0020 { 0021 public: 0022 0023 AslTagIterator(const QString &location, const QString &resourceType) 0024 : m_location(location) 0025 , m_resourceType(resourceType) 0026 {} 0027 0028 bool hasNext() const override {return false;} 0029 void next() override {} 0030 0031 KisTagSP tag() const override { return nullptr; } 0032 0033 private: 0034 0035 QString m_location; 0036 QString m_resourceType; 0037 0038 }; 0039 0040 class AslIterator : public KisResourceStorage::ResourceIterator 0041 { 0042 0043 private: 0044 0045 QString m_filename; 0046 QSharedPointer<KisAslLayerStyleSerializer> m_aslSerializer; 0047 bool m_isLoaded; 0048 QHash<QString, KoPatternSP> m_patterns; 0049 QVector<KisPSDLayerStyleSP> m_styles; 0050 QScopedPointer<QHashIterator<QString, KoPatternSP>> m_patternsIterator; 0051 QScopedPointer<QVectorIterator<KisPSDLayerStyleSP>> m_stylesIterator; 0052 QString m_currentType; 0053 KoResourceSP m_currentResource; 0054 QString m_currentUuid; 0055 QString m_resourceType; 0056 0057 public: 0058 0059 AslIterator(QSharedPointer<KisAslLayerStyleSerializer> aslSerializer, const QString& filename, const QString& resourceType) 0060 : m_filename(filename) 0061 , m_aslSerializer(aslSerializer) 0062 , m_isLoaded(false) 0063 , m_resourceType(resourceType) 0064 { 0065 } 0066 0067 bool hasNext() const override 0068 { 0069 if (!m_isLoaded && (m_resourceType == ResourceType::Patterns || m_resourceType == ResourceType::LayerStyles)) { 0070 if (!m_aslSerializer->isInitialized()) { 0071 m_aslSerializer->readFromFile(m_filename); 0072 } 0073 0074 const_cast<AslIterator*>(this)->m_isLoaded = true; 0075 const_cast<AslIterator*>(this)->m_patterns = m_aslSerializer->patterns(); 0076 const_cast<AslIterator*>(this)->m_styles = m_aslSerializer->styles(); 0077 0078 const_cast<AslIterator*>(this)->m_patternsIterator.reset(new QHashIterator<QString, KoPatternSP>(m_patterns)); 0079 const_cast<AslIterator*>(this)->m_stylesIterator.reset(new QVectorIterator<KisPSDLayerStyleSP>(m_styles)); 0080 } 0081 if (!m_aslSerializer->isValid()) { 0082 return false; 0083 } 0084 0085 if (m_resourceType == ResourceType::Patterns) { 0086 return m_patternsIterator->hasNext(); 0087 } else if (m_resourceType == ResourceType::LayerStyles) { 0088 return m_stylesIterator->hasNext(); 0089 } 0090 return false; 0091 } 0092 void next() override 0093 { 0094 if (m_resourceType == ResourceType::Patterns) { 0095 if (m_patternsIterator->hasNext()) { 0096 m_currentType = ResourceType::Patterns; 0097 m_patternsIterator->next(); 0098 KoPatternSP currentPattern = m_patternsIterator->value(); 0099 m_currentResource = currentPattern; 0100 KIS_ASSERT(currentPattern); 0101 m_currentUuid = currentPattern->filename(); 0102 } 0103 } else if (m_resourceType == ResourceType::LayerStyles) { 0104 if (m_stylesIterator->hasNext()) { 0105 m_currentType = ResourceType::LayerStyles; 0106 KisPSDLayerStyleSP currentLayerStyle = m_stylesIterator->next(); 0107 m_currentResource = currentLayerStyle; 0108 KIS_ASSERT(currentLayerStyle); 0109 m_currentUuid = currentLayerStyle->filename(); 0110 } 0111 } 0112 } 0113 0114 QString url() const override 0115 { 0116 if (m_currentResource.isNull()) { 0117 return QString(); 0118 } 0119 return m_currentUuid; 0120 } 0121 0122 QString type() const override 0123 { 0124 return m_currentResource.isNull() ? QString() : m_currentType; 0125 } 0126 0127 QDateTime lastModified() const override { 0128 QFileInfo fi(m_filename); 0129 return fi.lastModified(); 0130 } 0131 0132 0133 /// This only loads the resource when called (but not in case of asl...) 0134 KoResourceSP resourceImpl() const override 0135 { 0136 return m_currentResource; 0137 } 0138 }; 0139 0140 KisAslStorage::KisAslStorage(const QString &location) 0141 : KisStoragePlugin(location) 0142 , m_aslSerializer(new KisAslLayerStyleSerializer()) 0143 { 0144 } 0145 0146 KisAslStorage::~KisAslStorage() 0147 { 0148 0149 } 0150 0151 KisResourceStorage::ResourceItem KisAslStorage::resourceItem(const QString &url) 0152 { 0153 KisResourceStorage::ResourceItem item; 0154 item.url = url; 0155 item.folder = location(); 0156 item.resourceType = url.contains("pattern") ? ResourceType::Patterns : ResourceType::LayerStyles; 0157 item.lastModified = QFileInfo(location()).lastModified(); 0158 return item; 0159 } 0160 0161 KoResourceSP KisAslStorage::resource(const QString &url) 0162 { 0163 if (!m_aslSerializer->isInitialized()) { 0164 m_aslSerializer->readFromFile(location()); 0165 } 0166 int indexOfUnderscore = url.lastIndexOf("_"); 0167 QString realUuid = url; 0168 if (indexOfUnderscore >= 0) { 0169 realUuid.remove(indexOfUnderscore, url.length() - indexOfUnderscore); // remove _pattern or _style added in iterator 0170 } 0171 // TODO: RESOURCES: Since we do get a resource type at the beginning of the path now 0172 // maybe we could skip adding the _[resourcetype] at the end of the path as well? 0173 realUuid = QFileInfo(realUuid).baseName(); // remove patterns/ at the beginning, if there are any 0174 0175 if (url.contains("pattern") || url.contains(".pat")) { 0176 QHash<QString, KoPatternSP> patterns = m_aslSerializer->patterns(); 0177 0178 if (patterns.contains(realUuid)) { 0179 return patterns[realUuid]; 0180 } 0181 } 0182 else { 0183 QHash<QString, KisPSDLayerStyleSP> styles = m_aslSerializer->stylesHash(); 0184 if (styles.contains(realUuid)) { 0185 return styles[realUuid]; 0186 } else { 0187 // can be {realUuid} or {realUuid} 0188 if (realUuid.startsWith("{")) { 0189 realUuid = realUuid.right(realUuid.length() - 1); 0190 } 0191 if (realUuid.endsWith("}")) { 0192 realUuid = realUuid.left(realUuid.length() - 1); 0193 } 0194 0195 if (styles.contains(realUuid)) { 0196 return styles[realUuid]; 0197 } else { 0198 Q_FOREACH(QString ke, styles.keys()) { 0199 } 0200 } 0201 0202 } 0203 } 0204 return 0; 0205 } 0206 0207 bool KisAslStorage::loadVersionedResource(KoResourceSP /*resource*/) 0208 { 0209 return false; 0210 } 0211 0212 bool KisAslStorage::supportsVersioning() const 0213 { 0214 return false; 0215 } 0216 0217 QSharedPointer<KisResourceStorage::ResourceIterator> KisAslStorage::resources(const QString &resourceType) 0218 { 0219 return QSharedPointer<KisResourceStorage::ResourceIterator>(new AslIterator(m_aslSerializer, location(), resourceType)); 0220 } 0221 0222 QSharedPointer<KisResourceStorage::TagIterator> KisAslStorage::tags(const QString &resourceType) 0223 { 0224 return QSharedPointer<KisResourceStorage::TagIterator>(new AslTagIterator(location(), resourceType)); 0225 } 0226 0227 bool KisAslStorage::saveAsNewVersion(const QString &/*resourceType*/, KoResourceSP /*resource*/) 0228 { 0229 // not implemented yet 0230 warnKrita << "KisAslStorage::saveAsNewVersion is not implemented yet"; 0231 return false; 0232 } 0233 0234 bool KisAslStorage::addResource(const QString &/*resourceType*/, KoResourceSP resource) 0235 { 0236 if (!resource) { 0237 warnKrita << "Trying to add a null resource to KisAslStorage"; 0238 return false; 0239 } 0240 KisPSDLayerStyleSP layerStyle = resource.dynamicCast<KisPSDLayerStyle>(); 0241 if (!layerStyle) { 0242 warnKrita << "Trying to add a resource that is not a layer style to KisAslStorage"; 0243 return false; 0244 } 0245 0246 QVector<KisPSDLayerStyleSP> styles = m_aslSerializer->styles(); 0247 styles << layerStyle; 0248 m_aslSerializer->setStyles(styles); 0249 return m_aslSerializer->saveToFile(location()); 0250 } 0251 0252 bool KisAslStorage::isValid() const 0253 { 0254 if (!m_aslSerializer->isInitialized()) { 0255 m_aslSerializer->readFromFile(location()); 0256 } 0257 return m_aslSerializer->isValid(); 0258 }