File indexing completed on 2024-05-12 15:59:51
0001 /* 0002 * SPDX-FileCopyrightText: 2020 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 #include "KisResourcesInterface.h" 0007 0008 0009 #include <QString> 0010 #include "kis_assert.h" 0011 #include "KisResourcesInterface_p.h" 0012 0013 #include "kis_debug.h" 0014 0015 //#define SANITY_CHECKS 0016 0017 0018 KisResourcesInterface::KisResourcesInterface() 0019 : d_ptr(new KisResourcesInterfacePrivate) 0020 { 0021 } 0022 0023 KisResourcesInterface::KisResourcesInterface(KisResourcesInterfacePrivate *dd) 0024 : d_ptr(dd) 0025 { 0026 } 0027 0028 KisResourcesInterface::~KisResourcesInterface() 0029 { 0030 0031 } 0032 0033 KisResourcesInterface::ResourceSourceAdapter &KisResourcesInterface::source(const QString &type) const 0034 { 0035 Q_D(const KisResourcesInterface); 0036 0037 // use double-locking for fetching the source 0038 0039 ResourceSourceAdapter *source = 0; 0040 0041 { 0042 QReadLocker l(&d->lock); 0043 source = d->findExistingSource(type); 0044 if (source) return *source; 0045 } 0046 0047 { 0048 QWriteLocker l(&d->lock); 0049 source = d->findExistingSource(type); 0050 if (source) return *source; 0051 0052 source = createSourceImpl(type); 0053 0054 std::unique_ptr<ResourceSourceAdapter> sourcePtr(source); 0055 d->sourceAdapters.emplace(type, std::move(sourcePtr)); 0056 } 0057 0058 KIS_ASSERT(source); 0059 return *source; 0060 } 0061 0062 KisResourcesInterface::ResourceSourceAdapter::ResourceSourceAdapter(const QString &type) 0063 : m_type(type) 0064 { 0065 } 0066 0067 KisResourcesInterface::ResourceSourceAdapter::~ResourceSourceAdapter() 0068 { 0069 } 0070 0071 KoResourceSP KisResourcesInterface::ResourceSourceAdapter::bestMatch(const QString md5, const QString filename, const QString name) 0072 { 0073 QVector<QPair<KoResourceSP, int>> foundResources; 0074 0075 if (!md5.isEmpty()) { 0076 Q_FOREACH (KoResourceSP res, resourcesForMD5(md5)) { 0077 int penalty = 0; 0078 0079 if (!res->active()) { 0080 penalty += 100; 0081 } 0082 0083 if (!filename.isEmpty() && filename != res->filename()) { 0084 /// filename is more important than name, so it gives 0085 /// higher penalty 0086 penalty += 2; 0087 } 0088 0089 if (!name.isEmpty() && name != res->name()) { 0090 penalty++; 0091 } 0092 0093 foundResources.append(qMakePair(res, penalty)); 0094 } 0095 } 0096 0097 #ifdef SANITY_CHECKS 0098 /** 0099 * When we request a resource using MD5, but it is found only via its 0100 * filename, it is, most probably, a problem with the preset. Namely, 0101 * the MD5 tag saved into the preset is wrong. Let's just warn about 0102 * that. 0103 */ 0104 const bool warnAboutIncorrectMd5Fetch = 0105 foundResources.isEmpty() && !md5.isEmpty(); 0106 #endif 0107 0108 if (foundResources.isEmpty()) { 0109 if (!filename.isEmpty()) { 0110 Q_FOREACH (KoResourceSP res, resourcesForFilename(filename)) { 0111 int penalty = 0; 0112 0113 if (!res->active()) { 0114 penalty += 100; 0115 } 0116 0117 if (!name.isEmpty() && name != res->name()) { 0118 penalty++; 0119 } 0120 0121 foundResources.append(qMakePair(res, penalty)); 0122 } 0123 } else if (!name.isEmpty()) { 0124 Q_FOREACH (KoResourceSP res, resourcesForName(name)) { 0125 int penalty = 0; 0126 0127 if (!res->active()) { 0128 penalty += 100; 0129 } 0130 0131 foundResources.append(qMakePair(res, penalty)); 0132 } 0133 } 0134 } 0135 0136 auto it = std::min_element(foundResources.begin(), foundResources.end(), 0137 [] (const QPair<KoResourceSP, int> &lhs, 0138 const QPair<KoResourceSP, int> &rhs) {return lhs.second < rhs.second;}); 0139 0140 KoResourceSP result = it != foundResources.end() ? it->first : KoResourceSP(); 0141 0142 #ifdef SANITY_CHECKS 0143 if (warnAboutIncorrectMd5Fetch && result) { 0144 qWarning() << "KisResourcesInterface::ResourceSourceAdapter::bestMatch: failed to fetch a resource using md5; falling back for filename..."; 0145 qWarning() << " requested:" << ppVar(md5) << ppVar(filename) << ppVar(name); 0146 qWarning() << " found:" << result; 0147 } 0148 #endif 0149 0150 return result; 0151 } 0152 0153 KoResourceLoadResult KisResourcesInterface::ResourceSourceAdapter::bestMatchLoadResult(const QString md5, const QString filename, const QString name) 0154 { 0155 KoResourceSP resource = bestMatch(md5, filename, name); 0156 return 0157 resource ? 0158 KoResourceLoadResult(resource) : 0159 KoResourceLoadResult(KoResourceSignature(m_type, md5, filename, name)); 0160 }