diff --git a/src/libs/utils/fileinprojectfinder.cpp b/src/libs/utils/fileinprojectfinder.cpp index 2be64260e8a..90be2416961 100644 --- a/src/libs/utils/fileinprojectfinder.cpp +++ b/src/libs/utils/fileinprojectfinder.cpp @@ -24,8 +24,11 @@ ****************************************************************************/ #include "fileinprojectfinder.h" + +#include "algorithm.h" #include "fileutils.h" #include "hostosinfo.h" +#include "qrcparser.h" #include "qtcassert.h" #include @@ -102,6 +105,7 @@ void FileInProjectFinder::setProjectFiles(const FileNameList &projectFiles) m_projectFiles = projectFiles; m_cache.clear(); + m_qrcUrlFinder.setProjectFiles(projectFiles); } void FileInProjectFinder::setSysroot(const FileName &sysroot) @@ -140,6 +144,13 @@ QString FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const { qCDebug(finderLog) << "FileInProjectFinder: trying to find file" << fileUrl.toString() << "..."; + if (fileUrl.scheme() == "qrc" || fileUrl.toString().startsWith(':')) { + const QString result = m_qrcUrlFinder.find(fileUrl); + if (success) + *success = !result.isEmpty(); + return result; + } + QString originalPath = fileUrl.toLocalFile(); if (originalPath.isEmpty()) // e.g. qrc:// originalPath = fileUrl.path(); @@ -421,4 +432,34 @@ FileInProjectFinder::PathMappingNode::~PathMappingNode() qDeleteAll(children); } +QString FileInProjectFinder::QrcUrlFinder::find(const QUrl &fileUrl) const +{ + QString result; + const auto fileIt = m_fileCache.constFind(fileUrl); + if (fileIt != m_fileCache.cend()) + return fileIt.value(); + for (const FileName &f : m_allQrcFiles) { + QrcParser::Ptr &qrcParser = m_parserCache[f]; + if (!qrcParser) + qrcParser = QrcParser::parseQrcFile(f.toString(), QString()); + if (!qrcParser->isValid()) + continue; + QStringList hits; + qrcParser->collectFilesAtPath(QrcParser::normalizedQrcFilePath(fileUrl.toString()), &hits); + if (!hits.empty()) { + result = hits.first(); + break; + } + } + m_fileCache.insert(fileUrl, result); + return result; +} + +void FileInProjectFinder::QrcUrlFinder::setProjectFiles(const FileNameList &projectFiles) +{ + m_allQrcFiles = filtered(projectFiles, [](const FileName &f) { return f.endsWith(".qrc"); }); + m_fileCache.clear(); + m_parserCache.clear(); +} + } // namespace Utils diff --git a/src/libs/utils/fileinprojectfinder.h b/src/libs/utils/fileinprojectfinder.h index 43a954ff930..2b1dc940902 100644 --- a/src/libs/utils/fileinprojectfinder.h +++ b/src/libs/utils/fileinprojectfinder.h @@ -29,11 +29,13 @@ #include #include +#include #include QT_FORWARD_DECLARE_CLASS(QUrl) namespace Utils { +class QrcParser; class QTCREATOR_UTILS_EXPORT FileInProjectFinder { @@ -73,6 +75,16 @@ private: int matchLength = 0; }; + class QrcUrlFinder { + public: + QString find(const QUrl &fileUrl) const; + void setProjectFiles(const FileNameList &projectFiles); + private: + FileNameList m_allQrcFiles; + mutable QHash m_fileCache; + mutable QHash> m_parserCache; + }; + CacheEntry findInSearchPaths(const QString &filePath, FileHandler fileHandler, DirectoryHandler directoryHandler) const; static CacheEntry findInSearchPath(const QString &searchPath, const QString &filePath, @@ -93,6 +105,7 @@ private: PathMappingNode m_pathMapRoot; mutable QHash m_cache; + QrcUrlFinder m_qrcUrlFinder; }; } // namespace Utils