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