fix: propagate per monitor overlay signals to main

This commit is contained in:
2 * r + 2 * t 2026-04-12 03:01:58 +10:00
parent ef00097a51
commit ee9dce0268
8 changed files with 43 additions and 26 deletions

View file

@ -10,20 +10,20 @@ Scope {
Toaster.toast(qsTr("Config loaded"), qsTr("Config loaded successfully!"), "rule_settings");
}
function onLoadFailed(error: string): void {
Toaster.toast(qsTr("Failed to parse config"), error, "settings_alert", Toast.Warning);
function onLoadFailed(error: string, screen: string): void {
Toaster.toast(qsTr("Failed to parse config%1").arg(screen ? " for " + screen : ""), error, "settings_alert", Toast.Warning);
}
function onSaveFailed(error: string): void {
Toaster.toast(qsTr("Failed to save config"), error, "settings_alert", Toast.Error);
function onSaveFailed(error: string, screen: string): void {
Toaster.toast(qsTr("Failed to save config%1").arg(screen ? " for " + screen : ""), error, "settings_alert", Toast.Error);
}
target: GlobalConfig
}
Connections {
function onLoadFailed(error: string): void {
Toaster.toast(qsTr("Failed to parse token config"), error, "settings_alert", Toast.Warning);
function onLoadFailed(error: string, screen: string): void {
Toaster.toast(qsTr("Failed to parse token config%1").arg(screen ? "for " + screen : ""), error, "settings_alert", Toast.Warning);
}
target: TokenConfig

View file

@ -37,7 +37,7 @@ GlobalConfig::GlobalConfig(QObject* parent)
setupFileBackend(configDir() + QStringLiteral("shell.json"));
}
GlobalConfig::GlobalConfig(GlobalConfig* fallback, const QString& filePath, QObject* parent)
GlobalConfig::GlobalConfig(GlobalConfig* fallback, const QString& filePath, const QString& screen, QObject* parent)
: RootConfig(parent)
, m_appearance(new AppearanceConfig(this))
, m_general(new GeneralConfig(this))
@ -57,7 +57,7 @@ GlobalConfig::GlobalConfig(GlobalConfig* fallback, const QString& filePath, QObj
, m_services(new ServiceConfig(this))
, m_paths(new UserPaths(this)) {
if (!filePath.isEmpty())
setupFileBackend(filePath);
setupFileBackend(filePath, screen);
if (fallback)
syncFromGlobal(fallback);
@ -73,7 +73,7 @@ GlobalConfig* GlobalConfig::instance() {
GlobalConfig* GlobalConfig::defaults() {
if (!m_defaults)
m_defaults = new GlobalConfig(nullptr, QString(), this); // Non-singleton constructor
m_defaults = new GlobalConfig(nullptr, QString(), QString(), this);
return m_defaults;
}

View file

@ -56,7 +56,8 @@ public:
private:
friend class MonitorConfigManager;
explicit GlobalConfig(QObject* parent = nullptr);
explicit GlobalConfig(GlobalConfig* fallback, const QString& filePath, QObject* parent = nullptr);
explicit GlobalConfig(
GlobalConfig* fallback, const QString& filePath, const QString& screen = {}, QObject* parent = nullptr);
GlobalConfig* m_defaults = nullptr;
bool m_tokensBound = false;

View file

@ -32,7 +32,13 @@ GlobalConfig* MonitorConfigManager::configForScreen(const QString& screen) {
auto& overlay = m_overlays[screen];
if (!overlay.config) {
auto dir = monitorConfigDir(screen);
overlay.config = new GlobalConfig(GlobalConfig::instance(), dir + QStringLiteral("shell.json"), this);
overlay.config = new GlobalConfig(GlobalConfig::instance(), dir + QStringLiteral("shell.json"), screen, this);
auto* const global = GlobalConfig::instance();
connect(overlay.config, &GlobalConfig::loaded, global, &GlobalConfig::loaded);
connect(overlay.config, &GlobalConfig::saved, global, &GlobalConfig::saved);
connect(overlay.config, &GlobalConfig::loadFailed, global, &GlobalConfig::loadFailed);
connect(overlay.config, &GlobalConfig::saveFailed, global, &GlobalConfig::saveFailed);
}
return overlay.config;
}
@ -41,7 +47,14 @@ TokenConfig* MonitorConfigManager::tokensForScreen(const QString& screen) {
auto& overlay = m_overlays[screen];
if (!overlay.tokens) {
auto dir = monitorConfigDir(screen);
overlay.tokens = new TokenConfig(TokenConfig::instance(), dir + QStringLiteral("shell-tokens.json"), this);
overlay.tokens =
new TokenConfig(TokenConfig::instance(), dir + QStringLiteral("shell-tokens.json"), screen, this);
auto* const global = TokenConfig::instance();
connect(overlay.tokens, &TokenConfig::loaded, global, &TokenConfig::loaded);
connect(overlay.tokens, &TokenConfig::saved, global, &TokenConfig::saved);
connect(overlay.tokens, &TokenConfig::loadFailed, global, &TokenConfig::loadFailed);
connect(overlay.tokens, &TokenConfig::saveFailed, global, &TokenConfig::saveFailed);
}
return overlay.tokens;
}

View file

@ -19,8 +19,9 @@ QString watchRoot() {
RootConfig::RootConfig(QObject* parent)
: ConfigObject(parent) {}
void RootConfig::setupFileBackend(const QString& path) {
void RootConfig::setupFileBackend(const QString& path, const QString& screen) {
m_filePath = path;
m_screen = screen;
m_watcher = new QFileSystemWatcher(this);
m_saveTimer = new QTimer(this);
@ -40,7 +41,7 @@ void RootConfig::setupFileBackend(const QString& path) {
if (!file.open(QIODevice::WriteOnly)) {
auto err = QStringLiteral("Failed to write %1: %2").arg(m_filePath, file.errorString());
qCWarning(lcConfig, "%s", qUtf8Printable(err));
emit saveFailed(err);
emit saveFailed(err, m_screen);
return;
}
@ -51,7 +52,7 @@ void RootConfig::setupFileBackend(const QString& path) {
// Update watches — save may have created directories
updateWatch();
emit saved();
emit saved(m_screen);
});
m_cooldownTimer->setSingleShot(true);
@ -169,9 +170,9 @@ void RootConfig::reload() {
auto result = reloadFromFile();
if (result.has_value()) {
if (result->isEmpty())
emit loaded();
emit loaded(m_screen);
else
emit loadFailed(*result);
emit loadFailed(*result, m_screen);
}
}

View file

@ -16,7 +16,7 @@ class RootConfig : public ConfigObject {
public:
explicit RootConfig(QObject* parent = nullptr);
void setupFileBackend(const QString& path);
void setupFileBackend(const QString& path, const QString& screen = {});
void saveToFile();
// Returns nullopt if retrying, empty string on success, error message on failure.
[[nodiscard]] std::optional<QString> reloadFromFile();
@ -27,16 +27,17 @@ public:
Q_INVOKABLE void reload();
signals:
void loaded();
void loadFailed(const QString& error);
void saved();
void saveFailed(const QString& error);
void loaded(const QString& screen);
void loadFailed(const QString& error, const QString& screen);
void saved(const QString& screen);
void saveFailed(const QString& error, const QString& screen);
private:
void updateWatch();
void onWatcherEvent();
QString m_filePath;
QString m_screen;
QString m_watchedDir;
bool m_recentlySaved = false;

View file

@ -22,12 +22,12 @@ TokenConfig::TokenConfig(QObject* parent)
setupFileBackend(configDir() + QStringLiteral("shell-tokens.json"));
}
TokenConfig::TokenConfig(TokenConfig* fallback, const QString& filePath, QObject* parent)
TokenConfig::TokenConfig(TokenConfig* fallback, const QString& filePath, const QString& screen, QObject* parent)
: RootConfig(parent)
, m_appearance(new AppearanceTokens(this))
, m_sizes(new SizeTokens(this)) {
if (!filePath.isEmpty())
setupFileBackend(filePath);
setupFileBackend(filePath, screen);
if (fallback)
syncFromGlobal(fallback);
}
@ -39,7 +39,7 @@ TokenConfig* TokenConfig::instance() {
TokenConfig* TokenConfig::defaults() {
if (!m_defaults)
m_defaults = new TokenConfig(nullptr, QString(), this); // Non-singleton constructor
m_defaults = new TokenConfig(nullptr, QString(), QString(), this);
return m_defaults;
}

View file

@ -335,7 +335,8 @@ public:
private:
friend class MonitorConfigManager;
explicit TokenConfig(QObject* parent = nullptr);
explicit TokenConfig(TokenConfig* fallback, const QString& filePath, QObject* parent = nullptr);
explicit TokenConfig(
TokenConfig* fallback, const QString& filePath, const QString& screen = {}, QObject* parent = nullptr);
TokenConfig* m_defaults = nullptr;
};