Gui: Add YamlParameterSource for StyleParameters

This adds ability to read and write Style Parameters from YAML files.
This will allow to move certain tokens out of the User Parameter system
to ensure that they can be update without user needing to reapply the
theme.
This commit is contained in:
Kacper Donat
2025-08-16 12:20:01 +02:00
parent e6dcbe66de
commit 333a6c4585
4 changed files with 138 additions and 0 deletions

View File

@@ -146,7 +146,9 @@ target_include_directories(
${QtNetwork_INCLUDE_DIRS}
${QtUiTools_INCLUDE_DIRS}
${QtXml_INCLUDE_DIRS}
${YAML_CPP_INCLUDE_DIRS}
)
list(APPEND FreeCADGui_LIBS
${QtCore_LIBRARIES}
${QtWidgets_LIBRARIES}
@@ -159,6 +161,18 @@ list(APPEND FreeCADGui_LIBS
${QtUiTools_LIBRARIES}
)
link_directories(${YAML_CPP_LIBRARY_DIR})
if(yaml-cpp_VERSION VERSION_LESS 0.8.0)
list(APPEND FreeCADGui_LIBS
${YAML_CPP_LIBRARIES}
)
else()
list(APPEND FreeCADGui_LIBS
yaml-cpp::yaml-cpp
)
endif()
if(${Qt5WinExtras_FOUND})
target_include_directories(
FreeCADGui

View File

@@ -465,6 +465,10 @@ void StyleParametersModel::flush()
}
});
for (auto* source : sources) {
source->flush();
}
reset();
}

View File

@@ -26,6 +26,10 @@
#include "ParameterManager.h"
#include "Parser.h"
#include <QFile>
#include <fstream>
#include <yaml-cpp/yaml.h>
#ifndef _PreComp_
#include <QColor>
#include <QRegularExpression>
@@ -35,6 +39,8 @@
#include <variant>
#endif
FC_LOG_LEVEL_INIT("Gui", true, true)
namespace Gui::StyleParameters
{
@@ -215,6 +221,81 @@ void UserParameterSource::remove(const std::string& name)
hGrp->RemoveASCII(name.c_str());
}
YamlParameterSource::YamlParameterSource(const std::string& filePath, const Metadata& metadata)
: ParameterSource(metadata)
, filePath(filePath)
{
QFile file(QString::fromStdString(filePath));
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
FC_TRACE("StyleParameters: Unable to open file " << filePath);
return;
}
if (filePath.starts_with(":/")) {
this->metadata.options |= ReadOnly;
}
QTextStream in(&file);
std::string content = in.readAll().toStdString();
YAML::Node root = YAML::Load(content);
for (auto it = root.begin(); it != root.end(); ++it) {
auto key = it->first.as<std::string>();
auto value = it->second.as<std::string>();
parameters[key] = Parameter {
.name = key,
.value = value,
};
}
}
std::list<Parameter> YamlParameterSource::all() const
{
std::list<Parameter> result;
for (const auto& param : parameters | std::views::values) {
result.push_back(param);
}
return result;
}
std::optional<Parameter> YamlParameterSource::get(const std::string& name) const
{
if (auto it = parameters.find(name); it != parameters.end()) {
return it->second;
}
return std::nullopt;
}
void YamlParameterSource::define(const Parameter& param)
{
parameters[param.name] = param;
}
void YamlParameterSource::remove(const std::string& name)
{
parameters.erase(name);
}
void YamlParameterSource::flush()
{
YAML::Node root;
for (const auto& [name, param] : parameters) {
root[name] = param.value;
}
QFile file(QString::fromStdString(filePath));
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
FC_TRACE("StyleParameters: Unable to open file " << filePath);
return;
}
QTextStream out(&file);
out << QString::fromStdString(YAML::Dump(root));
}
ParameterManager::ParameterManager() = default;
void ParameterManager::reload()

View File

@@ -306,6 +306,11 @@ public:
* @param[in] name The name of the parameter to remove.
*/
virtual void remove([[maybe_unused]] const std::string& name) {}
/**
* @brief Flushes buffered changes into more persistent storage.
*/
virtual void flush() {}
};
/**
@@ -376,6 +381,40 @@ public:
void remove(const std::string& name) override;
};
/**
* @class YamlParameterSource
* @brief A ParameterSource implementation that loads and saves parameters
* from a YAML file using yaml-cpp.
*
* This class maintains an in-memory map of parameters loaded from a YAML file.
* Any changes through define() or remove() will also update the file.
*/
class GuiExport YamlParameterSource : public ParameterSource
{
public:
/**
* @brief Constructs a YamlParameterSource that reads parameters from the given YAML file.
*
* If the file exists, all key-value pairs are loaded into memory.
* If the file does not exist, an empty parameter set is initialized.
*
* @param filePath Path to the YAML file used for persistence.
* @param metadata Optional metadata describing this source.
*/
explicit YamlParameterSource(const std::string& filePath, const Metadata& metadata = {});
std::list<Parameter> all() const override;
std::optional<Parameter> get(const std::string& name) const override;
void define(const Parameter& param) override;
void remove(const std::string& name) override;
void flush() override;
private:
std::string filePath;
std::map<std::string, Parameter> parameters;
};
/**
* @brief Central manager for style parameters that aggregates multiple sources.
*