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
|
qml_module(caelestia-config
|
||||||
URI Caelestia.Config
|
URI Caelestia.Config
|
||||||
SOURCES
|
SOURCES
|
||||||
config.hpp config.cpp
|
config.cpp
|
||||||
configobject.hpp
|
configobject.cpp
|
||||||
|
appearanceconfig.cpp
|
||||||
advancedconfig.hpp
|
advancedconfig.hpp
|
||||||
appearanceconfig.hpp
|
|
||||||
backgroundconfig.hpp
|
backgroundconfig.hpp
|
||||||
barconfig.hpp
|
barconfig.hpp
|
||||||
borderconfig.hpp
|
borderconfig.hpp
|
||||||
|
|
@ -21,7 +21,6 @@ qml_module(caelestia-config
|
||||||
userpaths.hpp
|
userpaths.hpp
|
||||||
utilitiesconfig.hpp
|
utilitiesconfig.hpp
|
||||||
winfoconfig.hpp
|
winfoconfig.hpp
|
||||||
configobject.cpp
|
|
||||||
LIBRARIES
|
LIBRARIES
|
||||||
Qt::Quick
|
Qt::Quick
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -32,14 +32,91 @@ public:
|
||||||
, m_expressiveSlowSpatial({ 0.39, 1.29, 0.35, 0.98, 1, 1 }) {}
|
, 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 {
|
class AdvancedAppearance : public ConfigObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
CONFIG_SUBOBJECT(AnimCurves, curves)
|
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:
|
public:
|
||||||
explicit AdvancedAppearance(QObject* parent = nullptr)
|
explicit AdvancedAppearance(QObject* parent = nullptr)
|
||||||
: ConfigObject(parent)
|
: 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 {
|
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 {
|
namespace caelestia::config {
|
||||||
|
|
||||||
|
// Forward declare token types from advancedconfig.hpp
|
||||||
|
class RoundingTokens;
|
||||||
|
class SpacingTokens;
|
||||||
|
class PaddingTokens;
|
||||||
|
class FontSizeTokens;
|
||||||
|
class AnimDurationTokens;
|
||||||
|
|
||||||
class AppearanceRounding : public ConfigObject {
|
class AppearanceRounding : public ConfigObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
CONFIG_PROPERTY(qreal, scale, 1)
|
CONFIG_PROPERTY(qreal, scale, 1)
|
||||||
|
|
||||||
Q_PROPERTY(int small READ small NOTIFY scaleChanged)
|
Q_PROPERTY(int small READ small NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int normal READ normal NOTIFY scaleChanged)
|
Q_PROPERTY(int normal READ normal NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int large READ large NOTIFY scaleChanged)
|
Q_PROPERTY(int large READ large NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int full READ full NOTIFY scaleChanged)
|
Q_PROPERTY(int full READ full NOTIFY valuesChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit AppearanceRounding(QObject* parent = nullptr)
|
explicit AppearanceRounding(QObject* parent = nullptr)
|
||||||
: ConfigObject(parent) {}
|
: 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 {
|
class AppearanceSpacing : public ConfigObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
CONFIG_PROPERTY(qreal, scale, 1)
|
CONFIG_PROPERTY(qreal, scale, 1)
|
||||||
|
|
||||||
Q_PROPERTY(int small READ small NOTIFY scaleChanged)
|
Q_PROPERTY(int small READ small NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int smaller READ smaller NOTIFY scaleChanged)
|
Q_PROPERTY(int smaller READ smaller NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int normal READ normal NOTIFY scaleChanged)
|
Q_PROPERTY(int normal READ normal NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int larger READ larger NOTIFY scaleChanged)
|
Q_PROPERTY(int larger READ larger NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int large READ large NOTIFY scaleChanged)
|
Q_PROPERTY(int large READ large NOTIFY valuesChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit AppearanceSpacing(QObject* parent = nullptr)
|
explicit AppearanceSpacing(QObject* parent = nullptr)
|
||||||
: ConfigObject(parent) {}
|
: 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); }
|
private:
|
||||||
|
SpacingTokens* m_tokens = nullptr;
|
||||||
[[nodiscard]] int large() const { return static_cast<int>(20 * m_scale); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AppearancePadding : public ConfigObject {
|
class AppearancePadding : public ConfigObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
CONFIG_PROPERTY(qreal, scale, 1)
|
CONFIG_PROPERTY(qreal, scale, 1)
|
||||||
|
|
||||||
Q_PROPERTY(int small READ small NOTIFY scaleChanged)
|
Q_PROPERTY(int small READ small NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int smaller READ smaller NOTIFY scaleChanged)
|
Q_PROPERTY(int smaller READ smaller NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int normal READ normal NOTIFY scaleChanged)
|
Q_PROPERTY(int normal READ normal NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int larger READ larger NOTIFY scaleChanged)
|
Q_PROPERTY(int larger READ larger NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int large READ large NOTIFY scaleChanged)
|
Q_PROPERTY(int large READ large NOTIFY valuesChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit AppearancePadding(QObject* parent = nullptr)
|
explicit AppearancePadding(QObject* parent = nullptr)
|
||||||
: ConfigObject(parent) {}
|
: 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); }
|
private:
|
||||||
|
PaddingTokens* m_tokens = nullptr;
|
||||||
[[nodiscard]] int large() const { return static_cast<int>(15 * m_scale); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FontFamily : public ConfigObject {
|
class FontFamily : public ConfigObject {
|
||||||
|
|
@ -94,28 +111,30 @@ class FontSize : public ConfigObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
CONFIG_PROPERTY(qreal, scale, 1)
|
CONFIG_PROPERTY(qreal, scale, 1)
|
||||||
|
|
||||||
Q_PROPERTY(int small READ small NOTIFY scaleChanged)
|
Q_PROPERTY(int small READ small NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int smaller READ smaller NOTIFY scaleChanged)
|
Q_PROPERTY(int smaller READ smaller NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int normal READ normal NOTIFY scaleChanged)
|
Q_PROPERTY(int normal READ normal NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int larger READ larger NOTIFY scaleChanged)
|
Q_PROPERTY(int larger READ larger NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int large READ large NOTIFY scaleChanged)
|
Q_PROPERTY(int large READ large NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int extraLarge READ extraLarge NOTIFY scaleChanged)
|
Q_PROPERTY(int extraLarge READ extraLarge NOTIFY valuesChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FontSize(QObject* parent = nullptr)
|
explicit FontSize(QObject* parent = nullptr)
|
||||||
: ConfigObject(parent) {}
|
: 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); }
|
private:
|
||||||
|
FontSizeTokens* m_tokens = nullptr;
|
||||||
[[nodiscard]] int large() const { return static_cast<int>(18 * m_scale); }
|
|
||||||
|
|
||||||
[[nodiscard]] int extraLarge() const { return static_cast<int>(28 * m_scale); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AppearanceFont : public ConfigObject {
|
class AppearanceFont : public ConfigObject {
|
||||||
|
|
@ -134,31 +153,32 @@ class AnimDurations : public ConfigObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
CONFIG_PROPERTY(qreal, scale, 1)
|
CONFIG_PROPERTY(qreal, scale, 1)
|
||||||
|
|
||||||
Q_PROPERTY(int small READ small NOTIFY scaleChanged)
|
Q_PROPERTY(int small READ small NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int normal READ normal NOTIFY scaleChanged)
|
Q_PROPERTY(int normal READ normal NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int large READ large NOTIFY scaleChanged)
|
Q_PROPERTY(int large READ large NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int extraLarge READ extraLarge NOTIFY scaleChanged)
|
Q_PROPERTY(int extraLarge READ extraLarge NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int expressiveFastSpatial READ expressiveFastSpatial NOTIFY scaleChanged)
|
Q_PROPERTY(int expressiveFastSpatial READ expressiveFastSpatial NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int expressiveDefaultSpatial READ expressiveDefaultSpatial NOTIFY scaleChanged)
|
Q_PROPERTY(int expressiveDefaultSpatial READ expressiveDefaultSpatial NOTIFY valuesChanged)
|
||||||
Q_PROPERTY(int expressiveSlowSpatial READ expressiveSlowSpatial NOTIFY scaleChanged)
|
Q_PROPERTY(int expressiveSlowSpatial READ expressiveSlowSpatial NOTIFY valuesChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit AnimDurations(QObject* parent = nullptr)
|
explicit AnimDurations(QObject* parent = nullptr)
|
||||||
: ConfigObject(parent) {}
|
: 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); }
|
private:
|
||||||
|
AnimDurationTokens* m_tokens = nullptr;
|
||||||
[[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); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AppearanceAnim : public ConfigObject {
|
class AppearanceAnim : public ConfigObject {
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,15 @@
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
|
|
||||||
#include <qdir.h>
|
|
||||||
#include <qfile.h>
|
|
||||||
#include <qfileinfo.h>
|
|
||||||
#include <qjsondocument.h>
|
|
||||||
#include <qjsonobject.h>
|
|
||||||
#include <qlogging.h>
|
|
||||||
#include <qstandardpaths.h>
|
#include <qstandardpaths.h>
|
||||||
|
|
||||||
namespace caelestia::config {
|
namespace caelestia::config {
|
||||||
|
|
||||||
static GlobalConfig* s_instance = nullptr;
|
static GlobalConfig* s_instance = nullptr;
|
||||||
|
|
||||||
|
static QString configDir() {
|
||||||
|
return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/caelestia/");
|
||||||
|
}
|
||||||
|
|
||||||
GlobalConfig::GlobalConfig(QObject* parent)
|
GlobalConfig::GlobalConfig(QObject* parent)
|
||||||
: ConfigObject(parent)
|
: ConfigObject(parent)
|
||||||
, m_appearance(new AppearanceConfig(this))
|
, m_appearance(new AppearanceConfig(this))
|
||||||
|
|
@ -34,91 +32,32 @@ GlobalConfig::GlobalConfig(QObject* parent)
|
||||||
, m_advanced(new AdvancedConfig(this)) {
|
, m_advanced(new AdvancedConfig(this)) {
|
||||||
s_instance = this;
|
s_instance = this;
|
||||||
|
|
||||||
m_configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) +
|
// Bind token base values from advanced config to appearance computed properties
|
||||||
QStringLiteral("/caelestia/shell.json");
|
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);
|
// Each has its own file backend
|
||||||
m_saveTimer.setInterval(500);
|
setupFileBackend(configDir() + QStringLiteral("shell.json"));
|
||||||
connect(&m_saveTimer, &QTimer::timeout, this, &GlobalConfig::writeToFile);
|
m_advanced->setupFileBackend(configDir() + QStringLiteral("advanced.json"));
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalConfig* GlobalConfig::instance() {
|
GlobalConfig* GlobalConfig::instance() {
|
||||||
return s_instance;
|
return s_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GlobalConfig::recentlySaved() const {
|
|
||||||
return m_recentlySaved;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GlobalConfig::save() {
|
void GlobalConfig::save() {
|
||||||
m_saveTimer.start();
|
saveToFile();
|
||||||
m_recentlySaved = true;
|
|
||||||
emit recentlySavedChanged();
|
|
||||||
m_cooldownTimer.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalConfig::reload() {
|
void GlobalConfig::reload() {
|
||||||
QFile file(m_configPath);
|
reloadFromFile();
|
||||||
|
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
|
||||||
qWarning() << "Config: failed to open" << m_configPath;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
load(file.readAll());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalConfig::load(const QByteArray& contents) {
|
// Config (attached type)
|
||||||
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::Config(QQuickItem* parent)
|
Config::Config(QQuickItem* parent)
|
||||||
: QQuickItem(parent) {}
|
: QQuickItem(parent) {}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <qfilesystemwatcher.h>
|
|
||||||
#include <qjsondocument.h>
|
|
||||||
#include <qjsonobject.h>
|
|
||||||
#include <qobject.h>
|
|
||||||
#include <qqmlintegration.h>
|
#include <qqmlintegration.h>
|
||||||
#include <qquickitem.h>
|
#include <qquickitem.h>
|
||||||
#include <qtimer.h>
|
|
||||||
|
|
||||||
#include "advancedconfig.hpp"
|
#include "advancedconfig.hpp"
|
||||||
#include "appearanceconfig.hpp"
|
#include "appearanceconfig.hpp"
|
||||||
|
|
@ -51,33 +46,21 @@ class GlobalConfig : public ConfigObject {
|
||||||
CONFIG_SUBOBJECT(SidebarConfig, sidebar)
|
CONFIG_SUBOBJECT(SidebarConfig, sidebar)
|
||||||
CONFIG_SUBOBJECT(ServiceConfig, services)
|
CONFIG_SUBOBJECT(ServiceConfig, services)
|
||||||
CONFIG_SUBOBJECT(UserPaths, paths)
|
CONFIG_SUBOBJECT(UserPaths, paths)
|
||||||
CONFIG_SUBOBJECT(AdvancedConfig, advanced)
|
// advanced is NOT a CONFIG_SUBOBJECT — it has its own file backend
|
||||||
|
Q_PROPERTY(AdvancedConfig* advanced READ advanced CONSTANT)
|
||||||
Q_PROPERTY(bool recentlySaved READ recentlySaved NOTIFY recentlySavedChanged)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit GlobalConfig(QObject* parent = nullptr);
|
explicit GlobalConfig(QObject* parent = nullptr);
|
||||||
|
|
||||||
static GlobalConfig* instance();
|
static GlobalConfig* instance();
|
||||||
|
|
||||||
[[nodiscard]] bool recentlySaved() const;
|
[[nodiscard]] AdvancedConfig* advanced() const { return m_advanced; }
|
||||||
|
|
||||||
Q_INVOKABLE void save();
|
Q_INVOKABLE void save();
|
||||||
Q_INVOKABLE void reload();
|
Q_INVOKABLE void reload();
|
||||||
|
|
||||||
signals:
|
|
||||||
void recentlySavedChanged();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void load(const QByteArray& contents);
|
AdvancedConfig* m_advanced = nullptr;
|
||||||
void onFileChanged();
|
|
||||||
void writeToFile();
|
|
||||||
|
|
||||||
bool m_recentlySaved = false;
|
|
||||||
QString m_configPath;
|
|
||||||
QFileSystemWatcher m_watcher;
|
|
||||||
QTimer m_saveTimer;
|
|
||||||
QTimer m_cooldownTimer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Config : public QQuickItem {
|
class Config : public QQuickItem {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
#include "configobject.hpp"
|
#include "configobject.hpp"
|
||||||
|
|
||||||
|
#include <qdir.h>
|
||||||
|
#include <qfile.h>
|
||||||
|
#include <qfileinfo.h>
|
||||||
#include <qjsonarray.h>
|
#include <qjsonarray.h>
|
||||||
|
#include <qjsondocument.h>
|
||||||
#include <qjsonvalue.h>
|
#include <qjsonvalue.h>
|
||||||
#include <qloggingcategory.h>
|
#include <qloggingcategory.h>
|
||||||
#include <qmetaobject.h>
|
#include <qmetaobject.h>
|
||||||
|
|
@ -104,4 +108,74 @@ QJsonObject ConfigObject::toJsonObject() const {
|
||||||
return obj;
|
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
|
} // namespace caelestia::config
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <qfilesystemwatcher.h>
|
||||||
#include <qjsonobject.h>
|
#include <qjsonobject.h>
|
||||||
#include <qobject.h>
|
#include <qobject.h>
|
||||||
#include <qqmlintegration.h>
|
#include <qqmlintegration.h>
|
||||||
|
#include <qtimer.h>
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
// Declares a serialized config property with getter, setter (change-detected), signal, and member.
|
// Declares a serialized config property with getter, setter (change-detected), signal, and member.
|
||||||
#define CONFIG_PROPERTY(Type, name, ...) \
|
#define CONFIG_PROPERTY(Type, name, ...) \
|
||||||
|
|
@ -16,7 +16,7 @@ public:
|
||||||
} \
|
} \
|
||||||
void set_##name(const Type& val) { \
|
void set_##name(const Type& val) { \
|
||||||
if (caelestia::config::ConfigObject::updateMember(m_##name, val)) \
|
if (caelestia::config::ConfigObject::updateMember(m_##name, val)) \
|
||||||
emit name##Changed(); \
|
Q_EMIT name##Changed(); \
|
||||||
} \
|
} \
|
||||||
Q_SIGNAL void name##Changed(); \
|
Q_SIGNAL void name##Changed(); \
|
||||||
\
|
\
|
||||||
|
|
@ -47,6 +47,14 @@ public:
|
||||||
void loadFromJson(const QJsonObject& obj);
|
void loadFromJson(const QJsonObject& obj);
|
||||||
[[nodiscard]] QJsonObject toJsonObject() const;
|
[[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) {
|
template <typename T> static bool updateMember(T& member, const T& value) {
|
||||||
if constexpr (std::is_floating_point_v<T>) {
|
if constexpr (std::is_floating_point_v<T>) {
|
||||||
if (qFuzzyCompare(member + 1.0, value + 1.0))
|
if (qFuzzyCompare(member + 1.0, value + 1.0))
|
||||||
|
|
@ -58,6 +66,16 @@ public:
|
||||||
member = value;
|
member = value;
|
||||||
return true;
|
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
|
} // namespace caelestia::config
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue