config(service): show startup notifications for settings.toml parse errors

This commit is contained in:
Ly-sec
2026-05-07 21:16:36 +02:00
parent 1ab5634d9e
commit 0408f951e5
2 changed files with 36 additions and 20 deletions
+34 -20
View File
@@ -688,6 +688,7 @@ void ConfigService::loadOverridesFromFile() {
m_defaultWallpaperPath.clear();
m_monitorWallpaperPaths.clear();
m_setupWizardCompleted = false;
m_overridesParseError.clear();
if (m_overridesPath.empty() || !std::filesystem::exists(m_overridesPath)) {
return;
@@ -697,7 +698,12 @@ void ConfigService::loadOverridesFromFile() {
try {
m_overridesTable = toml::parse_file(m_overridesPath);
} catch (const toml::parse_error& e) {
kLog.warn("parse error in {}: {}", m_overridesPath, e.what());
const auto& src = e.source();
kLog.warn("parse error in {} at line {}, column {}: {}", m_overridesPath, src.begin.line, src.begin.column,
e.description());
m_overridesParseError =
std::format("{} line {}, column {}: {}", std::filesystem::path(m_overridesPath).filename().string(),
src.begin.line, src.begin.column, e.description());
m_overridesTable = toml::table{};
return;
}
@@ -706,6 +712,28 @@ void ConfigService::loadOverridesFromFile() {
extractWallpaperFromOverrides();
}
void ConfigService::setConfigParseError(std::string parseError) {
if (parseError.empty()) {
// Dismiss any previous config-error notification.
if (m_notificationManager != nullptr && m_configErrorNotificationId != 0) {
m_notificationManager->close(m_configErrorNotificationId);
m_configErrorNotificationId = 0;
}
m_pendingError.clear();
return;
}
if (m_notificationManager != nullptr) {
if (m_configErrorNotificationId != 0) {
m_notificationManager->close(m_configErrorNotificationId);
}
m_configErrorNotificationId =
m_notificationManager->addInternal("Noctalia", "Config parse error", parseError, Urgency::Critical, 0);
} else {
m_pendingError = std::move(parseError);
}
}
void ConfigService::deepMerge(toml::table& base, const toml::table& overlay) {
for (const auto& [k, v] : overlay) {
if (const auto* overlayTbl = v.as_table()) {
@@ -857,6 +885,7 @@ void ConfigService::loadAll() {
});
m_config.bars.push_back(BarConfig{});
m_config.controlCenter.shortcuts = defaultControlCenterShortcuts();
setConfigParseError(m_overridesParseError);
return;
}
@@ -868,25 +897,10 @@ void ConfigService::loadAll() {
kLog.warn("config parse error: {}", semanticError);
}
const std::string parseError = !firstError.empty() ? firstError : semanticError;
if (parseError.empty()) {
// Dismiss any previous config-error notification.
if (m_notificationManager != nullptr && m_configErrorNotificationId != 0) {
m_notificationManager->close(m_configErrorNotificationId);
m_configErrorNotificationId = 0;
}
m_pendingError.clear();
} else {
if (m_notificationManager != nullptr) {
if (m_configErrorNotificationId != 0) {
m_notificationManager->close(m_configErrorNotificationId);
}
m_configErrorNotificationId =
m_notificationManager->addInternal("Noctalia", "Config parse error", parseError, Urgency::Critical, 0);
} else {
m_pendingError = parseError;
}
}
const std::string parseError = !firstError.empty() ? firstError
: !m_overridesParseError.empty() ? m_overridesParseError
: semanticError;
setConfigParseError(parseError);
}
void ConfigService::parseTable(const toml::table& tbl) { parseTableInto(tbl, m_config, true); }
+2
View File
@@ -97,6 +97,7 @@ private:
void setupWatch();
void fireReloadCallbacks();
void loadOverridesFromFile();
void setConfigParseError(std::string parseError);
bool writeOverridesToFile();
void extractWallpaperFromOverrides();
@@ -116,6 +117,7 @@ private:
bool m_setupWizardCompleted = false;
mutable std::unordered_map<std::string, bool> m_effectiveOverrideCache;
std::string m_overridesParseError;
std::string m_pendingError; // parse error from initial load, sent as notification once manager is wired up
uint32_t m_configErrorNotificationId = 0; // ID of the active config-error notification, 0 if none
NotificationManager* m_notificationManager = nullptr;