fix: move scale back to normal config
This commit is contained in:
parent
d530e209b3
commit
8d73d6037d
8 changed files with 445 additions and 168 deletions
|
|
@ -1,10 +1,10 @@
|
|||
qml_module(caelestia-config
|
||||
URI Caelestia.Config
|
||||
SOURCES
|
||||
config.hpp config.cpp
|
||||
configobject.hpp
|
||||
config.cpp
|
||||
configobject.cpp
|
||||
appearanceconfig.cpp
|
||||
advancedconfig.hpp
|
||||
appearanceconfig.hpp
|
||||
backgroundconfig.hpp
|
||||
barconfig.hpp
|
||||
borderconfig.hpp
|
||||
|
|
@ -21,7 +21,6 @@ qml_module(caelestia-config
|
|||
userpaths.hpp
|
||||
utilitiesconfig.hpp
|
||||
winfoconfig.hpp
|
||||
configobject.cpp
|
||||
LIBRARIES
|
||||
Qt::Quick
|
||||
)
|
||||
|
|
|
|||
|
|
@ -32,14 +32,91 @@ public:
|
|||
, m_expressiveSlowSpatial({ 0.39, 1.29, 0.35, 0.98, 1, 1 }) {}
|
||||
};
|
||||
|
||||
class RoundingTokens : public ConfigObject {
|
||||
Q_OBJECT
|
||||
CONFIG_PROPERTY(int, small, 12)
|
||||
CONFIG_PROPERTY(int, normal, 17)
|
||||
CONFIG_PROPERTY(int, large, 25)
|
||||
CONFIG_PROPERTY(int, full, 1000)
|
||||
|
||||
public:
|
||||
explicit RoundingTokens(QObject* parent = nullptr)
|
||||
: ConfigObject(parent) {}
|
||||
};
|
||||
|
||||
class SpacingTokens : public ConfigObject {
|
||||
Q_OBJECT
|
||||
CONFIG_PROPERTY(int, small, 7)
|
||||
CONFIG_PROPERTY(int, smaller, 10)
|
||||
CONFIG_PROPERTY(int, normal, 12)
|
||||
CONFIG_PROPERTY(int, larger, 15)
|
||||
CONFIG_PROPERTY(int, large, 20)
|
||||
|
||||
public:
|
||||
explicit SpacingTokens(QObject* parent = nullptr)
|
||||
: ConfigObject(parent) {}
|
||||
};
|
||||
|
||||
class PaddingTokens : public ConfigObject {
|
||||
Q_OBJECT
|
||||
CONFIG_PROPERTY(int, small, 5)
|
||||
CONFIG_PROPERTY(int, smaller, 7)
|
||||
CONFIG_PROPERTY(int, normal, 10)
|
||||
CONFIG_PROPERTY(int, larger, 12)
|
||||
CONFIG_PROPERTY(int, large, 15)
|
||||
|
||||
public:
|
||||
explicit PaddingTokens(QObject* parent = nullptr)
|
||||
: ConfigObject(parent) {}
|
||||
};
|
||||
|
||||
class FontSizeTokens : public ConfigObject {
|
||||
Q_OBJECT
|
||||
CONFIG_PROPERTY(int, small, 11)
|
||||
CONFIG_PROPERTY(int, smaller, 12)
|
||||
CONFIG_PROPERTY(int, normal, 13)
|
||||
CONFIG_PROPERTY(int, larger, 15)
|
||||
CONFIG_PROPERTY(int, large, 18)
|
||||
CONFIG_PROPERTY(int, extraLarge, 28)
|
||||
|
||||
public:
|
||||
explicit FontSizeTokens(QObject* parent = nullptr)
|
||||
: ConfigObject(parent) {}
|
||||
};
|
||||
|
||||
class AnimDurationTokens : public ConfigObject {
|
||||
Q_OBJECT
|
||||
CONFIG_PROPERTY(int, small, 200)
|
||||
CONFIG_PROPERTY(int, normal, 400)
|
||||
CONFIG_PROPERTY(int, large, 600)
|
||||
CONFIG_PROPERTY(int, extraLarge, 1000)
|
||||
CONFIG_PROPERTY(int, expressiveFastSpatial, 350)
|
||||
CONFIG_PROPERTY(int, expressiveDefaultSpatial, 500)
|
||||
CONFIG_PROPERTY(int, expressiveSlowSpatial, 650)
|
||||
|
||||
public:
|
||||
explicit AnimDurationTokens(QObject* parent = nullptr)
|
||||
: ConfigObject(parent) {}
|
||||
};
|
||||
|
||||
class AdvancedAppearance : public ConfigObject {
|
||||
Q_OBJECT
|
||||
CONFIG_SUBOBJECT(AnimCurves, curves)
|
||||
CONFIG_SUBOBJECT(RoundingTokens, rounding)
|
||||
CONFIG_SUBOBJECT(SpacingTokens, spacing)
|
||||
CONFIG_SUBOBJECT(PaddingTokens, padding)
|
||||
CONFIG_SUBOBJECT(FontSizeTokens, fontSize)
|
||||
CONFIG_SUBOBJECT(AnimDurationTokens, animDurations)
|
||||
|
||||
public:
|
||||
explicit AdvancedAppearance(QObject* parent = nullptr)
|
||||
: ConfigObject(parent)
|
||||
, m_curves(new AnimCurves(this)) {}
|
||||
, m_curves(new AnimCurves(this))
|
||||
, m_rounding(new RoundingTokens(this))
|
||||
, m_spacing(new SpacingTokens(this))
|
||||
, m_padding(new PaddingTokens(this))
|
||||
, m_fontSize(new FontSizeTokens(this))
|
||||
, m_animDurations(new AnimDurationTokens(this)) {}
|
||||
};
|
||||
|
||||
class BarSizes : public ConfigObject {
|
||||
|
|
|
|||
167
plugin/src/Caelestia/Config/appearanceconfig.cpp
Normal file
167
plugin/src/Caelestia/Config/appearanceconfig.cpp
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
#include "appearanceconfig.hpp"
|
||||
#include "advancedconfig.hpp"
|
||||
|
||||
#include <qmetaobject.h>
|
||||
|
||||
namespace caelestia::config {
|
||||
|
||||
// Helper: connect all changed signals from a token object to a single valuesChanged signal,
|
||||
// plus connect the local scaleChanged signal.
|
||||
template <typename Source, typename Target> static void connectTokenSignals(Source* source, Target* target) {
|
||||
const auto* meta = source->metaObject();
|
||||
|
||||
for (int i = meta->propertyOffset(); i < meta->propertyCount(); ++i) {
|
||||
auto prop = meta->property(i);
|
||||
|
||||
if (prop.hasNotifySignal())
|
||||
QObject::connect(source, prop.notifySignal(), target,
|
||||
target->metaObject()->method(target->metaObject()->indexOfSignal("valuesChanged()")));
|
||||
}
|
||||
|
||||
QObject::connect(target, &Target::scaleChanged, target, &Target::valuesChanged);
|
||||
}
|
||||
|
||||
// AppearanceRounding
|
||||
|
||||
void AppearanceRounding::bindTokens(RoundingTokens* tokens) {
|
||||
m_tokens = tokens;
|
||||
connectTokenSignals(tokens, this);
|
||||
}
|
||||
|
||||
int AppearanceRounding::small() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->small() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int AppearanceRounding::normal() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->normal() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int AppearanceRounding::large() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->large() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int AppearanceRounding::full() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->full() * m_scale) : 0;
|
||||
}
|
||||
|
||||
// AppearanceSpacing
|
||||
|
||||
void AppearanceSpacing::bindTokens(SpacingTokens* tokens) {
|
||||
m_tokens = tokens;
|
||||
connectTokenSignals(tokens, this);
|
||||
}
|
||||
|
||||
int AppearanceSpacing::small() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->small() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int AppearanceSpacing::smaller() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->smaller() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int AppearanceSpacing::normal() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->normal() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int AppearanceSpacing::larger() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->larger() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int AppearanceSpacing::large() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->large() * m_scale) : 0;
|
||||
}
|
||||
|
||||
// AppearancePadding
|
||||
|
||||
void AppearancePadding::bindTokens(PaddingTokens* tokens) {
|
||||
m_tokens = tokens;
|
||||
connectTokenSignals(tokens, this);
|
||||
}
|
||||
|
||||
int AppearancePadding::small() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->small() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int AppearancePadding::smaller() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->smaller() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int AppearancePadding::normal() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->normal() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int AppearancePadding::larger() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->larger() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int AppearancePadding::large() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->large() * m_scale) : 0;
|
||||
}
|
||||
|
||||
// FontSize
|
||||
|
||||
void FontSize::bindTokens(FontSizeTokens* tokens) {
|
||||
m_tokens = tokens;
|
||||
connectTokenSignals(tokens, this);
|
||||
}
|
||||
|
||||
int FontSize::small() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->small() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int FontSize::smaller() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->smaller() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int FontSize::normal() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->normal() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int FontSize::larger() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->larger() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int FontSize::large() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->large() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int FontSize::extraLarge() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->extraLarge() * m_scale) : 0;
|
||||
}
|
||||
|
||||
// AnimDurations
|
||||
|
||||
void AnimDurations::bindTokens(AnimDurationTokens* tokens) {
|
||||
m_tokens = tokens;
|
||||
connectTokenSignals(tokens, this);
|
||||
}
|
||||
|
||||
int AnimDurations::small() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->small() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int AnimDurations::normal() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->normal() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int AnimDurations::large() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->large() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int AnimDurations::extraLarge() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->extraLarge() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int AnimDurations::expressiveFastSpatial() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->expressiveFastSpatial() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int AnimDurations::expressiveDefaultSpatial() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->expressiveDefaultSpatial() * m_scale) : 0;
|
||||
}
|
||||
|
||||
int AnimDurations::expressiveSlowSpatial() const {
|
||||
return m_tokens ? static_cast<int>(m_tokens->expressiveSlowSpatial() * m_scale) : 0;
|
||||
}
|
||||
|
||||
} // namespace caelestia::config
|
||||
|
|
@ -6,76 +6,93 @@
|
|||
|
||||
namespace caelestia::config {
|
||||
|
||||
// Forward declare token types from advancedconfig.hpp
|
||||
class RoundingTokens;
|
||||
class SpacingTokens;
|
||||
class PaddingTokens;
|
||||
class FontSizeTokens;
|
||||
class AnimDurationTokens;
|
||||
|
||||
class AppearanceRounding : public ConfigObject {
|
||||
Q_OBJECT
|
||||
CONFIG_PROPERTY(qreal, scale, 1)
|
||||
|
||||
Q_PROPERTY(int small READ small NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int normal READ normal NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int large READ large NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int full READ full NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int small READ small NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int normal READ normal NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int large READ large NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int full READ full NOTIFY valuesChanged)
|
||||
|
||||
public:
|
||||
explicit AppearanceRounding(QObject* parent = nullptr)
|
||||
: ConfigObject(parent) {}
|
||||
|
||||
[[nodiscard]] int small() const { return static_cast<int>(12 * m_scale); }
|
||||
void bindTokens(RoundingTokens* tokens);
|
||||
|
||||
[[nodiscard]] int normal() const { return static_cast<int>(17 * m_scale); }
|
||||
[[nodiscard]] int small() const;
|
||||
[[nodiscard]] int normal() const;
|
||||
[[nodiscard]] int large() const;
|
||||
[[nodiscard]] int full() const;
|
||||
|
||||
[[nodiscard]] int large() const { return static_cast<int>(25 * m_scale); }
|
||||
Q_SIGNAL void valuesChanged();
|
||||
|
||||
[[nodiscard]] int full() const { return static_cast<int>(1000 * m_scale); }
|
||||
private:
|
||||
RoundingTokens* m_tokens = nullptr;
|
||||
};
|
||||
|
||||
class AppearanceSpacing : public ConfigObject {
|
||||
Q_OBJECT
|
||||
CONFIG_PROPERTY(qreal, scale, 1)
|
||||
|
||||
Q_PROPERTY(int small READ small NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int smaller READ smaller NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int normal READ normal NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int larger READ larger NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int large READ large NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int small READ small NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int smaller READ smaller NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int normal READ normal NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int larger READ larger NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int large READ large NOTIFY valuesChanged)
|
||||
|
||||
public:
|
||||
explicit AppearanceSpacing(QObject* parent = nullptr)
|
||||
: ConfigObject(parent) {}
|
||||
|
||||
[[nodiscard]] int small() const { return static_cast<int>(7 * m_scale); }
|
||||
void bindTokens(SpacingTokens* tokens);
|
||||
|
||||
[[nodiscard]] int smaller() const { return static_cast<int>(10 * m_scale); }
|
||||
[[nodiscard]] int small() const;
|
||||
[[nodiscard]] int smaller() const;
|
||||
[[nodiscard]] int normal() const;
|
||||
[[nodiscard]] int larger() const;
|
||||
[[nodiscard]] int large() const;
|
||||
|
||||
[[nodiscard]] int normal() const { return static_cast<int>(12 * m_scale); }
|
||||
Q_SIGNAL void valuesChanged();
|
||||
|
||||
[[nodiscard]] int larger() const { return static_cast<int>(15 * m_scale); }
|
||||
|
||||
[[nodiscard]] int large() const { return static_cast<int>(20 * m_scale); }
|
||||
private:
|
||||
SpacingTokens* m_tokens = nullptr;
|
||||
};
|
||||
|
||||
class AppearancePadding : public ConfigObject {
|
||||
Q_OBJECT
|
||||
CONFIG_PROPERTY(qreal, scale, 1)
|
||||
|
||||
Q_PROPERTY(int small READ small NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int smaller READ smaller NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int normal READ normal NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int larger READ larger NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int large READ large NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int small READ small NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int smaller READ smaller NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int normal READ normal NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int larger READ larger NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int large READ large NOTIFY valuesChanged)
|
||||
|
||||
public:
|
||||
explicit AppearancePadding(QObject* parent = nullptr)
|
||||
: ConfigObject(parent) {}
|
||||
|
||||
[[nodiscard]] int small() const { return static_cast<int>(5 * m_scale); }
|
||||
void bindTokens(PaddingTokens* tokens);
|
||||
|
||||
[[nodiscard]] int smaller() const { return static_cast<int>(7 * m_scale); }
|
||||
[[nodiscard]] int small() const;
|
||||
[[nodiscard]] int smaller() const;
|
||||
[[nodiscard]] int normal() const;
|
||||
[[nodiscard]] int larger() const;
|
||||
[[nodiscard]] int large() const;
|
||||
|
||||
[[nodiscard]] int normal() const { return static_cast<int>(10 * m_scale); }
|
||||
Q_SIGNAL void valuesChanged();
|
||||
|
||||
[[nodiscard]] int larger() const { return static_cast<int>(12 * m_scale); }
|
||||
|
||||
[[nodiscard]] int large() const { return static_cast<int>(15 * m_scale); }
|
||||
private:
|
||||
PaddingTokens* m_tokens = nullptr;
|
||||
};
|
||||
|
||||
class FontFamily : public ConfigObject {
|
||||
|
|
@ -94,28 +111,30 @@ class FontSize : public ConfigObject {
|
|||
Q_OBJECT
|
||||
CONFIG_PROPERTY(qreal, scale, 1)
|
||||
|
||||
Q_PROPERTY(int small READ small NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int smaller READ smaller NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int normal READ normal NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int larger READ larger NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int large READ large NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int extraLarge READ extraLarge NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int small READ small NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int smaller READ smaller NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int normal READ normal NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int larger READ larger NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int large READ large NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int extraLarge READ extraLarge NOTIFY valuesChanged)
|
||||
|
||||
public:
|
||||
explicit FontSize(QObject* parent = nullptr)
|
||||
: ConfigObject(parent) {}
|
||||
|
||||
[[nodiscard]] int small() const { return static_cast<int>(11 * m_scale); }
|
||||
void bindTokens(FontSizeTokens* tokens);
|
||||
|
||||
[[nodiscard]] int smaller() const { return static_cast<int>(12 * m_scale); }
|
||||
[[nodiscard]] int small() const;
|
||||
[[nodiscard]] int smaller() const;
|
||||
[[nodiscard]] int normal() const;
|
||||
[[nodiscard]] int larger() const;
|
||||
[[nodiscard]] int large() const;
|
||||
[[nodiscard]] int extraLarge() const;
|
||||
|
||||
[[nodiscard]] int normal() const { return static_cast<int>(13 * m_scale); }
|
||||
Q_SIGNAL void valuesChanged();
|
||||
|
||||
[[nodiscard]] int larger() const { return static_cast<int>(15 * m_scale); }
|
||||
|
||||
[[nodiscard]] int large() const { return static_cast<int>(18 * m_scale); }
|
||||
|
||||
[[nodiscard]] int extraLarge() const { return static_cast<int>(28 * m_scale); }
|
||||
private:
|
||||
FontSizeTokens* m_tokens = nullptr;
|
||||
};
|
||||
|
||||
class AppearanceFont : public ConfigObject {
|
||||
|
|
@ -134,31 +153,32 @@ class AnimDurations : public ConfigObject {
|
|||
Q_OBJECT
|
||||
CONFIG_PROPERTY(qreal, scale, 1)
|
||||
|
||||
Q_PROPERTY(int small READ small NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int normal READ normal NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int large READ large NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int extraLarge READ extraLarge NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int expressiveFastSpatial READ expressiveFastSpatial NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int expressiveDefaultSpatial READ expressiveDefaultSpatial NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int expressiveSlowSpatial READ expressiveSlowSpatial NOTIFY scaleChanged)
|
||||
Q_PROPERTY(int small READ small NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int normal READ normal NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int large READ large NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int extraLarge READ extraLarge NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int expressiveFastSpatial READ expressiveFastSpatial NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int expressiveDefaultSpatial READ expressiveDefaultSpatial NOTIFY valuesChanged)
|
||||
Q_PROPERTY(int expressiveSlowSpatial READ expressiveSlowSpatial NOTIFY valuesChanged)
|
||||
|
||||
public:
|
||||
explicit AnimDurations(QObject* parent = nullptr)
|
||||
: ConfigObject(parent) {}
|
||||
|
||||
[[nodiscard]] int small() const { return static_cast<int>(200 * m_scale); }
|
||||
void bindTokens(AnimDurationTokens* tokens);
|
||||
|
||||
[[nodiscard]] int normal() const { return static_cast<int>(400 * m_scale); }
|
||||
[[nodiscard]] int small() const;
|
||||
[[nodiscard]] int normal() const;
|
||||
[[nodiscard]] int large() const;
|
||||
[[nodiscard]] int extraLarge() const;
|
||||
[[nodiscard]] int expressiveFastSpatial() const;
|
||||
[[nodiscard]] int expressiveDefaultSpatial() const;
|
||||
[[nodiscard]] int expressiveSlowSpatial() const;
|
||||
|
||||
[[nodiscard]] int large() const { return static_cast<int>(600 * m_scale); }
|
||||
Q_SIGNAL void valuesChanged();
|
||||
|
||||
[[nodiscard]] int extraLarge() const { return static_cast<int>(1000 * m_scale); }
|
||||
|
||||
[[nodiscard]] int expressiveFastSpatial() const { return static_cast<int>(350 * m_scale); }
|
||||
|
||||
[[nodiscard]] int expressiveDefaultSpatial() const { return static_cast<int>(500 * m_scale); }
|
||||
|
||||
[[nodiscard]] int expressiveSlowSpatial() const { return static_cast<int>(650 * m_scale); }
|
||||
private:
|
||||
AnimDurationTokens* m_tokens = nullptr;
|
||||
};
|
||||
|
||||
class AppearanceAnim : public ConfigObject {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,15 @@
|
|||
#include "config.hpp"
|
||||
|
||||
#include <qdir.h>
|
||||
#include <qfile.h>
|
||||
#include <qfileinfo.h>
|
||||
#include <qjsondocument.h>
|
||||
#include <qjsonobject.h>
|
||||
#include <qlogging.h>
|
||||
#include <qstandardpaths.h>
|
||||
|
||||
namespace caelestia::config {
|
||||
|
||||
static GlobalConfig* s_instance = nullptr;
|
||||
|
||||
static QString configDir() {
|
||||
return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/caelestia/");
|
||||
}
|
||||
|
||||
GlobalConfig::GlobalConfig(QObject* parent)
|
||||
: ConfigObject(parent)
|
||||
, m_appearance(new AppearanceConfig(this))
|
||||
|
|
@ -34,91 +32,32 @@ GlobalConfig::GlobalConfig(QObject* parent)
|
|||
, m_advanced(new AdvancedConfig(this)) {
|
||||
s_instance = this;
|
||||
|
||||
m_configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) +
|
||||
QStringLiteral("/caelestia/shell.json");
|
||||
// Bind token base values from advanced config to appearance computed properties
|
||||
auto* adv = m_advanced->appearance();
|
||||
m_appearance->rounding()->bindTokens(adv->rounding());
|
||||
m_appearance->spacing()->bindTokens(adv->spacing());
|
||||
m_appearance->padding()->bindTokens(adv->padding());
|
||||
m_appearance->font()->size()->bindTokens(adv->fontSize());
|
||||
m_appearance->anim()->durations()->bindTokens(adv->animDurations());
|
||||
|
||||
m_saveTimer.setSingleShot(true);
|
||||
m_saveTimer.setInterval(500);
|
||||
connect(&m_saveTimer, &QTimer::timeout, this, &GlobalConfig::writeToFile);
|
||||
|
||||
m_cooldownTimer.setSingleShot(true);
|
||||
m_cooldownTimer.setInterval(2000);
|
||||
connect(&m_cooldownTimer, &QTimer::timeout, this, [this] {
|
||||
m_recentlySaved = false;
|
||||
emit recentlySavedChanged();
|
||||
});
|
||||
|
||||
connect(&m_watcher, &QFileSystemWatcher::fileChanged, this, &GlobalConfig::onFileChanged);
|
||||
|
||||
reload();
|
||||
|
||||
if (QFile::exists(m_configPath)) {
|
||||
m_watcher.addPath(m_configPath);
|
||||
}
|
||||
// Each has its own file backend
|
||||
setupFileBackend(configDir() + QStringLiteral("shell.json"));
|
||||
m_advanced->setupFileBackend(configDir() + QStringLiteral("advanced.json"));
|
||||
}
|
||||
|
||||
GlobalConfig* GlobalConfig::instance() {
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
bool GlobalConfig::recentlySaved() const {
|
||||
return m_recentlySaved;
|
||||
}
|
||||
|
||||
void GlobalConfig::save() {
|
||||
m_saveTimer.start();
|
||||
m_recentlySaved = true;
|
||||
emit recentlySavedChanged();
|
||||
m_cooldownTimer.start();
|
||||
saveToFile();
|
||||
}
|
||||
|
||||
void GlobalConfig::reload() {
|
||||
QFile file(m_configPath);
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
qWarning() << "Config: failed to open" << m_configPath;
|
||||
return;
|
||||
}
|
||||
|
||||
load(file.readAll());
|
||||
reloadFromFile();
|
||||
}
|
||||
|
||||
void GlobalConfig::load(const QByteArray& contents) {
|
||||
QJsonParseError error{};
|
||||
auto doc = QJsonDocument::fromJson(contents, &error);
|
||||
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qWarning() << "Config: failed to parse JSON:" << error.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
loadFromJson(doc.object());
|
||||
}
|
||||
|
||||
void GlobalConfig::onFileChanged() {
|
||||
if (!m_watcher.files().contains(m_configPath)) {
|
||||
m_watcher.addPath(m_configPath);
|
||||
}
|
||||
|
||||
if (!m_recentlySaved) {
|
||||
reload();
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalConfig::writeToFile() {
|
||||
QDir().mkpath(QFileInfo(m_configPath).absolutePath());
|
||||
|
||||
QFile file(m_configPath);
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
qWarning() << "Config: failed to write" << m_configPath;
|
||||
return;
|
||||
}
|
||||
|
||||
file.write(QJsonDocument(toJsonObject()).toJson(QJsonDocument::Indented));
|
||||
}
|
||||
|
||||
// Config
|
||||
// Config (attached type)
|
||||
|
||||
Config::Config(QQuickItem* parent)
|
||||
: QQuickItem(parent) {}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <qfilesystemwatcher.h>
|
||||
#include <qjsondocument.h>
|
||||
#include <qjsonobject.h>
|
||||
#include <qobject.h>
|
||||
#include <qqmlintegration.h>
|
||||
#include <qquickitem.h>
|
||||
#include <qtimer.h>
|
||||
|
||||
#include "advancedconfig.hpp"
|
||||
#include "appearanceconfig.hpp"
|
||||
|
|
@ -51,33 +46,21 @@ class GlobalConfig : public ConfigObject {
|
|||
CONFIG_SUBOBJECT(SidebarConfig, sidebar)
|
||||
CONFIG_SUBOBJECT(ServiceConfig, services)
|
||||
CONFIG_SUBOBJECT(UserPaths, paths)
|
||||
CONFIG_SUBOBJECT(AdvancedConfig, advanced)
|
||||
|
||||
Q_PROPERTY(bool recentlySaved READ recentlySaved NOTIFY recentlySavedChanged)
|
||||
// advanced is NOT a CONFIG_SUBOBJECT — it has its own file backend
|
||||
Q_PROPERTY(AdvancedConfig* advanced READ advanced CONSTANT)
|
||||
|
||||
public:
|
||||
explicit GlobalConfig(QObject* parent = nullptr);
|
||||
|
||||
static GlobalConfig* instance();
|
||||
|
||||
[[nodiscard]] bool recentlySaved() const;
|
||||
[[nodiscard]] AdvancedConfig* advanced() const { return m_advanced; }
|
||||
|
||||
Q_INVOKABLE void save();
|
||||
Q_INVOKABLE void reload();
|
||||
|
||||
signals:
|
||||
void recentlySavedChanged();
|
||||
|
||||
private:
|
||||
void load(const QByteArray& contents);
|
||||
void onFileChanged();
|
||||
void writeToFile();
|
||||
|
||||
bool m_recentlySaved = false;
|
||||
QString m_configPath;
|
||||
QFileSystemWatcher m_watcher;
|
||||
QTimer m_saveTimer;
|
||||
QTimer m_cooldownTimer;
|
||||
AdvancedConfig* m_advanced = nullptr;
|
||||
};
|
||||
|
||||
class Config : public QQuickItem {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
#include "configobject.hpp"
|
||||
|
||||
#include <qdir.h>
|
||||
#include <qfile.h>
|
||||
#include <qfileinfo.h>
|
||||
#include <qjsonarray.h>
|
||||
#include <qjsondocument.h>
|
||||
#include <qjsonvalue.h>
|
||||
#include <qloggingcategory.h>
|
||||
#include <qmetaobject.h>
|
||||
|
|
@ -104,4 +108,74 @@ QJsonObject ConfigObject::toJsonObject() const {
|
|||
return obj;
|
||||
}
|
||||
|
||||
void ConfigObject::setupFileBackend(const QString& path) {
|
||||
m_filePath = path;
|
||||
|
||||
m_watcher = new QFileSystemWatcher(this);
|
||||
m_saveTimer = new QTimer(this);
|
||||
m_cooldownTimer = new QTimer(this);
|
||||
|
||||
m_saveTimer->setSingleShot(true);
|
||||
m_saveTimer->setInterval(500);
|
||||
connect(m_saveTimer, &QTimer::timeout, this, [this] {
|
||||
QDir().mkpath(QFileInfo(m_filePath).absolutePath());
|
||||
|
||||
QFile file(m_filePath);
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
qCWarning(lcConfig) << "Failed to write" << m_filePath;
|
||||
return;
|
||||
}
|
||||
|
||||
file.write(QJsonDocument(toJsonObject()).toJson(QJsonDocument::Indented));
|
||||
});
|
||||
|
||||
m_cooldownTimer->setSingleShot(true);
|
||||
m_cooldownTimer->setInterval(2000);
|
||||
connect(m_cooldownTimer, &QTimer::timeout, this, [this] {
|
||||
m_recentlySaved = false;
|
||||
});
|
||||
|
||||
connect(m_watcher, &QFileSystemWatcher::fileChanged, this, &ConfigObject::onFileChanged);
|
||||
|
||||
reloadFromFile();
|
||||
|
||||
if (QFile::exists(m_filePath))
|
||||
m_watcher->addPath(m_filePath);
|
||||
}
|
||||
|
||||
void ConfigObject::saveToFile() {
|
||||
if (!m_saveTimer)
|
||||
return;
|
||||
m_saveTimer->start();
|
||||
m_recentlySaved = true;
|
||||
m_cooldownTimer->start();
|
||||
}
|
||||
|
||||
void ConfigObject::reloadFromFile() {
|
||||
QFile file(m_filePath);
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
qCDebug(lcConfig) << "Failed to open" << m_filePath;
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonParseError error{};
|
||||
auto doc = QJsonDocument::fromJson(file.readAll(), &error);
|
||||
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(lcConfig) << "Failed to parse" << m_filePath << ":" << error.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
loadFromJson(doc.object());
|
||||
}
|
||||
|
||||
void ConfigObject::onFileChanged() {
|
||||
if (!m_watcher->files().contains(m_filePath))
|
||||
m_watcher->addPath(m_filePath);
|
||||
|
||||
if (!m_recentlySaved)
|
||||
reloadFromFile();
|
||||
}
|
||||
|
||||
} // namespace caelestia::config
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <qfilesystemwatcher.h>
|
||||
#include <qjsonobject.h>
|
||||
#include <qobject.h>
|
||||
#include <qqmlintegration.h>
|
||||
|
||||
#include <type_traits>
|
||||
#include <qtimer.h>
|
||||
|
||||
// Declares a serialized config property with getter, setter (change-detected), signal, and member.
|
||||
#define CONFIG_PROPERTY(Type, name, ...) \
|
||||
|
|
@ -16,7 +16,7 @@ public:
|
|||
} \
|
||||
void set_##name(const Type& val) { \
|
||||
if (caelestia::config::ConfigObject::updateMember(m_##name, val)) \
|
||||
emit name##Changed(); \
|
||||
Q_EMIT name##Changed(); \
|
||||
} \
|
||||
Q_SIGNAL void name##Changed(); \
|
||||
\
|
||||
|
|
@ -47,6 +47,14 @@ public:
|
|||
void loadFromJson(const QJsonObject& obj);
|
||||
[[nodiscard]] QJsonObject toJsonObject() const;
|
||||
|
||||
// File-backed config support. Call setupFileBackend() to enable
|
||||
// automatic file watching, debounced saving, and reload.
|
||||
void setupFileBackend(const QString& path);
|
||||
void saveToFile();
|
||||
void reloadFromFile();
|
||||
|
||||
[[nodiscard]] bool recentlySaved() const { return m_recentlySaved; }
|
||||
|
||||
template <typename T> static bool updateMember(T& member, const T& value) {
|
||||
if constexpr (std::is_floating_point_v<T>) {
|
||||
if (qFuzzyCompare(member + 1.0, value + 1.0))
|
||||
|
|
@ -58,6 +66,16 @@ public:
|
|||
member = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
void onFileChanged();
|
||||
|
||||
QString m_filePath;
|
||||
bool m_recentlySaved = false;
|
||||
// These are heap-allocated only when setupFileBackend is called
|
||||
QFileSystemWatcher* m_watcher = nullptr;
|
||||
QTimer* m_saveTimer = nullptr;
|
||||
QTimer* m_cooldownTimer = nullptr;
|
||||
};
|
||||
|
||||
} // namespace caelestia::config
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue