diff --git a/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp b/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp index 2fca452a123..c7d7c5a37d6 100644 --- a/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp +++ b/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -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 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 diff --git a/src/plugins/qmldesigner/puppetenvironmentbuilder.h b/src/plugins/qmldesigner/puppetenvironmentbuilder.h index 5b69309ff52..37795bbd1e4 100644 --- a/src/plugins/qmldesigner/puppetenvironmentbuilder.h +++ b/src/plugins/qmldesigner/puppetenvironmentbuilder.h @@ -51,6 +51,7 @@ private: void addCustomFileSelectors() const; void addDisableDeferredProperties() const; void addResolveUrlsOnAssignment() const; + void addMcuItems() const; void addMcuFonts() const; private: diff --git a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp index 802cb6c733d..c40fb3d2f23 100644 --- a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp +++ b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp @@ -702,14 +702,19 @@ Utils::EnvironmentItems QmlBuildSystem::environment() const { Utils::EnvironmentItems env = m_projectItem->environment(); - Utils::expected_str 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 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()}); } diff --git a/src/plugins/qmlprojectmanager/qmlprojectconstants.h b/src/plugins/qmlprojectmanager/qmlprojectconstants.h index 26a98635109..52b0c383e8c 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectconstants.h +++ b/src/plugins/qmlprojectmanager/qmlprojectconstants.h @@ -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 diff --git a/src/tools/qmlpuppet/CMakeLists.txt b/src/tools/qmlpuppet/CMakeLists.txt index 7d239d4adc8..a6376a09d7c 100644 --- a/src/tools/qmlpuppet/CMakeLists.txt +++ b/src/tools/qmlpuppet/CMakeLists.txt @@ -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 diff --git a/src/tools/qmlpuppet/qmlprivategate/qmlprivategate.cpp b/src/tools/qmlpuppet/qmlprivategate/qmlprivategate.cpp index 7978ba18355..edeceb26b85 100644 --- a/src/tools/qmlpuppet/qmlprivategate/qmlprivategate.cpp +++ b/src/tools/qmlpuppet/qmlprivategate/qmlprivategate.cpp @@ -3,8 +3,9 @@ #include "qmlprivategate.h" -#include #include +#include +#include #include #include @@ -43,7 +44,89 @@ #include #endif +#include +using namespace Qt::Literals::StringLiterals; + +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) +using EngineHandler = std::unique_ptr; +#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 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 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 -#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(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 {}; } diff --git a/src/tools/qmlpuppet/qmlpuppet/instances/nodeinstanceserver.cpp b/src/tools/qmlpuppet/qmlpuppet/instances/nodeinstanceserver.cpp index 1761ea45dbb..9e66929a1c8 100644 --- a/src/tools/qmlpuppet/qmlpuppet/instances/nodeinstanceserver.cpp +++ b/src/tools/qmlpuppet/qmlpuppet/instances/nodeinstanceserver.cpp @@ -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 diff --git a/src/tools/qmlpuppet/qmlpuppet/qmlbase.cpp b/src/tools/qmlpuppet/qmlpuppet/qmlbase.cpp new file mode 100644 index 00000000000..864b67f56c5 --- /dev/null +++ b/src/tools/qmlpuppet/qmlpuppet/qmlbase.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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(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(); + 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()); + } +} diff --git a/src/tools/qmlpuppet/qmlpuppet/qmlbase.h b/src/tools/qmlpuppet/qmlpuppet/qmlbase.h index 6f461bb5a75..00f5e9a4df5 100644 --- a/src/tools/qmlpuppet/qmlpuppet/qmlbase.h +++ b/src/tools/qmlpuppet/qmlpuppet/qmlbase.h @@ -5,11 +5,10 @@ #include #include +#include #include #include -#include - 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(); - qWarning() << "CoreApp is not initialized! Falling back to QGuiApplication!"; - } - - initParser(); - initQmlRunner(); - return m_coreApp->exec(); - } + int run(); QSharedPointer 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 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(QCoreApplication::instance()) != nullptr) { - QGuiApplication::setFont(QFont{defaultFontFamily}); - } - } } QSharedPointer 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(); }; diff --git a/src/tools/qmlpuppet/qmlpuppet/qmlpuppet.cpp b/src/tools/qmlpuppet/qmlpuppet/qmlpuppet.cpp index 7b180cdc2b6..0d74ec0d365 100644 --- a/src/tools/qmlpuppet/qmlpuppet/qmlpuppet.cpp +++ b/src/tools/qmlpuppet/qmlpuppet/qmlpuppet.cpp @@ -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) diff --git a/src/tools/qmlpuppet/qmlpuppet/runner/qmlruntime.cpp b/src/tools/qmlpuppet/qmlpuppet/runner/qmlruntime.cpp index 063ae273790..0be3aefcd1e 100644 --- a/src/tools/qmlpuppet/qmlpuppet/runner/qmlruntime.cpp +++ b/src/tools/qmlpuppet/qmlpuppet/runner/qmlruntime.cpp @@ -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());