diff --git a/Widgets/DankFileBrowser.qml b/Modals/FileBrowserModal.qml similarity index 89% rename from Widgets/DankFileBrowser.qml rename to Modals/FileBrowserModal.qml index 37adad37..5f304640 100644 --- a/Widgets/DankFileBrowser.qml +++ b/Modals/FileBrowserModal.qml @@ -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 diff --git a/Modals/ProcessListModal.qml b/Modals/ProcessListModal.qml index d8b4eb42..35b35d0c 100644 --- a/Modals/ProcessListModal.qml +++ b/Modals/ProcessListModal.qml @@ -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 } } diff --git a/Modals/SettingsModal.qml b/Modals/SettingsModal.qml index 60f8ffff..ffa8a9fb 100644 --- a/Modals/SettingsModal.qml +++ b/Modals/SettingsModal.qml @@ -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 {} - } - } - - // 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 - } + anchors.margins: Theme.spacingL + color: "transparent" + + // 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 {} + } } } } diff --git a/Modules/ControlCenter/ControlCenterPopout.qml b/Modules/ControlCenter/ControlCenterPopout.qml index 1479dae4..ca883a07 100644 --- a/Modules/ControlCenter/ControlCenterPopout.qml +++ b/Modules/ControlCenter/ControlCenterPopout.qml @@ -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 { diff --git a/Modules/Settings/AppearanceTab.qml b/Modules/Settings/AppearanceTab.qml index 8c77006d..14415a08 100644 --- a/Modules/Settings/AppearanceTab.qml +++ b/Modules/Settings/AppearanceTab.qml @@ -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); + } } } + } + + // 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 - Rectangle { - width: parent.width - height: 1 - color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) + 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); + } + } + } } + } + + // 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 - DisplayTab { - width: parent.width + 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"); + } + } } \ No newline at end of file diff --git a/Modules/Settings/ClockTab.qml b/Modules/Settings/ClockTab.qml deleted file mode 100644 index 9ce8ecdb..00000000 --- a/Modules/Settings/ClockTab.qml +++ /dev/null @@ -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); - } - } - -} diff --git a/Modules/Settings/DisplayTab.qml b/Modules/Settings/DisplayTab.qml deleted file mode 100644 index 4dfac026..00000000 --- a/Modules/Settings/DisplayTab.qml +++ /dev/null @@ -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"); - - } - } - -} diff --git a/Modules/Settings/PersonalizationTab.qml b/Modules/Settings/PersonalizationTab.qml index b636500e..375adc18 100644 --- a/Modules/Settings/PersonalizationTab.qml +++ b/Modules/Settings/PersonalizationTab.qml @@ -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 { + // Wallpaper Section + 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(""); + } + } + } + } + } } } + } + + // 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 - Rectangle { - width: parent.width - height: 1 - color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) - } - - 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 } \ No newline at end of file diff --git a/Modules/Settings/ProfileTab.qml b/Modules/Settings/ProfileTab.qml deleted file mode 100644 index 58949907..00000000 --- a/Modules/Settings/ProfileTab.qml +++ /dev/null @@ -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 - -} diff --git a/Modules/Settings/SystemTab.qml b/Modules/Settings/SystemTab.qml deleted file mode 100644 index 33f86279..00000000 --- a/Modules/Settings/SystemTab.qml +++ /dev/null @@ -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 - } - } - } -} \ No newline at end of file diff --git a/Modules/Settings/ThemePicker.qml b/Modules/Settings/ThemePicker.qml deleted file mode 100644 index 54633136..00000000 --- a/Modules/Settings/ThemePicker.qml +++ /dev/null @@ -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 - } - - } - - } - - } - -} diff --git a/Modules/Settings/TimeWeatherTab.qml b/Modules/Settings/TimeWeatherTab.qml new file mode 100644 index 00000000..4f494820 --- /dev/null +++ b/Modules/Settings/TimeWeatherTab.qml @@ -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 + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Modules/Settings/WallpaperTab.qml b/Modules/Settings/WallpaperTab.qml deleted file mode 100644 index d41bb505..00000000 --- a/Modules/Settings/WallpaperTab.qml +++ /dev/null @@ -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 -} \ No newline at end of file diff --git a/Modules/Settings/WeatherTab.qml b/Modules/Settings/WeatherTab.qml deleted file mode 100644 index 1af523d5..00000000 --- a/Modules/Settings/WeatherTab.qml +++ /dev/null @@ -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 - } - - } - - } - - } - -} diff --git a/Modules/Settings/WidgetsTab.qml b/Modules/Settings/WidgetsTab.qml index 60a10d4b..45d7f5d4 100644 --- a/Modules/Settings/WidgetsTab.qml +++ b/Modules/Settings/WidgetsTab.qml @@ -1,177 +1,334 @@ import QtQuick +import QtQuick.Controls import qs.Common import qs.Widgets -Column { - width: parent.width - spacing: Theme.spacingM - - 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); - } - } - +ScrollView { + id: widgetsTab + + contentWidth: availableWidth + contentHeight: column.implicitHeight + Theme.spacingXL + clip: true + Column { + id: column width: parent.width - spacing: Theme.spacingS - visible: Prefs.useOSLogo - - Item { + spacing: Theme.spacingXL + topPadding: Theme.spacingL + bottomPadding: Theme.spacingXL + + // Top Bar Widgets Section + StyledRect { width: parent.width - height: Theme.spacingS - } - - Text { - text: "OS Logo Customization" - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceVariantText - font.weight: Font.Medium - } - - Row { - width: parent.width - spacing: Theme.spacingM - - Text { - text: "Color Override:" - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - width: 90 - } - - 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; + 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 + + Column { + id: topBarSection + anchors.fill: parent + anchors.margins: Theme.spacingL + spacing: Theme.spacingM + + Row { + width: parent.width + spacing: Theme.spacingM + + DankIcon { + name: "widgets" + size: Theme.iconSize + color: Theme.primary + anchors.verticalCenter: parent.verticalCenter + } + + 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 - - Text { - text: "Brightness:" - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - width: 90 - } - - DankSlider { - width: 120 - height: 24 - minimum: 0 - maximum: 100 - value: Math.round(Prefs.osLogoBrightness * 100) - unit: "" - showValue: false - onSliderValueChanged: (newValue) => { - Prefs.setOSLogoBrightness(newValue / 100); + 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 + + Column { + id: workspaceSection + anchors.fill: parent + anchors.margins: Theme.spacingL + spacing: Theme.spacingM + + 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 - - Text { - text: "Contrast:" - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - width: 90 - } - - DankSlider { - width: 120 - height: 24 - minimum: 0 - maximum: 200 - value: Math.round(Prefs.osLogoContrast * 100) - unit: "" - showValue: false - onSliderValueChanged: (newValue) => { - Prefs.setOSLogoContrast(newValue / 100); + 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 + + Column { + id: appLauncherSection + anchors.fill: parent + anchors.margins: Theme.spacingL + spacing: Theme.spacingM + + 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 + } + } } } - } - } - -} +} \ No newline at end of file diff --git a/Modules/Settings/WorkspaceTab.qml b/Modules/Settings/WorkspaceTab.qml deleted file mode 100644 index 66969b69..00000000 --- a/Modules/Settings/WorkspaceTab.qml +++ /dev/null @@ -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); - } - } - -}