Utils/CloudViewApp/Src/CloudViewSettings.cpp

172 lines
8.0 KiB
C++
Raw Normal View History

2026-10-10 19:02:17 +08:00
#include "CloudViewSettings.h"
#include <QColor>
#include <QDir>
#include <QSettings>
#include <QStandardPaths>
#include <cmath>
namespace
{
QString settingsFilePath()
{
QString settingsDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
if (settingsDir.isEmpty()) {
settingsDir = QDir::homePath() + "/CloudView";
}
QDir().mkpath(settingsDir);
return QDir(settingsDir).filePath("CloudView.ini");
}
}
CloudViewSettingsData CloudViewSettings::load()
{
CloudViewSettingsData result;
QSettings settings(settingsFilePath(), QSettings::IniFormat);
// 模式独立于启用状态保存;缺失或非法配置默认采用“替换为全 0”。
const QVariant savedModeValue = settings.contains("PointCloudRange/filterMode")
? settings.value("PointCloudRange/filterMode")
: settings.value("PointCloudRange/mode",
static_cast<int>(PointCloudXYZRangeFilterMode::ReplaceWithZero));
const int savedFilterMode = savedModeValue.toInt();
const PointCloudXYZRangeFilterMode filterMode =
savedFilterMode == static_cast<int>(PointCloudXYZRangeFilterMode::Remove)
? PointCloudXYZRangeFilterMode::Remove
: PointCloudXYZRangeFilterMode::ReplaceWithZero;
const float poseAxisLength = settings.value("Display/poseAxisLength", result.poseAxisLength).toFloat();
if (std::isfinite(poseAxisLength) && poseAxisLength > 0.0f) {
result.poseAxisLength = poseAxisLength;
}
result.pseudoColorEnabled = settings.value("PseudoColor/enabled", result.pseudoColorEnabled).toBool();
const bool hasPaletteSetting = settings.contains("PseudoColor/defaultPalette");
result.pseudoColorDefaultPalette = hasPaletteSetting
? settings.value("PseudoColor/defaultPalette").toBool()
: result.pseudoColorDefaultPalette;
const float period = settings.value("PseudoColor/period", result.pseudoColorPeriod).toFloat();
if (std::isfinite(period) && period > 0.0f) {
result.pseudoColorPeriod = period;
}
const QColor startColor(settings.value("PseudoColor/startColor", "#0000ff").toString());
const QColor endColor(settings.value("PseudoColor/endColor", "#ff0000").toString());
if (startColor.isValid()) {
result.pseudoColorStartColor = QVector3D(startColor.redF(), startColor.greenF(), startColor.blueF());
}
if (endColor.isValid()) {
result.pseudoColorEndColor = QVector3D(endColor.redF(), endColor.greenF(), endColor.blueF());
}
if (!hasPaletteSetting && settings.contains("PseudoColor/period")) {
const QColor legacyStartColor(settings.value("PseudoColor/startColor", "#0000ff").toString());
const QColor legacyEndColor(settings.value("PseudoColor/endColor", "#ff0000").toString());
const bool legacyDefaults = qFuzzyCompare(result.pseudoColorPeriod, 100.0f) &&
legacyStartColor == QColor("#0000ff") &&
legacyEndColor == QColor("#ff0000");
if (legacyDefaults) {
// 旧版周期色环配置迁移为 Z 范围蓝→红梯度。
result.pseudoColorPeriod = 500.0f;
result.pseudoColorStartColor = QVector3D(0.0f, 0.0f, 1.0f);
result.pseudoColorEndColor = QVector3D(1.0f, 0.0f, 0.0f);
result.pseudoColorDefaultPalette = true;
} else {
// 非默认旧配置继续使用原有的自定义起止色渐变。
result.pseudoColorDefaultPalette = false;
}
}
const bool rangeEnabled = settings.value("PointCloudRange/enabled", false).toBool();
PointCloudXYZRange range;
range.enabled = rangeEnabled;
range.filterMode = filterMode;
if (rangeEnabled) {
const auto readBound = [&settings](const char* key, double fallback) {
bool ok = false;
const double value = settings.value(key).toDouble(&ok);
return ok && std::isfinite(value) ? value : fallback;
};
// Missing bounds retain the range object's implicit unbounded side.
range.minX = readBound("PointCloudRange/minX", range.minX);
range.maxX = readBound("PointCloudRange/maxX", range.maxX);
range.minY = readBound("PointCloudRange/minY", range.minY);
range.maxY = readBound("PointCloudRange/maxY", range.maxY);
range.minZ = readBound("PointCloudRange/minZ", range.minZ);
range.maxZ = readBound("PointCloudRange/maxZ", range.maxZ);
if (range.isValid()) {
result.pointCloudRange = range;
}
} else {
result.pointCloudRange = range;
}
// Keep the mode even when a persisted enabled range is invalid and is
// therefore reset to the disabled default range.
result.pointCloudRange.filterMode = filterMode;
return result;
}
bool CloudViewSettings::save(const CloudViewSettingsData& value)
{
QSettings settings(settingsFilePath(), QSettings::IniFormat);
if (std::isfinite(value.poseAxisLength) && value.poseAxisLength > 0.0f) {
settings.setValue("Display/poseAxisLength", value.poseAxisLength);
}
settings.setValue("PseudoColor/enabled", value.pseudoColorEnabled);
settings.setValue("PseudoColor/defaultPalette", value.pseudoColorDefaultPalette);
settings.setValue("PseudoColor/period", qMax(1.0f, value.pseudoColorPeriod));
settings.setValue("PseudoColor/startColor",
QColor::fromRgbF(value.pseudoColorStartColor.x(),
value.pseudoColorStartColor.y(),
value.pseudoColorStartColor.z()).name(QColor::HexRgb));
settings.setValue("PseudoColor/endColor",
QColor::fromRgbF(value.pseudoColorEndColor.x(),
value.pseudoColorEndColor.y(),
value.pseudoColorEndColor.z()).name(QColor::HexRgb));
const PointCloudXYZRange& range = value.pointCloudRange;
const bool saveRange = range.enabled && range.isValid();
settings.setValue("PointCloudRange/enabled", saveRange);
const int filterModeValue = range.filterMode == PointCloudXYZRangeFilterMode::Remove
? static_cast<int>(PointCloudXYZRangeFilterMode::Remove)
: static_cast<int>(PointCloudXYZRangeFilterMode::ReplaceWithZero);
settings.setValue("PointCloudRange/filterMode", filterModeValue);
settings.setValue("PointCloudRange/mode", filterModeValue);
if (saveRange) {
const auto saveBound = [&settings](const char* key, double bound) {
if (std::isfinite(bound)) {
settings.setValue(key, bound);
} else {
settings.remove(key);
}
};
saveBound("PointCloudRange/minX", range.minX);
saveBound("PointCloudRange/maxX", range.maxX);
saveBound("PointCloudRange/minY", range.minY);
saveBound("PointCloudRange/maxY", range.maxY);
saveBound("PointCloudRange/minZ", range.minZ);
saveBound("PointCloudRange/maxZ", range.maxZ);
} else {
// Disabled ranges use implicit infinite bounds; do not persist infinities.
settings.remove("PointCloudRange/minX");
settings.remove("PointCloudRange/maxX");
settings.remove("PointCloudRange/minY");
settings.remove("PointCloudRange/maxY");
settings.remove("PointCloudRange/minZ");
settings.remove("PointCloudRange/maxZ");
}
// Remove keys from the former min/max/stop based implementation so old
// values cannot reappear in the user configuration file.
settings.remove("PseudoColor/autoRange");
settings.remove("PseudoColor/minZ");
settings.remove("PseudoColor/maxZ");
settings.remove("PseudoColor/divisionCount");
settings.remove("PseudoColor/gradient");
settings.remove("PseudoColor/stops");
settings.sync();
return settings.status() == QSettings::NoError;
}