QML Designer: Load relevant fonts in MCU projects

For MCU projects, QDS will use fonts that are closer to those that are
used in QUL. This mostly applies to the cases of implicitly assumed
fonts (i.e. there's no user-specified font properties).
In this case text items will use the font set in
`MCU.Config.defaultFontFamily` property, and, if this property is not
set, DejaVu Sans, which corresponds to the behavior of Qt for MCUs.
Also only the relevant fonts will be suggested in the font picker
combobox. These come from the MCU installation and replace the standard
set of fonts (Arial, Courier, Times New Roman, etc.) in MCU projects.

From a technical perspective:
  * added a new model - `FontResourceModel` - as font handling logic is
    now too complex for a more generic `FileResourceModel`.
  * naturally, some wiring to be able to access MCU font throughout
    various parts of the project.

Fixes: QDS-10597
Fixes: QDS-15079
Fixes: QDS-15156
Change-Id: I25aa4b0f89cca864f8fd41e0812f448fe307b104
Reviewed-by: Knud Dollereder <knud.dollereder@qt.io>
This commit is contained in:
Andrii Semkiv
2025-04-11 11:38:52 +02:00
parent c80fb699cc
commit eb68868544
21 changed files with 417 additions and 59 deletions

View File

@@ -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)
}

View File

@@ -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 <cmakeprojectmanager/cmakekitaspect.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icontext.h>
@@ -38,6 +41,7 @@
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <qmljstools/qmljstoolsconstants.h>
#include <utils/expected.h>
#include <utils/filepath.h>
#include <utils/infobar.h>
@@ -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<Utils::FilePath> installationRoot();
};
void McuSupportPlugin::initialize()
@@ -286,6 +293,26 @@ void McuSupportPlugin::updateDeployStep(ProjectExplorer::Target *target, bool en
MCUBuildStepFactory::updateDeployStep(target, enabled);
}
expected_str<Utils::FilePath> 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"

View File

@@ -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

View File

@@ -20,6 +20,7 @@
#include <viewmanager.h>
#include <qmldesignerplugin.h>
#include <qmlobjectnode.h>
#include <qmlprojectmanager/qmlprojectconstants.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/project.h>
@@ -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());

View File

@@ -87,6 +87,7 @@ public:
void changeToDocumentModel();
bool isQtForMCUsProject() const;
[[nodiscard]] QString defaultFontFamilyMCU() const;
Utils::FilePath projectFolder() const;
bool hasProject() const;

View File

@@ -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 <cmakeprojectmanager/cmakekitaspect.h>
#include <designermcumanager.h>
#include <extensionsystem/iplugin.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/projectexplorer.h>
#include <qmlprojectmanager/qmlproject.h>
#include <qmlprojectmanager/qmlprojectconstants.h>
#include <utils/algorithm.h>
#include <utils/expected.h>
#include <utils/filepath.h>
#include <QFontDatabase>
#include <QLatin1String>
#include <QObject>
#include <QSet>
#include <QString>
#include <QStringList>
#include <QUrl>
#include <algorithm>
#include <iterator>
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<QSet<QString>> mcuFonts()
{
Utils::expected_str<Utils::FilePath> mcuFontsDir = QmlProjectManager::mcuFontsDir();
if (!mcuFontsDir) {
return Utils::make_unexpected(mcuFontsDir.error());
}
QSet<QString> fonts;
const Utils::FilePaths fontFiles = mcuFontsDir->dirEntries({fontFilesFilterList(), QDir::Files});
for (const auto &file : fontFiles) {
fonts.insert(fontFamily(file.absoluteFilePath().toFSPathString()));
}
return fonts;
}
QSet<QString> systemFonts()
{
QSet<QString> 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<FontResourcesModel>("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<QString> 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);
}

View File

@@ -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 <QObject>
#include <QString>
#include <QStringList>
#include <QUrl>
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)

View File

@@ -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();

View File

@@ -8,6 +8,7 @@
#include "designdocument.h"
#include <qmljs/qmljssimplereader.h>
#include <qmlprojectmanager/qmlprojectconstants.h>
#include <utils/qtcassert.h>
@@ -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()

View File

@@ -31,6 +31,7 @@ public:
static DesignerMcuManager& instance();
static QString mcuResourcesPath();
static QString defaultFontFamilyMCU();
bool isMCUProject() const;

View File

@@ -7,14 +7,18 @@
#include <model.h>
#include <designermcumanager.h>
#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/target.h>
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
#include <qmlprojectmanager/qmlmultilanguageaspect.h>
#include <qmlprojectmanager/qmlproject.h>
#include <qtsupport/qtkitaspect.h>
#include <qtsupport/qtversions.h>
#include <utils/algorithm.h>
#include <utils/expected.h>
#include <utils/hostosinfo.h>
#include <QLibraryInfo>
@@ -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<Utils::FilePath> 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()) {

View File

@@ -51,6 +51,7 @@ private:
void addCustomFileSelectors() const;
void addDisableDeferredProperties() const;
void addResolveUrlsOnAssignment() const;
void addMcuFonts() const;
private:
ProjectExplorer::Target *m_target = nullptr;

View File

@@ -4,6 +4,7 @@
#include "converters.h"
#include "utils/algorithm.h"
#include "../../qmlprojectexporter/filetypes.h"
#include "qmlprojectconstants.h"
#include <QJsonDocument>
@@ -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/<filename>".
// 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);
}
}

View File

@@ -22,10 +22,6 @@
#include <coreplugin/messagemanager.h>
#include <coreplugin/session.h>
#include <extensionsystem/iplugin.h>
#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
#include <projectexplorer/deploymentdata.h>
#include <projectexplorer/devicesupport/devicekitaspects.h>
#include <projectexplorer/devicesupport/idevice.h>
@@ -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<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()) {
env.append({Constants::QMLPUPPET_ENV_DEFAULT_FONT_FAMILY, defaultFontFamilyMCU()});
}
return env;
}
QStringList QmlBuildSystem::fileSelectors() const

View File

@@ -144,6 +144,9 @@ private:
void registerMenuButtons();
void updateDeploymentData();
[[nodiscard]] QString defaultFontFamilyMCU() const;
friend class FilesUpdateBlocker;
QmlProjectExporter::Exporter* m_fileGen;

View File

@@ -10,6 +10,10 @@
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
#include <extensionsystem/iplugin.h>
#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
#include <projectexplorer/devicesupport/devicekitaspects.h>
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/kitmanager.h>
@@ -26,10 +30,12 @@
#include <texteditor/textdocument.h>
#include <utils/algorithm.h>
#include <utils/expected.h>
#include <utils/infobar.h>
#include <utils/mimeconstants.h>
#include <utils/qtcprocess.h>
#include <utils/predicates.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <QDebug>
#include <QLoggingCategory>
@@ -40,9 +46,52 @@
using namespace Core;
using namespace ProjectExplorer;
using namespace Utils;
using namespace Qt::Literals::StringLiterals;
namespace {
expected_str<FilePath> mcuInstallationRoot()
{
ExtensionSystem::IPlugin *mcuSupportPlugin = QmlProjectManager::findMcuSupportPlugin();
if (mcuSupportPlugin == nullptr) {
return make_unexpected("Failed to find MCU Support plugin"_L1);
}
expected_str<FilePath> root;
QMetaObject::invokeMethod(mcuSupportPlugin,
"installationRoot",
Qt::DirectConnection,
Q_RETURN_ARG(expected_str<FilePath>, 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<FilePath> mcuFontsDir()
{
expected_str<FilePath> mcuRoot = mcuInstallationRoot();
if (!mcuRoot) {
return mcuRoot;
}
return *mcuRoot / "src" / "3rdparty" / "fonts";
}
QmlProject::QmlProject(const Utils::FilePath &fileName)
: Project(Utils::Constants::QMLPROJECT_MIMETYPE, fileName)
{

View File

@@ -5,7 +5,11 @@
#include "buildsystem/qmlbuildsystem.h" // IWYU pragma: keep
#include "qmlprojectmanager_global.h"
#include <extensionsystem/iplugin.h>
#include <projectexplorer/project.h>
#include <utils/expected.h>
#include <utils/filepath.h>
#include <QPointer>
@@ -13,6 +17,9 @@ namespace QmlProjectManager {
class QmlProject;
ExtensionSystem::IPlugin *findMcuSupportPlugin();
QMLPROJECTMANAGER_EXPORT Utils::expected_str<Utils::FilePath> mcuFontsDir();
class QMLPROJECTMANAGER_EXPORT QmlProject : public ProjectExplorer::Project
{
Q_OBJECT

View File

@@ -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

View File

@@ -8,6 +8,7 @@
#include "childrenchangeeventfilter.h"
#include "dummycontextobject.h"
#include "qmlpuppet/qmlbase.h"
#include <propertyabstractcontainer.h>
#include <propertybindingcontainer.h>
@@ -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);

View File

@@ -5,6 +5,7 @@
#include <QApplication>
#include <QCommandLineParser>
#include <QFont>
#include <QQmlApplicationEngine>
#include <iostream>
@@ -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<QGuiApplication *>(QCoreApplication::instance()) != nullptr) {
QGuiApplication::setFont(QFont{defaultFontFamily});
}
}
}
QSharedPointer<QCoreApplication> m_coreApp;

View File

@@ -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;