QML: Warn about relative QRC path
A runtime warning will now be issued if a relative QRC path is passed: a relative QRC path doesn't make a lot of sense, but it works to some extent (therefore it's only a warning). Task-number: QTCREATORBUG-32198 Change-Id: Ifd55013d01589149128ce5d3b31fd6748186fd05 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
parent
c27daa01f5
commit
bfdadbac48
|
@ -11,6 +11,8 @@
|
|||
#include <QtQml/private/qqmldirdata_p.h>
|
||||
#include <QtQml/private/qqmlfileselector_p.h>
|
||||
|
||||
using namespace Qt::Literals::StringLiterals;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QQmlApplicationEnginePrivate::QQmlApplicationEnginePrivate(QQmlEngine *e)
|
||||
|
@ -85,18 +87,19 @@ void QQmlApplicationEnginePrivate::_q_loadTranslations()
|
|||
#endif
|
||||
}
|
||||
|
||||
static QString translationsDirectoryFromLocalUrl(const QUrl &url)
|
||||
{
|
||||
QFileInfo fi(QQmlFile::urlToLocalFileOrQrc(url));
|
||||
return fi.path() + "/i18n"_L1;
|
||||
}
|
||||
|
||||
void QQmlApplicationEnginePrivate::startLoad(const QUrl &url, const QByteArray &data, bool dataFlag)
|
||||
{
|
||||
Q_Q(QQmlApplicationEngine);
|
||||
|
||||
ensureInitialized();
|
||||
|
||||
if (url.scheme() == QLatin1String("file") || url.scheme() == QLatin1String("qrc")) {
|
||||
QFileInfo fi(QQmlFile::urlToLocalFileOrQrc(url));
|
||||
translationsDirectory = fi.path() + QLatin1String("/i18n");
|
||||
} else {
|
||||
translationsDirectory.clear();
|
||||
}
|
||||
updateTranslationDirectory(url);
|
||||
|
||||
_q_loadTranslations(); //Translations must be loaded before the QML file is
|
||||
QQmlComponent *c = new QQmlComponent(q, q);
|
||||
|
@ -125,12 +128,9 @@ void QQmlApplicationEnginePrivate::startLoad(QAnyStringView uri, QAnyStringView
|
|||
if (type.sourceUrl().isValid()) {
|
||||
const auto qmlDirData = typeLoader.getQmldir(type.sourceUrl());
|
||||
const QUrl url = qmlDirData->finalUrl();
|
||||
if (url.scheme() == QLatin1String("file") || url.scheme() == QLatin1String("qrc")) {
|
||||
QFileInfo fi(QQmlFile::urlToLocalFileOrQrc(url));
|
||||
translationsDirectory = fi.path() + QLatin1String("/i18n");
|
||||
} else {
|
||||
translationsDirectory.clear();
|
||||
}
|
||||
// A QRC URL coming from a qmldir cannot contain a relative path
|
||||
Q_ASSERT(url.scheme() != "qrc"_L1 || url.path().startsWith('/'_L1));
|
||||
updateTranslationDirectory(url);
|
||||
}
|
||||
|
||||
/* Translations must be loaded before the QML file. They require translationDirectory to
|
||||
|
@ -188,6 +188,18 @@ void QQmlApplicationEnginePrivate::ensureLoadingFinishes(QQmlComponent *c)
|
|||
QObject::connect(c, &QQmlComponent::statusChanged, q, [this, c] { this->finishLoad(c); });
|
||||
}
|
||||
|
||||
void QQmlApplicationEnginePrivate::updateTranslationDirectory(const QUrl &url)
|
||||
{
|
||||
const QString scheme = url.scheme();
|
||||
if (scheme == "file"_L1) {
|
||||
translationsDirectory = translationsDirectoryFromLocalUrl(url);
|
||||
} else if (scheme == "qrc"_L1) {
|
||||
translationsDirectory = translationsDirectoryFromLocalUrl(url);
|
||||
} else {
|
||||
translationsDirectory.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QQmlApplicationEngine
|
||||
\since 5.1
|
||||
|
|
|
@ -39,6 +39,8 @@ public:
|
|||
void _q_loadTranslations();
|
||||
void finishLoad(QQmlComponent *component);
|
||||
void ensureLoadingFinishes(QQmlComponent *component);
|
||||
void updateTranslationDirectory(const QUrl &url);
|
||||
|
||||
QList<QObject *> objects;
|
||||
QVariantMap initialProperties;
|
||||
QStringList extraFileSelectors;
|
||||
|
|
|
@ -797,6 +797,12 @@ void QQmlComponentPrivate::loadUrl(const QUrl &newUrl, QQmlComponent::Compilatio
|
|||
m_url = newUrl;
|
||||
}
|
||||
|
||||
if (m_url.scheme() == "qrc"_L1 && !m_url.path().startsWith("/"_L1)) {
|
||||
qWarning().nospace().noquote()
|
||||
<< "QQmlComponent: attempted to load via a relative URL '" << m_url.toString()
|
||||
<< "' in resource file system. This is not fully supported and may not work";
|
||||
}
|
||||
|
||||
if (newUrl.isEmpty()) {
|
||||
QQmlError error;
|
||||
error.setDescription(QQmlComponent::tr("Invalid empty URL"));
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include <QDebug>
|
||||
#include <QtQuickTestUtils/private/qmlutils_p.h>
|
||||
|
||||
using namespace Qt::Literals::StringLiterals;
|
||||
|
||||
class tst_qqmlapplicationengine : public QQmlDataTest
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -33,6 +35,7 @@ private slots:
|
|||
void translationChange();
|
||||
void setInitialProperties();
|
||||
void failureToLoadTriggersWarningSignal();
|
||||
void relativeQrcPathTriggersWarningSignal();
|
||||
void errorWhileCreating();
|
||||
void createWithQrcPath();
|
||||
|
||||
|
@ -370,6 +373,24 @@ void tst_qqmlapplicationengine::failureToLoadTriggersWarningSignal()
|
|||
QTRY_COMPARE(warningObserver.size(), 1);
|
||||
}
|
||||
|
||||
void tst_qqmlapplicationengine::relativeQrcPathTriggersWarningSignal()
|
||||
{
|
||||
const auto url = QUrl("qrc:main.qml");
|
||||
qRegisterMetaType<QList<QQmlError>>();
|
||||
QTest::ignoreMessage(QtMsgType::QtWarningMsg, "QQmlApplicationEngine failed to load component");
|
||||
QTest::ignoreMessage(
|
||||
QtMsgType::QtWarningMsg,
|
||||
"QQmlComponent: attempted to load via a relative URL '%1' in resource file system. "
|
||||
"This is not fully supported and may not work"_L1.arg(url.toString())
|
||||
.toLocal8Bit()
|
||||
.data());
|
||||
QTest::ignoreMessage(QtMsgType::QtWarningMsg, "qrc:main.qml: No such file or directory");
|
||||
QQmlApplicationEngine test;
|
||||
const QSignalSpy warningObserver(&test, &QQmlApplicationEngine::warnings);
|
||||
test.load(url);
|
||||
QTRY_COMPARE(warningObserver.size(), 1);
|
||||
}
|
||||
|
||||
void tst_qqmlapplicationengine::errorWhileCreating()
|
||||
{
|
||||
auto url = testFileUrl("requiredViolation.qml");
|
||||
|
|
|
@ -151,6 +151,7 @@ private slots:
|
|||
void loadFromModuleRequired();
|
||||
void loadUrlRequired();
|
||||
void loadFromQrc();
|
||||
void loadFromRelativeQrcPath();
|
||||
void removeBinding();
|
||||
void complexObjectArgument();
|
||||
void bindingEvaluationOrder();
|
||||
|
@ -1636,6 +1637,20 @@ void tst_qqmlcomponent::loadFromQrc()
|
|||
QVERIFY(p->compilationUnit()->baseCompilationUnit()->aotCompiledFunctions);
|
||||
}
|
||||
|
||||
void tst_qqmlcomponent::loadFromRelativeQrcPath()
|
||||
{
|
||||
QQmlEngine e;
|
||||
QQmlComponent c(&e);
|
||||
const QUrl url = QUrl("qrc:main.qml");
|
||||
QTest::ignoreMessage(
|
||||
QtMsgType::QtWarningMsg,
|
||||
"QQmlComponent: attempted to load via a relative URL '%1' in resource file system. "
|
||||
"This is not fully supported and may not work"_L1.arg(url.toString())
|
||||
.toLocal8Bit()
|
||||
.data());
|
||||
c.loadUrl(url);
|
||||
}
|
||||
|
||||
void tst_qqmlcomponent::removeBinding()
|
||||
{
|
||||
QQmlEngine e;
|
||||
|
|
|
@ -33,6 +33,7 @@ private slots:
|
|||
void fromModuleCtor();
|
||||
void loadFromModule_data();
|
||||
void loadFromModule();
|
||||
void setSourceRelativeQrcPath();
|
||||
void overlay();
|
||||
};
|
||||
|
||||
|
@ -343,6 +344,20 @@ void tst_QQuickView::loadFromModule()
|
|||
QCOMPARE(view.source(), url);
|
||||
}
|
||||
|
||||
void tst_QQuickView::setSourceRelativeQrcPath()
|
||||
{
|
||||
QQuickView view;
|
||||
const auto url = QUrl("qrc:main.qml");
|
||||
QTest::ignoreMessage(
|
||||
QtMsgType::QtWarningMsg,
|
||||
"QQmlComponent: attempted to load via a relative URL '%1' in resource file system. "
|
||||
"This is not fully supported and may not work"_L1.arg(url.toString())
|
||||
.toLocal8Bit()
|
||||
.data());
|
||||
QTest::ignoreMessage(QtMsgType::QtWarningMsg, "qrc:main.qml: No such file or directory");
|
||||
view.setSource(url);
|
||||
}
|
||||
|
||||
void tst_QQuickView::overlay()
|
||||
{
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
|
|
Loading…
Reference in New Issue