mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-06 21:45:38 -05:00
settings: redesign
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
161
Modules/Settings/TimeWeatherTab.qml
Normal file
161
Modules/Settings/TimeWeatherTab.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user