feat: config object migration path and add new options to settings
This commit is contained in:
@@ -13,21 +13,17 @@ import qs.Paths
|
|||||||
Singleton {
|
Singleton {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property M3Palette current: M3Palette {
|
readonly property M3Palette current: M3Palette {}
|
||||||
}
|
|
||||||
property bool currentLight
|
property bool currentLight
|
||||||
property string flavour
|
property string flavour
|
||||||
readonly property bool light: showPreview ? previewLight : currentLight
|
readonly property bool light: showPreview ? previewLight : currentLight
|
||||||
readonly property M3Palette palette: showPreview ? preview : current
|
readonly property M3Palette palette: showPreview ? preview : current
|
||||||
readonly property M3Palette preview: M3Palette {
|
readonly property M3Palette preview: M3Palette {}
|
||||||
}
|
|
||||||
property bool previewLight
|
property bool previewLight
|
||||||
property string scheme
|
property string scheme
|
||||||
property bool showPreview
|
property bool showPreview
|
||||||
readonly property M3TPalette tPalette: M3TPalette {
|
readonly property M3TPalette tPalette: M3TPalette {}
|
||||||
}
|
readonly property Transparency transparency: Transparency {}
|
||||||
readonly property Transparency transparency: Transparency {
|
|
||||||
}
|
|
||||||
readonly property alias wallLuminance: analyser.luminance
|
readonly property alias wallLuminance: analyser.luminance
|
||||||
|
|
||||||
function alterColor(c: color, a: real, layer: int): color {
|
function alterColor(c: color, a: real, layer: int): color {
|
||||||
@@ -112,8 +108,7 @@ Singleton {
|
|||||||
|
|
||||||
function setMode(mode: string): void {
|
function setMode(mode: string): void {
|
||||||
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--mode", mode]);
|
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--mode", mode]);
|
||||||
Config.general.color.mode = mode;
|
Config.colors.mode = mode;
|
||||||
Config.save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function swapRG(c: color): color {
|
function swapRG(c: color): color {
|
||||||
|
|||||||
@@ -11,14 +11,14 @@ import qs.Services
|
|||||||
Singleton {
|
Singleton {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property int darkEnd: Config.general.color.scheduleDarkEnd
|
readonly property int darkEnd: Config.colors.scheduleDarkEnd
|
||||||
readonly property int darkStart: Config.general.color.scheduleDarkStart
|
readonly property int darkStart: Config.colors.scheduleDarkStart
|
||||||
readonly property bool enabled: Config.general.color.scheduleDark && Config.general.color.schemeGeneration
|
readonly property bool enabled: Config.colors.scheduleDark && Config.colors.schemeGen
|
||||||
|
|
||||||
function applyDarkMode() {
|
function applyDarkMode() {
|
||||||
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--mode", "dark"]);
|
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--mode", "dark"]);
|
||||||
|
|
||||||
Config.general.color.mode = "dark";
|
Config.colors.mode = "dark";
|
||||||
|
|
||||||
Quickshell.execDetached(["gsettings", "set", "org.gnome.desktop.interface", "color-scheme", "'prefer-dark'"]);
|
Quickshell.execDetached(["gsettings", "set", "org.gnome.desktop.interface", "color-scheme", "'prefer-dark'"]);
|
||||||
|
|
||||||
@@ -30,13 +30,13 @@ Singleton {
|
|||||||
function applyLightMode() {
|
function applyLightMode() {
|
||||||
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--mode", "light"]);
|
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--mode", "light"]);
|
||||||
|
|
||||||
Config.general.color.mode = "light";
|
Config.colors.mode = "light";
|
||||||
|
|
||||||
Quickshell.execDetached(["gsettings", "set", "org.gnome.desktop.interface", "color-scheme", "'prefer-light'"]);
|
Quickshell.execDetached(["gsettings", "set", "org.gnome.desktop.interface", "color-scheme", "'prefer-light'"]);
|
||||||
|
|
||||||
Quickshell.execDetached(["sh", "-c", `sed -i 's/color_scheme_path=\\(.*\\)Dark.colors/color_scheme_path=\\1Light.colors/' ${Paths.home}/.config/qt6ct/qt6ct.conf`]);
|
Quickshell.execDetached(["sh", "-c", `sed -i 's/color_scheme_path=\\(.*\\)Dark.colors/color_scheme_path=\\1Light.colors/' ${Paths.home}/.config/qt6ct/qt6ct.conf`]);
|
||||||
|
|
||||||
if (Config.general.color.neovimColors)
|
if (Config.colors.neovimColors)
|
||||||
Quickshell.execDetached(["sed", "-i", "'s/\\(vim.cmd.colorscheme \\).*/\\1\"onelight\"/'", "~/.config/nvim/lua/config/load-colorscheme.lua"]);
|
Quickshell.execDetached(["sed", "-i", "'s/\\(vim.cmd.colorscheme \\).*/\\1\"onelight\"/'", "~/.config/nvim/lua/config/load-colorscheme.lua"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ Singleton {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property bool enabled: service.enabled
|
readonly property bool enabled: service.enabled
|
||||||
readonly property int end: Config.general.color.scheduleHyprsunsetEnd
|
readonly property int end: Config.display.nightlight.scheduleEnd
|
||||||
property bool manualToggle: false
|
property bool manualToggle: false
|
||||||
readonly property int start: Config.general.color.scheduleHyprsunsetStart
|
readonly property int start: Config.display.nightlight.scheduleStart
|
||||||
readonly property int temp: Config.general.color.hyprsunsetTemp
|
readonly property int temp: Config.display.nightlight.temp
|
||||||
|
|
||||||
function checkStartup(): void {
|
function checkStartup(): void {
|
||||||
if (!Config.general.color.scheduleHyprsunset)
|
if (!Config.display.nightlight.schedule)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
service.apply();
|
service.apply();
|
||||||
@@ -29,11 +29,11 @@ Singleton {
|
|||||||
NightlightManager {
|
NightlightManager {
|
||||||
id: service
|
id: service
|
||||||
|
|
||||||
activeAuto: Config.general.color.scheduleHyprsunset
|
activeAuto: Config.display.nightlight.schedule
|
||||||
endTime: root.end
|
endTime: root.end
|
||||||
startTime: root.start
|
startTime: root.start
|
||||||
temp: root.temp
|
temp: root.temp
|
||||||
fadeDuration: Config.general.color.nativeFadeDuration / 1000
|
fadeDuration: Config.display.nightlight.fadeDuration / 1000
|
||||||
useNativeNightlight: Config.general.color.useNativeNightlight
|
useNativeNightlight: Config.display.nightlight.useNative
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ Searcher {
|
|||||||
previewPath = path;
|
previewPath = path;
|
||||||
showPreview = true;
|
showPreview = true;
|
||||||
|
|
||||||
if (Config.general.color.schemeGeneration)
|
if (Config.colors.schemeGen)
|
||||||
previewColorsProc.running = true;
|
previewColorsProc.running = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,8 +62,8 @@ Searcher {
|
|||||||
WallpaperPath.currentWallpaperPath = path;
|
WallpaperPath.currentWallpaperPath = path;
|
||||||
Quickshell.screens.forEach(n => setCrop(n.name, Qt.rect(0, 0, 1, 1), 1.0));
|
Quickshell.screens.forEach(n => setCrop(n.name, Qt.rect(0, 0, 1, 1), 1.0));
|
||||||
Quickshell.execDetached(["zshell-cli", "wallpaper", "lockscreen", "--input-image", `${root.actualCurrent}`, "--output-path", `${Paths.state}/lockscreen_bg.png`, "--blur-amount", `${Config.lock.blurAmount}`]);
|
Quickshell.execDetached(["zshell-cli", "wallpaper", "lockscreen", "--input-image", `${root.actualCurrent}`, "--output-path", `${Paths.state}/lockscreen_bg.png`, "--blur-amount", `${Config.lock.blurAmount}`]);
|
||||||
if (Config.general.color.schemeGeneration)
|
if (Config.colors.schemeGen)
|
||||||
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--image-path", `${root.actualCurrent}`, "--scheme", `${Config.colors.schemeType}`, "--mode", `${Config.general.color.mode}`]);
|
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--image-path", `${root.actualCurrent}`, "--scheme", `${Config.colors.schemeType}`, "--mode", `${Config.colors.mode}`]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopPreview(): void {
|
function stopPreview(): void {
|
||||||
|
|||||||
+11
-11
@@ -43,17 +43,17 @@ Item {
|
|||||||
|
|
||||||
Component.onCompleted: root.loadPage(root.sState.currentPageIdx)
|
Component.onCompleted: root.loadPage(root.sState.currentPageIdx)
|
||||||
|
|
||||||
CustomRect {
|
// CustomRect {
|
||||||
anchors.fill: parent
|
// anchors.fill: parent
|
||||||
color: Qt.alpha(Colors.palette.m3shadow, 0.3)
|
// color: Qt.alpha(Colors.palette.m3shadow, 0.3)
|
||||||
opacity: root.sState.dimmed ? 1 : 0
|
// opacity: root.sState.dimmed ? 1 : 0
|
||||||
visible: opacity > 0
|
// visible: opacity > 0
|
||||||
z: 0
|
// z: 0
|
||||||
|
//
|
||||||
Behavior on opacity {
|
// Behavior on opacity {
|
||||||
Anim {}
|
// Anim {}
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
|
|||||||
@@ -202,12 +202,12 @@ PageBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ToggleRow {
|
ToggleRow {
|
||||||
checked: Config.general.color.smart
|
checked: Config.colors.smart
|
||||||
settingAnchor: "services-smart-color-scheme"
|
settingAnchor: "services-smart-color-scheme"
|
||||||
subtext: qsTr("Derive theme mode from the wallpaper")
|
subtext: qsTr("Derive theme mode from the wallpaper")
|
||||||
text: qsTr("Smart color scheme")
|
text: qsTr("Smart color scheme")
|
||||||
|
|
||||||
onToggled: Config.general.color.smart = checked
|
onToggled: Config.colors.smart = checked
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectRow {
|
SelectRow {
|
||||||
|
|||||||
@@ -73,15 +73,15 @@ PageBase {
|
|||||||
ToggleRow {
|
ToggleRow {
|
||||||
text: qsTr("Dynamic colors")
|
text: qsTr("Dynamic colors")
|
||||||
first: true
|
first: true
|
||||||
subtext: qsTr("Automatic color scheme based on wallpaper is %1").arg(Config.general.color.schemeGeneration ? "enabled" : "disabled")
|
subtext: qsTr("Automatic color scheme based on wallpaper is %1").arg(Config.colors.schemeGen ? "enabled" : "disabled")
|
||||||
checked: Config.general.color.schemeGeneration
|
checked: Config.colors.schemeGen
|
||||||
settingAnchor: "colors-fonts-dynamic-colors"
|
settingAnchor: "colors-fonts-dynamic-colors"
|
||||||
|
|
||||||
onToggled: {
|
onToggled: {
|
||||||
Config.general.color.schemeGeneration = checked;
|
Config.colors.schemeGen = checked;
|
||||||
|
|
||||||
if (checked)
|
if (checked)
|
||||||
Colors.setMode(Config.general.color.mode);
|
Colors.setMode(Config.colors.mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ PageBase {
|
|||||||
settingAnchor: "colors-fonts-preset-scheme"
|
settingAnchor: "colors-fonts-preset-scheme"
|
||||||
model: root.schemes
|
model: root.schemes
|
||||||
acceptLabel: qsTr("Confirm")
|
acceptLabel: qsTr("Confirm")
|
||||||
enabled: !Config.general.color.schemeGeneration
|
enabled: !Config.colors.schemeGen
|
||||||
header: qsTr("Select scheme")
|
header: qsTr("Select scheme")
|
||||||
rowButton.activeItem: root.schemes.find(s => {
|
rowButton.activeItem: root.schemes.find(s => {
|
||||||
var regex = new RegExp(Config.colors.presets.name, "i");
|
var regex = new RegExp(Config.colors.presets.name, "i");
|
||||||
@@ -157,7 +157,7 @@ PageBase {
|
|||||||
}
|
}
|
||||||
// qmlformat on
|
// qmlformat on
|
||||||
acceptLabel: qsTr("Confirm")
|
acceptLabel: qsTr("Confirm")
|
||||||
enabled: !Config.general.color.schemeGeneration && model.length > 1
|
enabled: !Config.colors.schemeGen && model.length > 1
|
||||||
header: qsTr("Select variant")
|
header: qsTr("Select variant")
|
||||||
rowButton.activeItem: {
|
rowButton.activeItem: {
|
||||||
const v = Config.colors.presets.variant ?? "";
|
const v = Config.colors.presets.variant ?? "";
|
||||||
@@ -210,7 +210,7 @@ PageBase {
|
|||||||
}
|
}
|
||||||
// qmlformat on
|
// qmlformat on
|
||||||
acceptLabel: qsTr("Confirm")
|
acceptLabel: qsTr("Confirm")
|
||||||
enabled: !Config.general.color.schemeGeneration && model.length > 1
|
enabled: !Config.colors.schemeGen && model.length > 1
|
||||||
header: qsTr("Select accent")
|
header: qsTr("Select accent")
|
||||||
rowButton.activeItem: {
|
rowButton.activeItem: {
|
||||||
const a = Config.colors.presets.accent ?? "";
|
const a = Config.colors.presets.accent ?? "";
|
||||||
|
|||||||
@@ -96,20 +96,21 @@ PageBase {
|
|||||||
TimeDialogSelect {
|
TimeDialogSelect {
|
||||||
readonly property string endTime: {
|
readonly property string endTime: {
|
||||||
var d = new Date(0, 0, 0, 0, 0, 0, 0);
|
var d = new Date(0, 0, 0, 0, 0, 0, 0);
|
||||||
d.setMinutes(Config.general.color.scheduleDarkEnd);
|
d.setMinutes(Config.colors.scheduleDarkEnd);
|
||||||
return Qt.formatTime(d, "hh:mm AP");
|
return Qt.formatTime(d, "hh:mm AP");
|
||||||
}
|
}
|
||||||
readonly property string startTime: {
|
readonly property string startTime: {
|
||||||
var d = new Date(0, 0, 0, 0, 0, 0, 0);
|
var d = new Date(0, 0, 0, 0, 0, 0, 0);
|
||||||
d.setMinutes(Config.general.color.scheduleDarkStart);
|
d.setMinutes(Config.colors.scheduleDarkStart);
|
||||||
return Qt.formatTime(d, "hh:mm AP");
|
return Qt.formatTime(d, "hh:mm AP");
|
||||||
}
|
}
|
||||||
|
|
||||||
rowButton.checked: Config.general.color.scheduleDark
|
rowButton.checked: Config.colors.scheduleDark
|
||||||
rowButton.onToggled: Config.general.color.scheduleDark = rowButton.checked
|
rowButton.onToggled: Config.colors.scheduleDark = rowButton.checked
|
||||||
start: Config.general.color.scheduleDarkStart
|
start: Config.colors.scheduleDarkStart
|
||||||
end: Config.general.color.scheduleDarkEnd
|
end: Config.colors.scheduleDarkEnd
|
||||||
first: true
|
first: true
|
||||||
|
last: true
|
||||||
settingAnchor: "style-schedule-dark-mode"
|
settingAnchor: "style-schedule-dark-mode"
|
||||||
acceptLabel: qsTr("Apply")
|
acceptLabel: qsTr("Apply")
|
||||||
rootParent: root.flickable
|
rootParent: root.flickable
|
||||||
@@ -122,8 +123,8 @@ PageBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
Config.general.color.scheduleDarkStart = startCurrent;
|
Config.colors.scheduleDarkStart = startCurrent;
|
||||||
Config.general.color.scheduleDarkEnd = endCurrent;
|
Config.colors.scheduleDarkEnd = endCurrent;
|
||||||
ModeScheduler.checkStartup();
|
ModeScheduler.checkStartup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,27 +132,26 @@ PageBase {
|
|||||||
TimeDialogSelect {
|
TimeDialogSelect {
|
||||||
readonly property string endTime: {
|
readonly property string endTime: {
|
||||||
var d = new Date(0, 0, 0, 0, 0, 0, 0);
|
var d = new Date(0, 0, 0, 0, 0, 0, 0);
|
||||||
d.setMinutes(Config.general.color.scheduleHyprsunsetEnd);
|
d.setMinutes(Config.display.nightlight.scheduleEnd);
|
||||||
return Qt.formatTime(d, "hh:mm AP");
|
return Qt.formatTime(d, "hh:mm AP");
|
||||||
}
|
}
|
||||||
readonly property string startTime: {
|
readonly property string startTime: {
|
||||||
var d = new Date(0, 0, 0, 0, 0, 0, 0);
|
var d = new Date(0, 0, 0, 0, 0, 0, 0);
|
||||||
d.setMinutes(Config.general.color.scheduleHyprsunsetStart);
|
d.setMinutes(Config.display.nightlight.scheduleStart);
|
||||||
return Qt.formatTime(d, "hh:mm AP");
|
return Qt.formatTime(d, "hh:mm AP");
|
||||||
}
|
}
|
||||||
|
|
||||||
Layout.topMargin: Tokens.spacing.extraSmall / 2 - parent.spacing
|
rowButton.checked: Config.display.nightlight.schedule
|
||||||
rowButton.checked: Config.general.color.scheduleHyprsunset
|
rowButton.onToggled: Config.display.nightlight.schedule = rowButton.checked
|
||||||
rowButton.onToggled: Config.general.color.scheduleHyprsunset = rowButton.checked
|
start: Config.display.nightlight.scheduleStart
|
||||||
start: Config.general.color.scheduleHyprsunsetStart
|
end: Config.display.nightlight.scheduleEnd
|
||||||
end: Config.general.color.scheduleHyprsunsetEnd
|
first: true
|
||||||
last: true
|
settingAnchor: "style-schedule-nightlight"
|
||||||
settingAnchor: "style-schedule-hyprsunset"
|
|
||||||
acceptLabel: qsTr("Apply")
|
acceptLabel: qsTr("Apply")
|
||||||
rootParent: root.flickable
|
rootParent: root.flickable
|
||||||
header: qsTr("Select time")
|
header: qsTr("Select time")
|
||||||
subtext: qsTr("Hyprsunset will turn on at %1, and turn off at %2.").arg(startTime).arg(endTime)
|
subtext: qsTr("Nightlight will turn on at %1, and turn off at %2.").arg(startTime).arg(endTime)
|
||||||
label: qsTr("Schedule hyprsunset")
|
label: qsTr("Schedule nightlight")
|
||||||
|
|
||||||
onOpenChanged: {
|
onOpenChanged: {
|
||||||
root.sState.dimmed = open;
|
root.sState.dimmed = open;
|
||||||
@@ -163,5 +163,46 @@ PageBase {
|
|||||||
Nightlight.checkStartup();
|
Nightlight.checkStartup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ToggleRow {
|
||||||
|
Layout.topMargin: Tokens.spacing.extraSmall / 2 - parent.spacing
|
||||||
|
|
||||||
|
checked: Config.display.nightlight.useNative
|
||||||
|
settingAnchor: "display-nightlight-useNative"
|
||||||
|
text: qsTr("Use native")
|
||||||
|
subtext: qsTr("Use native shader nightlight for more features")
|
||||||
|
|
||||||
|
onToggled: Config.display.nightlight.useNative = checked
|
||||||
|
}
|
||||||
|
|
||||||
|
SpinRow {
|
||||||
|
Layout.topMargin: Tokens.spacing.extraSmall / 2 - parent.spacing
|
||||||
|
|
||||||
|
from: 2000
|
||||||
|
settingAnchor: "display-nightlight-temp"
|
||||||
|
stepSize: 100
|
||||||
|
subtext: qsTr("How warm/orange the screen will be. Lower is warmer (Kelvin)")
|
||||||
|
text: qsTr("Temperature")
|
||||||
|
to: 6500
|
||||||
|
value: Config.display.nightlight.temp
|
||||||
|
|
||||||
|
onMoved: v => Config.display.nightlight.temp = v
|
||||||
|
}
|
||||||
|
|
||||||
|
SpinRow {
|
||||||
|
Layout.topMargin: Tokens.spacing.extraSmall / 2 - parent.spacing
|
||||||
|
|
||||||
|
from: 0
|
||||||
|
settingAnchor: "display-nightlight-fade-duration"
|
||||||
|
enabled: Config.display.nightlight.useNative
|
||||||
|
last: true
|
||||||
|
stepSize: 1
|
||||||
|
subtext: qsTr("How long it takes for the gradual nightlight to finish (s)")
|
||||||
|
text: qsTr("Fade duration")
|
||||||
|
to: 60 * 5
|
||||||
|
value: Config.display.nightlight.fadeDuration / 1000
|
||||||
|
|
||||||
|
onMoved: v => Config.display.nightlight.fadeDuration = v * 1000
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ qml_module(ZShell-config
|
|||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
ZShell.Settings
|
ZShell.Settings
|
||||||
SOURCES
|
SOURCES
|
||||||
common.hpp common.cpp
|
confignode.hpp confignode.cpp
|
||||||
rootnodes.hpp rootnodes.cpp
|
configobject.hpp configobject.cpp
|
||||||
|
configlist.hpp configlist.cpp
|
||||||
|
config.hpp config.cpp
|
||||||
migration.hpp migration.cpp
|
migration.hpp migration.cpp
|
||||||
anim.hpp anim.cpp
|
anim.hpp anim.cpp
|
||||||
fontbuilder.hpp fontbuilder.cpp
|
fontbuilder.hpp fontbuilder.cpp
|
||||||
@@ -17,6 +19,7 @@ qml_module(ZShell-config
|
|||||||
clipboard.hpp
|
clipboard.hpp
|
||||||
colors.hpp
|
colors.hpp
|
||||||
dashboard.hpp
|
dashboard.hpp
|
||||||
|
display.hpp
|
||||||
dock.hpp
|
dock.hpp
|
||||||
enums.hpp
|
enums.hpp
|
||||||
general.hpp
|
general.hpp
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
#include "migration.hpp"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace ZShell::config {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// A stored value is "missing" if the path does not resolve to an entry.
|
||||||
|
// Note: default-constructed QJsonValue is Null, not Undefined.
|
||||||
|
bool isMissing(const QJsonValue& v) {
|
||||||
|
return v.isUndefined() || v.isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonValue valueAt(const QJsonObject& obj, const QStringList& path) {
|
||||||
|
QJsonObject cur = obj;
|
||||||
|
|
||||||
|
for (int i = 0; i < path.size() - 1; ++i) {
|
||||||
|
if (!cur.value(path.at(i)).isObject()) return QJsonValue::Undefined;
|
||||||
|
cur = cur.value(path.at(i)).toObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString key = path.last();
|
||||||
|
if (!cur.contains(key)) return QJsonValue::Undefined;
|
||||||
|
return cur.value(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject placeAt(QJsonObject obj, QStringList path, const QJsonValue& value) {
|
||||||
|
const QString head = path.takeFirst();
|
||||||
|
|
||||||
|
if (path.isEmpty()) {
|
||||||
|
obj[head] = value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject child = obj.value(head).isObject() ? obj.value(head).toObject()
|
||||||
|
: QJsonObject();
|
||||||
|
obj[head] = placeAt(child, path, value);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes `path` from `obj`. Returns true if a value was removed.
|
||||||
|
// Parent objects left empty are removed as well.
|
||||||
|
bool removeAt(QJsonObject& obj, const QStringList& path) {
|
||||||
|
const QString head = path.first();
|
||||||
|
|
||||||
|
if (path.size() == 1) {
|
||||||
|
if (!obj.contains(head)) return false;
|
||||||
|
obj.remove(head);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!obj.value(head).isObject()) return false;
|
||||||
|
|
||||||
|
QJsonObject child = obj.value(head).toObject();
|
||||||
|
const bool removed = removeAt(child, path.mid(1));
|
||||||
|
|
||||||
|
if (child.isEmpty())
|
||||||
|
obj.remove(head);
|
||||||
|
else
|
||||||
|
obj[head] = child;
|
||||||
|
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
const QList<ConfigMigrationRule>& ConfigMigrations::rules() {
|
||||||
|
static const QList<ConfigMigrationRule> s_rules = {
|
||||||
|
migrate(
|
||||||
|
"general.color.scheduleHyprsunset", "display.nightlight.schedule"),
|
||||||
|
migrate(
|
||||||
|
"general.color.scheduleHyprsunsetStart",
|
||||||
|
"display.nightlight.scheduleStart"),
|
||||||
|
migrate(
|
||||||
|
"general.color.scheduleHyprsunsetEnd",
|
||||||
|
"display.nightlight.scheduleEnd"),
|
||||||
|
migrate("general.color.scheduleDark", "colors.scheduleDark"),
|
||||||
|
migrate("general.color.scheduleDarkStart", "colors.scheduleDarkStart"),
|
||||||
|
migrate("general.color.scheduleDarkEnd", "colors.scheduleDarkEnd"),
|
||||||
|
migrate("general.color.schemeGeneration", "colors.schemeGen"),
|
||||||
|
migrate(
|
||||||
|
"general.color.useNativeNightlight",
|
||||||
|
"display.nightlight.useNative"),
|
||||||
|
migrate(
|
||||||
|
"general.color.nativeFadeDuration",
|
||||||
|
"display.nightlight.fadeDuration"),
|
||||||
|
migrate("general.color.hyprsunsetTemp", "display.nightlight.temp"),
|
||||||
|
migrate("general.color.neovimColors", "colors.neovimColors"),
|
||||||
|
migrate("general.color.mode", "colors.mode"),
|
||||||
|
migrate("general.color.smart", "colors.smart"),
|
||||||
|
};
|
||||||
|
return s_rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject ConfigMigrations::apply(const QJsonObject& json) {
|
||||||
|
QJsonObject obj = json;
|
||||||
|
|
||||||
|
for (const auto& rule : rules()) {
|
||||||
|
const QStringList from =
|
||||||
|
rule.from.split(QLatin1Char('.'), Qt::SkipEmptyParts);
|
||||||
|
const QStringList to =
|
||||||
|
rule.to.split(QLatin1Char('.'), Qt::SkipEmptyParts);
|
||||||
|
|
||||||
|
if (from.isEmpty() || to.isEmpty()) continue;
|
||||||
|
|
||||||
|
const QJsonValue oldValue = valueAt(obj, from);
|
||||||
|
if (isMissing(oldValue)) continue;
|
||||||
|
|
||||||
|
const bool targetExists = !isMissing(valueAt(obj, to));
|
||||||
|
if (!targetExists) obj = placeAt(obj, to, oldValue);
|
||||||
|
|
||||||
|
if (removeAt(obj, from)) {
|
||||||
|
qInfo() << "Config migration:" << rule.from << "->" << rule.to
|
||||||
|
<< (targetExists ? "(target already set, old value dropped)"
|
||||||
|
: "(value moved)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ZShell::config
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
namespace ZShell::config {
|
||||||
|
|
||||||
|
// A single migration rule: move the value stored at the dotted `from` path
|
||||||
|
// to the dotted `to` path, then delete the old key (and any parent objects
|
||||||
|
// left empty).
|
||||||
|
//
|
||||||
|
// Rules are applied to the raw JSON file on every load, before the schema
|
||||||
|
// loads it. They are idempotent: once the old key is gone the rule never
|
||||||
|
// fires again, so no version stamping is needed. Old rules can stay in the
|
||||||
|
// table forever.
|
||||||
|
//
|
||||||
|
// WARNING: the target path must exist in the schema (i.e. a ConfigObject
|
||||||
|
// property somewhere in the tree). If it does not, the migrated value is
|
||||||
|
// loaded as an unknown key and silently dropped on the next save.
|
||||||
|
struct ConfigMigrationRule {
|
||||||
|
QString from;
|
||||||
|
QString to;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper for writing rules: migrate("general.color.foo", "display.bar.foo")
|
||||||
|
inline ConfigMigrationRule migrate(const QString& from, const QString& to) {
|
||||||
|
return {from, to};
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConfigMigrations {
|
||||||
|
public:
|
||||||
|
[[nodiscard]] static const QList<ConfigMigrationRule>& rules();
|
||||||
|
|
||||||
|
// Applies all rules to `json`, returning the migrated object.
|
||||||
|
[[nodiscard]] static QJsonObject apply(const QJsonObject& json);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ZShell::config
|
||||||
@@ -10,7 +10,6 @@ namespace ZShell::services {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr const char* NL_EVENT = "zshell-nightlight";
|
constexpr const char* NL_EVENT = "zshell-nightlight";
|
||||||
constexpr int NEUTRAL_KELVIN = 6500;
|
|
||||||
constexpr int RECONNECT_MS = 2000;
|
constexpr int RECONNECT_MS = 2000;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@@ -404,7 +403,6 @@ void NightlightManager::handleEventLine(const QByteArray& line) {
|
|||||||
|
|
||||||
if (line.left(sep) != NL_EVENT) return;
|
if (line.left(sep) != NL_EVENT) return;
|
||||||
|
|
||||||
// data = enabled,animating,last,current
|
|
||||||
const auto fields = line.mid(sep + 2).split(',');
|
const auto fields = line.mid(sep + 2).split(',');
|
||||||
if (fields.size() < 4) return;
|
if (fields.size() < 4) return;
|
||||||
|
|
||||||
|
|||||||
+5
-9
@@ -13,21 +13,17 @@ import qs.Paths
|
|||||||
Singleton {
|
Singleton {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property M3Palette current: M3Palette {
|
readonly property M3Palette current: M3Palette {}
|
||||||
}
|
|
||||||
property bool currentLight
|
property bool currentLight
|
||||||
property string flavour
|
property string flavour
|
||||||
readonly property bool light: showPreview ? previewLight : currentLight
|
readonly property bool light: showPreview ? previewLight : currentLight
|
||||||
readonly property M3Palette palette: showPreview ? preview : current
|
readonly property M3Palette palette: showPreview ? preview : current
|
||||||
readonly property M3Palette preview: M3Palette {
|
readonly property M3Palette preview: M3Palette {}
|
||||||
}
|
|
||||||
property bool previewLight
|
property bool previewLight
|
||||||
property string scheme
|
property string scheme
|
||||||
property bool showPreview
|
property bool showPreview
|
||||||
readonly property M3TPalette tPalette: M3TPalette {
|
readonly property M3TPalette tPalette: M3TPalette {}
|
||||||
}
|
readonly property Transparency transparency: Transparency {}
|
||||||
readonly property Transparency transparency: Transparency {
|
|
||||||
}
|
|
||||||
readonly property alias wallLuminance: analyser.luminance
|
readonly property alias wallLuminance: analyser.luminance
|
||||||
|
|
||||||
function alterColor(c: color, a: real, layer: int): color {
|
function alterColor(c: color, a: real, layer: int): color {
|
||||||
@@ -112,7 +108,7 @@ Singleton {
|
|||||||
|
|
||||||
function setMode(mode: string): void {
|
function setMode(mode: string): void {
|
||||||
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--mode", mode]);
|
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--mode", mode]);
|
||||||
Config.general.color.mode = mode;
|
Config.colors.mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
function swapRG(c: color): color {
|
function swapRG(c: color): color {
|
||||||
|
|||||||
@@ -625,8 +625,8 @@ def generate(
|
|||||||
scheme_type = config["colors"].get("schemeType", "fruit-salad")
|
scheme_type = config["colors"].get("schemeType", "fruit-salad")
|
||||||
scheme = scheme or scheme_type
|
scheme = scheme or scheme_type
|
||||||
assert isinstance(scheme, str)
|
assert isinstance(scheme, str)
|
||||||
config_mode = config["general"]["color"]["mode"]
|
config_mode = config["colors"]["mode"]
|
||||||
smart = bool(config["general"]["color"].get("smart", False))
|
smart = bool(config["colors"].get("smart", False))
|
||||||
scheme_class = get_scheme_class(scheme)
|
scheme_class = get_scheme_class(scheme)
|
||||||
|
|
||||||
p_variant = "default"
|
p_variant = "default"
|
||||||
|
|||||||
Reference in New Issue
Block a user