Warning, file /office/calligra/libs/widgets/KoResourcePaths.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * Copyright (c) 2015 Boudewijn Rempt <boud@valdyas.org> 0003 * Copyright (c) 2015 Friedrich W. H. Kossebau <kossebau@kde.org> 0004 * 0005 * This library is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU Lesser General Public 0007 * License as published by the Free Software Foundation; either 0008 * version 2.1 of the License, or (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 * Lesser General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Lesser General Public 0016 * License along with this library; if not, write to the Free Software 0017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 0018 */ 0019 0020 #include "KoResourcePaths.h" 0021 0022 #include <QGlobalStatic> 0023 #include <QStringList> 0024 #include <QHash> 0025 #include <QStandardPaths> 0026 #include <QDir> 0027 #include <QFileInfo> 0028 #include <QDebug> 0029 #include <QSet> 0030 0031 0032 #ifdef Q_OS_WIN 0033 static const Qt::CaseSensitivity cs = Qt::CaseInsensitive; 0034 #else 0035 static const Qt::CaseSensitivity cs = Qt::CaseSensitive; 0036 #endif 0037 0038 class KoResourcePathsImpl 0039 { 0040 public: 0041 static QStandardPaths::StandardLocation mapTypeToQStandardPaths(const QString &type) 0042 { 0043 return 0044 type == QLatin1String("data") ? QStandardPaths::GenericDataLocation : 0045 type == QLatin1String("config") ? QStandardPaths::GenericConfigLocation : 0046 type == QLatin1String("cache") ? QStandardPaths::CacheLocation : 0047 type == QLatin1String("tmp") ? QStandardPaths::TempLocation : 0048 type == QLatin1String("appdata") ? QStandardPaths::DataLocation : 0049 type == QLatin1String("locale") ? QStandardPaths::GenericDataLocation : 0050 /* default */ QStandardPaths::GenericDataLocation; 0051 } 0052 0053 KoResourcePathsImpl() = default; 0054 ~KoResourcePathsImpl() = default; 0055 0056 void addResourceTypeInternal(const QString &type, const QString &basetype, 0057 const QString &relativeName, bool priority); 0058 0059 void addResourceDirInternal(const QString &type, const QString &absdir, bool priority); 0060 0061 QString findResourceInternal(const QString &type, const QString &fileName); 0062 0063 QStringList findDirsInternal(const QString &type, const QString &relDir); 0064 0065 QStringList findAllResourcesInternal(const QString &type, 0066 const QString &filter = QString(), 0067 KoResourcePaths::SearchOptions options = KoResourcePaths::NoSearchOptions) const; 0068 0069 QStringList resourceDirsInternal(const QString &type); 0070 0071 QString saveLocationInternal(const QString &type, const QString &suffix = QString(), bool create = true); 0072 0073 QString locateLocalInternal(const QString &type, const QString &filename, bool createDir = false); 0074 0075 private: 0076 QHash<QString, QStringList> m_absolutes; // For each resource type, the list of absolute paths, from most local (most priority) to most global 0077 QHash<QString, QStringList> m_relatives; // Same with relative paths 0078 }; 0079 0080 void KoResourcePathsImpl::addResourceTypeInternal(const QString &type, const QString &basetype, 0081 const QString &relativename, 0082 bool priority) 0083 { 0084 if (relativename.isEmpty()) return; 0085 0086 QString copy = relativename; 0087 0088 Q_ASSERT(basetype == "data"); 0089 0090 if (!copy.endsWith(QLatin1Char('/'))) { 0091 copy += QLatin1Char('/'); 0092 } 0093 0094 QStringList &rels = m_relatives[type]; // find or insert 0095 0096 if (!rels.contains(copy, cs)) { 0097 if (priority) { 0098 rels.prepend(copy); 0099 } else { 0100 rels.append(copy); 0101 } 0102 } 0103 0104 //qDebug() << "addResourceType: type" << type << "basetype" << basetype << "relativename" << relativename << "priority" << priority << m_relatives[type]; 0105 } 0106 0107 void KoResourcePathsImpl::addResourceDirInternal(const QString &type, const QString &absdir, bool priority) 0108 { 0109 if (absdir.isEmpty() || type.isEmpty()) return; 0110 0111 // find or insert entry in the map 0112 QString copy = absdir; 0113 if (!copy.endsWith(QLatin1Char('/'))) { 0114 copy += QLatin1Char('/'); 0115 } 0116 0117 QStringList &paths = m_absolutes[type]; 0118 if (!paths.contains(copy, cs)) { 0119 if (priority) { 0120 paths.prepend(copy); 0121 } else { 0122 paths.append(copy); 0123 } 0124 } 0125 0126 //qDebug() << "addResourceDir: type" << type << "absdir" << absdir << "priority" << priority << m_absolutes[type]; 0127 } 0128 0129 QString KoResourcePathsImpl::findResourceInternal(const QString &type, const QString &fileName) 0130 { 0131 const QStandardPaths::StandardLocation location = mapTypeToQStandardPaths(type); 0132 QString resource = QStandardPaths::locate(location, fileName, QStandardPaths::LocateFile); 0133 if (resource.isEmpty()) { 0134 foreach(const QString &relative, m_relatives.value(type)) { 0135 resource = QStandardPaths::locate(location, relative + fileName, QStandardPaths::LocateFile); 0136 if (!resource.isEmpty()) { 0137 break; 0138 } 0139 } 0140 } 0141 if (resource.isEmpty()) { 0142 foreach(const QString &absolute, m_absolutes.value(type)) { 0143 const QString filePath = absolute + fileName; 0144 if (QFileInfo::exists(filePath)) { 0145 resource = filePath; 0146 break; 0147 } 0148 } 0149 } 0150 //Q_ASSERT(!resource.isEmpty()); 0151 //qDebug() << "findResource: type" << type << "filename" << fileName << "resource" << resource; 0152 return resource; 0153 } 0154 0155 QStringList KoResourcePathsImpl::findDirsInternal(const QString &type, const QString &relDir) 0156 { 0157 const QStandardPaths::StandardLocation location = mapTypeToQStandardPaths(type); 0158 0159 QStringList dirs = QStandardPaths::locateAll(location, relDir, QStandardPaths::LocateDirectory); 0160 0161 foreach(const QString &relative, m_relatives.value(type)) { 0162 dirs << QStandardPaths::locateAll(location, relative + relDir, QStandardPaths::LocateDirectory); 0163 } 0164 0165 foreach(const QString &absolute, m_absolutes.value(type)) { 0166 const QString dirPath = absolute + relDir; 0167 if (QDir(dirPath).exists()) { 0168 dirs << dirPath; 0169 } 0170 } 0171 0172 //Q_ASSERT(!dirs.isEmpty()); 0173 //qDebug() << "findDirs: type" << type << "relDir" << relDir<< "resource" << dirs; 0174 return dirs; 0175 } 0176 0177 0178 QStringList filesInDir(const QString &startdir, const QString & filter, bool noduplicates, bool recursive) 0179 { 0180 //qDebug() << "filesInDir: startdir" << startdir << "filter" << filter << "noduplicates" << noduplicates << "recursive" << recursive; 0181 QStringList result; 0182 0183 // First the entries in this path 0184 QStringList nameFilters; 0185 nameFilters << filter; 0186 const QStringList fileNames = QDir(startdir).entryList(nameFilters, QDir::Files | QDir::CaseSensitive, QDir::Name); 0187 //qDebug() << "\tFound:" << fileNames.size() << ":" << fileNames; 0188 Q_FOREACH (const QString &fileName, fileNames) { 0189 QString file = startdir + '/' + fileName; 0190 result << file; 0191 } 0192 0193 // And then everything underneath, if recursive is specified 0194 if (recursive) { 0195 const QStringList entries = QDir(startdir).entryList(QDir::Dirs | QDir::NoDotAndDotDot); 0196 Q_FOREACH (const QString &subdir, entries) { 0197 //qDebug() << "\tGoing to look in subdir" << subdir << "of" << startdir; 0198 result << filesInDir(startdir + '/' + subdir, filter, noduplicates, recursive); 0199 } 0200 } 0201 return result; 0202 } 0203 0204 QStringList KoResourcePathsImpl::findAllResourcesInternal(const QString &type, 0205 const QString &_filter, 0206 KoResourcePaths::SearchOptions options) const 0207 { 0208 //qDebug() << "====================================================="; 0209 0210 bool noDuplicates = options & KoResourcePaths::NoDuplicates; 0211 bool recursive = options & KoResourcePaths::Recursive; 0212 0213 //qDebug() << "findAllResources: type" << type << "filter" << _filter << "no dups" << noDuplicates << "recursive" << recursive; 0214 0215 const QStandardPaths::StandardLocation location = mapTypeToQStandardPaths(type); 0216 0217 const QStringList relatives = m_relatives.value(type); 0218 QString filter = _filter; 0219 QString prefix; 0220 0221 // In cases where the filter is like "color-schemes/*.colors" instead of "*.kpp", used with unregistgered resource types 0222 if (filter.indexOf('*') > 0) { 0223 prefix = filter.split('*').first(); 0224 filter = '*' + filter.split('*')[1]; 0225 //qDebug() << "Split up alias" << relatives << "filter" << filter; 0226 } 0227 0228 QStringList resources; 0229 if (relatives.isEmpty()) { 0230 resources << QStandardPaths::locateAll(location, prefix + filter, QStandardPaths::LocateFile); 0231 } 0232 0233 ////qDebug() << "\tresources from qstandardpaths:" << resources.size(); 0234 0235 0236 foreach(const QString &relative, relatives) { 0237 //qDebug() << "\t\relative:" << relative; 0238 const QStringList dirs = QStandardPaths::locateAll(location, relative + prefix, QStandardPaths::LocateDirectory); 0239 QSet<QString> s = QSet<QString>::fromList(dirs); 0240 0241 //qDebug() << "\t\tdirs:" << dirs; 0242 Q_FOREACH (const QString &dir, s) { 0243 resources << filesInDir(dir, filter, noDuplicates, recursive); 0244 } 0245 } 0246 0247 foreach(const QString &absolute, m_absolutes.value(type)) { 0248 const QString dir = absolute + prefix; 0249 if (QDir(dir).exists()) { 0250 resources << filesInDir(dir, filter, noDuplicates, recursive); 0251 } 0252 } 0253 0254 if (noDuplicates) { 0255 QSet<QString> s = QSet<QString>::fromList(resources); 0256 resources = s.toList(); 0257 } 0258 0259 //qDebug() << "\tresources also from aliases:" << resources.size(); 0260 //qDebug() << "====================================================="; 0261 0262 //Q_ASSERT(!resources.isEmpty()); 0263 0264 return resources; 0265 } 0266 0267 QStringList KoResourcePathsImpl::resourceDirsInternal(const QString &type) 0268 { 0269 //return KGlobal::dirs()->resourceDirs(type.toLatin1()); 0270 QStringList resourceDirs; 0271 0272 const QStandardPaths::StandardLocation location = mapTypeToQStandardPaths(type); 0273 foreach(const QString &relative, m_relatives.value(type)) { 0274 resourceDirs << QStandardPaths::locateAll(location, relative, QStandardPaths::LocateDirectory); 0275 } 0276 foreach(const QString &absolute, m_absolutes.value(type)) { 0277 if (QDir(absolute).exists()) { 0278 resourceDirs << absolute; 0279 } 0280 } 0281 //qDebug() << "resourceDirs: type" << type << resourceDirs; 0282 0283 return resourceDirs; 0284 } 0285 0286 QString KoResourcePathsImpl::saveLocationInternal(const QString &type, const QString &suffix, bool create) 0287 { 0288 QString path = QStandardPaths::writableLocation(mapTypeToQStandardPaths(type)) + '/' + suffix; 0289 QDir d(path); 0290 if (!d.exists() && create) { 0291 d.mkpath(path); 0292 } 0293 //qDebug() << "saveLocation: type" << type << "suffix" << suffix << "create" << create << "path" << path; 0294 0295 return path; 0296 } 0297 0298 QString KoResourcePathsImpl::locateLocalInternal(const QString &type, const QString &filename, bool createDir) 0299 { 0300 QString path = saveLocationInternal(type, "", createDir); 0301 //qDebug() << "locateLocal: type" << type << "filename" << filename << "CreateDir" << createDir << "path" << path; 0302 return path + '/' + filename; 0303 } 0304 0305 Q_GLOBAL_STATIC(KoResourcePathsImpl, s_instance); 0306 0307 0308 void KoResourcePaths::addResourceType(const char *type, const char *basetype, 0309 const QString &relativeName, bool priority) 0310 { 0311 s_instance->addResourceTypeInternal(QString::fromLatin1(type), QString::fromLatin1(basetype), relativeName, priority); 0312 } 0313 0314 void KoResourcePaths::addResourceDir(const char *type, const QString &dir, bool priority) 0315 { 0316 s_instance->addResourceDirInternal(QString::fromLatin1(type), dir, priority); 0317 } 0318 0319 QString KoResourcePaths::findResource(const char *type, const QString &fileName) 0320 { 0321 return s_instance->findResourceInternal(QString::fromLatin1(type), fileName); 0322 } 0323 0324 QStringList KoResourcePaths::findDirs(const char *type, const QString &reldir) 0325 { 0326 return s_instance->findDirsInternal(QString::fromLatin1(type), reldir); 0327 } 0328 0329 QStringList KoResourcePaths::findAllResources(const char *type, 0330 const QString &filter, 0331 SearchOptions options) 0332 { 0333 return s_instance->findAllResourcesInternal(QString::fromLatin1(type), filter, options); 0334 } 0335 0336 QStringList KoResourcePaths::resourceDirs(const char *type) 0337 { 0338 return s_instance->resourceDirsInternal(QString::fromLatin1(type)); 0339 } 0340 0341 QString KoResourcePaths::saveLocation(const char *type, const QString &suffix, bool create) 0342 { 0343 return s_instance->saveLocationInternal(QString::fromLatin1(type), suffix, create); 0344 } 0345 0346 QString KoResourcePaths::locate(const char *type, const QString &filename) 0347 { 0348 return s_instance->findResourceInternal(QString::fromLatin1(type), filename); 0349 } 0350 0351 QString KoResourcePaths::locateLocal(const char *type, const QString &filename, bool createDir) 0352 { 0353 return s_instance->locateLocalInternal(QString::fromLatin1(type), filename, createDir); 0354 }