feat: init quickshell
This commit is contained in:
@@ -0,0 +1,758 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import "root:/Data" as Data
|
||||
|
||||
// Appearance settings content
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 20
|
||||
|
||||
// Theme Setting in Collapsible Section
|
||||
SettingsCategory {
|
||||
width: parent.width
|
||||
title: "Theme Setting"
|
||||
icon: "palette"
|
||||
|
||||
content: Component {
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 30 // Increased spacing between major sections
|
||||
|
||||
// Dark/Light Mode Switch
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 12
|
||||
|
||||
Text {
|
||||
text: "Theme Mode"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 15
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: 16
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
Text {
|
||||
text: "Light"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 14
|
||||
font.family: "monospace"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
// Toggle switch - enhanced design
|
||||
Rectangle {
|
||||
width: 64
|
||||
height: 32
|
||||
radius: 16
|
||||
color: Data.ThemeManager.currentTheme.type === "dark" ? Qt.lighter(Data.ThemeManager.accentColor, 0.8) : Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.2)
|
||||
border.width: 2
|
||||
border.color: Data.ThemeManager.currentTheme.type === "dark" ? Data.ThemeManager.accentColor : Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.4)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
// Inner track shadow
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 2
|
||||
radius: parent.radius - 2
|
||||
color: "transparent"
|
||||
border.width: 1
|
||||
border.color: Qt.rgba(0, 0, 0, 0.1)
|
||||
}
|
||||
|
||||
// Toggle handle
|
||||
Rectangle {
|
||||
id: toggleHandle
|
||||
width: 26
|
||||
height: 26
|
||||
radius: 13
|
||||
color: Data.ThemeManager.currentTheme.type === "dark" ? Data.ThemeManager.bgColor : Data.ThemeManager.panelBackground
|
||||
border.width: 2
|
||||
border.color: Data.ThemeManager.currentTheme.type === "dark" ? Data.ThemeManager.accentColor : Data.ThemeManager.fgColor
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
x: Data.ThemeManager.currentTheme.type === "dark" ? parent.width - width - 3 : 3
|
||||
|
||||
// Handle shadow
|
||||
Rectangle {
|
||||
anchors.centerIn: parent
|
||||
anchors.verticalCenterOffset: 1
|
||||
width: parent.width - 2
|
||||
height: parent.height - 2
|
||||
radius: parent.radius - 1
|
||||
color: Qt.rgba(0, 0, 0, 0.1)
|
||||
z: -1
|
||||
}
|
||||
|
||||
// Handle highlight
|
||||
Rectangle {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width - 6
|
||||
height: parent.height - 6
|
||||
radius: parent.radius - 3
|
||||
color: Qt.rgba(255, 255, 255, 0.15)
|
||||
}
|
||||
|
||||
Behavior on x {
|
||||
NumberAnimation {
|
||||
duration: 250
|
||||
easing.type: Easing.OutBack
|
||||
easing.overshoot: 0.3
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on border.color {
|
||||
ColorAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Background color transition
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on border.color {
|
||||
ColorAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: {
|
||||
console.log("Theme switch clicked, current:", Data.ThemeManager.currentThemeId);
|
||||
var currentFamily = Data.ThemeManager.currentThemeId.replace(/_dark$|_light$/, "");
|
||||
var newType = Data.ThemeManager.currentTheme.type === "dark" ? "light" : "dark";
|
||||
var newThemeId = currentFamily + "_" + newType;
|
||||
console.log("Switching to:", newThemeId);
|
||||
Data.ThemeManager.setTheme(newThemeId);
|
||||
|
||||
// Force update the settings if currentTheme isn't being saved properly
|
||||
if (!Data.Settings.currentTheme) {
|
||||
Data.Settings.currentTheme = newThemeId;
|
||||
Data.Settings.saveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
onEntered: {
|
||||
parent.scale = 1.05;
|
||||
}
|
||||
|
||||
onExited: {
|
||||
parent.scale = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: 150
|
||||
easing.type: Easing.OutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Dark"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 14
|
||||
font.family: "monospace"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Separator
|
||||
Rectangle {
|
||||
width: parent.width - 40
|
||||
height: 1
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.1)
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
// Theme Selection
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 12
|
||||
|
||||
Text {
|
||||
text: "Theme Family"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 15
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Choose your preferred theme family"
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.7)
|
||||
font.pixelSize: 13
|
||||
font.family: "monospace"
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
// Compact 2x2 grid for themes
|
||||
GridLayout {
|
||||
columns: 2
|
||||
columnSpacing: 8
|
||||
rowSpacing: 8
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
property var themeFamily: {
|
||||
var currentFamily = Data.ThemeManager.currentThemeId.replace(/_dark$|_light$/, "");
|
||||
return currentFamily;
|
||||
}
|
||||
|
||||
property var themeFamilies: [
|
||||
{
|
||||
id: "oxocarbon",
|
||||
name: "Oxocarbon",
|
||||
description: "IBM Carbon"
|
||||
},
|
||||
{
|
||||
id: "dracula",
|
||||
name: "Dracula",
|
||||
description: "Vibrant"
|
||||
},
|
||||
{
|
||||
id: "gruvbox",
|
||||
name: "Gruvbox",
|
||||
description: "Retro"
|
||||
},
|
||||
{
|
||||
id: "catppuccin",
|
||||
name: "Catppuccin",
|
||||
description: "Pastel"
|
||||
},
|
||||
{
|
||||
id: "matugen",
|
||||
name: "Matugen",
|
||||
description: "Generated"
|
||||
}
|
||||
]
|
||||
|
||||
Repeater {
|
||||
model: parent.themeFamilies
|
||||
delegate: Rectangle {
|
||||
Layout.preferredWidth: 140
|
||||
Layout.preferredHeight: 50
|
||||
radius: 10
|
||||
color: parent.themeFamily === modelData.id ? Data.ThemeManager.accentColor : Qt.lighter(Data.ThemeManager.bgColor, 1.15)
|
||||
border.width: parent.themeFamily === modelData.id ? 2 : 1
|
||||
border.color: parent.themeFamily === modelData.id ? Data.ThemeManager.accentColor : Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.3)
|
||||
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.leftMargin: 10
|
||||
spacing: 6
|
||||
|
||||
// Compact theme preview colors
|
||||
Row {
|
||||
spacing: 1
|
||||
property var previewTheme: Data.ThemeManager.themes[modelData.id + "_" + Data.ThemeManager.currentTheme.type] || Data.ThemeManager.themes[modelData.id + "_dark"]
|
||||
Rectangle {
|
||||
width: 4
|
||||
height: 14
|
||||
radius: 1
|
||||
color: parent.previewTheme.base00
|
||||
}
|
||||
Rectangle {
|
||||
width: 4
|
||||
height: 14
|
||||
radius: 1
|
||||
color: parent.previewTheme.base0E
|
||||
}
|
||||
Rectangle {
|
||||
width: 4
|
||||
height: 14
|
||||
radius: 1
|
||||
color: parent.previewTheme.base0D
|
||||
}
|
||||
Rectangle {
|
||||
width: 4
|
||||
height: 14
|
||||
radius: 1
|
||||
color: parent.previewTheme.base0B
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
spacing: 1
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Text {
|
||||
text: modelData.name
|
||||
color: parent.parent.parent.parent.themeFamily === modelData.id ? Data.ThemeManager.bgColor : Data.ThemeManager.fgColor
|
||||
font.pixelSize: 12
|
||||
font.bold: parent.parent.parent.parent.themeFamily === modelData.id
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Text {
|
||||
text: modelData.description
|
||||
color: parent.parent.parent.parent.themeFamily === modelData.id ? Qt.rgba(Data.ThemeManager.bgColor.r, Data.ThemeManager.bgColor.g, Data.ThemeManager.bgColor.b, 0.8) : Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.6)
|
||||
font.pixelSize: 9
|
||||
font.family: "monospace"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: {
|
||||
var themeType = Data.ThemeManager.currentTheme.type;
|
||||
var newThemeId = modelData.id + "_" + themeType;
|
||||
console.log("Theme card clicked:", newThemeId);
|
||||
Data.ThemeManager.setTheme(newThemeId);
|
||||
}
|
||||
|
||||
onEntered: {
|
||||
parent.scale = 1.02;
|
||||
}
|
||||
|
||||
onExited: {
|
||||
parent.scale = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: 150
|
||||
easing.type: Easing.OutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Separator
|
||||
Rectangle {
|
||||
width: parent.width - 40
|
||||
height: 1
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.1)
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
// Accent Colors
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 12
|
||||
|
||||
Text {
|
||||
text: "Accent Colors"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 15
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Choose your preferred accent color for " + Data.ThemeManager.currentTheme.name
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.7)
|
||||
font.pixelSize: 13
|
||||
font.family: "monospace"
|
||||
wrapMode: Text.Wrap
|
||||
width: parent.width
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
// Compact flow layout for accent colors
|
||||
Flow {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: parent.width - 20 // Margins to prevent clipping
|
||||
spacing: 8
|
||||
|
||||
property var accentColors: {
|
||||
var currentFamily = Data.ThemeManager.currentThemeId.replace(/_dark$|_light$/, "");
|
||||
var themeColors = [];
|
||||
|
||||
// Theme-specific accent colors - reduced to 5 per theme for compactness
|
||||
if (currentFamily === "dracula") {
|
||||
themeColors.push({
|
||||
name: "Magenta",
|
||||
dark: "#ff79c6",
|
||||
light: "#e91e63"
|
||||
}, {
|
||||
name: "Purple",
|
||||
dark: "#bd93f9",
|
||||
light: "#6c7ce0"
|
||||
}, {
|
||||
name: "Cyan",
|
||||
dark: "#8be9fd",
|
||||
light: "#17a2b8"
|
||||
}, {
|
||||
name: "Green",
|
||||
dark: "#50fa7b",
|
||||
light: "#27ae60"
|
||||
}, {
|
||||
name: "Orange",
|
||||
dark: "#ffb86c",
|
||||
light: "#f39c12"
|
||||
});
|
||||
} else if (currentFamily === "gruvbox") {
|
||||
themeColors.push({
|
||||
name: "Orange",
|
||||
dark: "#fe8019",
|
||||
light: "#d65d0e"
|
||||
}, {
|
||||
name: "Red",
|
||||
dark: "#fb4934",
|
||||
light: "#cc241d"
|
||||
}, {
|
||||
name: "Yellow",
|
||||
dark: "#fabd2f",
|
||||
light: "#d79921"
|
||||
}, {
|
||||
name: "Green",
|
||||
dark: "#b8bb26",
|
||||
light: "#98971a"
|
||||
}, {
|
||||
name: "Purple",
|
||||
dark: "#d3869b",
|
||||
light: "#b16286"
|
||||
});
|
||||
} else if (currentFamily === "catppuccin") {
|
||||
themeColors.push({
|
||||
name: "Mauve",
|
||||
dark: "#cba6f7",
|
||||
light: "#8839ef"
|
||||
}, {
|
||||
name: "Blue",
|
||||
dark: "#89b4fa",
|
||||
light: "#1e66f5"
|
||||
}, {
|
||||
name: "Teal",
|
||||
dark: "#94e2d5",
|
||||
light: "#179299"
|
||||
}, {
|
||||
name: "Green",
|
||||
dark: "#a6e3a1",
|
||||
light: "#40a02b"
|
||||
}, {
|
||||
name: "Peach",
|
||||
dark: "#fab387",
|
||||
light: "#fe640b"
|
||||
});
|
||||
} else if (currentFamily === "matugen") {
|
||||
// Use dynamic matugen colors if available
|
||||
if (Data.ThemeManager.matugen && Data.ThemeManager.matugen.isMatugenActive()) {
|
||||
themeColors.push({
|
||||
name: "Primary",
|
||||
dark: Data.ThemeManager.matugen.getMatugenColor("primary") || "#adc6ff",
|
||||
light: Data.ThemeManager.matugen.getMatugenColor("primary") || "#0f62fe"
|
||||
}, {
|
||||
name: "Secondary",
|
||||
dark: Data.ThemeManager.matugen.getMatugenColor("secondary") || "#bfc6dc",
|
||||
light: Data.ThemeManager.matugen.getMatugenColor("secondary") || "#6272a4"
|
||||
}, {
|
||||
name: "Tertiary",
|
||||
dark: Data.ThemeManager.matugen.getMatugenColor("tertiary") || "#debcdf",
|
||||
light: Data.ThemeManager.matugen.getMatugenColor("tertiary") || "#b16286"
|
||||
}, {
|
||||
name: "Surface",
|
||||
dark: Data.ThemeManager.matugen.getMatugenColor("surface_tint") || "#adc6ff",
|
||||
light: Data.ThemeManager.matugen.getMatugenColor("surface_tint") || "#0f62fe"
|
||||
}, {
|
||||
name: "Error",
|
||||
dark: Data.ThemeManager.matugen.getMatugenColor("error") || "#ffb4ab",
|
||||
light: Data.ThemeManager.matugen.getMatugenColor("error") || "#ba1a1a"
|
||||
});
|
||||
} else {
|
||||
// Fallback matugen colors
|
||||
themeColors.push({
|
||||
name: "Primary",
|
||||
dark: "#adc6ff",
|
||||
light: "#0f62fe"
|
||||
}, {
|
||||
name: "Secondary",
|
||||
dark: "#bfc6dc",
|
||||
light: "#6272a4"
|
||||
}, {
|
||||
name: "Tertiary",
|
||||
dark: "#debcdf",
|
||||
light: "#b16286"
|
||||
}, {
|
||||
name: "Surface",
|
||||
dark: "#adc6ff",
|
||||
light: "#0f62fe"
|
||||
}, {
|
||||
name: "Error",
|
||||
dark: "#ffb4ab",
|
||||
light: "#ba1a1a"
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// oxocarbon and fallback
|
||||
themeColors.push({
|
||||
name: "Purple",
|
||||
dark: "#be95ff",
|
||||
light: "#8a3ffc"
|
||||
}, {
|
||||
name: "Blue",
|
||||
dark: "#78a9ff",
|
||||
light: "#0f62fe"
|
||||
}, {
|
||||
name: "Cyan",
|
||||
dark: "#3ddbd9",
|
||||
light: "#007d79"
|
||||
}, {
|
||||
name: "Green",
|
||||
dark: "#42be65",
|
||||
light: "#198038"
|
||||
}, {
|
||||
name: "Pink",
|
||||
dark: "#ff7eb6",
|
||||
light: "#d12771"
|
||||
});
|
||||
}
|
||||
|
||||
return themeColors;
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: parent.accentColors
|
||||
delegate: Rectangle {
|
||||
width: 60
|
||||
height: 50
|
||||
radius: 10
|
||||
color: Qt.lighter(Data.ThemeManager.bgColor, 1.15)
|
||||
border.width: Data.ThemeManager.accentColor.toString() === (Data.ThemeManager.currentTheme.type === "dark" ? modelData.dark : modelData.light) ? 3 : 1
|
||||
border.color: Data.ThemeManager.accentColor.toString() === (Data.ThemeManager.currentTheme.type === "dark" ? modelData.dark : modelData.light) ? Data.ThemeManager.accentColor : Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.3)
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: 4
|
||||
|
||||
Rectangle {
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 10
|
||||
color: Data.ThemeManager.currentTheme.type === "dark" ? modelData.dark : modelData.light
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
text: modelData.name
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 9
|
||||
font.family: "monospace"
|
||||
font.bold: true
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: {
|
||||
// Set custom accent
|
||||
Data.Settings.useCustomAccent = true;
|
||||
Data.ThemeManager.setCustomAccent(modelData.dark, modelData.light);
|
||||
}
|
||||
|
||||
onEntered: {
|
||||
parent.scale = 1.05;
|
||||
}
|
||||
|
||||
onExited: {
|
||||
parent.scale = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: 150
|
||||
easing.type: Easing.OutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Animation Settings in Collapsible Section
|
||||
SettingsCategory {
|
||||
width: parent.width
|
||||
title: "Animation Settings"
|
||||
icon: "animation"
|
||||
|
||||
content: Component {
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 20
|
||||
|
||||
Text {
|
||||
text: "Configure workspace change animations"
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.7)
|
||||
font.pixelSize: 13
|
||||
font.family: "monospace"
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
// Workspace Burst Toggle
|
||||
Row {
|
||||
width: parent.width
|
||||
height: 40
|
||||
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: parent.width - 80
|
||||
|
||||
Text {
|
||||
text: "Workspace Burst Effect"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 14
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Expanding rings when switching workspaces"
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.6)
|
||||
font.pixelSize: 11
|
||||
font.family: "monospace"
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle switch for burst
|
||||
Rectangle {
|
||||
width: 50
|
||||
height: 25
|
||||
radius: 12.5
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
color: Data.Settings.workspaceBurstEnabled ? Qt.lighter(Data.ThemeManager.accentColor, 0.8) : Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.2)
|
||||
border.width: 1
|
||||
border.color: Data.Settings.workspaceBurstEnabled ? Data.ThemeManager.accentColor : Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.4)
|
||||
|
||||
Rectangle {
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 10
|
||||
color: Data.ThemeManager.bgColor
|
||||
border.width: 1.5
|
||||
border.color: Data.Settings.workspaceBurstEnabled ? Data.ThemeManager.accentColor : Data.ThemeManager.fgColor
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
x: Data.Settings.workspaceBurstEnabled ? parent.width - width - 2.5 : 2.5
|
||||
|
||||
Behavior on x {
|
||||
NumberAnimation {
|
||||
duration: 200
|
||||
easing.type: Easing.OutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
Behavior on border.color {
|
||||
ColorAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
Data.Settings.workspaceBurstEnabled = !Data.Settings.workspaceBurstEnabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Workspace Glow Toggle
|
||||
Row {
|
||||
width: parent.width
|
||||
height: 40
|
||||
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: parent.width - 80
|
||||
|
||||
Text {
|
||||
text: "Workspace Shadow Glow"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 14
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Accent color glow in workspace shadow"
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.6)
|
||||
font.pixelSize: 11
|
||||
font.family: "monospace"
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle switch for glow
|
||||
Rectangle {
|
||||
width: 50
|
||||
height: 25
|
||||
radius: 12.5
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
color: Data.Settings.workspaceGlowEnabled ? Qt.lighter(Data.ThemeManager.accentColor, 0.8) : Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.2)
|
||||
border.width: 1
|
||||
border.color: Data.Settings.workspaceGlowEnabled ? Data.ThemeManager.accentColor : Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.4)
|
||||
|
||||
Rectangle {
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 10
|
||||
color: Data.ThemeManager.bgColor
|
||||
border.width: 1.5
|
||||
border.color: Data.Settings.workspaceGlowEnabled ? Data.ThemeManager.accentColor : Data.ThemeManager.fgColor
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
x: Data.Settings.workspaceGlowEnabled ? parent.width - width - 2.5 : 2.5
|
||||
|
||||
Behavior on x {
|
||||
NumberAnimation {
|
||||
duration: 200
|
||||
easing.type: Easing.OutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
Behavior on border.color {
|
||||
ColorAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
Data.Settings.workspaceGlowEnabled = !Data.Settings.workspaceGlowEnabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import "root:/Data" as Data
|
||||
|
||||
// Music Player settings content
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 20
|
||||
|
||||
// Auto-switch to active player
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 12
|
||||
|
||||
Text {
|
||||
text: "Auto-switch to Active Player"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Automatically switch to the player that starts playing music"
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.7)
|
||||
font.pixelSize: 13
|
||||
font.family: "monospace"
|
||||
wrapMode: Text.Wrap
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 200
|
||||
height: 35
|
||||
radius: 18
|
||||
color: Data.Settings.autoSwitchPlayer ? Data.ThemeManager.accentColor : Qt.lighter(Data.ThemeManager.bgColor, 1.15)
|
||||
border.width: 1
|
||||
border.color: Data.ThemeManager.accentColor
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: Data.Settings.autoSwitchPlayer ? "Enabled" : "Disabled"
|
||||
color: Data.Settings.autoSwitchPlayer ? Data.ThemeManager.bgColor : Data.ThemeManager.fgColor
|
||||
font.pixelSize: 14
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
Data.Settings.autoSwitchPlayer = !Data.Settings.autoSwitchPlayer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Always show player dropdown
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 12
|
||||
|
||||
Text {
|
||||
text: "Always Show Player Dropdown"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Show the player selection dropdown even with only one player"
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.7)
|
||||
font.pixelSize: 13
|
||||
font.family: "monospace"
|
||||
wrapMode: Text.Wrap
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 200
|
||||
height: 35
|
||||
radius: 18
|
||||
color: Data.Settings.alwaysShowPlayerDropdown ? Data.ThemeManager.accentColor : Qt.lighter(Data.ThemeManager.bgColor, 1.15)
|
||||
border.width: 1
|
||||
border.color: Data.ThemeManager.accentColor
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: Data.Settings.alwaysShowPlayerDropdown ? "Enabled" : "Disabled"
|
||||
color: Data.Settings.alwaysShowPlayerDropdown ? Data.ThemeManager.bgColor : Data.ThemeManager.fgColor
|
||||
font.pixelSize: 14
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
Data.Settings.alwaysShowPlayerDropdown = !Data.Settings.alwaysShowPlayerDropdown;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,531 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import "root:/Data" as Data
|
||||
|
||||
// Night Light settings content
|
||||
Item {
|
||||
id: nightLightSettings
|
||||
width: parent.width
|
||||
height: contentColumn.height
|
||||
|
||||
Column {
|
||||
id: contentColumn
|
||||
width: parent.width
|
||||
spacing: 20
|
||||
|
||||
// Night Light Enable Toggle
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: 16
|
||||
|
||||
Column {
|
||||
width: parent.width - nightLightToggle.width - 16
|
||||
spacing: 4
|
||||
|
||||
Text {
|
||||
text: "Enable Night Light"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Reduces blue light to help protect your eyes and improve sleep"
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.7)
|
||||
font.pixelSize: 13
|
||||
font.family: "monospace"
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: nightLightToggle
|
||||
width: 50
|
||||
height: 28
|
||||
radius: 14
|
||||
color: Data.Settings.nightLightEnabled ? Data.ThemeManager.accentColor : Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.3)
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 10
|
||||
color: Data.ThemeManager.bgColor
|
||||
x: Data.Settings.nightLightEnabled ? parent.width - width - 4 : 4
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Behavior on x {
|
||||
NumberAnimation {
|
||||
duration: 200
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
Data.Settings.nightLightEnabled = !Data.Settings.nightLightEnabled;
|
||||
}
|
||||
onEntered: {
|
||||
parent.scale = 1.05;
|
||||
}
|
||||
onExited: {
|
||||
parent.scale = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: 150
|
||||
easing.type: Easing.OutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Warmth Level Slider
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 12
|
||||
|
||||
Text {
|
||||
text: "Warmth Level"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Adjust how warm the screen filter appears"
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.7)
|
||||
font.pixelSize: 13
|
||||
font.family: "monospace"
|
||||
wrapMode: Text.Wrap
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: 12
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "Cool"
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.6)
|
||||
font.pixelSize: 12
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: warmthSlider
|
||||
width: parent.width - 120
|
||||
height: 30
|
||||
from: 0.1
|
||||
to: 1.0
|
||||
value: Data.Settings.nightLightWarmth || 0.4
|
||||
stepSize: 0.1
|
||||
|
||||
onValueChanged: {
|
||||
Data.Settings.nightLightWarmth = value;
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: parent.width
|
||||
height: 6
|
||||
radius: 3
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.2)
|
||||
|
||||
Rectangle {
|
||||
width: warmthSlider.visualPosition * parent.width
|
||||
height: parent.height
|
||||
radius: parent.radius
|
||||
color: Qt.rgba(1.0, 0.8 - warmthSlider.value * 0.3, 0.4, 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
handle: Rectangle {
|
||||
x: warmthSlider.leftPadding + warmthSlider.visualPosition * (warmthSlider.availableWidth - width)
|
||||
y: warmthSlider.topPadding + warmthSlider.availableHeight / 2 - height / 2
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 10
|
||||
color: Data.ThemeManager.accentColor
|
||||
border.color: Qt.lighter(Data.ThemeManager.accentColor, 1.2)
|
||||
border.width: 2
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "Warm"
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.6)
|
||||
font.pixelSize: 12
|
||||
font.family: "monospace"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-enable Toggle
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: 16
|
||||
|
||||
Column {
|
||||
width: parent.width - autoToggle.width - 16
|
||||
spacing: 4
|
||||
|
||||
Text {
|
||||
text: "Auto-enable Schedule"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Automatically turn on night light at sunset/bedtime"
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.7)
|
||||
font.pixelSize: 13
|
||||
font.family: "monospace"
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: autoToggle
|
||||
width: 50
|
||||
height: 28
|
||||
radius: 14
|
||||
color: Data.Settings.nightLightAuto ? Data.ThemeManager.accentColor : Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.3)
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 10
|
||||
color: Data.ThemeManager.bgColor
|
||||
x: Data.Settings.nightLightAuto ? parent.width - width - 4 : 4
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Behavior on x {
|
||||
NumberAnimation {
|
||||
duration: 200
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
Data.Settings.nightLightAuto = !Data.Settings.nightLightAuto;
|
||||
}
|
||||
onEntered: {
|
||||
parent.scale = 1.05;
|
||||
}
|
||||
onExited: {
|
||||
parent.scale = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: 150
|
||||
easing.type: Easing.OutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Schedule Time Controls - visible when auto-enable is on
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 16
|
||||
visible: Data.Settings.nightLightAuto
|
||||
opacity: Data.Settings.nightLightAuto ? 1.0 : 0.0
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Schedule Times"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
// Start and End Time Row
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: 20
|
||||
|
||||
// Start Time
|
||||
Column {
|
||||
id: startTimeColumn
|
||||
width: (parent.width - parent.spacing) / 2
|
||||
spacing: 8
|
||||
|
||||
Text {
|
||||
text: "Start Time"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 14
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Night light turns on"
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.7)
|
||||
font.pixelSize: 12
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: startTimeButton
|
||||
width: parent.width
|
||||
height: 40
|
||||
radius: 8
|
||||
color: Qt.lighter(Data.ThemeManager.bgColor, 1.15)
|
||||
border.width: 1
|
||||
border.color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.3)
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 8
|
||||
|
||||
Text {
|
||||
text: (Data.Settings.nightLightStartHour || 20).toString().padStart(2, '0') + ":00"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
startTimePopup.open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Start Time Popup
|
||||
Popup {
|
||||
id: startTimePopup
|
||||
width: startTimeButton.width
|
||||
height: 170
|
||||
modal: true
|
||||
focus: true
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||
y: startTimeButton.y - height - 10
|
||||
x: startTimeButton.x
|
||||
dim: false
|
||||
|
||||
background: Rectangle {
|
||||
color: Data.ThemeManager.bgColor
|
||||
radius: 12
|
||||
border.width: 2
|
||||
border.color: Data.ThemeManager.accentColor
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: 12
|
||||
|
||||
Text {
|
||||
text: "Select Start Hour"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 14
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
columns: 6
|
||||
columnSpacing: 6
|
||||
rowSpacing: 6
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
Repeater {
|
||||
model: 24
|
||||
delegate: Rectangle {
|
||||
width: 24
|
||||
height: 24
|
||||
radius: 4
|
||||
color: (Data.Settings.nightLightStartHour || 20) === modelData ? Data.ThemeManager.accentColor : Qt.lighter(Data.ThemeManager.bgColor, 1.15)
|
||||
border.width: 1
|
||||
border.color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.3)
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: modelData.toString().padStart(2, '0')
|
||||
color: (Data.Settings.nightLightStartHour || 20) === modelData ? Data.ThemeManager.bgColor : Data.ThemeManager.fgColor
|
||||
font.pixelSize: 10
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
Data.Settings.nightLightStartHour = modelData;
|
||||
startTimePopup.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// End Time
|
||||
Column {
|
||||
id: endTimeColumn
|
||||
width: (parent.width - parent.spacing) / 2
|
||||
spacing: 8
|
||||
|
||||
Text {
|
||||
text: "End Time"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 14
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Night light turns off"
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.7)
|
||||
font.pixelSize: 12
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: endTimeButton
|
||||
width: parent.width
|
||||
height: 40
|
||||
radius: 8
|
||||
color: Qt.lighter(Data.ThemeManager.bgColor, 1.15)
|
||||
border.width: 1
|
||||
border.color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.3)
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 8
|
||||
|
||||
Text {
|
||||
text: (Data.Settings.nightLightEndHour || 6).toString().padStart(2, '0') + ":00"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
endTimePopup.open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// End Time Popup
|
||||
Popup {
|
||||
id: endTimePopup
|
||||
width: endTimeButton.width
|
||||
height: 170
|
||||
modal: true
|
||||
focus: true
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||
y: endTimeButton.y - height - 10
|
||||
x: endTimeButton.x
|
||||
dim: false
|
||||
|
||||
background: Rectangle {
|
||||
color: Data.ThemeManager.bgColor
|
||||
radius: 12
|
||||
border.width: 2
|
||||
border.color: Data.ThemeManager.accentColor
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: 12
|
||||
|
||||
Text {
|
||||
text: "Select End Hour"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 14
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
columns: 6
|
||||
columnSpacing: 6
|
||||
rowSpacing: 6
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
Repeater {
|
||||
model: 24
|
||||
delegate: Rectangle {
|
||||
width: 24
|
||||
height: 24
|
||||
radius: 4
|
||||
color: (Data.Settings.nightLightEndHour || 6) === modelData ? Data.ThemeManager.accentColor : Qt.lighter(Data.ThemeManager.bgColor, 1.15)
|
||||
border.width: 1
|
||||
border.color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.3)
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: modelData.toString().padStart(2, '0')
|
||||
color: (Data.Settings.nightLightEndHour || 6) === modelData ? Data.ThemeManager.bgColor : Data.ThemeManager.fgColor
|
||||
font.pixelSize: 10
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
Data.Settings.nightLightEndHour = modelData;
|
||||
endTimePopup.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,536 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import "root:/Data" as Data
|
||||
|
||||
// Notification settings content
|
||||
Item {
|
||||
id: notificationSettings
|
||||
width: parent.width
|
||||
height: contentColumn.height
|
||||
|
||||
// Expose the text input focus for parent keyboard management
|
||||
property bool anyTextInputFocused: appNameInput.activeFocus
|
||||
|
||||
Column {
|
||||
id: contentColumn
|
||||
width: parent.width
|
||||
spacing: 20
|
||||
|
||||
// Display Time Setting
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 12
|
||||
|
||||
Text {
|
||||
text: "Display Time"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "How long notifications stay visible on screen"
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.7)
|
||||
font.pixelSize: 13
|
||||
font.family: "monospace"
|
||||
wrapMode: Text.Wrap
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: 16
|
||||
width: parent.width
|
||||
|
||||
Slider {
|
||||
id: displayTimeSlider
|
||||
width: parent.width - timeLabel.width - 16
|
||||
height: 30
|
||||
from: 2000
|
||||
to: 15000
|
||||
stepSize: 1000
|
||||
value: Data.Settings.displayTime
|
||||
|
||||
onValueChanged: {
|
||||
Data.Settings.displayTime = value;
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
width: displayTimeSlider.availableWidth
|
||||
height: 6
|
||||
radius: 3
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.3)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Rectangle {
|
||||
width: displayTimeSlider.visualPosition * parent.width
|
||||
height: parent.height
|
||||
radius: parent.radius
|
||||
color: Data.ThemeManager.accentColor
|
||||
}
|
||||
}
|
||||
|
||||
handle: Rectangle {
|
||||
x: displayTimeSlider.leftPadding + displayTimeSlider.visualPosition * (displayTimeSlider.availableWidth - width)
|
||||
y: displayTimeSlider.topPadding + displayTimeSlider.availableHeight / 2 - height / 2
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 10
|
||||
color: Data.ThemeManager.accentColor
|
||||
border.color: Qt.lighter(Data.ThemeManager.accentColor, 1.2)
|
||||
border.width: 2
|
||||
|
||||
scale: displayTimeSlider.pressed ? 1.2 : 1.0
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: 150
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: timeLabel
|
||||
text: (displayTimeSlider.value / 1000).toFixed(1) + "s"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 14
|
||||
font.family: "monospace"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 40
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Max History Items
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 12
|
||||
|
||||
Text {
|
||||
text: "History Limit"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Maximum number of notifications to keep in history"
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.7)
|
||||
font.pixelSize: 13
|
||||
font.family: "monospace"
|
||||
wrapMode: Text.Wrap
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: 16
|
||||
width: parent.width
|
||||
|
||||
Slider {
|
||||
id: historySlider
|
||||
width: parent.width - historyLabel.width - 16
|
||||
height: 30
|
||||
from: 10
|
||||
to: 100
|
||||
stepSize: 5
|
||||
value: Data.Settings.historyLimit
|
||||
|
||||
onValueChanged: {
|
||||
Data.Settings.historyLimit = value;
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
width: historySlider.availableWidth
|
||||
height: 6
|
||||
radius: 3
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.3)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Rectangle {
|
||||
width: historySlider.visualPosition * parent.width
|
||||
height: parent.height
|
||||
radius: parent.radius
|
||||
color: Data.ThemeManager.accentColor
|
||||
}
|
||||
}
|
||||
|
||||
handle: Rectangle {
|
||||
x: historySlider.leftPadding + historySlider.visualPosition * (historySlider.availableWidth - width)
|
||||
y: historySlider.topPadding + historySlider.availableHeight / 2 - height / 2
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 10
|
||||
color: Data.ThemeManager.accentColor
|
||||
border.color: Qt.lighter(Data.ThemeManager.accentColor, 1.2)
|
||||
border.width: 2
|
||||
|
||||
scale: historySlider.pressed ? 1.2 : 1.0
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: 150
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: historyLabel
|
||||
text: historySlider.value + " items"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 14
|
||||
font.family: "monospace"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 60
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ignored Apps Setting
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 12
|
||||
|
||||
Text {
|
||||
text: "Ignored Applications"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Applications that won't show notifications"
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.7)
|
||||
font.pixelSize: 13
|
||||
font.family: "monospace"
|
||||
wrapMode: Text.Wrap
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
// Current ignored apps list
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: Math.max(100, ignoredAppsFlow.height + 16)
|
||||
radius: 12
|
||||
color: Qt.lighter(Data.ThemeManager.bgColor, 1.15)
|
||||
border.width: 1
|
||||
border.color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.3)
|
||||
|
||||
Flow {
|
||||
id: ignoredAppsFlow
|
||||
anchors.fill: parent
|
||||
anchors.margins: 8
|
||||
spacing: 6
|
||||
|
||||
Repeater {
|
||||
model: Data.Settings.ignoredApps
|
||||
delegate: Rectangle {
|
||||
width: appNameText.width + removeButton.width + 16
|
||||
height: 28
|
||||
radius: 14
|
||||
color: Qt.rgba(Data.ThemeManager.accentColor.r, Data.ThemeManager.accentColor.g, Data.ThemeManager.accentColor.b, 0.15)
|
||||
border.width: 1
|
||||
border.color: Qt.rgba(Data.ThemeManager.accentColor.r, Data.ThemeManager.accentColor.g, Data.ThemeManager.accentColor.b, 0.3)
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 4
|
||||
|
||||
Text {
|
||||
id: appNameText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: modelData
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 12
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: removeButton
|
||||
width: 18
|
||||
height: 18
|
||||
radius: 9
|
||||
color: removeMouseArea.containsMouse ? Qt.rgba(1, 0.3, 0.3, 0.8) : Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.5)
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 150
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "×"
|
||||
color: "white"
|
||||
font.pixelSize: 12
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: removeMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
Data.Settings.removeIgnoredApp(modelData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add new app button
|
||||
Rectangle {
|
||||
width: addAppText.width + 36
|
||||
height: 28
|
||||
radius: 14
|
||||
color: addAppMouseArea.containsMouse ? Qt.rgba(Data.ThemeManager.accentColor.r, Data.ThemeManager.accentColor.g, Data.ThemeManager.accentColor.b, 0.2) : Qt.lighter(Data.ThemeManager.bgColor, 1.2)
|
||||
border.width: 2
|
||||
border.color: Data.ThemeManager.accentColor
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 150
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 6
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "add"
|
||||
font.family: "Material Symbols Outlined"
|
||||
font.pixelSize: 14
|
||||
color: Data.ThemeManager.accentColor
|
||||
}
|
||||
|
||||
Text {
|
||||
id: addAppText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "Add App"
|
||||
color: Data.ThemeManager.accentColor
|
||||
font.pixelSize: 12
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: addAppMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: addAppPopup.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Quick suggestions
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 8
|
||||
|
||||
Text {
|
||||
text: "Common Apps"
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.7)
|
||||
font.pixelSize: 12
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Flow {
|
||||
width: parent.width
|
||||
spacing: 6
|
||||
|
||||
Repeater {
|
||||
model: ["Discord", "Spotify", "Steam", "Firefox", "Chrome", "VSCode", "Slack"]
|
||||
delegate: Rectangle {
|
||||
width: suggestedAppText.width + 16
|
||||
height: 24
|
||||
radius: 12
|
||||
color: suggestionMouseArea.containsMouse ? Qt.rgba(Data.ThemeManager.accentColor.r, Data.ThemeManager.accentColor.g, Data.ThemeManager.accentColor.b, 0.1) : "transparent"
|
||||
border.width: 1
|
||||
border.color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.3)
|
||||
|
||||
Text {
|
||||
id: suggestedAppText
|
||||
anchors.centerIn: parent
|
||||
text: modelData
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.7)
|
||||
font.pixelSize: 11
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: suggestionMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
Data.Settings.addIgnoredApp(modelData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add app popup
|
||||
Popup {
|
||||
id: addAppPopup
|
||||
parent: notificationSettings
|
||||
width: 280
|
||||
height: 160
|
||||
x: (parent.width - width) / 2
|
||||
y: (parent.height - height) / 2
|
||||
modal: true
|
||||
focus: true
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||
|
||||
background: Rectangle {
|
||||
color: Data.ThemeManager.bgColor
|
||||
border.color: Data.ThemeManager.accentColor
|
||||
border.width: 2
|
||||
radius: 20
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: 16
|
||||
width: parent.width - 40
|
||||
|
||||
Text {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: "Add Ignored App"
|
||||
color: Data.ThemeManager.accentColor
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 40
|
||||
radius: 20
|
||||
color: Qt.lighter(Data.ThemeManager.bgColor, 1.15)
|
||||
border.width: appNameInput.activeFocus ? 2 : 1
|
||||
border.color: appNameInput.activeFocus ? Data.ThemeManager.accentColor : Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.3)
|
||||
|
||||
Behavior on border.color {
|
||||
ColorAnimation {
|
||||
duration: 150
|
||||
}
|
||||
}
|
||||
|
||||
TextInput {
|
||||
id: appNameInput
|
||||
anchors.fill: parent
|
||||
anchors.margins: 12
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 14
|
||||
font.family: "monospace"
|
||||
selectByMouse: true
|
||||
clip: true
|
||||
verticalAlignment: TextInput.AlignVCenter
|
||||
focus: true
|
||||
activeFocusOnTab: true
|
||||
inputMethodHints: Qt.ImhNone
|
||||
|
||||
Keys.onPressed: function (event) {
|
||||
if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
|
||||
addAppButton.clicked();
|
||||
event.accepted = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Placeholder text implementation
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 12
|
||||
text: "App name (e.g. Discord)"
|
||||
color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.5)
|
||||
font.pixelSize: 14
|
||||
font.family: "monospace"
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
visible: appNameInput.text === ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: 12
|
||||
|
||||
Rectangle {
|
||||
width: 80
|
||||
height: 32
|
||||
radius: 16
|
||||
color: cancelMouseArea.containsMouse ? Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.1) : "transparent"
|
||||
border.width: 1
|
||||
border.color: Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.3)
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "Cancel"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 12
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: cancelMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
appNameInput.text = "";
|
||||
addAppPopup.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: addAppButton
|
||||
width: 80
|
||||
height: 32
|
||||
radius: 16
|
||||
color: addMouseArea.containsMouse ? Qt.lighter(Data.ThemeManager.accentColor, 1.1) : Data.ThemeManager.accentColor
|
||||
|
||||
signal clicked
|
||||
onClicked: {
|
||||
if (appNameInput.text.trim() !== "") {
|
||||
if (Data.Settings.addIgnoredApp(appNameInput.text.trim())) {
|
||||
appNameInput.text = "";
|
||||
addAppPopup.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "Add"
|
||||
color: Data.ThemeManager.bgColor
|
||||
font.pixelSize: 12
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: addMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: parent.clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
appNameInput.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import "root:/Data" as Data
|
||||
|
||||
// Reusable collapsible settings category component
|
||||
Item {
|
||||
id: categoryRoot
|
||||
|
||||
property string title: ""
|
||||
property string icon: ""
|
||||
property bool expanded: false
|
||||
property alias content: contentLoader.sourceComponent
|
||||
|
||||
height: headerRect.height + (expanded ? contentLoader.height + 20 : 0)
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
duration: 250
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
// Category header
|
||||
Rectangle {
|
||||
id: headerRect
|
||||
width: parent.width
|
||||
height: 50
|
||||
radius: 12
|
||||
color: expanded ? Qt.rgba(Data.ThemeManager.accentColor.r, Data.ThemeManager.accentColor.g, Data.ThemeManager.accentColor.b, 0.1) : Qt.lighter(Data.ThemeManager.bgColor, 1.15)
|
||||
border.width: expanded ? 2 : 1
|
||||
border.color: expanded ? Data.ThemeManager.accentColor : Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.3)
|
||||
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.leftMargin: 16
|
||||
spacing: 12
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: categoryRoot.icon
|
||||
font.family: "Material Symbols Outlined"
|
||||
font.pixelSize: 20
|
||||
color: expanded ? Data.ThemeManager.accentColor : Data.ThemeManager.fgColor
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: categoryRoot.title
|
||||
color: expanded ? Data.ThemeManager.accentColor : Data.ThemeManager.fgColor
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
}
|
||||
|
||||
// Expand/collapse arrow
|
||||
Text {
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.rightMargin: 16
|
||||
text: expanded ? "expand_less" : "expand_more"
|
||||
font.family: "Material Symbols Outlined"
|
||||
font.pixelSize: 20
|
||||
color: expanded ? Data.ThemeManager.accentColor : Data.ThemeManager.fgColor
|
||||
|
||||
Behavior on rotation {
|
||||
NumberAnimation {
|
||||
duration: 250
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
categoryRoot.expanded = !categoryRoot.expanded;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Category content
|
||||
Loader {
|
||||
id: contentLoader
|
||||
anchors.top: headerRect.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: expanded ? 20 : 0
|
||||
anchors.leftMargin: 16
|
||||
anchors.rightMargin: 16
|
||||
|
||||
visible: expanded
|
||||
opacity: expanded ? 1 : 0
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: 250
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import "root:/Data" as Data
|
||||
|
||||
// System settings content
|
||||
Item {
|
||||
id: systemSettings
|
||||
width: parent.width
|
||||
height: contentColumn.height
|
||||
|
||||
// Expose the text input focus for parent keyboard management
|
||||
property bool anyTextInputFocused: videoPathInput.activeFocus
|
||||
|
||||
Column {
|
||||
id: contentColumn
|
||||
width: parent.width
|
||||
spacing: 20
|
||||
|
||||
// Video Recording Path
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 8
|
||||
|
||||
Text {
|
||||
text: "Video Recording Path"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 40
|
||||
radius: 8
|
||||
color: Qt.lighter(Data.ThemeManager.bgColor, 1.15)
|
||||
border.width: videoPathInput.activeFocus ? 2 : 1
|
||||
border.color: videoPathInput.activeFocus ? Data.ThemeManager.accentColor : Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.3)
|
||||
|
||||
Behavior on border.color {
|
||||
ColorAnimation {
|
||||
duration: 150
|
||||
}
|
||||
}
|
||||
|
||||
TextInput {
|
||||
id: videoPathInput
|
||||
anchors.fill: parent
|
||||
anchors.margins: 12
|
||||
text: Data.Settings.videoPath
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 14
|
||||
font.family: "monospace"
|
||||
selectByMouse: true
|
||||
clip: true
|
||||
verticalAlignment: TextInput.AlignVCenter
|
||||
focus: true
|
||||
activeFocusOnTab: true
|
||||
inputMethodHints: Qt.ImhNone
|
||||
|
||||
onTextChanged: {
|
||||
Data.Settings.videoPath = text;
|
||||
}
|
||||
|
||||
Keys.onPressed: function (event) {}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
videoPathInput.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import "root:/Data" as Data
|
||||
|
||||
// Weather settings content
|
||||
Item {
|
||||
id: weatherSettings
|
||||
width: parent.width
|
||||
height: contentColumn.height
|
||||
|
||||
required property var shell
|
||||
|
||||
// Expose the text input focus for parent keyboard management
|
||||
property bool anyTextInputFocused: locationInput.activeFocus
|
||||
|
||||
Column {
|
||||
id: contentColumn
|
||||
width: parent.width
|
||||
spacing: 20
|
||||
|
||||
// Location Setting
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 8
|
||||
|
||||
Text {
|
||||
text: "Location"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: 12
|
||||
|
||||
Rectangle {
|
||||
width: parent.width - applyButton.width - 12
|
||||
height: 40
|
||||
radius: 8
|
||||
color: Qt.lighter(Data.ThemeManager.bgColor, 1.15)
|
||||
border.width: locationInput.activeFocus ? 2 : 1
|
||||
border.color: locationInput.activeFocus ? Data.ThemeManager.accentColor : Qt.rgba(Data.ThemeManager.fgColor.r, Data.ThemeManager.fgColor.g, Data.ThemeManager.fgColor.b, 0.3)
|
||||
|
||||
Behavior on border.color {
|
||||
ColorAnimation {
|
||||
duration: 150
|
||||
}
|
||||
}
|
||||
|
||||
TextInput {
|
||||
id: locationInput
|
||||
anchors.fill: parent
|
||||
anchors.margins: 12
|
||||
text: Data.Settings.weatherLocation
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 14
|
||||
font.family: "monospace"
|
||||
selectByMouse: true
|
||||
clip: true
|
||||
verticalAlignment: TextInput.AlignVCenter
|
||||
focus: true
|
||||
activeFocusOnTab: true
|
||||
inputMethodHints: Qt.ImhNone
|
||||
|
||||
Keys.onPressed: function (event) {
|
||||
if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
|
||||
applyButton.clicked();
|
||||
event.accepted = true;
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
locationInput.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: applyButton
|
||||
width: 80
|
||||
height: 40
|
||||
radius: 8
|
||||
color: applyMouseArea.containsMouse ? Qt.lighter(Data.ThemeManager.accentColor, 1.1) : Data.ThemeManager.accentColor
|
||||
|
||||
signal clicked
|
||||
onClicked: {
|
||||
Data.Settings.weatherLocation = locationInput.text;
|
||||
weatherSettings.shell.weatherService.loadWeather();
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "Apply"
|
||||
color: Data.ThemeManager.bgColor
|
||||
font.pixelSize: 12
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: applyMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: parent.clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Temperature Units
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 12
|
||||
|
||||
Text {
|
||||
text: "Temperature Units"
|
||||
color: Data.ThemeManager.fgColor
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: 12
|
||||
|
||||
Rectangle {
|
||||
width: 80
|
||||
height: 35
|
||||
radius: 18
|
||||
color: !Data.Settings.useFahrenheit ? Data.ThemeManager.accentColor : Qt.lighter(Data.ThemeManager.bgColor, 1.15)
|
||||
border.width: 1
|
||||
border.color: Data.ThemeManager.accentColor
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "°C"
|
||||
color: !Data.Settings.useFahrenheit ? Data.ThemeManager.bgColor : Data.ThemeManager.fgColor
|
||||
font.pixelSize: 14
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
Data.Settings.useFahrenheit = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 80
|
||||
height: 35
|
||||
radius: 18
|
||||
color: Data.Settings.useFahrenheit ? Data.ThemeManager.accentColor : Qt.lighter(Data.ThemeManager.bgColor, 1.15)
|
||||
border.width: 1
|
||||
border.color: Data.ThemeManager.accentColor
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "°F"
|
||||
color: Data.Settings.useFahrenheit ? Data.ThemeManager.bgColor : Data.ThemeManager.fgColor
|
||||
font.pixelSize: 14
|
||||
font.bold: true
|
||||
font.family: "monospace"
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
Data.Settings.useFahrenheit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user