1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-06 21:45:38 -05:00

settings: redesign

This commit is contained in:
bbedward
2025-07-24 16:02:53 -04:00
parent c6df2bc11d
commit 0e968d910d
16 changed files with 1623 additions and 1549 deletions

View File

@@ -7,10 +7,8 @@ import Qt.labs.folderlistmodel
import Quickshell.Io
import qs.Common
import qs.Widgets
import qs.Modals
DankModal {
id: fileBrowser
id: fileBrowserModal
signal fileSelected(string path)
@@ -119,36 +117,40 @@ DankModal {
spacing: Theme.spacingS
// Header
Row {
Item {
width: parent.width
spacing: Theme.spacingM
height: 40
DankIcon {
name: browserIcon
size: Theme.iconSizeLarge
color: Theme.primary
Row {
spacing: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
DankIcon {
name: browserIcon
size: Theme.iconSizeLarge
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: browserTitle
font.pixelSize: Theme.fontSizeXLarge
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
StyledText {
text: browserTitle
font.pixelSize: Theme.fontSizeXLarge
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
Item {
width: parent.width - 200
height: 1
}
// Close button
// Close button positioned at right
DankActionButton {
circular: false
iconName: "close"
iconSize: Theme.iconSizeSmall
iconSize: Theme.iconSize - 4
iconColor: Theme.surfaceText
onClicked: fileBrowser.visible = false
hoverColor: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
onClicked: fileBrowserModal.visible = false
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
}
}
@@ -182,7 +184,7 @@ DankModal {
}
StyledText {
text: "Current folder: " + fileBrowser.currentPath
text: "Current folder: " + fileBrowserModal.currentPath
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
width: parent.width - 40 - Theme.spacingS

View File

@@ -77,31 +77,31 @@ DankModal {
anchors.margins: Theme.spacingXL
spacing: Theme.spacingL
Row {
RowLayout {
Layout.fillWidth: true
height: 40
spacing: Theme.spacingM
StyledText {
anchors.verticalCenter: parent.verticalCenter
text: "System Monitor"
font.pixelSize: Theme.fontSizeLarge + 4
font.weight: Font.Bold
color: Theme.surfaceText
Layout.alignment: Qt.AlignVCenter
}
Item {
width: parent.width - 280
height: 1
Layout.fillWidth: true // Spacer to push close button to the right
}
StyledText {
anchors.verticalCenter: parent.verticalCenter
text: SysMonitorService.processes.length + " processes"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
width: Math.min(implicitWidth, 120)
elide: Text.ElideRight
// Close button
DankActionButton {
circular: false
iconName: "close"
iconSize: Theme.iconSize - 4
iconColor: Theme.surfaceText
hoverColor: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
onClicked: processListModal.hide()
Layout.alignment: Qt.AlignVCenter
}
}

View File

@@ -23,7 +23,6 @@ DankModal {
width: 650
height: 750
keyboardFocus: "ondemand"
enableShadow: true
onBackgroundClicked: {
settingsVisible = false;
}
@@ -101,64 +100,54 @@ DankModal {
width: parent.width
height: parent.height - settingsTabBar.height
// Personalization Tab
Loader {
// Content container with proper padding
Rectangle {
anchors.fill: parent
active: settingsTabBar.currentIndex === 0
visible: active
asynchronous: true
sourceComponent: Component {
PersonalizationTab {}
}
}
anchors.margins: Theme.spacingL
color: "transparent"
// Time & Weather Tab
Loader {
anchors.fill: parent
active: settingsTabBar.currentIndex === 1
visible: active
asynchronous: true
sourceComponent: Component {
Column {
spacing: Theme.spacingL
topPadding: Theme.spacingM
ClockTab {
width: parent.width
}
Rectangle {
width: parent.width
height: Theme.spacingL
color: "transparent"
}
WeatherTab {
width: parent.width
}
// Personalization Tab
Loader {
anchors.fill: parent
active: settingsTabBar.currentIndex === 0
visible: active
asynchronous: true
sourceComponent: Component {
PersonalizationTab {}
}
}
}
// System Tab
Loader {
anchors.fill: parent
active: settingsTabBar.currentIndex === 2
visible: active
asynchronous: true
sourceComponent: Component {
SystemTab {}
// Time & Weather Tab
Loader {
anchors.fill: parent
active: settingsTabBar.currentIndex === 1
visible: active
asynchronous: true
sourceComponent: Component {
TimeWeatherTab {}
}
}
}
// Appearance Tab
Loader {
anchors.fill: parent
active: settingsTabBar.currentIndex === 3
visible: active
asynchronous: true
sourceComponent: Component {
AppearanceTab {}
// System Tab
Loader {
anchors.fill: parent
active: settingsTabBar.currentIndex === 2
visible: active
asynchronous: true
sourceComponent: Component {
WidgetsTab {}
}
}
// Appearance Tab
Loader {
anchors.fill: parent
active: settingsTabBar.currentIndex === 3
visible: active
asynchronous: true
sourceComponent: Component {
AppearanceTab {}
}
}
}
}

View File

@@ -665,10 +665,32 @@ PanelWindow {
}
// Display Tab
DisplayTab {
Column {
anchors.fill: parent
anchors.margins: Theme.spacingM
visible: root.currentTab === "display"
spacing: Theme.spacingL
DankToggle {
width: parent.width
text: "Night Mode"
description: "Apply warm color temperature to reduce eye strain"
checked: Prefs.nightModeEnabled
onToggled: (checked) => {
Prefs.setNightModeEnabled(checked);
}
}
DankToggle {
width: parent.width
text: "Light Mode"
description: "Use light theme instead of dark theme"
checked: Prefs.isLightMode
onToggled: (checked) => {
Prefs.setLightMode(checked);
Theme.isLightMode = checked;
}
}
}
Behavior on height {

View File

@@ -1,56 +1,554 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import Quickshell.Io
import qs.Common
import qs.Services
import qs.Widgets
ScrollView {
id: root
id: appearanceTab
contentWidth: availableWidth
contentHeight: column.implicitHeight + Theme.spacingXL
clip: true
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
Column {
width: root.width - 20
spacing: Theme.spacingL
topPadding: Theme.spacingM
bottomPadding: Theme.spacingL
id: column
width: parent.width
spacing: Theme.spacingXL
topPadding: Theme.spacingL
bottomPadding: Theme.spacingXL
// Display Settings
Column {
// Display Settings Section
StyledRect {
width: parent.width
spacing: Theme.spacingM
height: displaySection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1
Row {
spacing: Theme.spacingS
Column {
id: displaySection
anchors.fill: parent
anchors.margins: Theme.spacingL
spacing: Theme.spacingM
DankIcon {
name: "monitor"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
Row {
width: parent.width
spacing: Theme.spacingM
DankIcon {
name: "monitor"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Display Settings"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Text {
text: "Display"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
DankToggle {
width: parent.width
text: "Night Mode"
description: "Apply warm color temperature to reduce eye strain"
checked: Prefs.nightModeEnabled
onToggled: (checked) => {
Prefs.setNightModeEnabled(checked);
if (checked)
nightModeEnableProcess.running = true;
else
nightModeDisableProcess.running = true;
}
}
DankToggle {
width: parent.width
text: "Light Mode"
description: "Use light theme instead of dark theme"
checked: Prefs.isLightMode
onToggled: (checked) => {
Prefs.setLightMode(checked);
Theme.isLightMode = checked;
}
}
DankDropdown {
width: parent.width
text: "Icon Theme"
description: "Select icon theme (requires restart)"
currentValue: Prefs.iconTheme
options: Prefs.availableIconThemes
onValueChanged: (value) => {
Prefs.setIconTheme(value);
}
}
}
}
Rectangle {
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
// Transparency Settings Section
StyledRect {
width: parent.width
height: transparencySection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1
Column {
id: transparencySection
anchors.fill: parent
anchors.margins: Theme.spacingL
spacing: Theme.spacingM
Row {
width: parent.width
spacing: Theme.spacingM
DankIcon {
name: "opacity"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Transparency Settings"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Column {
width: parent.width
spacing: Theme.spacingS
StyledText {
text: "Top Bar Transparency"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Medium
}
DankSlider {
width: parent.width
height: 24
value: Math.round(Prefs.topBarTransparency * 100)
minimum: 0
maximum: 100
unit: ""
showValue: false
onSliderValueChanged: (newValue) => {
Prefs.setTopBarTransparency(newValue / 100);
}
}
}
Column {
width: parent.width
spacing: Theme.spacingS
StyledText {
text: "Popup Transparency"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Medium
}
DankSlider {
width: parent.width
height: 24
value: Math.round(Prefs.popupTransparency * 100)
minimum: 0
maximum: 100
unit: ""
showValue: false
onSliderValueChanged: (newValue) => {
Prefs.setPopupTransparency(newValue / 100);
}
}
}
}
}
DisplayTab {
width: parent.width
// Theme Picker Section
StyledRect {
width: parent.width
height: themeSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1
Column {
id: themeSection
anchors.fill: parent
anchors.margins: Theme.spacingL
spacing: Theme.spacingM
Row {
width: parent.width
spacing: Theme.spacingM
DankIcon {
name: "palette"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Theme Color"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Column {
width: parent.width
spacing: Theme.spacingS
StyledText {
text: "Current Theme: " + (Theme.isDynamicTheme ? "Auto" : (Theme.currentThemeIndex < Theme.themes.length ? Theme.themes[Theme.currentThemeIndex].name : "Blue"))
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: {
if (Theme.isDynamicTheme)
return "Wallpaper-based dynamic colors";
var descriptions = ["Material blue inspired by modern interfaces", "Deep blue inspired by material 3", "Rich purple tones for BB elegance", "Natural green for productivity", "Energetic orange for creativity", "Bold red for impact", "Cool cyan for tranquility", "Vibrant pink for expression", "Warm amber for comfort", "Soft coral for gentle warmth"];
return descriptions[Theme.currentThemeIndex] || "Select a theme";
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
anchors.horizontalCenter: parent.horizontalCenter
wrapMode: Text.WordWrap
width: Math.min(parent.width, 400)
horizontalAlignment: Text.AlignHCenter
}
}
// Theme Grid
Column {
spacing: Theme.spacingS
anchors.horizontalCenter: parent.horizontalCenter
// First row - Blue, Deep Blue, Purple, Green, Orange
Row {
spacing: Theme.spacingM
anchors.horizontalCenter: parent.horizontalCenter
Repeater {
model: 5
Rectangle {
width: 32
height: 32
radius: 16
color: Theme.themes[index].primary
border.color: Theme.outline
border.width: (Theme.currentThemeIndex === index && !Theme.isDynamicTheme) ? 2 : 1
scale: (Theme.currentThemeIndex === index && !Theme.isDynamicTheme) ? 1.1 : 1
// Theme name tooltip
Rectangle {
width: nameText.contentWidth + Theme.spacingS * 2
height: nameText.contentHeight + Theme.spacingXS * 2
color: Theme.surfaceContainer
border.color: Theme.outline
border.width: 1
radius: Theme.cornerRadiusSmall
anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingXS
anchors.horizontalCenter: parent.horizontalCenter
visible: mouseArea.containsMouse
StyledText {
id: nameText
text: Theme.themes[index].name
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.centerIn: parent
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
Theme.switchTheme(index, false);
}
}
Behavior on scale {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on border.width {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
}
}
}
// Second row - Red, Cyan, Pink, Amber, Coral
Row {
spacing: Theme.spacingM
anchors.horizontalCenter: parent.horizontalCenter
Repeater {
model: 5
Rectangle {
property int themeIndex: index + 5
width: 32
height: 32
radius: 16
color: themeIndex < Theme.themes.length ? Theme.themes[themeIndex].primary : "transparent"
border.color: Theme.outline
border.width: Theme.currentThemeIndex === themeIndex ? 2 : 1
visible: themeIndex < Theme.themes.length
scale: Theme.currentThemeIndex === themeIndex ? 1.1 : 1
// Theme name tooltip
Rectangle {
width: nameText2.contentWidth + Theme.spacingS * 2
height: nameText2.contentHeight + Theme.spacingXS * 2
color: Theme.surfaceContainer
border.color: Theme.outline
border.width: 1
radius: Theme.cornerRadiusSmall
anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingXS
anchors.horizontalCenter: parent.horizontalCenter
visible: mouseArea2.containsMouse && themeIndex < Theme.themes.length
StyledText {
id: nameText2
text: themeIndex < Theme.themes.length ? Theme.themes[themeIndex].name : ""
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.centerIn: parent
}
}
MouseArea {
id: mouseArea2
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (themeIndex < Theme.themes.length)
Theme.switchTheme(themeIndex);
}
}
Behavior on scale {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on border.width {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
}
}
}
// Spacer
Item {
width: 1
height: Theme.spacingM
}
// Auto theme button
Rectangle {
width: 120
height: 40
radius: 20
anchors.horizontalCenter: parent.horizontalCenter
color: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12);
else
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3);
}
border.color: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.5);
else if (Theme.isDynamicTheme)
return Theme.primary;
else
return Theme.outline;
}
border.width: Theme.isDynamicTheme ? 2 : 1
scale: Theme.isDynamicTheme ? 1.1 : (autoMouseArea.containsMouse ? 1.02 : 1)
Row {
anchors.centerIn: parent
spacing: Theme.spacingS
DankIcon {
name: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
return "error";
else
return "palette";
}
size: 16
color: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
return Theme.error;
else
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (ToastService.wallpaperErrorStatus === "error")
return "Error";
else if (ToastService.wallpaperErrorStatus === "matugen_missing")
return "No matugen";
else
return "Auto";
}
font.pixelSize: Theme.fontSizeMedium
color: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
return Theme.error;
else
return Theme.surfaceText;
}
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
id: autoMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (ToastService.wallpaperErrorStatus === "matugen_missing") {
ToastService.showError("matugen not found - install matugen package for dynamic theming");
} else if (ToastService.wallpaperErrorStatus === "error") {
ToastService.showError("Wallpaper processing failed - check wallpaper path");
} else {
Theme.switchTheme(10, true);
}
}
}
// Tooltip for Auto button
Rectangle {
width: autoTooltipText.contentWidth + Theme.spacingM * 2
height: autoTooltipText.contentHeight + Theme.spacingS * 2
color: Theme.surfaceContainer
border.color: Theme.outline
border.width: 1
radius: Theme.cornerRadiusSmall
anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingS
anchors.horizontalCenter: parent.horizontalCenter
visible: autoMouseArea.containsMouse && (!Theme.isDynamicTheme || ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
StyledText {
id: autoTooltipText
text: {
if (ToastService.wallpaperErrorStatus === "error")
return "Wallpaper symlink missing at ~/quickshell/current_wallpaper";
else if (ToastService.wallpaperErrorStatus === "matugen_missing")
return "Install matugen package for dynamic themes";
else
return "Dynamic wallpaper-based colors";
}
font.pixelSize: Theme.fontSizeSmall
color: (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing") ? Theme.error : Theme.surfaceText
anchors.centerIn: parent
wrapMode: Text.WordWrap
width: Math.min(implicitWidth, 250)
horizontalAlignment: Text.AlignHCenter
}
}
Behavior on scale {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on color {
ColorAnimation {
duration: Theme.mediumDuration
easing.type: Theme.standardEasing
}
}
Behavior on border.color {
ColorAnimation {
duration: Theme.mediumDuration
easing.type: Theme.standardEasing
}
}
}
}
}
}
}
// Night mode processes
Process {
id: nightModeEnableProcess
command: ["bash", "-c", "if command -v wlsunset > /dev/null; then pkill wlsunset; wlsunset -t 3000 & elif command -v redshift > /dev/null; then pkill redshift; redshift -P -O 3000 & else echo 'No night mode tool available'; fi"]
running: false
onExited: (exitCode) => {
if (exitCode !== 0) {
console.warn("Failed to enable night mode");
Prefs.setNightModeEnabled(false);
}
}
}
Process {
id: nightModeDisableProcess
command: ["bash", "-c", "pkill wlsunset; pkill redshift; if command -v wlsunset > /dev/null; then wlsunset -t 6500 -T 6500 & sleep 1; pkill wlsunset; elif command -v redshift > /dev/null; then redshift -P -O 6500; redshift -x; fi"]
running: false
onExited: (exitCode) => {
if (exitCode !== 0)
console.warn("Failed to disable night mode");
}
}
}

View File

@@ -1,18 +0,0 @@
import QtQuick
import qs.Common
import qs.Widgets
Column {
width: parent.width
spacing: Theme.spacingM
DankToggle {
text: "24-Hour Format"
description: "Use 24-hour time format instead of 12-hour AM/PM"
checked: Prefs.use24HourClock
onToggled: (checked) => {
return Prefs.setClockFormat(checked);
}
}
}

View File

@@ -1,163 +0,0 @@
import QtQuick
import Quickshell.Io
import qs.Common
import qs.Widgets
Column {
id: root
width: parent.width
spacing: Theme.spacingL
DankToggle {
text: "Night Mode"
description: "Apply warm color temperature to reduce eye strain"
checked: Prefs.nightModeEnabled
onToggled: (checked) => {
Prefs.setNightModeEnabled(checked);
if (checked)
nightModeEnableProcess.running = true;
else
nightModeDisableProcess.running = true;
}
}
DankToggle {
text: "Light Mode"
description: "Use light theme instead of dark theme"
checked: Prefs.isLightMode
onToggled: (checked) => {
Prefs.setLightMode(checked);
Theme.isLightMode = checked;
}
}
DankDropdown {
text: "Icon Theme"
description: "Select icon theme (requires restart)"
currentValue: Prefs.iconTheme
options: Prefs.availableIconThemes
onValueChanged: (value) => {
Prefs.setIconTheme(value);
}
}
// Top Bar Transparency
Column {
width: parent.width
spacing: Theme.spacingS
Text {
text: "Top Bar Transparency"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
}
DankSlider {
width: parent.width
value: Math.round(Prefs.topBarTransparency * 100)
minimum: 0
maximum: 100
leftIcon: "opacity"
rightIcon: "circle"
unit: "%"
showValue: true
onSliderDragFinished: (finalValue) => {
let transparencyValue = finalValue / 100;
Prefs.setTopBarTransparency(transparencyValue);
}
}
Text {
text: "Adjust the transparency of the top bar background"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width
}
}
// Popup Transparency
Column {
width: parent.width
spacing: Theme.spacingS
Text {
text: "Popup Transparency"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
}
DankSlider {
width: parent.width
value: Math.round(Prefs.popupTransparency * 100)
minimum: 0
maximum: 100
leftIcon: "blur_on"
rightIcon: "circle"
unit: "%"
showValue: true
onSliderDragFinished: (finalValue) => {
let transparencyValue = finalValue / 100;
Prefs.setPopupTransparency(transparencyValue);
}
}
Text {
text: "Adjust transparency for dialogs, menus, and popups"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width
}
}
// Theme Picker
Column {
width: parent.width
spacing: Theme.spacingS
Text {
text: "Theme Color"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
}
ThemePicker {
anchors.horizontalCenter: parent.horizontalCenter
}
}
// Night mode processes
Process {
id: nightModeEnableProcess
command: ["bash", "-c", "if command -v wlsunset > /dev/null; then pkill wlsunset; wlsunset -t 3000 & elif command -v redshift > /dev/null; then pkill redshift; redshift -P -O 3000 & else echo 'No night mode tool available'; fi"]
running: false
onExited: (exitCode) => {
if (exitCode !== 0) {
console.warn("Failed to enable night mode");
Prefs.setNightModeEnabled(false);
}
}
}
Process {
id: nightModeDisableProcess
command: ["bash", "-c", "pkill wlsunset; pkill redshift; if command -v wlsunset > /dev/null; then wlsunset -t 6500 -T 6500 & sleep 1; pkill wlsunset; elif command -v redshift > /dev/null; then redshift -P -O 6500; redshift -x; fi"]
running: false
onExited: (exitCode) => {
if (exitCode !== 0)
console.warn("Failed to disable night mode");
}
}
}

View File

@@ -1,91 +1,544 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import QtQuick.Effects
import Quickshell
import qs.Common
import qs.Services
import qs.Widgets
import qs.Modals
ScrollView {
id: root
id: personalizationTab
contentWidth: availableWidth
contentHeight: column.implicitHeight
clip: true
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
Column {
width: root.width - 20
spacing: Theme.spacingL
topPadding: Theme.spacingM
bottomPadding: Theme.spacingL
id: column
width: parent.width
spacing: Theme.spacingXL
// Profile Section
Column {
StyledRect {
width: parent.width
spacing: Theme.spacingM
height: profileSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1
Row {
spacing: Theme.spacingS
Column {
id: profileSection
anchors.fill: parent
anchors.margins: Theme.spacingL
spacing: Theme.spacingM
DankIcon {
name: "person"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
Row {
width: parent.width
spacing: Theme.spacingM
DankIcon {
name: "person"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Profile Image"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Text {
text: "Profile"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
Row {
width: parent.width
spacing: Theme.spacingL
// Circular profile image preview
Item {
id: avatarContainer
property bool hasImage: avatarImageSource.status === Image.Ready
width: 80
height: 80
Rectangle {
anchors.fill: parent
radius: width / 2
color: "transparent"
border.color: Theme.primary
border.width: 1
visible: parent.hasImage
}
Image {
id: avatarImageSource
source: {
if (Prefs.profileImage === "")
return "";
if (Prefs.profileImage.startsWith("/"))
return "file://" + Prefs.profileImage;
return Prefs.profileImage;
}
smooth: true
asynchronous: true
mipmap: true
cache: true
visible: false
}
MultiEffect {
anchors.fill: parent
anchors.margins: 5
source: avatarImageSource
maskEnabled: true
maskSource: settingsCircularMask
visible: avatarContainer.hasImage
maskThresholdMin: 0.5
maskSpreadAtMin: 1
}
Item {
id: settingsCircularMask
width: 70
height: 70
layer.enabled: true
layer.smooth: true
visible: false
Rectangle {
anchors.fill: parent
radius: width / 2
color: "black"
antialiasing: true
}
}
Rectangle {
anchors.fill: parent
radius: width / 2
color: Theme.primary
visible: !parent.hasImage
DankIcon {
anchors.centerIn: parent
name: "person"
size: Theme.iconSizeLarge + 8
color: Theme.primaryText
}
}
DankIcon {
anchors.centerIn: parent
name: "warning"
size: Theme.iconSizeLarge
color: Theme.error
visible: Prefs.profileImage !== "" && avatarImageSource.status === Image.Error
}
}
Column {
width: parent.width - 80 - Theme.spacingL
spacing: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: Prefs.profileImage ? Prefs.profileImage.split('/').pop() : "No profile image selected"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
elide: Text.ElideMiddle
width: parent.width
}
StyledText {
text: Prefs.profileImage ? Prefs.profileImage : ""
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
elide: Text.ElideMiddle
width: parent.width
visible: Prefs.profileImage !== ""
}
Row {
spacing: Theme.spacingS
StyledRect {
width: 100
height: 32
radius: Theme.cornerRadius
color: Theme.primary
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: "folder_open"
size: Theme.iconSizeSmall
color: Theme.primaryText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Browse"
color: Theme.primaryText
font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
profileBrowserLoader.active = true;
profileBrowser.visible = true;
}
}
}
StyledRect {
width: 80
height: 32
radius: Theme.cornerRadius
color: Theme.surfaceVariant
opacity: Prefs.profileImage !== "" ? 1.0 : 0.5
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: "clear"
size: Theme.iconSizeSmall
color: Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Clear"
color: Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
enabled: Prefs.profileImage !== ""
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
Prefs.setProfileImage("");
}
}
}
}
}
}
}
Rectangle {
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
}
ProfileTab {
width: parent.width
}
}
// Wallpaper Section
Column {
StyledRect {
width: parent.width
spacing: Theme.spacingM
height: wallpaperSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1
Row {
spacing: Theme.spacingS
Column {
id: wallpaperSection
anchors.fill: parent
anchors.margins: Theme.spacingL
spacing: Theme.spacingM
DankIcon {
name: "wallpaper"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
Row {
width: parent.width
spacing: Theme.spacingM
DankIcon {
name: "wallpaper"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Wallpaper"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Text {
text: "Wallpaper"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
Row {
width: parent.width
spacing: Theme.spacingL
// Wallpaper Preview
StyledRect {
width: 160
height: 90
radius: Theme.cornerRadius
color: Theme.surfaceVariant
border.color: Theme.outline
border.width: 1
CachingImage {
anchors.fill: parent
anchors.margins: 1
imagePath: Prefs.wallpaperPath || ""
fillMode: Image.PreserveAspectCrop
visible: Prefs.wallpaperPath !== ""
maxCacheSize: 160
layer.enabled: true
layer.effect: MultiEffect {
maskEnabled: true
maskSource: wallpaperMask
maskThresholdMin: 0.5
maskSpreadAtMin: 1.0
}
}
Rectangle {
id: wallpaperMask
anchors.fill: parent
anchors.margins: 1
radius: Theme.cornerRadius - 1
color: "black"
visible: false
layer.enabled: true
}
DankIcon {
anchors.centerIn: parent
name: "image"
size: Theme.iconSizeLarge + 8
color: Theme.surfaceVariantText
visible: Prefs.wallpaperPath === ""
}
}
Column {
width: parent.width - 160 - Theme.spacingL
spacing: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: Prefs.wallpaperPath ? Prefs.wallpaperPath.split('/').pop() : "No wallpaper selected"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
elide: Text.ElideMiddle
width: parent.width
}
StyledText {
text: Prefs.wallpaperPath ? Prefs.wallpaperPath : ""
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
elide: Text.ElideMiddle
width: parent.width
visible: Prefs.wallpaperPath !== ""
}
Row {
spacing: Theme.spacingS
StyledRect {
width: 100
height: 32
radius: Theme.cornerRadius
color: Theme.primary
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: "folder_open"
size: Theme.iconSizeSmall
color: Theme.primaryText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Browse"
color: Theme.primaryText
font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
wallpaperBrowserLoader.active = true;
wallpaperBrowser.visible = true;
}
}
}
StyledRect {
width: 80
height: 32
radius: Theme.cornerRadius
color: Theme.surfaceVariant
opacity: Prefs.wallpaperPath !== "" ? 1.0 : 0.5
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: "clear"
size: Theme.iconSizeSmall
color: Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Clear"
color: Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
enabled: Prefs.wallpaperPath !== ""
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
Prefs.setWallpaperPath("");
}
}
}
}
}
}
}
}
Rectangle {
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
}
// Dynamic Theming Section
StyledRect {
width: parent.width
height: dynamicThemeSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1
WallpaperTab {
width: parent.width
Column {
id: dynamicThemeSection
anchors.fill: parent
anchors.margins: Theme.spacingL
spacing: Theme.spacingM
Row {
width: parent.width
spacing: Theme.spacingM
DankIcon {
name: "palette"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
Column {
width: parent.width - Theme.iconSize - Theme.spacingM - toggle.width - Theme.spacingM
spacing: Theme.spacingXS
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: "Dynamic Theming"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
}
StyledText {
text: "Automatically extract colors from wallpaper"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width
}
}
DankToggle {
id: toggle
anchors.verticalCenter: parent.verticalCenter
checked: Theme.isDynamicTheme
enabled: ToastService.wallpaperErrorStatus !== "matugen_missing"
onToggled: (toggled) => {
if (toggled) {
Theme.switchTheme(10, true)
} else {
Theme.switchTheme(0)
}
}
}
}
StyledText {
text: "matugen not detected - dynamic theming unavailable"
font.pixelSize: Theme.fontSizeSmall
color: Theme.error
visible: ToastService.wallpaperErrorStatus === "matugen_missing"
width: parent.width
leftPadding: Theme.iconSize + Theme.spacingM
}
}
}
}
LazyLoader {
id: profileBrowserLoader
active: false
FileBrowserModal {
id: profileBrowser
browserTitle: "Select Profile Image"
browserIcon: "person"
browserType: "profile"
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: (path) => {
Prefs.setProfileImage(path);
visible = false;
}
}
}
LazyLoader {
id: wallpaperBrowserLoader
active: false
FileBrowserModal {
id: wallpaperBrowser
browserTitle: "Select Wallpaper"
browserIcon: "wallpaper"
browserType: "wallpaper"
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: (path) => {
Prefs.setWallpaperPath(path);
visible = false;
}
}
}
property alias profileBrowser: profileBrowserLoader.item
property alias wallpaperBrowser: wallpaperBrowserLoader.item
}

View File

@@ -1,241 +0,0 @@
import QtQuick
import QtQuick.Effects
import Quickshell
import qs.Common
import qs.Widgets
Column {
width: parent.width
spacing: Theme.spacingM
// Profile Image Preview and Input
Column {
width: parent.width
spacing: Theme.spacingM
StyledText {
text: "Profile Image"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
}
// Profile Image Preview with circular crop
Row {
width: parent.width
spacing: Theme.spacingM
// Circular profile image preview
Item {
id: avatarContainer
property bool hasImage: avatarImageSource.status === Image.Ready
width: 54
height: 54
Rectangle {
anchors.fill: parent
radius: width / 2
color: "transparent"
border.color: Theme.primary
border.width: 1
visible: parent.hasImage
}
CachingImage {
id: avatarImageSource
imagePath: {
if (Prefs.profileImage === "")
return "";
if (Prefs.profileImage.startsWith("/"))
return Prefs.profileImage;
return Prefs.profileImage;
}
smooth: true
asynchronous: true
maxCacheSize: 80
cache: true
visible: false
}
MultiEffect {
anchors.fill: parent
anchors.margins: 5
source: avatarImageSource
maskEnabled: true
maskSource: settingsCircularMask
visible: avatarContainer.hasImage
maskThresholdMin: 0.5
maskSpreadAtMin: 1
}
Item {
id: settingsCircularMask
width: 54 - 10
height: 54 - 10
layer.enabled: true
layer.smooth: true
visible: false
Rectangle {
anchors.fill: parent
radius: width / 2
color: "black"
antialiasing: true
}
}
Rectangle {
anchors.fill: parent
radius: width / 2
color: Theme.primary
visible: !parent.hasImage
DankIcon {
anchors.centerIn: parent
name: "person"
size: Theme.iconSize + 8
color: Theme.primaryText
}
}
DankIcon {
anchors.centerIn: parent
name: "warning"
size: Theme.iconSize + 8
color: Theme.primaryText
visible: Prefs.profileImage !== "" && avatarImageSource.status === Image.Error
}
}
Column {
width: parent.width - 54 - Theme.spacingM
spacing: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: Prefs.profileImage ? Prefs.profileImage.split('/').pop() : "No profile image selected"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
elide: Text.ElideMiddle
width: parent.width
}
StyledText {
text: Prefs.profileImage ? Prefs.profileImage : ""
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
elide: Text.ElideMiddle
width: parent.width
visible: Prefs.profileImage !== ""
}
}
}
Row {
width: parent.width
spacing: Theme.spacingS
StyledRect {
width: 100
height: 32
radius: Theme.cornerRadius
color: Theme.primary
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: "folder_open"
size: Theme.iconSizeSmall
color: Theme.primaryText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Browse..."
color: Theme.primaryText
font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
profileBrowserLoader.active = true;
profileBrowser.visible = true;
}
}
}
StyledRect {
width: 80
height: 32
radius: Theme.cornerRadius
color: Theme.surfaceVariant
opacity: Prefs.profileImage !== "" ? 1.0 : 0.5
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: "clear"
size: Theme.iconSizeSmall
color: Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Clear"
color: Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
enabled: Prefs.profileImage !== ""
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
Prefs.setProfileImage("");
}
}
}
}
}
LazyLoader {
id: profileBrowserLoader
active: false
DankFileBrowser {
id: profileBrowser
browserTitle: "Select Profile Image"
browserIcon: "person"
browserType: "profile"
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: (path) => {
Prefs.setProfileImage(path);
visible = false;
}
}
}
property alias profileBrowser: profileBrowserLoader.item
}

View File

@@ -1,91 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import qs.Common
import qs.Widgets
ScrollView {
id: root
clip: true
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
Column {
width: root.width - 20
spacing: Theme.spacingL
topPadding: Theme.spacingM
bottomPadding: Theme.spacingL
// Top Bar Widgets
Column {
width: parent.width
spacing: Theme.spacingM
Row {
spacing: Theme.spacingS
DankIcon {
name: "widgets"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: "Top Bar Widgets"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
Rectangle {
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
}
WidgetsTab {
width: parent.width
}
}
// Workspaces
Column {
width: parent.width
spacing: Theme.spacingM
Row {
spacing: Theme.spacingS
DankIcon {
name: "tab"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: "Workspaces"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
Rectangle {
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
}
WorkspaceTab {
width: parent.width
}
}
}
}

View File

@@ -1,345 +0,0 @@
import QtQuick
import qs.Common
import qs.Services
import qs.Widgets
Column {
id: themePicker
spacing: Theme.spacingS
Text {
text: "Current Theme: " + (Theme.isDynamicTheme ? "Auto" : (Theme.currentThemeIndex < Theme.themes.length ? Theme.themes[Theme.currentThemeIndex].name : "Blue"))
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
anchors.horizontalCenter: parent.horizontalCenter
}
// Theme description
Text {
text: {
if (Theme.isDynamicTheme)
return "Wallpaper-based dynamic colors";
var descriptions = ["Material blue inspired by modern interfaces", "Deep blue inspired by material 3", "Rich purple tones for BB elegance", "Natural green for productivity", "Energetic orange for creativity", "Bold red for impact", "Cool cyan for tranquility", "Vibrant pink for expression", "Warm amber for comfort", "Soft coral for gentle warmth"];
return descriptions[Theme.currentThemeIndex] || "Select a theme";
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
anchors.horizontalCenter: parent.horizontalCenter
wrapMode: Text.WordWrap
width: Math.min(parent.width, 200)
horizontalAlignment: Text.AlignHCenter
}
// Grid layout for 10 themes (2 rows of 5)
Column {
spacing: Theme.spacingS
anchors.horizontalCenter: parent.horizontalCenter
// First row - Blue, Deep Blue, Purple, Green, Orange
Row {
spacing: Theme.spacingM
anchors.horizontalCenter: parent.horizontalCenter
Repeater {
model: 5
Rectangle {
width: 32
height: 32
radius: 16
color: Theme.themes[index].primary
border.color: Theme.outline
border.width: (Theme.currentThemeIndex === index && !Theme.isDynamicTheme) ? 2 : 1
scale: (Theme.currentThemeIndex === index && !Theme.isDynamicTheme) ? 1.1 : 1
// Theme name tooltip
Rectangle {
width: nameText.contentWidth + Theme.spacingS * 2
height: nameText.contentHeight + Theme.spacingXS * 2
color: Theme.surfaceContainer
border.color: Theme.outline
border.width: 1
radius: Theme.cornerRadiusSmall
anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingXS
anchors.horizontalCenter: parent.horizontalCenter
visible: mouseArea.containsMouse
Text {
id: nameText
text: Theme.themes[index].name
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.centerIn: parent
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
Theme.switchTheme(index, false);
}
}
Behavior on scale {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on border.width {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
}
}
}
// Second row - Red, Cyan, Pink, Amber, Coral
Row {
spacing: Theme.spacingM
anchors.horizontalCenter: parent.horizontalCenter
Repeater {
model: 5
Rectangle {
property int themeIndex: index + 5
width: 32
height: 32
radius: 16
color: themeIndex < Theme.themes.length ? Theme.themes[themeIndex].primary : "transparent"
border.color: Theme.outline
border.width: Theme.currentThemeIndex === themeIndex ? 2 : 1
visible: themeIndex < Theme.themes.length
scale: Theme.currentThemeIndex === themeIndex ? 1.1 : 1
// Theme name tooltip
Rectangle {
width: nameText2.contentWidth + Theme.spacingS * 2
height: nameText2.contentHeight + Theme.spacingXS * 2
color: Theme.surfaceContainer
border.color: Theme.outline
border.width: 1
radius: Theme.cornerRadiusSmall
anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingXS
anchors.horizontalCenter: parent.horizontalCenter
visible: mouseArea2.containsMouse && themeIndex < Theme.themes.length
Text {
id: nameText2
text: themeIndex < Theme.themes.length ? Theme.themes[themeIndex].name : ""
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.centerIn: parent
}
}
MouseArea {
id: mouseArea2
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (themeIndex < Theme.themes.length)
Theme.switchTheme(themeIndex);
}
}
Behavior on scale {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on border.width {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
}
}
}
// Spacer for better visual separation
Item {
width: 1
height: Theme.spacingM
}
// Auto theme button - prominent oval below the grid
Rectangle {
width: 120
height: 40
radius: 20
anchors.horizontalCenter: parent.horizontalCenter
color: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12);
else
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3);
}
border.color: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.5);
else if (Theme.isDynamicTheme)
return Theme.primary;
else
return Theme.outline;
}
border.width: Theme.isDynamicTheme ? 2 : 1
scale: Theme.isDynamicTheme ? 1.1 : (autoMouseArea.containsMouse ? 1.02 : 1)
Row {
anchors.centerIn: parent
spacing: Theme.spacingS
DankIcon {
name: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
return "error";
else
return "palette";
}
size: 16
color: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
return Theme.error;
else
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: {
if (ToastService.wallpaperErrorStatus === "error")
return "Error";
else if (ToastService.wallpaperErrorStatus === "matugen_missing")
return "No matugen";
else
return "Auto";
}
font.pixelSize: Theme.fontSizeMedium
color: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
return Theme.error;
else
return Theme.surfaceText;
}
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
id: autoMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (ToastService.wallpaperErrorStatus === "matugen_missing") {
ToastService.showError("matugen not found - install matugen package for dynamic theming");
} else if (ToastService.wallpaperErrorStatus === "error") {
ToastService.showError("Wallpaper processing failed - check wallpaper path");
} else {
Theme.switchTheme(10, true);
}
}
}
// Tooltip for Auto button
Rectangle {
width: autoTooltipText.contentWidth + Theme.spacingM * 2
height: autoTooltipText.contentHeight + Theme.spacingS * 2
color: Theme.surfaceContainer
border.color: Theme.outline
border.width: 1
radius: Theme.cornerRadiusSmall
anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingS
anchors.horizontalCenter: parent.horizontalCenter
visible: autoMouseArea.containsMouse && (!Theme.isDynamicTheme || ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
Text {
id: autoTooltipText
text: {
if (ToastService.wallpaperErrorStatus === "error")
return "Wallpaper symlink missing at ~/quickshell/current_wallpaper";
else if (ToastService.wallpaperErrorStatus === "matugen_missing")
return "Install matugen package for dynamic themes";
else
return "Dynamic wallpaper-based colors";
}
font.pixelSize: Theme.fontSizeSmall
color: (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing") ? Theme.error : Theme.surfaceText
anchors.centerIn: parent
wrapMode: Text.WordWrap
width: Math.min(implicitWidth, 250)
horizontalAlignment: Text.AlignHCenter
}
}
Behavior on scale {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on color {
ColorAnimation {
duration: Theme.mediumDuration
easing.type: Theme.standardEasing
}
}
Behavior on border.color {
ColorAnimation {
duration: Theme.mediumDuration
easing.type: Theme.standardEasing
}
}
}
}
}

View File

@@ -0,0 +1,161 @@
import QtQuick
import QtQuick.Controls
import qs.Common
import qs.Widgets
ScrollView {
id: timeWeatherTab
contentWidth: availableWidth
contentHeight: column.implicitHeight
clip: true
Column {
id: column
width: parent.width
spacing: Theme.spacingXL
// Time Settings Section
StyledRect {
width: parent.width
height: timeSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1
Column {
id: timeSection
anchors.fill: parent
anchors.margins: Theme.spacingL
spacing: Theme.spacingM
Row {
width: parent.width
spacing: Theme.spacingM
DankIcon {
name: "schedule"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Time Format"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
DankToggle {
width: parent.width
text: "24-Hour Format"
description: "Use 24-hour time format instead of 12-hour AM/PM"
checked: Prefs.use24HourClock
onToggled: (checked) => {
return Prefs.setClockFormat(checked);
}
}
}
}
// Weather Settings Section
StyledRect {
width: parent.width
height: weatherSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1
Column {
id: weatherSection
anchors.fill: parent
anchors.margins: Theme.spacingL
spacing: Theme.spacingM
Row {
width: parent.width
spacing: Theme.spacingM
DankIcon {
name: "cloud"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Weather"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
DankToggle {
width: parent.width
text: "Fahrenheit"
description: "Use Fahrenheit instead of Celsius for temperature"
checked: Prefs.useFahrenheit
onToggled: (checked) => {
return Prefs.setTemperatureUnit(checked);
}
}
DankToggle {
width: parent.width
text: "Override Location"
description: "Use a specific location instead of auto-detection"
checked: Prefs.weatherLocationOverrideEnabled
onToggled: (checked) => {
return Prefs.setWeatherLocationOverrideEnabled(checked);
}
}
// Location input - only visible when override is enabled
Column {
width: parent.width
spacing: Theme.spacingS
visible: Prefs.weatherLocationOverrideEnabled
opacity: visible ? 1 : 0
StyledText {
text: "Location"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
}
DankLocationSearch {
width: parent.width
currentLocation: Prefs.weatherLocationOverride
placeholderText: "Search for a location..."
onLocationSelected: (displayName, coordinates) => {
Prefs.setWeatherLocationOverride(coordinates);
}
}
StyledText {
text: "Examples: \"New York\", \"Tokyo\", \"44511\""
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width
}
Behavior on opacity {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
}
}
}
}

View File

@@ -1,248 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Effects
import Quickshell
import qs.Common
import qs.Services
import qs.Widgets
Column {
id: wallpaperTab
width: parent.width
spacing: Theme.spacingM
// Current Wallpaper Section
Column {
width: parent.width
spacing: Theme.spacingS
StyledText {
text: "Current Wallpaper"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
}
Row {
width: parent.width
spacing: Theme.spacingM
// Wallpaper Preview
StyledRect {
width: 120
height: 67
radius: Theme.cornerRadius
color: Theme.surfaceVariant
border.color: Theme.outline
border.width: 1
CachingImage {
anchors.fill: parent
anchors.margins: 1
imagePath: Prefs.wallpaperPath || ""
fillMode: Image.PreserveAspectCrop
visible: Prefs.wallpaperPath !== ""
maxCacheSize: 120
layer.enabled: true
layer.effect: MultiEffect {
maskEnabled: true
maskSource: mask
maskThresholdMin: 0.5
maskSpreadAtMin: 1.0
}
}
Rectangle {
id: mask
anchors.fill: parent
anchors.margins: 1
radius: Theme.cornerRadius - 1
color: "black"
visible: false
layer.enabled: true
}
DankIcon {
anchors.centerIn: parent
name: "image"
size: Theme.iconSizeLarge
color: Theme.surfaceVariantText
visible: Prefs.wallpaperPath === ""
}
}
Column {
width: parent.width - 120 - Theme.spacingM
spacing: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: Prefs.wallpaperPath ? Prefs.wallpaperPath.split('/').pop() : "No wallpaper selected"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
elide: Text.ElideMiddle
width: parent.width
}
StyledText {
text: Prefs.wallpaperPath ? Prefs.wallpaperPath : ""
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
elide: Text.ElideMiddle
width: parent.width
visible: Prefs.wallpaperPath !== ""
}
}
}
Row {
width: parent.width
spacing: Theme.spacingS
StyledRect {
width: 100
height: 32
radius: Theme.cornerRadius
color: Theme.primary
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: "folder_open"
size: Theme.iconSizeSmall
color: Theme.primaryText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Browse..."
color: Theme.primaryText
font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
wallpaperBrowserLoader.active = true;
wallpaperBrowser.visible = true;
}
}
}
StyledRect {
width: 80
height: 32
radius: Theme.cornerRadius
color: Theme.surfaceVariant
opacity: Prefs.wallpaperPath !== "" ? 1.0 : 0.5
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: "clear"
size: Theme.iconSizeSmall
color: Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Clear"
color: Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
enabled: Prefs.wallpaperPath !== ""
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
Prefs.setWallpaperPath("");
}
}
}
}
}
// Dynamic Theming Section
Column {
width: parent.width
spacing: Theme.spacingS
Row {
width: parent.width
spacing: Theme.spacingM
Column {
width: parent.width - toggle.width - Theme.spacingM
spacing: Theme.spacingXS
StyledText {
text: "Dynamic Theming"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
}
StyledText {
text: "Automatically extract colors from wallpaper"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width
}
}
DankToggle {
id: toggle
anchors.verticalCenter: parent.verticalCenter
checked: Theme.isDynamicTheme
enabled: ToastService.wallpaperErrorStatus !== "matugen_missing"
onToggled: (toggled) => {
if (toggled) {
Theme.switchTheme(10, true)
} else {
Theme.switchTheme(0)
}
}
}
}
StyledText {
text: "matugen not detected"
font.pixelSize: Theme.fontSizeSmall
color: Theme.error
visible: ToastService.wallpaperErrorStatus === "matugen_missing"
width: parent.width
}
}
LazyLoader {
id: wallpaperBrowserLoader
active: false
DankFileBrowser {
id: wallpaperBrowser
browserTitle: "Select Wallpaper"
browserIcon: "wallpaper"
browserType: "wallpaper"
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: (path) => {
Prefs.setWallpaperPath(path);
visible = false;
}
}
}
property alias wallpaperBrowser: wallpaperBrowserLoader.item
}

View File

@@ -1,75 +0,0 @@
import QtQuick
import qs.Common
import qs.Widgets
Column {
width: parent.width
spacing: Theme.spacingM
DankToggle {
text: "Fahrenheit"
description: "Use Fahrenheit instead of Celsius for temperature"
checked: Prefs.useFahrenheit
onToggled: (checked) => {
return Prefs.setTemperatureUnit(checked);
}
}
// Weather Location Override
Column {
width: parent.width
spacing: Theme.spacingM
DankToggle {
text: "Override Location"
description: "Use a specific location instead of auto-detection"
checked: Prefs.weatherLocationOverrideEnabled
onToggled: (checked) => {
return Prefs.setWeatherLocationOverrideEnabled(checked);
}
}
// Location input - only visible when override is enabled
Column {
width: parent.width
spacing: Theme.spacingS
visible: Prefs.weatherLocationOverrideEnabled
opacity: visible ? 1 : 0
Text {
text: "Location"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
}
DankLocationSearch {
width: parent.width
currentLocation: Prefs.weatherLocationOverride
placeholderText: "Search for a location..."
onLocationSelected: (displayName, coordinates) => {
Prefs.setWeatherLocationOverride(coordinates);
}
}
Text {
text: "Examples: \"New York\", \"Tokyo\", \"44511\""
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width
}
Behavior on opacity {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
}
}

View File

@@ -1,177 +1,334 @@
import QtQuick
import QtQuick.Controls
import qs.Common
import qs.Widgets
Column {
width: parent.width
spacing: Theme.spacingM
ScrollView {
id: widgetsTab
DankToggle {
text: "Focused Window"
description: "Show the currently focused application in the top bar"
checked: Prefs.showFocusedWindow
onToggled: (checked) => {
return Prefs.setShowFocusedWindow(checked);
}
}
DankToggle {
text: "Weather Widget"
description: "Display weather information in the top bar"
checked: Prefs.showWeather
onToggled: (checked) => {
return Prefs.setShowWeather(checked);
}
}
DankToggle {
text: "Media Controls"
description: "Show currently playing media in the top bar"
checked: Prefs.showMusic
onToggled: (checked) => {
return Prefs.setShowMusic(checked);
}
}
DankToggle {
text: "Clipboard Button"
description: "Show clipboard access button in the top bar"
checked: Prefs.showClipboard
onToggled: (checked) => {
return Prefs.setShowClipboard(checked);
}
}
DankToggle {
text: "System Resources"
description: "Display CPU and RAM usage indicators"
checked: Prefs.showSystemResources
onToggled: (checked) => {
return Prefs.setShowSystemResources(checked);
}
}
DankToggle {
text: "System Tray"
description: "Show system tray icons in the top bar"
checked: Prefs.showSystemTray
onToggled: (checked) => {
return Prefs.setShowSystemTray(checked);
}
}
DankToggle {
text: "Use OS Logo for App Launcher"
description: "Display operating system logo instead of apps icon"
checked: Prefs.useOSLogo
onToggled: (checked) => {
return Prefs.setUseOSLogo(checked);
}
}
contentWidth: availableWidth
contentHeight: column.implicitHeight + Theme.spacingXL
clip: true
Column {
id: column
width: parent.width
spacing: Theme.spacingS
visible: Prefs.useOSLogo
spacing: Theme.spacingXL
topPadding: Theme.spacingL
bottomPadding: Theme.spacingXL
Item {
// Top Bar Widgets Section
StyledRect {
width: parent.width
height: Theme.spacingS
}
height: topBarSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1
Text {
text: "OS Logo Customization"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
font.weight: Font.Medium
}
Column {
id: topBarSection
anchors.fill: parent
anchors.margins: Theme.spacingL
spacing: Theme.spacingM
Row {
width: parent.width
spacing: Theme.spacingM
Row {
width: parent.width
spacing: Theme.spacingM
Text {
text: "Color Override:"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
width: 90
}
DankIcon {
name: "widgets"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
DankTextField {
width: 120
height: 36
placeholderText: "#ffffff"
text: Prefs.osLogoColorOverride
maximumLength: 7
font.pixelSize: Theme.fontSizeMedium
topPadding: Theme.spacingS
bottomPadding: Theme.spacingS
onEditingFinished: {
var color = text.trim();
if (color === "" || /^#[0-9A-Fa-f]{6}$/.test(color))
Prefs.setOSLogoColorOverride(color);
else
text = Prefs.osLogoColorOverride;
StyledText {
text: "Top Bar Widgets"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
DankToggle {
width: parent.width
text: "Focused Window"
description: "Show the currently focused application in the top bar"
checked: Prefs.showFocusedWindow
onToggled: (checked) => {
return Prefs.setShowFocusedWindow(checked);
}
}
DankToggle {
width: parent.width
text: "Weather Widget"
description: "Display weather information in the top bar"
checked: Prefs.showWeather
onToggled: (checked) => {
return Prefs.setShowWeather(checked);
}
}
DankToggle {
width: parent.width
text: "Media Controls"
description: "Show currently playing media in the top bar"
checked: Prefs.showMusic
onToggled: (checked) => {
return Prefs.setShowMusic(checked);
}
}
DankToggle {
width: parent.width
text: "Clipboard Button"
description: "Show clipboard access button in the top bar"
checked: Prefs.showClipboard
onToggled: (checked) => {
return Prefs.setShowClipboard(checked);
}
}
DankToggle {
width: parent.width
text: "System Resources"
description: "Display CPU and RAM usage indicators"
checked: Prefs.showSystemResources
onToggled: (checked) => {
return Prefs.setShowSystemResources(checked);
}
}
DankToggle {
width: parent.width
text: "System Tray"
description: "Show system tray icons in the top bar"
checked: Prefs.showSystemTray
onToggled: (checked) => {
return Prefs.setShowSystemTray(checked);
}
}
}
}
Row {
// Workspace Section
StyledRect {
width: parent.width
spacing: Theme.spacingM
height: workspaceSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1
Text {
text: "Brightness:"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
width: 90
}
Column {
id: workspaceSection
anchors.fill: parent
anchors.margins: Theme.spacingL
spacing: Theme.spacingM
DankSlider {
width: 120
height: 24
minimum: 0
maximum: 100
value: Math.round(Prefs.osLogoBrightness * 100)
unit: ""
showValue: false
onSliderValueChanged: (newValue) => {
Prefs.setOSLogoBrightness(newValue / 100);
Row {
width: parent.width
spacing: Theme.spacingM
DankIcon {
name: "view_module"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "Workspace Settings"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
DankToggle {
width: parent.width
text: "Workspace Index Numbers"
description: "Show workspace index numbers in the top bar workspace switcher"
checked: Prefs.showWorkspaceIndex
onToggled: (checked) => {
return Prefs.setShowWorkspaceIndex(checked);
}
}
DankToggle {
width: parent.width
text: "Workspace Padding"
description: "Always show a minimum of 3 workspaces, even if fewer are available"
checked: Prefs.showWorkspacePadding
onToggled: (checked) => {
return Prefs.setShowWorkspacePadding(checked);
}
}
}
}
Row {
// App Launcher Section
StyledRect {
width: parent.width
spacing: Theme.spacingM
height: appLauncherSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1
Text {
text: "Contrast:"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
width: 90
}
Column {
id: appLauncherSection
anchors.fill: parent
anchors.margins: Theme.spacingL
spacing: Theme.spacingM
DankSlider {
width: 120
height: 24
minimum: 0
maximum: 200
value: Math.round(Prefs.osLogoContrast * 100)
unit: ""
showValue: false
onSliderValueChanged: (newValue) => {
Prefs.setOSLogoContrast(newValue / 100);
Row {
width: parent.width
spacing: Theme.spacingM
DankIcon {
name: "apps"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "App Launcher"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
DankToggle {
width: parent.width
text: "Use OS Logo for App Launcher"
description: "Display operating system logo instead of apps icon"
checked: Prefs.useOSLogo
onToggled: (checked) => {
return Prefs.setUseOSLogo(checked);
}
}
// OS Logo Customization - only visible when OS logo is enabled
StyledRect {
width: parent.width
height: logoCustomization.implicitHeight + Theme.spacingM * 2
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
border.width: 1
visible: Prefs.useOSLogo
opacity: visible ? 1 : 0
Column {
id: logoCustomization
anchors.fill: parent
anchors.margins: Theme.spacingM
spacing: Theme.spacingM
StyledText {
text: "OS Logo Customization"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
}
Column {
width: parent.width
spacing: Theme.spacingS
StyledText {
text: "Color Override"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Medium
}
DankTextField {
width: 160
height: 36
placeholderText: "#ffffff"
text: Prefs.osLogoColorOverride
maximumLength: 7
font.pixelSize: Theme.fontSizeMedium
topPadding: Theme.spacingS
bottomPadding: Theme.spacingS
onEditingFinished: {
var color = text.trim();
if (color === "" || /^#[0-9A-Fa-f]{6}$/.test(color))
Prefs.setOSLogoColorOverride(color);
else
text = Prefs.osLogoColorOverride;
}
}
}
Column {
width: parent.width
spacing: Theme.spacingS
StyledText {
text: "Brightness"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Medium
}
DankSlider {
width: parent.width
height: 24
minimum: 0
maximum: 100
value: Math.round(Prefs.osLogoBrightness * 100)
unit: ""
showValue: false
onSliderValueChanged: (newValue) => {
Prefs.setOSLogoBrightness(newValue / 100);
}
}
}
Column {
width: parent.width
spacing: Theme.spacingS
StyledText {
text: "Contrast"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Medium
}
DankSlider {
width: parent.width
height: 24
minimum: 0
maximum: 200
value: Math.round(Prefs.osLogoContrast * 100)
unit: ""
showValue: false
onSliderValueChanged: (newValue) => {
Prefs.setOSLogoContrast(newValue / 100);
}
}
}
}
Behavior on opacity {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
}
}
}
}

View File

@@ -1,27 +0,0 @@
import QtQuick
import qs.Common
import qs.Widgets
Column {
width: parent.width
spacing: Theme.spacingM
DankToggle {
text: "Workspace Index Numbers"
description: "Show workspace index numbers in the top bar workspace switcher"
checked: Prefs.showWorkspaceIndex
onToggled: (checked) => {
return Prefs.setShowWorkspaceIndex(checked);
}
}
DankToggle {
text: "Workspace Padding"
description: "Always show a minimum of 3 workspaces, even if fewer are available"
checked: Prefs.showWorkspacePadding
onToggled: (checked) => {
return Prefs.setShowWorkspacePadding(checked);
}
}
}