diff --git a/plugin/src/Caelestia/Config/configobject.cpp b/plugin/src/Caelestia/Config/configobject.cpp index 8b53b6d1..030ecabe 100644 --- a/plugin/src/Caelestia/Config/configobject.cpp +++ b/plugin/src/Caelestia/Config/configobject.cpp @@ -30,8 +30,8 @@ void ConfigObject::loadFromJson(const QJsonObject& obj) { continue; if (isGlobalOnly(key)) - qCWarning( - lcConfig, "Option '%s' is global-only and will be ignored in per-monitor config", qUtf8Printable(key)); + qCWarning(lcConfig, "Option '%s' is global-only and will be ignored in per-monitor config", + qUtf8Printable(propertyPath(key))); const auto jsonVal = obj.value(key); @@ -210,6 +210,38 @@ void ConfigObject::resyncFromGlobal() { } } +QString ConfigObject::propertyPath(const QString& name) const { + QStringList parts; + parts.append(name); + + const QObject* obj = this; + while (auto* parentObj = obj->parent()) { + auto* parentConfig = qobject_cast(parentObj); + if (!parentConfig) + break; + + // Find which property name this child is on the parent + const auto* meta = parentConfig->metaObject(); + bool found = false; + for (int i = meta->propertyOffset(); i < meta->propertyCount(); ++i) { + auto prop = meta->property(i); + auto val = prop.read(parentObj); + if (val.value() == obj) { + parts.prepend(QString::fromUtf8(prop.name())); + found = true; + break; + } + } + + if (!found) + break; + + obj = parentObj; + } + + return parts.join(QLatin1Char('.')); +} + bool ConfigObject::isPropertyLoaded(const QString& name) const { return m_loadedKeys.contains(name); } diff --git a/plugin/src/Caelestia/Config/configobject.hpp b/plugin/src/Caelestia/Config/configobject.hpp index d13e6119..c35d812c 100644 --- a/plugin/src/Caelestia/Config/configobject.hpp +++ b/plugin/src/Caelestia/Config/configobject.hpp @@ -48,12 +48,14 @@ private: public: \ [[nodiscard]] Type name() const { \ if (isOverlay()) \ - qCWarning(caelestia::config::lcConfig, "Reading global-only option '%s' on per-monitor overlay", #name); \ + qCWarning(caelestia::config::lcConfig, "Reading global-only option '%s' on per-monitor overlay", \ + qUtf8Printable(propertyPath(QStringLiteral(#name)))); \ return m_##name; \ } \ void set_##name(const Type& val) { \ if (isOverlay()) \ - qCWarning(caelestia::config::lcConfig, "Writing global-only option '%s' on per-monitor overlay", #name); \ + qCWarning(caelestia::config::lcConfig, "Writing global-only option '%s' on per-monitor overlay", \ + qUtf8Printable(propertyPath(QStringLiteral(#name)))); \ if (caelestia::config::ConfigObject::updateMember(m_##name, val)) { \ markPropertyLoaded(QStringLiteral(#name)); \ Q_EMIT name##Changed(); \ @@ -88,6 +90,7 @@ public: void clearLoadedKeys(); [[nodiscard]] bool isPropertyLoaded(const QString& name) const; + [[nodiscard]] QString propertyPath(const QString& name) const; [[nodiscard]] bool isOverlay() const; // Returns true only on overlays — global singleton always returns false. [[nodiscard]] bool isGlobalOnly(const QString& name) const;