| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the QtQml module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "resourcefilemapper.h" |
| |
| #include <QFileInfo> |
| #include <QDir> |
| #include <QXmlStreamReader> |
| |
| ResourceFileMapper::ResourceFileMapper(const QStringList &resourceFiles) |
| { |
| for (const QString &fileName: resourceFiles) { |
| QFile f(fileName); |
| if (!f.open(QIODevice::ReadOnly)) |
| continue; |
| populateFromQrcFile(f); |
| } |
| } |
| |
| bool ResourceFileMapper::isEmpty() const |
| { |
| return qrcPathToFileSystemPath.isEmpty(); |
| } |
| |
| QStringList ResourceFileMapper::resourcePaths(const QString &fileName) |
| { |
| const QString absPath = QDir::cleanPath(QDir::current().absoluteFilePath(fileName)); |
| QStringList resourcePaths; |
| for (auto it = qrcPathToFileSystemPath.cbegin(), end = qrcPathToFileSystemPath.cend(); it != end; ++it) { |
| if (QFileInfo(it.value()) == QFileInfo(absPath)) |
| resourcePaths.append(it.key()); |
| } |
| return resourcePaths; |
| } |
| |
| QStringList ResourceFileMapper::qmlCompilerFiles(FileOutput fo) const |
| { |
| QStringList files; |
| for (auto it = qrcPathToFileSystemPath.constBegin(), end = qrcPathToFileSystemPath.constEnd(); |
| it != end; ++it) { |
| const QString &qrcPath = it.key(); |
| const QString suffix = QFileInfo(qrcPath).suffix(); |
| if (suffix != QStringLiteral("qml") && suffix != QStringLiteral("js") && suffix != QStringLiteral("mjs")) |
| continue; |
| if (fo == FileOutput::AbsoluteFilePath) |
| files << it.value(); |
| else |
| files << qrcPath; |
| } |
| return files; |
| } |
| |
| void ResourceFileMapper::populateFromQrcFile(QFile &file) |
| { |
| enum State { |
| InitialState, |
| InRCC, |
| InResource, |
| InFile |
| }; |
| State state = InitialState; |
| |
| QDir qrcDir = QFileInfo(file).absoluteDir(); |
| |
| QString prefix; |
| QString currentFileName; |
| QXmlStreamAttributes currentFileAttributes; |
| |
| QXmlStreamReader reader(&file); |
| while (!reader.atEnd()) { |
| switch (reader.readNext()) { |
| case QXmlStreamReader::StartElement: |
| if (reader.name() == QStringLiteral("RCC")) { |
| if (state != InitialState) |
| return; |
| state = InRCC; |
| continue; |
| } else if (reader.name() == QStringLiteral("qresource")) { |
| if (state != InRCC) |
| return; |
| state = InResource; |
| QXmlStreamAttributes attributes = reader.attributes(); |
| if (attributes.hasAttribute(QStringLiteral("prefix"))) |
| prefix = attributes.value(QStringLiteral("prefix")).toString(); |
| if (!prefix.startsWith(QLatin1Char('/'))) |
| prefix.prepend(QLatin1Char('/')); |
| if (!prefix.endsWith(QLatin1Char('/'))) |
| prefix.append(QLatin1Char('/')); |
| continue; |
| } else if (reader.name() == QStringLiteral("file")) { |
| if (state != InResource) |
| return; |
| state = InFile; |
| currentFileAttributes = reader.attributes(); |
| continue; |
| } |
| return; |
| |
| case QXmlStreamReader::EndElement: |
| if (reader.name() == QStringLiteral("file")) { |
| if (state != InFile) |
| return; |
| state = InResource; |
| continue; |
| } else if (reader.name() == QStringLiteral("qresource")) { |
| if (state != InResource) |
| return; |
| state = InRCC; |
| continue; |
| } else if (reader.name() == QStringLiteral("RCC")) { |
| if (state != InRCC) |
| return; |
| state = InitialState; |
| continue; |
| } |
| return; |
| |
| case QXmlStreamReader::Characters: { |
| if (reader.isWhitespace()) |
| break; |
| if (state != InFile) |
| return; |
| currentFileName = reader.text().toString(); |
| if (currentFileName.isEmpty()) |
| continue; |
| |
| const QString fsPath = QDir::cleanPath(qrcDir.absoluteFilePath(currentFileName)); |
| |
| if (currentFileAttributes.hasAttribute(QStringLiteral("alias"))) |
| currentFileName = currentFileAttributes.value(QStringLiteral("alias")).toString(); |
| |
| currentFileName = QDir::cleanPath(currentFileName); |
| while (currentFileName.startsWith(QLatin1String("../"))) |
| currentFileName.remove(0, 3); |
| |
| const QString qrcPath = prefix + currentFileName; |
| if (QFile::exists(fsPath)) |
| qrcPathToFileSystemPath.insert(qrcPath, fsPath); |
| continue; |
| } |
| |
| default: break; |
| } |
| } |
| } |