forked from qt-creator/qt-creator
QML Puppet: Support for absolute QRC paths
Enabled support for absolute QRC paths, e.g.: * qrc:path/to/some/file * qrc:/path/to/some/file * /path/to/some/file The QRC paths are mapped to the actual file system path in QML Puppet via the environment variable QMLPUPPET_PROJECT_ROOT. A bit of refactoring so that QML Puppet and QML Runtime share some common pieces of code. Fixes: QDS-15385 Change-Id: I3b549eae5700493a3ea654660dbe7d94b4e5b6de Reviewed-by: Knud Dollereder <knud.dollereder@qt.io>
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <extensionsystem/pluginspec.h>
|
||||
#include <projectexplorer/kit.h>
|
||||
#include <projectexplorer/projectmanager.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <qmlprojectmanager/qmlmultilanguageaspect.h>
|
||||
#include <qmlprojectmanager/qmlproject.h>
|
||||
@@ -55,7 +56,7 @@ QProcessEnvironment PuppetEnvironmentBuilder::processEnvironment() const
|
||||
addCustomFileSelectors();
|
||||
addDisableDeferredProperties();
|
||||
addResolveUrlsOnAssignment();
|
||||
addMcuFonts();
|
||||
addMcuItems();
|
||||
|
||||
qCInfo(puppetEnvirmentBuild) << "Puppet environment:" << m_environment.toStringList();
|
||||
|
||||
@@ -254,6 +255,19 @@ void PuppetEnvironmentBuilder::addResolveUrlsOnAssignment() const
|
||||
m_environment.set("QML_COMPAT_RESOLVE_URLS_ON_ASSIGNMENT", "true");
|
||||
}
|
||||
|
||||
void PuppetEnvironmentBuilder::addMcuItems() const
|
||||
{
|
||||
if (QmlDesigner::DesignerMcuManager::instance().isMCUProject()) {
|
||||
addMcuFonts();
|
||||
|
||||
const Utils::FilePath projectRoot = ProjectExplorer::ProjectManager::startupProject()
|
||||
->projectFilePath()
|
||||
.parentDir();
|
||||
m_environment.set(QmlProjectManager::Constants::QMLPUPPET_ENV_PROJECT_ROOT,
|
||||
projectRoot.toUserOutput());
|
||||
}
|
||||
}
|
||||
|
||||
void PuppetEnvironmentBuilder::addMcuFonts() const
|
||||
{
|
||||
const Utils::expected_str<Utils::FilePath> mcuFontsDir = QmlProjectManager::mcuFontsDir();
|
||||
@@ -265,11 +279,9 @@ void PuppetEnvironmentBuilder::addMcuFonts() const
|
||||
|
||||
m_environment.set(QmlProjectManager::Constants::QMLPUPPET_ENV_MCU_FONTS_DIR,
|
||||
mcuFontsDir->toUserOutput());
|
||||
if (QmlDesigner::DesignerMcuManager::instance().isMCUProject()) {
|
||||
const QString defaultFontFamily = DesignerMcuManager::defaultFontFamilyMCU();
|
||||
m_environment.set(QmlProjectManager::Constants::QMLPUPPET_ENV_DEFAULT_FONT_FAMILY,
|
||||
defaultFontFamily);
|
||||
}
|
||||
const QString defaultFontFamily = DesignerMcuManager::defaultFontFamilyMCU();
|
||||
m_environment.set(QmlProjectManager::Constants::QMLPUPPET_ENV_DEFAULT_FONT_FAMILY,
|
||||
defaultFontFamily);
|
||||
}
|
||||
|
||||
PuppetType PuppetEnvironmentBuilder::determinePuppetType() const
|
||||
|
@@ -51,6 +51,7 @@ private:
|
||||
void addCustomFileSelectors() const;
|
||||
void addDisableDeferredProperties() const;
|
||||
void addResolveUrlsOnAssignment() const;
|
||||
void addMcuItems() const;
|
||||
void addMcuFonts() const;
|
||||
|
||||
private:
|
||||
|
@@ -702,14 +702,19 @@ Utils::EnvironmentItems QmlBuildSystem::environment() const
|
||||
{
|
||||
Utils::EnvironmentItems env = m_projectItem->environment();
|
||||
|
||||
Utils::expected_str<Utils::FilePath> fontsDir = mcuFontsDir();
|
||||
if (!fontsDir) {
|
||||
qWarning() << "Failed to locate MCU installation." << fontsDir.error();
|
||||
return env;
|
||||
}
|
||||
|
||||
env.append({Constants::QMLPUPPET_ENV_MCU_FONTS_DIR, fontsDir->toUserOutput()});
|
||||
if (qtForMCUs()) {
|
||||
const Utils::FilePath projectRoot = ProjectExplorer::ProjectManager::startupProject()
|
||||
->projectFilePath()
|
||||
.parentDir();
|
||||
env.append({Constants::QMLPUPPET_ENV_PROJECT_ROOT, projectRoot.toUserOutput()});
|
||||
|
||||
Utils::expected_str<Utils::FilePath> fontsDir = mcuFontsDir();
|
||||
if (!fontsDir) {
|
||||
qWarning() << "Failed to locate MCU installation." << fontsDir.error();
|
||||
return env;
|
||||
}
|
||||
|
||||
env.append({Constants::QMLPUPPET_ENV_MCU_FONTS_DIR, fontsDir->toUserOutput()});
|
||||
env.append({Constants::QMLPUPPET_ENV_DEFAULT_FONT_FAMILY, defaultFontFamilyMCU()});
|
||||
}
|
||||
|
||||
|
@@ -46,5 +46,6 @@ constexpr char FALLBACK_MCU_FONT_FAMILY[] = "DejaVu Sans";
|
||||
// These constants should be kept in sync with their counterparts in qmlbase.h
|
||||
constexpr char QMLPUPPET_ENV_MCU_FONTS_DIR[] = "QMLPUPPET_MCU_FONTS_DIR";
|
||||
constexpr char QMLPUPPET_ENV_DEFAULT_FONT_FAMILY[] = "QMLPUPPET_DEFAULT_FONT_FAMILY";
|
||||
constexpr char QMLPUPPET_ENV_PROJECT_ROOT[] = "QMLPUPPET_PROJECT_ROOT";
|
||||
|
||||
} // QmlProjectManager::Constants
|
||||
|
@@ -40,7 +40,7 @@ add_qtc_executable(qmlpuppet
|
||||
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
SOURCES
|
||||
qmlpuppet/qmlpuppetmain.cpp
|
||||
qmlpuppet/qmlbase.h
|
||||
qmlpuppet/qmlbase.h qmlpuppet/qmlbase.cpp
|
||||
qmlpuppet/qmlpuppet.h qmlpuppet/qmlpuppet.cpp
|
||||
qmlpuppet/configcrashpad.h
|
||||
qmlpuppet.qrc
|
||||
|
@@ -3,8 +3,9 @@
|
||||
|
||||
#include "qmlprivategate.h"
|
||||
|
||||
#include <objectnodeinstance.h>
|
||||
#include <nodeinstanceserver.h>
|
||||
#include <objectnodeinstance.h>
|
||||
#include <qmlpuppet/qmlbase.h>
|
||||
|
||||
#include <QQuickItem>
|
||||
#include <QQmlComponent>
|
||||
@@ -43,7 +44,89 @@
|
||||
#include <private/qquick3drepeater_p.h>
|
||||
#endif
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
using namespace Qt::Literals::StringLiterals;
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
||||
using EngineHandler = std::unique_ptr<QAbstractFileEngine>;
|
||||
#else
|
||||
using EngineHandler = QAbstractFileEngine *;
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
QString qmlDesignerRCPath()
|
||||
{
|
||||
static const QString qmlDesignerRcPathsString = QString::fromLocal8Bit(
|
||||
qgetenv("QMLDESIGNER_RC_PATHS"));
|
||||
return qmlDesignerRcPathsString;
|
||||
}
|
||||
|
||||
QString fixResourcePath(QString path, const QString &before, const QString &after)
|
||||
{
|
||||
path.replace(path.indexOf(before), before.length(), after);
|
||||
return path;
|
||||
}
|
||||
|
||||
EngineHandler makeNormalizedPathEngineHandler(QString path)
|
||||
{
|
||||
path.replace("//", "/");
|
||||
path.replace('\\', '/');
|
||||
return EngineHandler{new QFSFileEngine(path)};
|
||||
}
|
||||
|
||||
std::optional<EngineHandler> tryMakeEngineHandler(QString fixedPath)
|
||||
{
|
||||
// It turns out that `QFileInfo::exists` uses `QAbstractFileHandler` internally, so we cannot
|
||||
// call it inside `QAbstractFileHandler::create` (directly or indirectly), otherwise it creates
|
||||
// infinite recursion. `std::filesystem::exists` is fine though.
|
||||
if (std::filesystem::exists(fixedPath.toStdString())) {
|
||||
return makeNormalizedPathEngineHandler(std::move(fixedPath));
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<EngineHandler> tryMakeEngineHandlerWithProjectRoot(
|
||||
const QString &fileName, const QString &prefix)
|
||||
{
|
||||
if (const auto projectRoot = QString::fromLocal8Bit(
|
||||
qgetenv(QmlBase::QMLPUPPET_ENV_PROJECT_ROOT));
|
||||
!projectRoot.isEmpty()) {
|
||||
QString fixedPath = fixResourcePath(fileName, prefix, projectRoot + '/');
|
||||
if (auto handler = tryMakeEngineHandler(std::move(fixedPath))) {
|
||||
return std::move(*handler);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
EngineHandler makeQrcResourceHandler(const QString &fileName, const QString &prefix)
|
||||
{
|
||||
const QStringList searchPaths = qmlDesignerRCPath().split(';', Qt::SkipEmptyParts);
|
||||
for (const QString &qrcPath : searchPaths) {
|
||||
const QStringList qrcDefintion = qrcPath.split('=');
|
||||
if (qrcDefintion.count() == 2) {
|
||||
QString fixedPath
|
||||
= fixResourcePath(fileName, prefix + qrcDefintion.first(), qrcDefintion.last() + '/');
|
||||
if (auto handler = tryMakeEngineHandler(std::move(fixedPath))) {
|
||||
return std::move(*handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If none of the user-defined mappings above worked, let's try the path relative
|
||||
// to the project root.
|
||||
if (auto handler = tryMakeEngineHandlerWithProjectRoot(fileName, prefix)) {
|
||||
return std::move(*handler);
|
||||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
@@ -568,13 +651,6 @@ QObject *createPrimitive(const QString &typeName, int majorNumber, int minorNumb
|
||||
return QQuickDesignerSupportItems::createPrimitive(typeName, revision, context);
|
||||
}
|
||||
|
||||
static QString qmlDesignerRCPath()
|
||||
{
|
||||
static const QString qmlDesignerRcPathsString = QString::fromLocal8Bit(
|
||||
qgetenv("QMLDESIGNER_RC_PATHS"));
|
||||
return qmlDesignerRcPathsString;
|
||||
}
|
||||
|
||||
QVariant fixResourcePaths(const QVariant &value)
|
||||
{
|
||||
if (value.typeId() == QMetaType::QUrl) {
|
||||
@@ -582,13 +658,20 @@ QVariant fixResourcePaths(const QVariant &value)
|
||||
if (url.scheme() == QLatin1String("qrc")) {
|
||||
const QString path = QLatin1String("qrc:") + url.path();
|
||||
if (!qmlDesignerRCPath().isEmpty()) {
|
||||
const QStringList searchPaths = qmlDesignerRCPath().split(QLatin1Char(';'));
|
||||
const QStringList searchPaths
|
||||
= qmlDesignerRCPath().split(QLatin1Char(';'), Qt::SkipEmptyParts);
|
||||
for (const QString &qrcPath : searchPaths) {
|
||||
const QStringList qrcDefintion = qrcPath.split(QLatin1Char('='));
|
||||
if (qrcDefintion.count() == 2) {
|
||||
QString fixedPath = path;
|
||||
fixedPath.replace(QLatin1String("qrc:") + qrcDefintion.first(), qrcDefintion.last() + QLatin1Char('/'));
|
||||
if (QFileInfo::exists(fixedPath)) {
|
||||
fixedPath.replace(
|
||||
QLatin1String("qrc:") + qrcDefintion.first(),
|
||||
qrcDefintion.last() + QLatin1Char('/'));
|
||||
// It turns out that `QFileInfo::exists` uses `QAbstractFileHandler`
|
||||
// internally, so we cannot call it inside `QAbstractFileHandler::create`
|
||||
// (directly or indirectly), otherwise it creates infinite recursion.
|
||||
// `std::filesystem::exists` is fine though.
|
||||
if (std::filesystem::exists(fixedPath.toStdString())) {
|
||||
fixedPath.replace(QLatin1String("//"), QLatin1String("/"));
|
||||
fixedPath.replace(QLatin1Char('\\'), QLatin1Char('/'));
|
||||
return QUrl::fromLocalFile(fixedPath);
|
||||
@@ -936,43 +1019,38 @@ public:
|
||||
#endif
|
||||
};
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
||||
std::unique_ptr<QAbstractFileEngine>
|
||||
#else
|
||||
QAbstractFileEngine *
|
||||
#endif
|
||||
QrcEngineHandler::create(const QString &fileName) const
|
||||
EngineHandler QrcEngineHandler::create(const QString &fileName) const
|
||||
{
|
||||
if (fileName.startsWith(":/qt-project.org"))
|
||||
if (fileName.startsWith(":/qt-project.org") || fileName.startsWith("qrc:/qt-project.org"))
|
||||
return {};
|
||||
|
||||
if (fileName.startsWith(":/qtquickplugin"))
|
||||
if (fileName.startsWith(":/qtquickplugin") || fileName.startsWith("qrc:/qtquickplugin"))
|
||||
return {};
|
||||
|
||||
if (fileName.startsWith(":/")) {
|
||||
const QStringList searchPaths = qmlDesignerRCPath().split(';');
|
||||
for (const QString &qrcPath : searchPaths) {
|
||||
const QStringList qrcDefintion = qrcPath.split('=');
|
||||
if (qrcDefintion.count() == 2) {
|
||||
QString fixedPath = fileName;
|
||||
fixedPath.replace(":" + qrcDefintion.first(), qrcDefintion.last() + '/');
|
||||
|
||||
if (fileName == fixedPath)
|
||||
return {};
|
||||
|
||||
if (QFileInfo::exists(fixedPath)) {
|
||||
fixedPath.replace("//", "/");
|
||||
fixedPath.replace('\\', '/');
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
||||
return std::make_unique<QFSFileEngine>(fixedPath);
|
||||
#else
|
||||
return new QFSFileEngine(fixedPath);
|
||||
#endif
|
||||
}
|
||||
for (const auto &scheme : {QString::fromLatin1(":"), QString::fromLatin1("qrc:")}) {
|
||||
for (const auto &prefix : {QString{scheme + '/'}, scheme}) {
|
||||
if (fileName.startsWith(prefix)) {
|
||||
return makeQrcResourceHandler(fileName, prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fileName.startsWith('/')) {
|
||||
// On UNIX it might be a valid filesystem path
|
||||
#if !defined(Q_OS_WIN)
|
||||
// It turns out that `QFileInfo::exists` uses `QAbstractFileHandler` internally,
|
||||
// so we cannot call it inside `QAbstractFileHandler::create` (directly or indirectly),
|
||||
// otherwise it creates infinite recursion. `std::filesystem::exists` is fine though.
|
||||
if (std::filesystem::exists(fileName.toStdString())) {
|
||||
return {};
|
||||
}
|
||||
#endif
|
||||
|
||||
if (auto handler = tryMakeEngineHandlerWithProjectRoot(fileName, "/")) {
|
||||
return std::move(*handler);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@@ -313,10 +313,6 @@ void NodeInstanceServer::stopRenderTimer()
|
||||
void NodeInstanceServer::createScene(const CreateSceneCommand &command)
|
||||
{
|
||||
initializeView();
|
||||
if (const QString mcuFontsFolder = qEnvironmentVariable(QmlBase::QMLPUPPET_ENV_MCU_FONTS_DIR);
|
||||
!mcuFontsFolder.isEmpty()) {
|
||||
registerFonts(QUrl::fromLocalFile(mcuFontsFolder));
|
||||
}
|
||||
registerFonts(command.resourceUrl);
|
||||
setTranslationLanguage(command.language);
|
||||
|
||||
@@ -1581,11 +1577,7 @@ void NodeInstanceServer::registerFonts(const QUrl &resourceUrl) const
|
||||
if (!resourceUrl.isValid())
|
||||
return;
|
||||
|
||||
// Autoregister all fonts found inside the project
|
||||
QDirIterator it {QFileInfo(resourceUrl.toLocalFile()).absoluteFilePath(),
|
||||
{"*.ttf", "*.otf"}, QDir::Files, QDirIterator::Subdirectories};
|
||||
while (it.hasNext())
|
||||
QFontDatabase::addApplicationFont(it.next());
|
||||
QmlBase::registerFonts(resourceUrl.toLocalFile());
|
||||
}
|
||||
|
||||
bool NodeInstanceServer::isInformationServer() const
|
||||
|
101
src/tools/qmlpuppet/qmlpuppet/qmlbase.cpp
Normal file
101
src/tools/qmlpuppet/qmlpuppet/qmlbase.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "qmlbase.h"
|
||||
#include "qmlprivategate/qmlprivategate.h"
|
||||
|
||||
#include <QCommandLineOption>
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QFileInfo>
|
||||
#include <QFont>
|
||||
#include <QFontDatabase>
|
||||
#include <QGuiApplication>
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
#include <QtEnvironmentVariables>
|
||||
#include <QtLogging>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
QmlBase::QmlBase(int &argc, char **argv, QObject *parent)
|
||||
: QObject{parent}
|
||||
, m_args({.argc = argc, .argv = argv})
|
||||
{
|
||||
m_argParser.setApplicationDescription("QML Runtime Provider for QDS");
|
||||
m_argParser.addOption({"qml-puppet", "Run QML Puppet (default)"});
|
||||
m_argParser.addOption({"qml-renderer", "Run QML Renderer"});
|
||||
#ifdef ENABLE_INTERNAL_QML_RUNTIME
|
||||
m_argParser.addOption({"qml-runtime", "Run QML Runtime"});
|
||||
#endif
|
||||
m_argParser.addOption({"test", "Run test mode"});
|
||||
}
|
||||
|
||||
int QmlBase::startTestMode()
|
||||
{
|
||||
qDebug() << "Test mode is not implemented for this type of runner";
|
||||
return 0;
|
||||
}
|
||||
|
||||
void QmlBase::initQmlRunner()
|
||||
{
|
||||
QmlDesigner::Internal::QmlPrivateGate::registerFixResourcePathsForObjectCallBack();
|
||||
|
||||
if (const QString defaultFontFamily = qEnvironmentVariable(QMLPUPPET_ENV_DEFAULT_FONT_FAMILY);
|
||||
!defaultFontFamily.isEmpty()) {
|
||||
if (qobject_cast<QGuiApplication *>(QCoreApplication::instance()) != nullptr) {
|
||||
QGuiApplication::setFont(QFont{defaultFontFamily});
|
||||
}
|
||||
}
|
||||
|
||||
if (const QString mcuFontsFolder = qEnvironmentVariable(QMLPUPPET_ENV_MCU_FONTS_DIR);
|
||||
!mcuFontsFolder.isEmpty()) {
|
||||
registerFonts(mcuFontsFolder);
|
||||
}
|
||||
}
|
||||
|
||||
int QmlBase::run()
|
||||
{
|
||||
populateParser();
|
||||
initCoreApp();
|
||||
|
||||
if (!m_coreApp) { //default to QGuiApplication
|
||||
createCoreApp<QGuiApplication>();
|
||||
qWarning() << "CoreApp is not initialized! Falling back to QGuiApplication!";
|
||||
}
|
||||
|
||||
initParser();
|
||||
initQmlRunner();
|
||||
return QCoreApplication::exec();
|
||||
}
|
||||
|
||||
void QmlBase::initParser()
|
||||
{
|
||||
const QCommandLineOption optHelp = m_argParser.addHelpOption();
|
||||
|
||||
if (!m_argParser.parse(QCoreApplication::arguments())) {
|
||||
std::cout << "Error: " << m_argParser.errorText().toStdString() << "\n";
|
||||
if (m_argParser.errorText().contains("qml-runtime")) {
|
||||
std::cout << "Note: --qml-runtime is only available when Qt is 6.4.x or higher\n";
|
||||
}
|
||||
std::cout << "\n";
|
||||
|
||||
m_argParser.showHelp(1);
|
||||
} else if (m_argParser.isSet(optHelp)) {
|
||||
m_argParser.showHelp(0);
|
||||
} else if (m_argParser.isSet("test")) {
|
||||
exit(startTestMode());
|
||||
}
|
||||
}
|
||||
|
||||
void QmlBase::registerFonts(const QDir &dir)
|
||||
{
|
||||
// Autoregister all fonts found inside the dir
|
||||
QDirIterator
|
||||
itr{dir.absolutePath(), {"*.ttf", "*.otf"}, QDir::Files, QDirIterator::Subdirectories};
|
||||
while (itr.hasNext()) {
|
||||
QFontDatabase::addApplicationFont(itr.next());
|
||||
}
|
||||
}
|
@@ -5,11 +5,10 @@
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCommandLineParser>
|
||||
#include <QDir>
|
||||
#include <QFont>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
class QmlBase : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -17,6 +16,9 @@ public:
|
||||
// These constants should be kept in sync with their counterparts in qmlprojectconstants.h
|
||||
static constexpr char QMLPUPPET_ENV_MCU_FONTS_DIR[] = "QMLPUPPET_MCU_FONTS_DIR";
|
||||
static constexpr char QMLPUPPET_ENV_DEFAULT_FONT_FAMILY[] = "QMLPUPPET_DEFAULT_FONT_FAMILY";
|
||||
static constexpr char QMLPUPPET_ENV_PROJECT_ROOT[] = "QMLPUPPET_PROJECT_ROOT";
|
||||
|
||||
static void registerFonts(const QDir &dir);
|
||||
|
||||
struct AppArgs
|
||||
{
|
||||
@@ -25,58 +27,22 @@ public:
|
||||
char **argv;
|
||||
};
|
||||
|
||||
QmlBase(int &argc, char **argv, QObject *parent = nullptr)
|
||||
: QObject{parent}
|
||||
, m_args({argc, argv})
|
||||
{
|
||||
m_argParser.setApplicationDescription("QML Runtime Provider for QDS");
|
||||
m_argParser.addOption({"qml-puppet", "Run QML Puppet (default)"});
|
||||
m_argParser.addOption({"qml-renderer", "Run QML Renderer"});
|
||||
#ifdef ENABLE_INTERNAL_QML_RUNTIME
|
||||
m_argParser.addOption({"qml-runtime", "Run QML Runtime"});
|
||||
#endif
|
||||
m_argParser.addOption({"test", "Run test mode"});
|
||||
}
|
||||
QmlBase(int &argc, char **argv, QObject *parent = nullptr);
|
||||
|
||||
int run()
|
||||
{
|
||||
populateParser();
|
||||
initCoreApp();
|
||||
|
||||
if (!m_coreApp) { //default to QGuiApplication
|
||||
createCoreApp<QGuiApplication>();
|
||||
qWarning() << "CoreApp is not initialized! Falling back to QGuiApplication!";
|
||||
}
|
||||
|
||||
initParser();
|
||||
initQmlRunner();
|
||||
return m_coreApp->exec();
|
||||
}
|
||||
int run();
|
||||
|
||||
QSharedPointer<QCoreApplication> coreApp() const { return m_coreApp; }
|
||||
|
||||
protected:
|
||||
virtual void initCoreApp() = 0;
|
||||
virtual void populateParser() = 0;
|
||||
virtual void initQmlRunner() = 0;
|
||||
|
||||
virtual int startTestMode()
|
||||
{
|
||||
qDebug() << "Test mode is not implemented for this type of runner";
|
||||
return 0;
|
||||
}
|
||||
virtual void initQmlRunner();
|
||||
virtual int startTestMode();
|
||||
|
||||
template<typename T>
|
||||
void createCoreApp()
|
||||
{
|
||||
m_coreApp.reset(new T(m_args.argc, m_args.argv));
|
||||
if (const QString defaultFontFamily = qEnvironmentVariable(
|
||||
QMLPUPPET_ENV_DEFAULT_FONT_FAMILY);
|
||||
!defaultFontFamily.isEmpty()) {
|
||||
if (qobject_cast<QGuiApplication *>(QCoreApplication::instance()) != nullptr) {
|
||||
QGuiApplication::setFont(QFont{defaultFontFamily});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QSharedPointer<QCoreApplication> m_coreApp;
|
||||
@@ -86,23 +52,5 @@ protected:
|
||||
AppArgs m_args;
|
||||
|
||||
private:
|
||||
void initParser()
|
||||
{
|
||||
QCommandLineOption optHelp = m_argParser.addHelpOption();
|
||||
|
||||
if (!m_argParser.parse(m_coreApp->arguments())) {
|
||||
std::cout << "Error: " << m_argParser.errorText().toStdString() << std::endl;
|
||||
if (m_argParser.errorText().contains("qml-runtime")) {
|
||||
std::cout << "Note: --qml-runtime is only availabe when Qt is 6.4.x or higher"
|
||||
<< std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
m_argParser.showHelp(1);
|
||||
} else if (m_argParser.isSet(optHelp)) {
|
||||
m_argParser.showHelp(0);
|
||||
} else if (m_argParser.isSet("test")) {
|
||||
exit(startTestMode());
|
||||
}
|
||||
}
|
||||
void initParser();
|
||||
};
|
||||
|
@@ -90,6 +90,8 @@ QString crashReportsPath()
|
||||
|
||||
void QmlPuppet::initQmlRunner()
|
||||
{
|
||||
QmlBase::initQmlRunner();
|
||||
|
||||
if (m_coreApp->arguments().count() < 2
|
||||
|| (m_argParser.isSet("readcapturedstream") && m_coreApp->arguments().count() < 3)
|
||||
|| (m_argParser.isSet("import3dAsset") && m_coreApp->arguments().count() < 6)
|
||||
|
@@ -21,18 +21,6 @@
|
||||
#define FILE_OPEN_EVENT_WAIT_TIME 3000 // ms
|
||||
#define QSL QStringLiteral
|
||||
|
||||
static void registerFonts(const QDir &projectDir)
|
||||
{
|
||||
// Autoregister all fonts found inside the project
|
||||
QDirIterator it{projectDir.absolutePath(),
|
||||
{"*.ttf", "*.otf"},
|
||||
QDir::Files,
|
||||
QDirIterator::Subdirectories};
|
||||
while (it.hasNext()) {
|
||||
QFontDatabase::addApplicationFont(it.next());
|
||||
}
|
||||
}
|
||||
|
||||
static QDir findProjectFolder(const QDir ¤tDir, int ret = 0)
|
||||
{
|
||||
if (ret > 2)
|
||||
@@ -161,12 +149,9 @@ void QmlRuntime::initCoreApp()
|
||||
|
||||
void QmlRuntime::initQmlRunner()
|
||||
{
|
||||
registerFonts(findProjectFolder(QDir::current()));
|
||||
QmlBase::initQmlRunner();
|
||||
|
||||
if (const QString mcuFontsFolder = qEnvironmentVariable(QmlBase::QMLPUPPET_ENV_MCU_FONTS_DIR);
|
||||
!mcuFontsFolder.isEmpty()) {
|
||||
registerFonts(mcuFontsFolder);
|
||||
}
|
||||
registerFonts(findProjectFolder(QDir::current()));
|
||||
|
||||
m_qmlEngine.reset(new QQmlApplicationEngine());
|
||||
|
||||
|
Reference in New Issue
Block a user