expandable dialogs for color scheme, fonts and scheduling modes
This commit is contained in:
@@ -55,6 +55,10 @@ PageBase {
|
||||
enabled: Object.keys(model).length > 0
|
||||
header: qsTr("Add new entry")
|
||||
icon: "add"
|
||||
settingAnchor: "panels-bar-status-icons-add-item"
|
||||
onOpenChanged: {
|
||||
root.sState.dimmed = open;
|
||||
}
|
||||
last: true
|
||||
label: qsTr("Add entry")
|
||||
model: {
|
||||
|
||||
@@ -75,10 +75,18 @@ PageBase {
|
||||
|
||||
acceptLabel: qsTr("Confirm")
|
||||
enabled: Object.keys(model).length > 0
|
||||
settingAnchor: "panels-sidebar-select-scheme"
|
||||
separateContent: false
|
||||
header: qsTr("Select scheme")
|
||||
first: true
|
||||
last: true
|
||||
icon: "add"
|
||||
icon: "format_paint"
|
||||
iconLabel.font.pointSize: Tokens.font.size.large
|
||||
rowButton.trailingIcon: "open_in_new"
|
||||
onOpenChanged: {
|
||||
root.sState.dimmed = open;
|
||||
}
|
||||
rowButton.activeItem: root.schemes.find(s => s.id === Config.llm.appearance.scheme).label
|
||||
label: qsTr("Color scheme")
|
||||
subtext: qsTr("Select the color scheme used for code blocks")
|
||||
model: root.schemes
|
||||
|
||||
@@ -88,6 +88,10 @@ PageBase {
|
||||
enabled: Object.keys(model).length > 0
|
||||
header: qsTr("Add new entry")
|
||||
icon: "add"
|
||||
onOpenChanged: {
|
||||
root.sState.dimmed = open;
|
||||
}
|
||||
settingAnchor: "panels-sidebar-quick-toggles-add-item"
|
||||
label: qsTr("Add entry")
|
||||
last: true
|
||||
model: {
|
||||
|
||||
@@ -0,0 +1,327 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import ZShell.Config
|
||||
import qs.Paths
|
||||
import qs.Services
|
||||
import qs.Modules.Settings.Common
|
||||
|
||||
PageBase {
|
||||
id: root
|
||||
|
||||
readonly property list<string> fonts: Qt.fontFamilies()
|
||||
readonly property var schemes: [
|
||||
{
|
||||
id: "onedark",
|
||||
label: qsTr("One Dark")
|
||||
},
|
||||
{
|
||||
id: "nord",
|
||||
label: qsTr("Nord")
|
||||
},
|
||||
{
|
||||
id: "dracula",
|
||||
label: qsTr("Dracula")
|
||||
},
|
||||
{
|
||||
id: "darkgreen",
|
||||
label: qsTr("Darkgreen")
|
||||
},
|
||||
{
|
||||
id: "solarized",
|
||||
label: qsTr("Solarized")
|
||||
},
|
||||
{
|
||||
id: "rosepine",
|
||||
label: qsTr("Rosepine")
|
||||
},
|
||||
{
|
||||
id: "gruvbox",
|
||||
label: qsTr("Gruvbox")
|
||||
},
|
||||
{
|
||||
id: "catppuccin",
|
||||
label: qsTr("Catppuccin")
|
||||
},
|
||||
{
|
||||
id: "tokyonight",
|
||||
label: qsTr("Tokyo Night")
|
||||
},
|
||||
{
|
||||
id: "shadotheme",
|
||||
label: qsTr("Shadotheme")
|
||||
}
|
||||
]
|
||||
|
||||
isSubPage: true
|
||||
title: qsTr("Colors & font")
|
||||
|
||||
ColumnLayout {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
spacing: Tokens.spacing.extraSmall / 2
|
||||
width: root.cappedWidth
|
||||
|
||||
SectionHeader {
|
||||
first: true
|
||||
text: qsTr("Colors")
|
||||
}
|
||||
|
||||
ToggleRow {
|
||||
text: qsTr("Dynamic colors")
|
||||
first: true
|
||||
subtext: qsTr("Automatic color scheme based on wallpaper is %1").arg(Config.general.color.schemeGeneration ? "enabled" : "disabled")
|
||||
checked: Config.general.color.schemeGeneration
|
||||
settingAnchor: "colors-fonts-dynamic-colors"
|
||||
|
||||
onToggled: {
|
||||
Config.general.color.schemeGeneration = checked;
|
||||
|
||||
if (checked)
|
||||
Colors.setMode(Config.general.color.mode);
|
||||
}
|
||||
}
|
||||
|
||||
DialogSelectButton {
|
||||
settingAnchor: "colors-fonts-preset-scheme"
|
||||
model: root.schemes
|
||||
acceptLabel: qsTr("Confirm")
|
||||
enabled: !Config.general.color.schemeGeneration
|
||||
header: qsTr("Select scheme")
|
||||
rowButton.activeItem: root.schemes.find(s => {
|
||||
var regex = new RegExp(Config.colors.presets.name, "i");
|
||||
return regex.test(s.id);
|
||||
}).label ?? ""
|
||||
label: qsTr("Preset scheme")
|
||||
subtext: qsTr("Select preset color scheme")
|
||||
rootParent: root.flickable
|
||||
|
||||
FileView {
|
||||
id: view
|
||||
path: `${Paths.state}/presets.json`
|
||||
|
||||
watchChanges: true
|
||||
onFileChanged: reload()
|
||||
|
||||
JsonAdapter {
|
||||
id: adapter
|
||||
|
||||
property var presets
|
||||
}
|
||||
}
|
||||
|
||||
initialSelect: Config.colors.presets.name.toLowerCase()
|
||||
|
||||
onAccepted: {
|
||||
if (!selectedItem)
|
||||
return;
|
||||
|
||||
const s = selectedItem.toLowerCase();
|
||||
let v = "";
|
||||
let a = "";
|
||||
const existingVariant = Config.colors.presets.variant;
|
||||
const existingAccent = Config.colors.presets.accent;
|
||||
const variantKeys = Object.keys(adapter.presets[s].variants);
|
||||
|
||||
if (existingVariant !== "" && variantKeys.some(v => v === existingVariant))
|
||||
v = existingVariant;
|
||||
|
||||
if (v !== "" && existingAccent !== "" && adapter.presets[s].variants[v]?.accents.some(a => a === existingAccent))
|
||||
a = existingAccent;
|
||||
|
||||
if (a !== "")
|
||||
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--preset", `${s}:${v}`, "-a", `${a}`]);
|
||||
else if (v !== "")
|
||||
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--preset", `${s}:${v}`]);
|
||||
else
|
||||
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--preset", `${s}:${variantKeys[0]}`]);
|
||||
}
|
||||
}
|
||||
|
||||
DialogSelectButton {
|
||||
settingAnchor: "colors-fonts-preset-variant"
|
||||
// qmlformat off
|
||||
model: {
|
||||
const v = adapter.presets[Config.colors.presets.name].variants;
|
||||
const map = Object.keys(v).map(v => ({
|
||||
id: v,
|
||||
label: qsTr("%1%2")
|
||||
.arg(v.charAt(0).toUpperCase())
|
||||
.arg(v.slice(1).toLowerCase())
|
||||
}));
|
||||
|
||||
return map;
|
||||
}
|
||||
// qmlformat on
|
||||
acceptLabel: qsTr("Confirm")
|
||||
enabled: !Config.general.color.schemeGeneration && model.length > 1
|
||||
header: qsTr("Select variant")
|
||||
rowButton.activeItem: {
|
||||
const v = Config.colors.presets.variant ?? "";
|
||||
if (v === "")
|
||||
return "";
|
||||
return qsTr("%1%2").arg(v.charAt(0).toUpperCase()).arg(v.slice(1).toLowerCase());
|
||||
}
|
||||
label: qsTr("Variant")
|
||||
subtext: qsTr("Select preset variant")
|
||||
rootParent: root.flickable
|
||||
|
||||
initialSelect: Config.colors.presets.variant
|
||||
|
||||
onAccepted: {
|
||||
if (!selectedItem)
|
||||
return;
|
||||
|
||||
const v = selectedItem.toLowerCase();
|
||||
const s = Config.colors.presets.name;
|
||||
const existingAccent = Config.colors.presets.accent;
|
||||
let a = "";
|
||||
|
||||
if (existingAccent !== "" && adapter.presets[s].variants[v]?.accents.some(a => a === existingAccent))
|
||||
a = existingAccent;
|
||||
|
||||
if (a !== "")
|
||||
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--preset", `${s}:${v}`, "-a", `${a}`]);
|
||||
else
|
||||
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--preset", `${s}:${v}`]);
|
||||
}
|
||||
}
|
||||
|
||||
DialogSelectButton {
|
||||
settingAnchor: "colors-fonts-preset-accent"
|
||||
// qmlformat off
|
||||
model: {
|
||||
const a = adapter.presets[Config.colors.presets.name].variants[Config.colors.presets.variant]?.accents ?? [];
|
||||
|
||||
if (a.length === 0)
|
||||
return a;
|
||||
|
||||
const map = a.map(a => ({
|
||||
id: a,
|
||||
label: qsTr("%1%2")
|
||||
.arg(a.charAt(0).toUpperCase())
|
||||
.arg(a.slice(1).toLowerCase())
|
||||
}));
|
||||
|
||||
return map;
|
||||
}
|
||||
// qmlformat on
|
||||
acceptLabel: qsTr("Confirm")
|
||||
enabled: !Config.general.color.schemeGeneration && model.length > 1
|
||||
header: qsTr("Select accent")
|
||||
rowButton.activeItem: {
|
||||
const a = Config.colors.presets.accent ?? "";
|
||||
if (a === "")
|
||||
return "";
|
||||
return qsTr("%1%2").arg(a.charAt(0).toUpperCase()).arg(a.slice(1).toLowerCase());
|
||||
}
|
||||
label: qsTr("Accent")
|
||||
last: true
|
||||
subtext: qsTr("Select preset accent")
|
||||
rootParent: root.flickable
|
||||
|
||||
initialSelect: Config.colors.presets.accent
|
||||
|
||||
onAccepted: {
|
||||
if (!selectedItem)
|
||||
return;
|
||||
|
||||
const a = selectedItem.toLowerCase();
|
||||
const v = Config.colors.presets.variant;
|
||||
const s = Config.colors.presets.name;
|
||||
|
||||
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--preset", `${s}:${v}`, "-a", `${a}`]);
|
||||
}
|
||||
}
|
||||
|
||||
SectionHeader {
|
||||
text: qsTr("Fonts")
|
||||
}
|
||||
|
||||
SearchPopup {
|
||||
id: selectSansFont
|
||||
|
||||
settingAnchor: "colors-fonts-sans-font"
|
||||
model: root.fonts
|
||||
acceptLabel: qsTr("Confirm")
|
||||
enabled: Object.keys(model).length > 0
|
||||
separateContent: false
|
||||
header: qsTr("Select font")
|
||||
first: true
|
||||
rowButton.activeItem: root.fonts.find(s => {
|
||||
var regex = new RegExp(Config.appearance.font.family.sans, "i");
|
||||
return regex.test(s);
|
||||
}) ?? ""
|
||||
label: qsTr("Sans font")
|
||||
subtext: qsTr("Select desired sans font")
|
||||
rootParent: root.flickable
|
||||
|
||||
initialSelect: Config.appearance.font.family.sans
|
||||
|
||||
onAccepted: {
|
||||
if (!selectedItem)
|
||||
return;
|
||||
|
||||
Config.appearance.font.family.sans = selectedItem;
|
||||
}
|
||||
}
|
||||
|
||||
SearchPopup {
|
||||
id: selectMonoFont
|
||||
|
||||
acceptLabel: qsTr("Confirm")
|
||||
enabled: Object.keys(model).length > 0
|
||||
settingAnchor: "colors-fonts-mono-font"
|
||||
separateContent: false
|
||||
header: qsTr("Select font")
|
||||
rowButton.activeItem: root.fonts.find(s => {
|
||||
var regex = new RegExp(Config.appearance.font.family.mono, "i");
|
||||
return regex.test(s);
|
||||
}) ?? ""
|
||||
label: qsTr("Mono font")
|
||||
subtext: qsTr("Select desired mono font")
|
||||
model: root.fonts
|
||||
rootParent: root.flickable
|
||||
|
||||
initialSelect: Config.appearance.font.family.mono
|
||||
|
||||
onAccepted: {
|
||||
if (!selectedItem)
|
||||
return;
|
||||
|
||||
Config.appearance.font.family.mono = selectedItem;
|
||||
}
|
||||
}
|
||||
|
||||
SearchPopup {
|
||||
id: selectClockFont
|
||||
|
||||
acceptLabel: qsTr("Confirm")
|
||||
enabled: Object.keys(model).length > 0
|
||||
separateContent: false
|
||||
settingAnchor: "colors-fonts-clock-font"
|
||||
header: qsTr("Select font")
|
||||
last: true
|
||||
rowButton.activeItem: root.fonts.find(s => {
|
||||
var regex = new RegExp(Config.appearance.font.family.clock, "i");
|
||||
return regex.test(s);
|
||||
}) ?? ""
|
||||
label: qsTr("Clock font")
|
||||
subtext: qsTr("Select desired clock font")
|
||||
model: root.fonts
|
||||
rootParent: root.flickable
|
||||
|
||||
initialSelect: Config.appearance.font.family.clock
|
||||
|
||||
onAccepted: {
|
||||
if (!selectedItem)
|
||||
return;
|
||||
|
||||
Config.appearance.font.family.clock = selectedItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,18 +33,35 @@ PageBase {
|
||||
}
|
||||
}
|
||||
|
||||
IconTextButton {
|
||||
ButtonRow {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
enabled: Config.background.enabled
|
||||
horizontalPadding: Tokens.padding.extraLarge
|
||||
icon: "wallpaper"
|
||||
isRound: true
|
||||
shapeMorph: true
|
||||
text: qsTr("Wallpapers")
|
||||
type: IconTextButton.Tonal
|
||||
verticalPadding: Tokens.padding.small
|
||||
spacing: Tokens.spacing.small
|
||||
|
||||
onClicked: root.sState.openSubPage(1) // Wallpaper page
|
||||
IconTextButton {
|
||||
enabled: Config.background.enabled
|
||||
horizontalPadding: Tokens.padding.extraLarge
|
||||
icon: "wallpaper"
|
||||
isRound: true
|
||||
shapeMorph: true
|
||||
text: qsTr("Wallpapers")
|
||||
type: IconTextButton.Tonal
|
||||
verticalPadding: Tokens.padding.small
|
||||
|
||||
onClicked: root.sState.openSubPage(1) // Wallpaper page
|
||||
}
|
||||
|
||||
IconTextButton {
|
||||
enabled: Config.background.enabled
|
||||
horizontalPadding: Tokens.padding.extraLarge
|
||||
icon: "palette"
|
||||
isRound: true
|
||||
shapeMorph: true
|
||||
text: qsTr("Colors & font")
|
||||
type: IconTextButton.Tonal
|
||||
verticalPadding: Tokens.padding.small
|
||||
|
||||
onClicked: root.sState.openSubPage(2) // Colors & font page
|
||||
}
|
||||
}
|
||||
|
||||
ToggleRow {
|
||||
@@ -76,9 +93,7 @@ PageBase {
|
||||
onToggled: Colors.setMode(checked ? "dark" : "light")
|
||||
}
|
||||
|
||||
OverlayRow {
|
||||
id: darkMode
|
||||
|
||||
TimeDialogSelect {
|
||||
readonly property string endTime: {
|
||||
var d = new Date(0, 0, 0, 0, 0, 0, 0);
|
||||
d.setMinutes(Config.general.color.scheduleDarkEnd);
|
||||
@@ -90,35 +105,30 @@ PageBase {
|
||||
return Qt.formatTime(d, "hh:mm AP");
|
||||
}
|
||||
|
||||
checked: Config.general.color.scheduleDark
|
||||
rowButton.checked: Config.general.color.scheduleDark
|
||||
rowButton.onToggled: Config.general.color.scheduleDark = rowButton.checked
|
||||
start: Config.general.color.scheduleDarkStart
|
||||
end: Config.general.color.scheduleDarkEnd
|
||||
first: true
|
||||
settingAnchor: "style-schedule-dark-mode"
|
||||
acceptLabel: qsTr("Apply")
|
||||
rootParent: root.flickable
|
||||
header: qsTr("Select time")
|
||||
subtext: qsTr("Dark mode will turn on at %1, and turn off at %2.").arg(startTime).arg(endTime)
|
||||
text: qsTr("Schedule dark mode")
|
||||
label: qsTr("Schedule dark mode")
|
||||
|
||||
popup: Component {
|
||||
TimeInput {
|
||||
object: Config.general.color
|
||||
settings: ["scheduleDark", "scheduleDarkStart", "scheduleDarkEnd"]
|
||||
|
||||
onApplySettings: (start, end) => {
|
||||
Config.general.color.scheduleDarkStart = start;
|
||||
Config.general.color.scheduleDarkEnd = end;
|
||||
ModeScheduler.checkStartup();
|
||||
PopupManager.requestClose();
|
||||
}
|
||||
onClose: PopupManager.requestClose()
|
||||
}
|
||||
onOpenChanged: {
|
||||
root.sState.dimmed = open;
|
||||
}
|
||||
|
||||
onClicked: value => {
|
||||
Config.general.color.scheduleDark = value;
|
||||
onAccepted: {
|
||||
Config.general.color.scheduleDarkStart = startCurrent;
|
||||
Config.general.color.scheduleDarkEnd = endCurrent;
|
||||
ModeScheduler.checkStartup();
|
||||
}
|
||||
}
|
||||
|
||||
OverlayRow {
|
||||
id: hyprsunset
|
||||
|
||||
TimeDialogSelect {
|
||||
readonly property string endTime: {
|
||||
var d = new Date(0, 0, 0, 0, 0, 0, 0);
|
||||
d.setMinutes(Config.general.color.scheduleHyprsunsetEnd);
|
||||
@@ -131,29 +141,26 @@ PageBase {
|
||||
}
|
||||
|
||||
Layout.topMargin: Tokens.spacing.extraSmall / 2 - parent.spacing
|
||||
checked: Config.general.color.scheduleHyprsunset
|
||||
rowButton.checked: Config.general.color.scheduleHyprsunset
|
||||
rowButton.onToggled: Config.general.color.scheduleHyprsunset = rowButton.checked
|
||||
start: Config.general.color.scheduleHyprsunsetStart
|
||||
end: Config.general.color.scheduleHyprsunsetEnd
|
||||
last: true
|
||||
settingAnchor: "style-schedule-hyprsunset"
|
||||
acceptLabel: qsTr("Apply")
|
||||
rootParent: root.flickable
|
||||
header: qsTr("Select time")
|
||||
subtext: qsTr("Hyprsunset will turn on at %1, and turn off at %2.").arg(startTime).arg(endTime)
|
||||
text: qsTr("Schedule hyprsunset")
|
||||
label: qsTr("Schedule hyprsunset")
|
||||
|
||||
popup: Component {
|
||||
TimeInput {
|
||||
object: Config.general.color
|
||||
settings: ["scheduleHyprsunset", "scheduleHyprsunsetStart", "scheduleHyprsunsetEnd"]
|
||||
|
||||
onApplySettings: (start, end) => {
|
||||
Config.general.color.scheduleHyprsunsetStart = start;
|
||||
Config.general.color.scheduleHyprsunsetEnd = end;
|
||||
Hyprsunset.checkStartup();
|
||||
PopupManager.requestClose();
|
||||
}
|
||||
onClose: PopupManager.requestClose()
|
||||
}
|
||||
onOpenChanged: {
|
||||
root.sState.dimmed = open;
|
||||
}
|
||||
|
||||
onClicked: value => {
|
||||
Config.general.color.scheduleHyprsunset = value;
|
||||
onAccepted: {
|
||||
Config.general.color.scheduleHyprsunsetStart = startCurrent;
|
||||
Config.general.color.scheduleHyprsunsetEnd = endCurrent;
|
||||
Hyprsunset.checkStartup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user