diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontComboBox.qml index 37286ce7701..eee1fd956ba 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontComboBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontComboBox.qml @@ -20,10 +20,9 @@ StudioControls.ComboBox { onTextColorChanged: root.setColor() - FileResourcesModel { + FontResourcesModel { id: fileModel modelNodeBackendProperty: modelNodeBackend - filter: root.fontFilter } DropArea { @@ -59,19 +58,7 @@ StudioControls.ComboBox { } function setupModel() { - // default fonts - var familyNames = ["Arial", "Times New Roman", "Courier", "Verdana", "Tahoma"] - - for (var i = 0; i < fileModel.model.length; ++i) { // add custom fonts - var fontLoader = root.createFontLoader(fileModel.docPath + "/" - + fileModel.model[i].relativeFilePath) - familyNames.push(fontLoader.name) - } - - // Remove duplicate family names - familyNames = [...new Set(familyNames)] - familyNames.sort() - root.model = familyNames + root.model = fileModel.model root.currentIndex = root.find(root.backendValue.value) } diff --git a/src/plugins/mcusupport/mcusupportplugin.cpp b/src/plugins/mcusupport/mcusupportplugin.cpp index ea8ceabae60..f93da50ad78 100644 --- a/src/plugins/mcusupport/mcusupportplugin.cpp +++ b/src/plugins/mcusupport/mcusupportplugin.cpp @@ -3,6 +3,7 @@ #include "mcubuildstep.h" #include "mcukitmanager.h" +#include "mculegacyconstants.h" #include "mcuqmlprojectnode.h" #include "mcusupportconstants.h" #include "mcusupportdevice.h" @@ -16,6 +17,8 @@ #include "test/unittest.h" #endif +#include + #include #include #include @@ -38,6 +41,7 @@ #include #include +#include #include #include @@ -49,6 +53,8 @@ using namespace Core; using namespace ProjectExplorer; +using namespace Qt::Literals::StringLiterals; + namespace McuSupport::Internal { const char setupMcuSupportKits[] = "SetupMcuSupportKits"; @@ -192,6 +198,7 @@ public: void extensionsInitialized() final; Q_INVOKABLE static void updateDeployStep(ProjectExplorer::Target *target, bool enabled); + Q_INVOKABLE static expected_str installationRoot(); }; void McuSupportPlugin::initialize() @@ -286,6 +293,26 @@ void McuSupportPlugin::updateDeployStep(ProjectExplorer::Target *target, bool en MCUBuildStepFactory::updateDeployStep(target, enabled); } +expected_str McuSupportPlugin::installationRoot() +{ + const ProjectExplorer::Kit *kit = MCUBuildStepFactory::findMostRecentQulKit(); + if (kit == nullptr) { + return make_unexpected("No QUL kits installed"_L1); + } + + const auto config + = CMakeProjectManager::CMakeConfigurationKitAspect::configuration(kit).toList(); + const auto key = QString{Internal::Legacy::Constants::QUL_CMAKE_VAR}.toUtf8(); + for (const CMakeProjectManager::CMakeConfigItem &configItem : config) { + if (configItem.key == key) { + return Utils::FilePath::fromUserInput(QString::fromUtf8(configItem.value)); + } + } + return make_unexpected("No QUL installation root ('%1') key in kit '%2' configuration"_L1 + .arg(Internal::Legacy::Constants::QUL_CMAKE_VAR) + .arg(kit->displayName())); +} + } // namespace McuSupport::Internal #include "mcusupportplugin.moc" diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index 227e7067dac..e146a30f18e 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -409,6 +409,7 @@ extend_qtc_plugin(QmlDesigner compatibleproperties.cpp compatibleproperties.h designerpropertymap.cpp designerpropertymap.h fileresourcesmodel.cpp fileresourcesmodel.h + fontresourcesmodel.cpp fontresourcesmodel.h itemfiltermodel.cpp itemfiltermodel.h listvalidator.cpp listvalidator.h gradientmodel.cpp gradientmodel.h diff --git a/src/plugins/qmldesigner/components/integration/designdocument.cpp b/src/plugins/qmldesigner/components/integration/designdocument.cpp index bb0dc231301..9925f3b785e 100644 --- a/src/plugins/qmldesigner/components/integration/designdocument.cpp +++ b/src/plugins/qmldesigner/components/integration/designdocument.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -423,6 +424,16 @@ bool DesignDocument::isQtForMCUsProject() const return false; } +QString DesignDocument::defaultFontFamilyMCU() const +{ + if (m_currentTarget == nullptr) { + return QmlProjectManager::Constants::FALLBACK_MCU_FONT_FAMILY; + } + + return m_currentTarget->additionalData(QmlProjectManager::Constants::customDefaultFontFamilyMCU) + .toString(); +} + Utils::FilePath DesignDocument::projectFolder() const { ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectManager::projectForFile(fileName()); diff --git a/src/plugins/qmldesigner/components/integration/designdocument.h b/src/plugins/qmldesigner/components/integration/designdocument.h index 1f67ff4b30b..eaab3e1a8b1 100644 --- a/src/plugins/qmldesigner/components/integration/designdocument.h +++ b/src/plugins/qmldesigner/components/integration/designdocument.h @@ -87,6 +87,7 @@ public: void changeToDocumentModel(); bool isQtForMCUsProject() const; + [[nodiscard]] QString defaultFontFamilyMCU() const; Utils::FilePath projectFolder() const; bool hasProject() const; diff --git a/src/plugins/qmldesigner/components/propertyeditor/fontresourcesmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/fontresourcesmodel.cpp new file mode 100644 index 00000000000..e8086058385 --- /dev/null +++ b/src/plugins/qmldesigner/components/propertyeditor/fontresourcesmodel.cpp @@ -0,0 +1,156 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "fontresourcesmodel.h" +#include "fileresourcesmodel.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace Qt::Literals::StringLiterals; + +namespace { + +QStringList makeFontFilesFilterList() +{ + QStringList filterList; + filterList.reserve(std::size(QmlProjectManager::Constants::QDS_FONT_FILES_FILTERS)); + std::ranges::transform(QmlProjectManager::Constants::QDS_FONT_FILES_FILTERS, + std::back_inserter(filterList), + [](const char *filter) { return QString::fromLatin1(filter); }); + + return filterList; +} + +const QStringList &fontFilesFilterList() +{ + static const QStringList list = makeFontFilesFilterList(); + return list; +} + +QString fontFamily(const QString &fontPath) +{ + const int fontId = QFontDatabase::addApplicationFont(fontPath); + QString fontFamily = QFontDatabase::applicationFontFamilies(fontId).front(); + QFontDatabase::removeApplicationFont(fontId); + return fontFamily; +} + +Utils::expected_str> mcuFonts() +{ + Utils::expected_str mcuFontsDir = QmlProjectManager::mcuFontsDir(); + if (!mcuFontsDir) { + return Utils::make_unexpected(mcuFontsDir.error()); + } + + QSet fonts; + const Utils::FilePaths fontFiles = mcuFontsDir->dirEntries({fontFilesFilterList(), QDir::Files}); + for (const auto &file : fontFiles) { + fonts.insert(fontFamily(file.absoluteFilePath().toFSPathString())); + } + + return fonts; +} + +QSet systemFonts() +{ + QSet defaultFonts{ + "Arial", + "Courier", + "Tahoma", + "Times New Roman", + "Verdana", + }; + + if (QmlDesigner::DesignerMcuManager::instance().isMCUProject()) { + const auto fonts = mcuFonts(); + if (!fonts) { + qWarning() << "Failed to load MCU fonts." << fonts.error(); + return defaultFonts; + } + + return *fonts; + } + + return defaultFonts; +} + +} // namespace + +void FontResourcesModel::registerDeclarativeType() +{ + qmlRegisterType("HelperWidgets", 2, 0, "FontResourcesModel"); +} + +QVariant FontResourcesModel::modelNodeBackend() +{ + return {}; +} + +FontResourcesModel::FontResourcesModel(QObject *parent) + : QObject{parent} + , m_resourceModel{new FileResourcesModel{this}} +{ + m_resourceModel->setFilter(fontFilesFilterList().join(' ')); +} + +void FontResourcesModel::setModelNodeBackend(const QVariant &modelNodeBackend) +{ + m_resourceModel->setModelNodeBackend(modelNodeBackend); +} + +QStringList FontResourcesModel::model() const +{ + QSet fonts; + for (const auto &item : m_resourceModel->model()) { + fonts.insert(fontFamily(item.absoluteFilePath())); + } + + fonts.unite(systemFonts()); + + auto ret = QStringList{fonts.cbegin(), fonts.cend()}; + ret.sort(); + + return ret; +} + +void FontResourcesModel::refreshModel() +{ + m_resourceModel->refreshModel(); +} + +void FontResourcesModel::openFileDialog(const QString &customPath) +{ + m_resourceModel->openFileDialog(customPath); +} + +QString FontResourcesModel::resolve(const QString &relative) const +{ + return m_resourceModel->resolve(relative); +} + +bool FontResourcesModel::isLocal(const QString &path) const +{ + return m_resourceModel->isLocal(path); +} diff --git a/src/plugins/qmldesigner/components/propertyeditor/fontresourcesmodel.h b/src/plugins/qmldesigner/components/propertyeditor/fontresourcesmodel.h new file mode 100644 index 00000000000..d317ba284a5 --- /dev/null +++ b/src/plugins/qmldesigner/components/propertyeditor/fontresourcesmodel.h @@ -0,0 +1,47 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include "fileresourcesmodel.h" + +#include +#include +#include +#include + +class FontResourcesModel : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QVariant modelNodeBackendProperty READ modelNodeBackend WRITE setModelNodeBackend + NOTIFY modelNodeBackendChanged) + Q_PROPERTY(QStringList model READ model NOTIFY modelChanged) + +public: + static void registerDeclarativeType(); + [[nodiscard]] static QVariant modelNodeBackend(); + + explicit FontResourcesModel(QObject *parent = nullptr); + + void setModelNodeBackend(const QVariant &modelNodeBackend); + [[nodiscard]] QStringList model() const; + + void refreshModel(); + + Q_INVOKABLE void openFileDialog(const QString &customPath = {}); + Q_INVOKABLE [[nodiscard]] QString resolve(const QString &relative) const; + Q_INVOKABLE [[nodiscard]] bool isLocal(const QString &path) const; + +signals: + void fileNameChanged(const QUrl &fileName); + void filterChanged(const QString &filter); + void modelNodeBackendChanged(); + void pathChanged(const QUrl &path); + void modelChanged(); + +private: + FileResourcesModel *m_resourceModel; +}; + +QML_DECLARE_TYPE(FontResourcesModel) diff --git a/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp index 30e9f6908f6..87e92578520 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp @@ -13,6 +13,7 @@ #include "bindingeditor/bindingeditor.h" #include "colorpalettebackend.h" #include "fileresourcesmodel.h" +#include "fontresourcesmodel.h" #include "gradientmodel.h" #include "gradientpresetcustomlistmodel.h" #include "gradientpresetdefaultlistmodel.h" @@ -60,6 +61,7 @@ void Quick2PropertyEditorView::registerQmlTypes() declarativeTypesRegistered = true; PropertyEditorValue::registerDeclarativeTypes(); FileResourcesModel::registerDeclarativeType(); + FontResourcesModel::registerDeclarativeType(); GradientModel::registerDeclarativeType(); GradientPresetDefaultListModel::registerDeclarativeType(); GradientPresetCustomListModel::registerDeclarativeType(); diff --git a/src/plugins/qmldesigner/designermcumanager.cpp b/src/plugins/qmldesigner/designermcumanager.cpp index e42c28ac3ef..ab52f579e34 100644 --- a/src/plugins/qmldesigner/designermcumanager.cpp +++ b/src/plugins/qmldesigner/designermcumanager.cpp @@ -8,6 +8,7 @@ #include "designdocument.h" #include +#include #include @@ -45,6 +46,22 @@ QString DesignerMcuManager::mcuResourcesPath() return Core::ICore::resourcePath("qmldesigner/qt4mcu").toUrlishString(); } +QString DesignerMcuManager::defaultFontFamilyMCU() +{ + const QmlDesignerPlugin *designerPlugin = QmlDesigner::QmlDesignerPlugin::instance(); + if (designerPlugin == nullptr) { + return QmlProjectManager::Constants::FALLBACK_MCU_FONT_FAMILY; + } + + const QmlDesigner::DesignDocument *designDocument = designerPlugin->documentManager() + .currentDesignDocument(); + if (designDocument == nullptr) { + return QmlProjectManager::Constants::FALLBACK_MCU_FONT_FAMILY; + } + + return designDocument->defaultFontFamilyMCU(); +} + bool DesignerMcuManager::isMCUProject() const { QmlDesigner::DesignDocument *designDocument = QmlDesigner::QmlDesignerPlugin::instance() diff --git a/src/plugins/qmldesigner/designermcumanager.h b/src/plugins/qmldesigner/designermcumanager.h index 59ea892d468..9ca1c3f9414 100644 --- a/src/plugins/qmldesigner/designermcumanager.h +++ b/src/plugins/qmldesigner/designermcumanager.h @@ -31,6 +31,7 @@ public: static DesignerMcuManager& instance(); static QString mcuResourcesPath(); + static QString defaultFontFamilyMCU(); bool isMCUProject() const; diff --git a/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp b/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp index c7488558831..2fca452a123 100644 --- a/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp +++ b/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp @@ -7,14 +7,18 @@ #include +#include +#include +#include #include #include -#include -#include #include #include #include #include +#include +#include +#include #include @@ -51,6 +55,7 @@ QProcessEnvironment PuppetEnvironmentBuilder::processEnvironment() const addCustomFileSelectors(); addDisableDeferredProperties(); addResolveUrlsOnAssignment(); + addMcuFonts(); qCInfo(puppetEnvirmentBuild) << "Puppet environment:" << m_environment.toStringList(); @@ -249,6 +254,24 @@ void PuppetEnvironmentBuilder::addResolveUrlsOnAssignment() const m_environment.set("QML_COMPAT_RESOLVE_URLS_ON_ASSIGNMENT", "true"); } +void PuppetEnvironmentBuilder::addMcuFonts() const +{ + const Utils::expected_str mcuFontsDir = QmlProjectManager::mcuFontsDir(); + if (!mcuFontsDir) { + qCWarning(puppetEnvirmentBuild) + << "Failed to locate MCU installation." << mcuFontsDir.error(); + return; + } + + 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); + } +} + PuppetType PuppetEnvironmentBuilder::determinePuppetType() const { if (m_target && m_target->kit() && m_target->kit()->isValid()) { diff --git a/src/plugins/qmldesigner/puppetenvironmentbuilder.h b/src/plugins/qmldesigner/puppetenvironmentbuilder.h index 8179a36b90d..5b69309ff52 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 addMcuFonts() const; private: ProjectExplorer::Target *m_target = nullptr; diff --git a/src/plugins/qmlprojectmanager/buildsystem/projectitem/converters.cpp b/src/plugins/qmlprojectmanager/buildsystem/projectitem/converters.cpp index 26e31d71f45..e43b5418528 100644 --- a/src/plugins/qmlprojectmanager/buildsystem/projectitem/converters.cpp +++ b/src/plugins/qmlprojectmanager/buildsystem/projectitem/converters.cpp @@ -4,6 +4,7 @@ #include "converters.h" #include "utils/algorithm.h" #include "../../qmlprojectexporter/filetypes.h" +#include "qmlprojectconstants.h" #include @@ -11,27 +12,6 @@ namespace QmlProjectManager::Converters { const static QStringList qmlFilesFilter{QStringLiteral("*.qml")}; const static QStringList javaScriptFilesFilter{QStringLiteral("*.js"), QStringLiteral("*.ts")}; -const static QStringList fontFilesFilter{ - QStringLiteral("*.afm"), - QStringLiteral("*.bdf"), - QStringLiteral("*.ccc"), - QStringLiteral("*.cff"), - QStringLiteral("*.fmp"), - QStringLiteral("*.fnt"), - QStringLiteral("*.otc"), - QStringLiteral("*.otf"), - QStringLiteral("*.pcf"), - QStringLiteral("*.pfa"), - QStringLiteral("*.pfb"), - QStringLiteral("*.pfm"), - QStringLiteral("*.pfr"), - QStringLiteral("*.ttc"), - QStringLiteral("*.ttcf"), - QStringLiteral("*.tte"), - QStringLiteral("*.ttf"), - QStringLiteral("*.woff"), - QStringLiteral("*.woff2"), -}; const QStringList imageFilesFilter() { return imageFiles([](const QString& suffix) { return "*." + suffix; }); @@ -486,12 +466,12 @@ QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile) // and all files are prefixed such as "directory/". // if directory is empty, then the files are prefixed with the project directory if (childNodeFiles.empty()) { - auto inserter = [&childNodeFilters](const QStringList &filterSource) { + auto inserter = [&childNodeFilters](auto &filterSource) { if (!childNodeFilters.empty()) return; - std::for_each(filterSource.begin(), - filterSource.end(), + std::for_each(std::cbegin(filterSource), + std::cend(filterSource), [&childNodeFilters](const auto &value) { if (!childNodeFilters.contains(value)) { childNodeFilters << value; @@ -510,7 +490,7 @@ QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile) } else if (childNodeName == "imagefiles") { inserter(imageFilesFilter()); } else if (childNodeName == "fontfiles") { - inserter(fontFilesFilter); + inserter(QmlProjectManager::Constants::QDS_FONT_FILES_FILTERS); } } diff --git a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp index 5f60c0f61cb..802cb6c733d 100644 --- a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp +++ b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp @@ -22,10 +22,6 @@ #include #include -#include -#include -#include - #include #include #include @@ -51,17 +47,6 @@ namespace { Q_LOGGING_CATEGORY(infoLogger, "QmlProjectManager.QmlBuildSystem", QtInfoMsg) } -ExtensionSystem::IPlugin *findMcuSupportPlugin() -{ - const ExtensionSystem::PluginSpec *pluginSpec = Utils::findOrDefault( - ExtensionSystem::PluginManager::plugins(), - Utils::equal(&ExtensionSystem::PluginSpec::id, QString("mcusupport"))); - - if (pluginSpec) - return pluginSpec->plugin(); - return nullptr; -} - void updateMcuBuildStep(Target *target, bool mcuEnabled) { if (auto plugin = findMcuSupportPlugin()) { @@ -123,6 +108,18 @@ void QmlBuildSystem::updateDeploymentData() setDeploymentData(deploymentData); } +QString QmlBuildSystem::defaultFontFamilyMCU() const +{ + const QJsonObject project = m_projectItem->project(); + QString defaultFontFamily = project["mcu"].toObject()["config"].toObject()["defaultFontFamily"].toString(); + + if (!defaultFontFamily.isEmpty()) { + return defaultFontFamily; + } + + return QmlProjectManager::Constants::FALLBACK_MCU_FONT_FAMILY; +} + //probably this method needs to be moved into QmlProjectPlugin::initialize to be called only once void QmlBuildSystem::registerMenuButtons() { @@ -607,6 +604,8 @@ QVariant QmlBuildSystem::additionalData(Utils::Id id) const return mainFilePath().toUrlishString(); if (id == Constants::canonicalProjectDir) return canonicalProjectDir().toUrlishString(); + if (id == Constants::customDefaultFontFamilyMCU) + return defaultFontFamilyMCU(); return {}; } @@ -701,7 +700,20 @@ bool QmlBuildSystem::qt6Project() const Utils::EnvironmentItems QmlBuildSystem::environment() const { - return m_projectItem->environment(); + 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()) { + env.append({Constants::QMLPUPPET_ENV_DEFAULT_FONT_FAMILY, defaultFontFamilyMCU()}); + } + + return env; } QStringList QmlBuildSystem::fileSelectors() const diff --git a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h index 2017f9b3f77..83e4e9c341f 100644 --- a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h +++ b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h @@ -144,6 +144,9 @@ private: void registerMenuButtons(); void updateDeploymentData(); + + [[nodiscard]] QString defaultFontFamilyMCU() const; + friend class FilesUpdateBlocker; QmlProjectExporter::Exporter* m_fileGen; diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp index c37e56a6eaa..3a02801f03f 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.cpp +++ b/src/plugins/qmlprojectmanager/qmlproject.cpp @@ -10,6 +10,10 @@ #include #include +#include +#include +#include + #include #include #include @@ -26,10 +30,12 @@ #include #include +#include #include #include -#include +#include #include +#include #include #include @@ -40,9 +46,52 @@ using namespace Core; using namespace ProjectExplorer; using namespace Utils; +using namespace Qt::Literals::StringLiterals; + +namespace { +expected_str mcuInstallationRoot() +{ + ExtensionSystem::IPlugin *mcuSupportPlugin = QmlProjectManager::findMcuSupportPlugin(); + if (mcuSupportPlugin == nullptr) { + return make_unexpected("Failed to find MCU Support plugin"_L1); + } + + expected_str root; + QMetaObject::invokeMethod(mcuSupportPlugin, + "installationRoot", + Qt::DirectConnection, + Q_RETURN_ARG(expected_str, root)); + + return root; +} +} // namespace namespace QmlProjectManager { +ExtensionSystem::IPlugin *findMcuSupportPlugin() +{ + const QString pluginId = "mcusupport"; + const ExtensionSystem::PluginSpec *pluginSpec = Utils::findOrDefault( + ExtensionSystem::PluginManager::plugins(), + Utils::equal(&ExtensionSystem::PluginSpec::id, pluginId)); + + if (pluginSpec == nullptr) { + return nullptr; + } + + return pluginSpec->plugin(); +} + +expected_str mcuFontsDir() +{ + expected_str mcuRoot = mcuInstallationRoot(); + if (!mcuRoot) { + return mcuRoot; + } + + return *mcuRoot / "src" / "3rdparty" / "fonts"; +} + QmlProject::QmlProject(const Utils::FilePath &fileName) : Project(Utils::Constants::QMLPROJECT_MIMETYPE, fileName) { diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h index 39d903bffc9..04b69d8f548 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.h +++ b/src/plugins/qmlprojectmanager/qmlproject.h @@ -5,7 +5,11 @@ #include "buildsystem/qmlbuildsystem.h" // IWYU pragma: keep #include "qmlprojectmanager_global.h" + +#include #include +#include +#include #include @@ -13,6 +17,9 @@ namespace QmlProjectManager { class QmlProject; +ExtensionSystem::IPlugin *findMcuSupportPlugin(); +QMLPROJECTMANAGER_EXPORT Utils::expected_str mcuFontsDir(); + class QMLPROJECTMANAGER_EXPORT QmlProject : public ProjectExplorer::Project { Q_OBJECT diff --git a/src/plugins/qmlprojectmanager/qmlprojectconstants.h b/src/plugins/qmlprojectmanager/qmlprojectconstants.h index 0d0a35e884a..26a98635109 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectconstants.h +++ b/src/plugins/qmlprojectmanager/qmlprojectconstants.h @@ -11,6 +11,7 @@ const char primaryLanguageData[] = "PrimaryLanguageData"; const char customForceFreeTypeData[] = "CustomForceFreeType"; const char customQtForMCUs[] = "CustomQtForMCUs"; const char customQt6Project[] = "CustomQt6Project"; +const char customDefaultFontFamilyMCU[] = "CustomDefaultFontFamilyMCU"; const char mainFilePath[] = "MainFilePath"; const char canonicalProjectDir[] ="CanonicalProjectDir"; @@ -37,4 +38,13 @@ const char G_EXPORT_CONVERT[] = "QmlDesigner.Group.ConvertProject"; const char fakeProjectName[] = "fake85673.qmlproject"; +inline constexpr const char *QDS_FONT_FILES_FILTERS[] = { + "*.afm", "*.bdf", "*.ccc", "*.cff", "*.fmp", "*.fnt", "*.otc", "*.otf", "*.pcf", "*.pfa", + "*.pfb", "*.pfm", "*.pfr", "*.ttc", "*.ttcf", "*.tte", "*.ttf", "*.woff", "*.woff2", +}; +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"; + } // QmlProjectManager::Constants diff --git a/src/tools/qmlpuppet/qmlpuppet/instances/nodeinstanceserver.cpp b/src/tools/qmlpuppet/qmlpuppet/instances/nodeinstanceserver.cpp index eb8d2083e2e..1761ea45dbb 100644 --- a/src/tools/qmlpuppet/qmlpuppet/instances/nodeinstanceserver.cpp +++ b/src/tools/qmlpuppet/qmlpuppet/instances/nodeinstanceserver.cpp @@ -8,6 +8,7 @@ #include "childrenchangeeventfilter.h" #include "dummycontextobject.h" +#include "qmlpuppet/qmlbase.h" #include #include @@ -312,6 +313,10 @@ 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); diff --git a/src/tools/qmlpuppet/qmlpuppet/qmlbase.h b/src/tools/qmlpuppet/qmlpuppet/qmlbase.h index 7c1333544a9..6f461bb5a75 100644 --- a/src/tools/qmlpuppet/qmlpuppet/qmlbase.h +++ b/src/tools/qmlpuppet/qmlpuppet/qmlbase.h @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -13,6 +14,10 @@ class QmlBase : public QObject { Q_OBJECT 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"; + struct AppArgs { public: @@ -65,6 +70,13 @@ protected: 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; diff --git a/src/tools/qmlpuppet/qmlpuppet/runner/qmlruntime.cpp b/src/tools/qmlpuppet/qmlpuppet/runner/qmlruntime.cpp index 2876339a903..063ae273790 100644 --- a/src/tools/qmlpuppet/qmlpuppet/runner/qmlruntime.cpp +++ b/src/tools/qmlpuppet/qmlpuppet/runner/qmlruntime.cpp @@ -162,6 +162,12 @@ void QmlRuntime::initCoreApp() void QmlRuntime::initQmlRunner() { registerFonts(findProjectFolder(QDir::current())); + + if (const QString mcuFontsFolder = qEnvironmentVariable(QmlBase::QMLPUPPET_ENV_MCU_FONTS_DIR); + !mcuFontsFolder.isEmpty()) { + registerFonts(mcuFontsFolder); + } + m_qmlEngine.reset(new QQmlApplicationEngine()); QStringList files;