blob: b9cf463575a8b389e463c17d0a976dc17896166f [file] [log] [blame]
/****************************************************************************
**
** 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;
}
}
}