Possible ram improvement, move settings into sidebar
This commit is contained in:
parent
61e852ed51
commit
3f6bc3414d
17 changed files with 795 additions and 2454 deletions
|
|
@ -102,6 +102,7 @@ Scope {
|
||||||
}
|
}
|
||||||
|
|
||||||
NotificationIcon {
|
NotificationIcon {
|
||||||
|
shell: rootScope.shell
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,12 +136,9 @@ Scope {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsButton {
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
PanelPopup {
|
PanelPopup {
|
||||||
id: sidebarPopup
|
id: sidebarPopup
|
||||||
|
shell: rootScope.shell
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
|
|
@ -151,8 +149,7 @@ Scope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Background {}
|
|
||||||
Overview {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelWindow {
|
PanelWindow {
|
||||||
|
|
|
||||||
|
|
@ -55,9 +55,13 @@ Item {
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: {
|
||||||
bluetoothMenu.visible = !bluetoothMenu.visible;
|
if (!bluetoothMenuLoader.active) {
|
||||||
|
bluetoothMenuLoader.loading = true;
|
||||||
|
}
|
||||||
|
if (bluetoothMenuLoader.item) {
|
||||||
|
bluetoothMenuLoader.item.visible = !bluetoothMenuLoader.item.visible;
|
||||||
// Enable adapter and start discovery when menu opens
|
// Enable adapter and start discovery when menu opens
|
||||||
if (bluetoothMenu.visible && Bluetooth.defaultAdapter) {
|
if (bluetoothMenuLoader.item.visible && Bluetooth.defaultAdapter) {
|
||||||
if (!Bluetooth.defaultAdapter.enabled) {
|
if (!Bluetooth.defaultAdapter.enabled) {
|
||||||
Bluetooth.defaultAdapter.enabled = true;
|
Bluetooth.defaultAdapter.enabled = true;
|
||||||
}
|
}
|
||||||
|
|
@ -66,6 +70,7 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
onEntered: bluetoothTooltip.tooltipVisible = true
|
onEntered: bluetoothTooltip.tooltipVisible = true
|
||||||
onExited: bluetoothTooltip.tooltipVisible = false
|
onExited: bluetoothTooltip.tooltipVisible = false
|
||||||
}
|
}
|
||||||
|
|
@ -80,7 +85,11 @@ Item {
|
||||||
delay: 200
|
delay: 200
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelWindow {
|
// LazyLoader for Bluetooth menu
|
||||||
|
LazyLoader {
|
||||||
|
id: bluetoothMenuLoader
|
||||||
|
loading: false
|
||||||
|
component: PanelWindow {
|
||||||
id: bluetoothMenu
|
id: bluetoothMenu
|
||||||
implicitWidth: 320
|
implicitWidth: 320
|
||||||
implicitHeight: 480
|
implicitHeight: 480
|
||||||
|
|
@ -269,4 +278,5 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import qs.Settings
|
|
||||||
import qs.Components
|
|
||||||
import qs.Widgets.SettingsWindow
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
width: 22
|
|
||||||
height: 22
|
|
||||||
|
|
||||||
property var settingsWindow: null
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: button
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "transparent"
|
|
||||||
radius: width / 2
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: "settings"
|
|
||||||
font.family: "Material Symbols Outlined"
|
|
||||||
font.pixelSize: 16
|
|
||||||
color: mouseArea.containsMouse ? Theme.accentPrimary : Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: mouseArea
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
if (!settingsWindow) {
|
|
||||||
// Create new window
|
|
||||||
settingsWindow = settingsComponent.createObject(null); // No parent to avoid dependency issues
|
|
||||||
if (settingsWindow) {
|
|
||||||
settingsWindow.visible = true;
|
|
||||||
// Handle window closure
|
|
||||||
settingsWindow.visibleChanged.connect(function() {
|
|
||||||
if (settingsWindow && !settingsWindow.visible) {
|
|
||||||
var windowToDestroy = settingsWindow;
|
|
||||||
settingsWindow = null;
|
|
||||||
windowToDestroy.destroy();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (settingsWindow.visible) {
|
|
||||||
// Close and destroy window
|
|
||||||
var windowToDestroy = settingsWindow;
|
|
||||||
settingsWindow = null;
|
|
||||||
windowToDestroy.visible = false;
|
|
||||||
windowToDestroy.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledTooltip {
|
|
||||||
text: "Settings"
|
|
||||||
targetItem: mouseArea
|
|
||||||
tooltipVisible: mouseArea.containsMouse
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: settingsComponent
|
|
||||||
SettingsWindow {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up on destruction
|
|
||||||
Component.onDestruction: {
|
|
||||||
if (settingsWindow) {
|
|
||||||
var windowToDestroy = settingsWindow;
|
|
||||||
settingsWindow = null;
|
|
||||||
windowToDestroy.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -61,13 +61,18 @@ Item {
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: {
|
||||||
wifiMenu.visible = !wifiMenu.visible;
|
if (!wifiMenuLoader.active) {
|
||||||
if (wifiMenu.visible) {
|
wifiMenuLoader.loading = true;
|
||||||
|
}
|
||||||
|
if (wifiMenuLoader.item) {
|
||||||
|
wifiMenuLoader.item.visible = !wifiMenuLoader.item.visible;
|
||||||
|
if (wifiMenuLoader.item.visible) {
|
||||||
network.onMenuOpened();
|
network.onMenuOpened();
|
||||||
} else {
|
} else {
|
||||||
network.onMenuClosed();
|
network.onMenuClosed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
onEntered: wifiTooltip.tooltipVisible = true
|
onEntered: wifiTooltip.tooltipVisible = true
|
||||||
onExited: wifiTooltip.tooltipVisible = false
|
onExited: wifiTooltip.tooltipVisible = false
|
||||||
}
|
}
|
||||||
|
|
@ -82,7 +87,11 @@ Item {
|
||||||
delay: 200
|
delay: 200
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelWindow {
|
// LazyLoader for WiFi menu
|
||||||
|
LazyLoader {
|
||||||
|
id: wifiMenuLoader
|
||||||
|
loading: false
|
||||||
|
component: PanelWindow {
|
||||||
id: wifiMenu
|
id: wifiMenu
|
||||||
implicitWidth: 320
|
implicitWidth: 320
|
||||||
implicitHeight: 480
|
implicitHeight: 480
|
||||||
|
|
@ -367,4 +376,5 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -16,33 +16,33 @@ Shape {
|
||||||
|
|
||||||
property var modelData: null
|
property var modelData: null
|
||||||
|
|
||||||
// Position flags derived from position string
|
// Position flags derived from position string - calculated once
|
||||||
property bool _isTop: position.includes("top")
|
readonly property bool _isTop: position.includes("top")
|
||||||
property bool _isLeft: position.includes("left")
|
readonly property bool _isLeft: position.includes("left")
|
||||||
property bool _isRight: position.includes("right")
|
readonly property bool _isRight: position.includes("right")
|
||||||
property bool _isBottom: position.includes("bottom")
|
readonly property bool _isBottom: position.includes("bottom")
|
||||||
|
|
||||||
// Shift the path vertically if offsetY is negative to pull shape up
|
// Shift the path vertically if offsetY is negative to pull shape up
|
||||||
property real pathOffsetY: Math.min(offsetY, 0)
|
readonly property real pathOffsetY: Math.min(offsetY, 0)
|
||||||
|
|
||||||
// Base coordinates for left corner shape, shifted by pathOffsetY vertically
|
// Base coordinates for left corner shape, shifted by pathOffsetY vertically
|
||||||
property real _baseStartX: 30 * size
|
readonly property real _baseStartX: 30 * size
|
||||||
property real _baseStartY: (_isTop ? 20 * size : 0) + pathOffsetY
|
readonly property real _baseStartY: (_isTop ? 20 * size : 0) + pathOffsetY
|
||||||
property real _baseLineX: 30 * size
|
readonly property real _baseLineX: 30 * size
|
||||||
property real _baseLineY: (_isTop ? 0 : 20 * size) + pathOffsetY
|
readonly property real _baseLineY: (_isTop ? 0 : 20 * size) + pathOffsetY
|
||||||
property real _baseArcX: 50 * size
|
readonly property real _baseArcX: 50 * size
|
||||||
property real _baseArcY: (_isTop ? 20 * size : 0) + pathOffsetY
|
readonly property real _baseArcY: (_isTop ? 20 * size : 0) + pathOffsetY
|
||||||
|
|
||||||
// Mirror coordinates for right corners
|
// Mirror coordinates for right corners
|
||||||
property real _startX: _isRight ? (concaveWidth - _baseStartX) : _baseStartX
|
readonly property real _startX: _isRight ? (concaveWidth - _baseStartX) : _baseStartX
|
||||||
property real _startY: _baseStartY
|
readonly property real _startY: _baseStartY
|
||||||
property real _lineX: _isRight ? (concaveWidth - _baseLineX) : _baseLineX
|
readonly property real _lineX: _isRight ? (concaveWidth - _baseLineX) : _baseLineX
|
||||||
property real _lineY: _baseLineY
|
readonly property real _lineY: _baseLineY
|
||||||
property real _arcX: _isRight ? (concaveWidth - _baseArcX) : _baseArcX
|
readonly property real _arcX: _isRight ? (concaveWidth - _baseArcX) : _baseArcX
|
||||||
property real _arcY: _baseArcY
|
readonly property real _arcY: _baseArcY
|
||||||
|
|
||||||
// Arc direction varies by corner to maintain proper concave shape
|
// Arc direction varies by corner to maintain proper concave shape
|
||||||
property int _arcDirection: {
|
readonly property int _arcDirection: {
|
||||||
if (_isTop && _isLeft) return PathArc.Counterclockwise
|
if (_isTop && _isLeft) return PathArc.Counterclockwise
|
||||||
if (_isTop && _isRight) return PathArc.Clockwise
|
if (_isTop && _isRight) return PathArc.Clockwise
|
||||||
if (_isBottom && _isLeft) return PathArc.Clockwise
|
if (_isBottom && _isLeft) return PathArc.Clockwise
|
||||||
|
|
@ -57,9 +57,10 @@ Shape {
|
||||||
x: _isLeft ? offsetX : (parent ? parent.width - width + offsetX : 0)
|
x: _isLeft ? offsetX : (parent ? parent.width - width + offsetX : 0)
|
||||||
y: _isTop ? offsetY : (parent ? parent.height - height + offsetY : 0)
|
y: _isTop ? offsetY : (parent ? parent.height - height + offsetY : 0)
|
||||||
|
|
||||||
preferredRendererType: Shape.CurveRenderer
|
// Optimized rendering settings - reduced quality for better performance
|
||||||
layer.enabled: true
|
preferredRendererType: Shape.GeometryRenderer // Use simpler renderer
|
||||||
layer.samples: 4
|
layer.enabled: false // Disable layer rendering to save memory
|
||||||
|
antialiasing: true // Use standard antialiasing instead of MSAA
|
||||||
|
|
||||||
ShapePath {
|
ShapePath {
|
||||||
strokeWidth: 0
|
strokeWidth: 0
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ IpcHandler {
|
||||||
idleInhibitor.toggle()
|
idleInhibitor.toggle()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function toggleNotificationPopup(): void {
|
function toggleNotificationPopup(): void {
|
||||||
console.log("[IPC] NotificationPopup toggle() called")
|
console.log("[IPC] NotificationPopup toggle() called")
|
||||||
// Use the global toggle function from the notification manager
|
// Use the global toggle function from the notification manager
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,25 @@ Item {
|
||||||
id: root
|
id: root
|
||||||
width: 22; height: 22
|
width: 22; height: 22
|
||||||
property bool isSilence: false
|
property bool isSilence: false
|
||||||
|
property var shell: null
|
||||||
|
|
||||||
Process {
|
Process {
|
||||||
id: rightClickProcess
|
id: rightClickProcess
|
||||||
command: ["qs","ipc", "call", "globalIPC", "toggleNotificationPopup"]
|
command: ["qs","ipc", "call", "globalIPC", "toggleNotificationPopup"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Timer to check when NotificationHistory is loaded
|
||||||
|
Timer {
|
||||||
|
id: checkHistoryTimer
|
||||||
|
interval: 50
|
||||||
|
repeat: true
|
||||||
|
onTriggered: {
|
||||||
|
if (shell && shell.notificationHistoryWin) {
|
||||||
|
shell.notificationHistoryWin.visible = true;
|
||||||
|
checkHistoryTimer.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: bell
|
id: bell
|
||||||
|
|
@ -22,11 +34,23 @@ Item {
|
||||||
Text {
|
Text {
|
||||||
id: bellText
|
id: bellText
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: notificationHistoryWin.hasUnread ? "notifications_unread" : "notifications"
|
text: {
|
||||||
|
if (shell && shell.notificationHistoryWin && shell.notificationHistoryWin.hasUnread) {
|
||||||
|
return "notifications_unread";
|
||||||
|
} else {
|
||||||
|
return "notifications";
|
||||||
|
}
|
||||||
|
}
|
||||||
font.family: mouseAreaBell.containsMouse ? "Material Symbols Rounded" : "Material Symbols Outlined"
|
font.family: mouseAreaBell.containsMouse ? "Material Symbols Rounded" : "Material Symbols Outlined"
|
||||||
font.pixelSize: 16
|
font.pixelSize: 16
|
||||||
font.weight: notificationHistoryWin.hasUnread ? Font.Bold : Font.Normal
|
font.weight: {
|
||||||
color: mouseAreaBell.containsMouse ? Theme.accentPrimary : (notificationHistoryWin.hasUnread ? Theme.accentPrimary : Theme.textDisabled)
|
if (shell && shell.notificationHistoryWin && shell.notificationHistoryWin.hasUnread) {
|
||||||
|
return Font.Bold;
|
||||||
|
} else {
|
||||||
|
return Font.Normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
color: mouseAreaBell.containsMouse ? Theme.accentPrimary : (shell && shell.notificationHistoryWin && shell.notificationHistoryWin.hasUnread ? Theme.accentPrimary : Theme.textDisabled)
|
||||||
}
|
}
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: mouseAreaBell
|
id: mouseAreaBell
|
||||||
|
|
@ -42,10 +66,18 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mouse.button === Qt.LeftButton){
|
if (mouse.button === Qt.LeftButton){
|
||||||
notificationHistoryWin.visible = !notificationHistoryWin.visible
|
if (shell) {
|
||||||
|
if (!shell.notificationHistoryWin) {
|
||||||
|
// Use the shell function to load notification history
|
||||||
|
shell.loadNotificationHistory();
|
||||||
|
checkHistoryTimer.start();
|
||||||
|
} else {
|
||||||
|
// Already loaded, just toggle visibility
|
||||||
|
shell.notificationHistoryWin.visible = !shell.notificationHistoryWin.visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
onEntered: notificationTooltip.tooltipVisible = true
|
onEntered: notificationTooltip.tooltipVisible = true
|
||||||
onExited: notificationTooltip.tooltipVisible = false
|
onExited: notificationTooltip.tooltipVisible = false
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,32 @@ import qs.Widgets.SettingsWindow.Tabs.Components
|
||||||
|
|
||||||
PanelWindow {
|
PanelWindow {
|
||||||
id: panelMain
|
id: panelMain
|
||||||
implicitHeight: screen.height / 2
|
implicitHeight: Quickshell.screens.length > 0 ? Quickshell.screens[0].height / 2 : 400
|
||||||
implicitWidth: screen.width / 2
|
implicitWidth: Quickshell.screens.length > 0 ? Quickshell.screens[0].width / 2 : 600
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
property int activeTabIndex: 0
|
property int activeTabIndex: 0
|
||||||
|
|
||||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
|
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
|
||||||
|
|
||||||
|
// Add safety checks for component loading
|
||||||
|
Component.onCompleted: {
|
||||||
|
// Ensure we start with a valid tab
|
||||||
|
if (activeTabIndex < 0 || activeTabIndex > 8) {
|
||||||
|
activeTabIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup when window is hidden
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (!visible) {
|
||||||
|
// Reset to default tab when hiding to prevent state issues
|
||||||
|
activeTabIndex = 0;
|
||||||
|
if (tabName) {
|
||||||
|
tabName.text = "General";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: generalSettings
|
id: generalSettings
|
||||||
|
|
@ -84,7 +102,6 @@ PanelWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: settings
|
id: settings
|
||||||
color: Theme.backgroundPrimary
|
color: Theme.backgroundPrimary
|
||||||
|
|
@ -98,7 +115,6 @@ PanelWindow {
|
||||||
topRightRadius: 20
|
topRightRadius: 20
|
||||||
bottomRightRadius: 20
|
bottomRightRadius: 20
|
||||||
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: headerArea
|
id: headerArea
|
||||||
anchors {
|
anchors {
|
||||||
|
|
@ -114,7 +130,6 @@ PanelWindow {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
spacing: 12
|
spacing: 12
|
||||||
|
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: tabName
|
id: tabName
|
||||||
text: wallpaperSelector.visible ? "Select Wallpaper" : (activeTabIndex === 0 ? "General" :
|
text: wallpaperSelector.visible ? "Select Wallpaper" : (activeTabIndex === 0 ? "General" :
|
||||||
|
|
@ -189,7 +204,6 @@ PanelWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors {
|
anchors {
|
||||||
top: headerArea.bottom
|
top: headerArea.bottom
|
||||||
|
|
@ -213,35 +227,11 @@ PanelWindow {
|
||||||
topMargin: 32
|
topMargin: 32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Simplified single loader approach
|
||||||
Loader {
|
Loader {
|
||||||
id: settingsLoader
|
id: settingsLoader
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
sourceComponent: generalSettings
|
sourceComponent: generalSettings
|
||||||
opacity: 1
|
|
||||||
visible: opacity > 0
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: 150
|
|
||||||
easing.type: Easing.InOutQuad
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: settingsLoader2
|
|
||||||
anchors.fill: parent
|
|
||||||
opacity: 0
|
|
||||||
visible: opacity > 0
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: 150
|
|
||||||
easing.type: Easing.InOutQuad
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wallpaper Selector Component
|
// Wallpaper Selector Component
|
||||||
|
|
@ -252,11 +242,10 @@ PanelWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: tabs
|
id: tabs
|
||||||
color: Theme.surface
|
color: Theme.surface
|
||||||
width: screen.width / 9
|
width: Quickshell.screens.length > 0 ? Quickshell.screens[0].width / 9 : 100
|
||||||
height: panelMain.height
|
height: panelMain.height
|
||||||
topLeftRadius: 20
|
topLeftRadius: 20
|
||||||
bottomLeftRadius: 20
|
bottomLeftRadius: 20
|
||||||
|
|
@ -356,7 +345,6 @@ PanelWindow {
|
||||||
8: aboutSettings
|
8: aboutSettings
|
||||||
}[index];
|
}[index];
|
||||||
|
|
||||||
|
|
||||||
const tabNames = [
|
const tabNames = [
|
||||||
"General",
|
"General",
|
||||||
"Bar",
|
"Bar",
|
||||||
|
|
@ -370,21 +358,10 @@ PanelWindow {
|
||||||
];
|
];
|
||||||
tabName.text = tabNames[index];
|
tabName.text = tabNames[index];
|
||||||
|
|
||||||
|
// Simple component switching
|
||||||
if (settingsLoader.opacity === 1) {
|
if (newComponent) {
|
||||||
|
|
||||||
settingsLoader2.sourceComponent = newComponent;
|
|
||||||
settingsLoader.opacity = 0;
|
|
||||||
settingsLoader2.opacity = 1;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
settingsLoader.sourceComponent = newComponent;
|
settingsLoader.sourceComponent = newComponent;
|
||||||
settingsLoader2.opacity = 0;
|
|
||||||
settingsLoader.opacity = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Tab colors and indicators are now handled by property bindings
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import QtQuick.Controls
|
|
||||||
import qs.Settings
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
property alias title: headerText.text
|
|
||||||
property bool expanded: false // Hidden by default
|
|
||||||
default property alias content: contentItem.children
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
height: 44
|
|
||||||
radius: 12
|
|
||||||
color: Theme.surface
|
|
||||||
border.color: Theme.accentPrimary
|
|
||||||
border.width: 2
|
|
||||||
RowLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: 8
|
|
||||||
spacing: 8
|
|
||||||
Item { width: 2 }
|
|
||||||
Text {
|
|
||||||
id: headerText
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: Theme.fontSizeBody
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
Item { Layout.fillWidth: true }
|
|
||||||
Rectangle {
|
|
||||||
width: 32; height: 32
|
|
||||||
color: "transparent"
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: expanded ? "expand_less" : "expand_more"
|
|
||||||
font.family: "Material Symbols Outlined"
|
|
||||||
font.pixelSize: Theme.fontSizeBody
|
|
||||||
color: Theme.accentPrimary
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: expanded = !expanded
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Item { height: 8 }
|
|
||||||
ColumnLayout {
|
|
||||||
id: contentItem
|
|
||||||
Layout.fillWidth: true
|
|
||||||
visible: expanded
|
|
||||||
spacing: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,643 +0,0 @@
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import QtQuick.Effects
|
|
||||||
import QtQuick.Controls
|
|
||||||
import Quickshell.Widgets
|
|
||||||
import qs.Components
|
|
||||||
import qs.Settings
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: profileSettingsCard
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: 690
|
|
||||||
color: Theme.surface
|
|
||||||
radius: 18
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: 18
|
|
||||||
spacing: 12
|
|
||||||
|
|
||||||
// Header
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
spacing: 12
|
|
||||||
Text {
|
|
||||||
text: "settings"
|
|
||||||
font.family: "Material Symbols Outlined"
|
|
||||||
font.pixelSize: 20
|
|
||||||
color: Theme.accentPrimary
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
text: "Profile Settings"
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: 16
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Profile Image Input Section
|
|
||||||
ColumnLayout {
|
|
||||||
spacing: 8
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Profile Image"
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
spacing: 8
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
// Profile image
|
|
||||||
Rectangle {
|
|
||||||
width: 48
|
|
||||||
height: 48
|
|
||||||
radius: 24
|
|
||||||
|
|
||||||
// Border
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "transparent"
|
|
||||||
radius: 24
|
|
||||||
border.color: profileImageInput.activeFocus ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 2
|
|
||||||
z: 2
|
|
||||||
}
|
|
||||||
|
|
||||||
Avatar {}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: 40
|
|
||||||
radius: 16
|
|
||||||
color: Theme.surfaceVariant
|
|
||||||
border.color: profileImageInput.activeFocus ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
TextInput {
|
|
||||||
id: profileImageInput
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.leftMargin: 12
|
|
||||||
anchors.rightMargin: 12
|
|
||||||
anchors.topMargin: 6
|
|
||||||
anchors.bottomMargin: 6
|
|
||||||
text: Settings.settings.profileImage !== undefined ? Settings.settings.profileImage : ""
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: 13
|
|
||||||
color: Theme.textPrimary
|
|
||||||
verticalAlignment: TextInput.AlignVCenter
|
|
||||||
clip: true
|
|
||||||
selectByMouse: true
|
|
||||||
activeFocusOnTab: true
|
|
||||||
inputMethodHints: Qt.ImhUrlCharactersOnly
|
|
||||||
onTextChanged: {
|
|
||||||
Settings.settings.profileImage = text;
|
|
||||||
}
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.IBeamCursor
|
|
||||||
onClicked: profileImageInput.forceActiveFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show Active Window Icon Setting
|
|
||||||
RowLayout {
|
|
||||||
spacing: 8
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 8
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Show Active Window Icon"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: activeWindowIconSwitch
|
|
||||||
width: 52
|
|
||||||
height: 32
|
|
||||||
radius: 16
|
|
||||||
color: Settings.settings.showActiveWindowIcon ? Theme.accentPrimary : Theme.surfaceVariant
|
|
||||||
border.color: Settings.settings.showActiveWindowIcon ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 2
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: activeWindowIconThumb
|
|
||||||
width: 28
|
|
||||||
height: 28
|
|
||||||
radius: 14
|
|
||||||
color: Theme.surface
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
y: 2
|
|
||||||
x: Settings.settings.showActiveWindowIcon ? activeWindowIconSwitch.width - width - 2 : 2
|
|
||||||
|
|
||||||
Behavior on x {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: 200
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
Settings.settings.showActiveWindowIcon = !Settings.settings.showActiveWindowIcon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show System Info In Bar Setting
|
|
||||||
RowLayout {
|
|
||||||
spacing: 8
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 8
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Show System Info In Bar"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: systemInfoSwitch
|
|
||||||
width: 52
|
|
||||||
height: 32
|
|
||||||
radius: 16
|
|
||||||
color: Settings.settings.showSystemInfoInBar ? Theme.accentPrimary : Theme.surfaceVariant
|
|
||||||
border.color: Settings.settings.showSystemInfoInBar ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 2
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: systemInfoThumb
|
|
||||||
width: 28
|
|
||||||
height: 28
|
|
||||||
radius: 14
|
|
||||||
color: Theme.surface
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
y: 2
|
|
||||||
x: Settings.settings.showSystemInfoInBar ? systemInfoSwitch.width - width - 2 : 2
|
|
||||||
|
|
||||||
Behavior on x {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: 200
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
Settings.settings.showSystemInfoInBar = !Settings.settings.showSystemInfoInBar;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show Corners Setting
|
|
||||||
RowLayout {
|
|
||||||
spacing: 8
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 8
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Show Corners"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: cornersSwitch
|
|
||||||
width: 52
|
|
||||||
height: 32
|
|
||||||
radius: 16
|
|
||||||
color: Settings.settings.showCorners ? Theme.accentPrimary : Theme.surfaceVariant
|
|
||||||
border.color: Settings.settings.showCorners ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 2
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: cornersThumb
|
|
||||||
width: 28
|
|
||||||
height: 28
|
|
||||||
radius: 14
|
|
||||||
color: Theme.surface
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
y: 2
|
|
||||||
x: Settings.settings.showCorners ? cornersSwitch.width - width - 2 : 2
|
|
||||||
|
|
||||||
Behavior on x {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: 200
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
Settings.settings.showCorners = !Settings.settings.showCorners;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show Taskbar Setting
|
|
||||||
RowLayout {
|
|
||||||
spacing: 8
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 8
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Show Taskbar"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: taskbarSwitch
|
|
||||||
width: 52
|
|
||||||
height: 32
|
|
||||||
radius: 16
|
|
||||||
color: Settings.settings.showTaskbar ? Theme.accentPrimary : Theme.surfaceVariant
|
|
||||||
border.color: Settings.settings.showTaskbar ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 2
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: taskbarThumb
|
|
||||||
width: 28
|
|
||||||
height: 28
|
|
||||||
radius: 14
|
|
||||||
color: Theme.surface
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
y: 2
|
|
||||||
x: Settings.settings.showTaskbar ? taskbarSwitch.width - width - 2 : 2
|
|
||||||
|
|
||||||
Behavior on x {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: 200
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
Settings.settings.showTaskbar = !Settings.settings.showTaskbar;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show Dock Setting
|
|
||||||
RowLayout {
|
|
||||||
spacing: 8
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 8
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Show Dock"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: dockSwitch
|
|
||||||
width: 52
|
|
||||||
height: 32
|
|
||||||
radius: 16
|
|
||||||
color: Settings.settings.showDock ? Theme.accentPrimary : Theme.surfaceVariant
|
|
||||||
border.color: Settings.settings.showDock ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 2
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: dockThumb
|
|
||||||
width: 28
|
|
||||||
height: 28
|
|
||||||
radius: 14
|
|
||||||
color: Theme.surface
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
y: 2
|
|
||||||
x: Settings.settings.showDock ? taskbarSwitch.width - width - 2 : 2
|
|
||||||
|
|
||||||
Behavior on x {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: 200
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
Settings.settings.showDock = !Settings.settings.showDock;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show Media In Bar Setting
|
|
||||||
RowLayout {
|
|
||||||
spacing: 8
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 8
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Show Media In Bar"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: mediaSwitch
|
|
||||||
width: 52
|
|
||||||
height: 32
|
|
||||||
radius: 16
|
|
||||||
color: Settings.settings.showMediaInBar ? Theme.accentPrimary : Theme.surfaceVariant
|
|
||||||
border.color: Settings.settings.showMediaInBar ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 2
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: mediaThumb
|
|
||||||
width: 28
|
|
||||||
height: 28
|
|
||||||
radius: 14
|
|
||||||
color: Theme.surface
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
y: 2
|
|
||||||
x: Settings.settings.showMediaInBar ? mediaSwitch.width - width - 2 : 2
|
|
||||||
|
|
||||||
Behavior on x {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: 200
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
Settings.settings.showMediaInBar = !Settings.settings.showMediaInBar;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dim Windows Setting
|
|
||||||
RowLayout {
|
|
||||||
spacing: 8
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 8
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Dim Desktop"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: dimSwitch
|
|
||||||
width: 52
|
|
||||||
height: 32
|
|
||||||
radius: 16
|
|
||||||
color: Settings.settings.dimPanels ? Theme.accentPrimary : Theme.surfaceVariant
|
|
||||||
border.color: Settings.settings.dimPanels ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 2
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: dimThumb
|
|
||||||
width: 28
|
|
||||||
height: 28
|
|
||||||
radius: 14
|
|
||||||
color: Theme.surface
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
y: 2
|
|
||||||
x: Settings.settings.dimPanels ? dimSwitch.width - width - 2 : 2
|
|
||||||
|
|
||||||
Behavior on x {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: 200
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
Settings.settings.dimPanels = !Settings.settings.dimPanels;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Visualizer Type Selection
|
|
||||||
ColumnLayout {
|
|
||||||
spacing: 8
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Visualizer Type"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
ComboBox {
|
|
||||||
id: visualizerTypeComboBox
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: 40
|
|
||||||
model: ["radial", "fire", "diamond"]
|
|
||||||
currentIndex: model.indexOf(Settings.settings.visualizerType)
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
implicitWidth: 120
|
|
||||||
implicitHeight: 40
|
|
||||||
color: Theme.surfaceVariant
|
|
||||||
border.color: visualizerTypeComboBox.activeFocus ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
radius: 16
|
|
||||||
}
|
|
||||||
|
|
||||||
contentItem: Text {
|
|
||||||
leftPadding: 12
|
|
||||||
rightPadding: visualizerTypeComboBox.indicator.width + visualizerTypeComboBox.spacing
|
|
||||||
text: visualizerTypeComboBox.displayText.charAt(0).toUpperCase() + visualizerTypeComboBox.displayText.slice(1)
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: 13
|
|
||||||
color: Theme.textPrimary
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
elide: Text.ElideRight
|
|
||||||
}
|
|
||||||
|
|
||||||
indicator: Text {
|
|
||||||
x: visualizerTypeComboBox.width - width - 12
|
|
||||||
y: visualizerTypeComboBox.topPadding + (visualizerTypeComboBox.availableHeight - height) / 2
|
|
||||||
text: "arrow_drop_down"
|
|
||||||
font.family: "Material Symbols Outlined"
|
|
||||||
font.pixelSize: 24
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
popup: Popup {
|
|
||||||
y: visualizerTypeComboBox.height
|
|
||||||
width: visualizerTypeComboBox.width
|
|
||||||
implicitHeight: contentItem.implicitHeight
|
|
||||||
padding: 1
|
|
||||||
|
|
||||||
contentItem: ListView {
|
|
||||||
clip: true
|
|
||||||
implicitHeight: contentHeight
|
|
||||||
model: visualizerTypeComboBox.popup.visible ? visualizerTypeComboBox.delegateModel : null
|
|
||||||
currentIndex: visualizerTypeComboBox.highlightedIndex
|
|
||||||
|
|
||||||
ScrollIndicator.vertical: ScrollIndicator {}
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
color: Theme.surfaceVariant
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
radius: 16
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate: ItemDelegate {
|
|
||||||
width: visualizerTypeComboBox.width
|
|
||||||
contentItem: Text {
|
|
||||||
text: modelData.charAt(0).toUpperCase() + modelData.slice(1)
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: 13
|
|
||||||
color: Theme.textPrimary
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
elide: Text.ElideRight
|
|
||||||
}
|
|
||||||
highlighted: visualizerTypeComboBox.highlightedIndex === index
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
color: highlighted ? Theme.accentPrimary.toString().replace(/#/, "#1A") : "transparent"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onActivated: {
|
|
||||||
Settings.settings.visualizerType = model[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Video Path Input Section
|
|
||||||
ColumnLayout {
|
|
||||||
spacing: 8
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Video Path"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: 40
|
|
||||||
radius: 16
|
|
||||||
color: Theme.surfaceVariant
|
|
||||||
border.color: videoPathInput.activeFocus ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
TextInput {
|
|
||||||
id: videoPathInput
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.leftMargin: 12
|
|
||||||
anchors.rightMargin: 12
|
|
||||||
anchors.topMargin: 6
|
|
||||||
anchors.bottomMargin: 6
|
|
||||||
text: Settings.settings.videoPath !== undefined ? Settings.settings.videoPath : ""
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: 13
|
|
||||||
color: Theme.textPrimary
|
|
||||||
verticalAlignment: TextInput.AlignVCenter
|
|
||||||
clip: true
|
|
||||||
selectByMouse: true
|
|
||||||
activeFocusOnTab: true
|
|
||||||
inputMethodHints: Qt.ImhUrlCharactersOnly
|
|
||||||
onTextChanged: {
|
|
||||||
Settings.settings.videoPath = text;
|
|
||||||
}
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.IBeamCursor
|
|
||||||
onClicked: videoPathInput.forceActiveFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,6 +5,7 @@ import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import qs.Settings
|
import qs.Settings
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
import qs.Widgets.SettingsWindow
|
||||||
import qs.Components
|
import qs.Components
|
||||||
|
|
||||||
PanelWindow {
|
PanelWindow {
|
||||||
|
|
@ -19,164 +20,55 @@ PanelWindow {
|
||||||
margins.top: 0
|
margins.top: 0
|
||||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
|
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
|
||||||
|
|
||||||
Rectangle {
|
// Property to track the settings window instance
|
||||||
anchors.fill: parent
|
property var settingsWindow: null
|
||||||
color: Theme.backgroundPrimary
|
|
||||||
radius: 20
|
|
||||||
z: 0
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: content
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.leftMargin: 32
|
|
||||||
anchors.rightMargin: 32
|
|
||||||
anchors.topMargin: 32
|
|
||||||
spacing: 24
|
|
||||||
|
|
||||||
// Header
|
|
||||||
ColumnLayout {
|
|
||||||
id: header
|
|
||||||
Layout.fillWidth: true
|
|
||||||
spacing: 4
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
spacing: 20
|
|
||||||
Text {
|
|
||||||
text: "settings"
|
|
||||||
font.family: "Material Symbols Outlined"
|
|
||||||
font.pixelSize: 32
|
|
||||||
color: Theme.accentPrimary
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
text: "Settings"
|
|
||||||
font.pixelSize: 26
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
Rectangle {
|
|
||||||
width: 36
|
|
||||||
height: 36
|
|
||||||
radius: 18
|
|
||||||
color: closeButtonArea.containsMouse ? Theme.accentPrimary : "transparent"
|
|
||||||
border.color: Theme.accentPrimary
|
|
||||||
border.width: 1
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: "close"
|
|
||||||
font.family: closeButtonArea.containsMouse ? "Material Symbols Rounded" : "Material Symbols Outlined"
|
|
||||||
font.pixelSize: 20
|
|
||||||
color: closeButtonArea.containsMouse ? Theme.onAccent : Theme.accentPrimary
|
|
||||||
}
|
|
||||||
MouseArea {
|
|
||||||
id: closeButtonArea
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
onClicked: settingsModal.closeSettings()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Rectangle {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
height: 1
|
|
||||||
color: Theme.outline
|
|
||||||
opacity: 0.12
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tabs bar (reordered)
|
|
||||||
Tabs {
|
|
||||||
id: settingsTabs
|
|
||||||
Layout.fillWidth: true
|
|
||||||
tabsModel: [
|
|
||||||
{ icon: "settings", label: "System" },
|
|
||||||
{ icon: "wallpaper", label: "Wallpaper" },
|
|
||||||
{ icon: "cloud", label: "Weather" }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scrollable settings area
|
|
||||||
Rectangle {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: content.height - settingsTabs.height - header.height - 128
|
|
||||||
color: "transparent"
|
|
||||||
border.width: 0
|
|
||||||
radius: 20
|
|
||||||
|
|
||||||
Flickable {
|
|
||||||
id: flick
|
|
||||||
anchors.fill: parent
|
|
||||||
contentWidth: width
|
|
||||||
contentHeight: tabContentLoader.item ? tabContentLoader.item.implicitHeight : 0
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: tabContentLoader
|
|
||||||
anchors.top: parent.top
|
|
||||||
width: parent.width
|
|
||||||
sourceComponent: settingsTabs.currentIndex === 0 ? systemTab : settingsTabs.currentIndex === 1 ? wallpaperTab : weatherTab
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: systemTab
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
ProfileSettings {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.alignment: Qt.AlignTop
|
|
||||||
anchors.margins: 16
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: wallpaperTab
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
WallpaperSettings {
|
|
||||||
id: wallpaperSettings
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.alignment: Qt.AlignTop
|
|
||||||
anchors.margins: 16
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: weatherTab
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
WeatherSettings {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.alignment: Qt.AlignTop
|
|
||||||
anchors.margins: 16
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to open the modal and initialize temp values
|
// Function to open the modal and initialize temp values
|
||||||
function openSettings() {
|
function openSettings() {
|
||||||
visible = true;
|
if (!settingsWindow) {
|
||||||
focusTimer.start();
|
// Create new window
|
||||||
|
settingsWindow = settingsComponent.createObject(null); // No parent to avoid dependency issues
|
||||||
|
if (settingsWindow) {
|
||||||
|
settingsWindow.visible = true;
|
||||||
|
// Handle window closure
|
||||||
|
settingsWindow.visibleChanged.connect(function() {
|
||||||
|
if (settingsWindow && !settingsWindow.visible) {
|
||||||
|
var windowToDestroy = settingsWindow;
|
||||||
|
settingsWindow = null;
|
||||||
|
windowToDestroy.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (settingsWindow.visible) {
|
||||||
|
// Close and destroy window
|
||||||
|
var windowToDestroy = settingsWindow;
|
||||||
|
settingsWindow = null;
|
||||||
|
windowToDestroy.visible = false;
|
||||||
|
windowToDestroy.destroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to close the modal and release focus
|
// Function to close the modal and release focus
|
||||||
function closeSettings() {
|
function closeSettings() {
|
||||||
visible = false;
|
if (settingsWindow) {
|
||||||
|
var windowToDestroy = settingsWindow;
|
||||||
|
settingsWindow = null;
|
||||||
|
windowToDestroy.visible = false;
|
||||||
|
windowToDestroy.destroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Component {
|
||||||
id: focusTimer
|
id: settingsComponent
|
||||||
interval: 100
|
SettingsWindow {}
|
||||||
repeat: false
|
|
||||||
onTriggered: {
|
|
||||||
if (visible) {
|
|
||||||
// Focus logic can go here if needed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clean up on destruction
|
||||||
|
Component.onDestruction: {
|
||||||
|
if (settingsWindow) {
|
||||||
|
var windowToDestroy = settingsWindow;
|
||||||
|
settingsWindow = null;
|
||||||
|
windowToDestroy.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,722 +0,0 @@
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import qs.Settings
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: wallpaperSettingsCard
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: Settings.settings.useSWWW ? 720 : 360
|
|
||||||
color: Theme.surface
|
|
||||||
radius: 18
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: 18
|
|
||||||
spacing: 12
|
|
||||||
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
spacing: 12
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "image"
|
|
||||||
font.family: "Material Symbols Outlined"
|
|
||||||
font.pixelSize: 20
|
|
||||||
color: Theme.accentPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Wallpaper Settings"
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: 16
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
spacing: 8
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Wallpaper Path"
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: 40
|
|
||||||
radius: 16
|
|
||||||
color: Theme.surfaceVariant
|
|
||||||
border.color: folderInput.activeFocus ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
TextInput {
|
|
||||||
id: folderInput
|
|
||||||
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.leftMargin: 12
|
|
||||||
anchors.rightMargin: 12
|
|
||||||
anchors.topMargin: 6
|
|
||||||
anchors.bottomMargin: 6
|
|
||||||
text: Settings.settings.wallpaperFolder
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: 13
|
|
||||||
color: Theme.textPrimary
|
|
||||||
verticalAlignment: TextInput.AlignVCenter
|
|
||||||
clip: true
|
|
||||||
selectByMouse: true
|
|
||||||
activeFocusOnTab: true
|
|
||||||
inputMethodHints: Qt.ImhUrlCharactersOnly
|
|
||||||
onTextChanged: {
|
|
||||||
Settings.settings.wallpaperFolder = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.IBeamCursor
|
|
||||||
onClicked: folderInput.forceActiveFocus()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
spacing: 8
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 8
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Random Wallpaper"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom Material 3 Switch
|
|
||||||
Rectangle {
|
|
||||||
id: randomWallpaperSwitch
|
|
||||||
|
|
||||||
width: 52
|
|
||||||
height: 32
|
|
||||||
radius: 16
|
|
||||||
color: Settings.settings.randomWallpaper ? Theme.accentPrimary : Theme.surfaceVariant
|
|
||||||
border.color: Settings.settings.randomWallpaper ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 2
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: randomWallpaperThumb
|
|
||||||
|
|
||||||
width: 28
|
|
||||||
height: 28
|
|
||||||
radius: 14
|
|
||||||
color: Theme.surface
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
y: 2
|
|
||||||
x: Settings.settings.randomWallpaper ? randomWallpaperSwitch.width - width - 2 : 2
|
|
||||||
|
|
||||||
Behavior on x {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: 200
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
Settings.settings.randomWallpaper = !Settings.settings.randomWallpaper;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
spacing: 8
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 8
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Use Wallpaper Theme"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom Material 3 Switch
|
|
||||||
Rectangle {
|
|
||||||
id: wallpaperThemeSwitch
|
|
||||||
|
|
||||||
width: 52
|
|
||||||
height: 32
|
|
||||||
radius: 16
|
|
||||||
color: Settings.settings.useWallpaperTheme ? Theme.accentPrimary : Theme.surfaceVariant
|
|
||||||
border.color: Settings.settings.useWallpaperTheme ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 2
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: wallpaperThemeThumb
|
|
||||||
|
|
||||||
width: 28
|
|
||||||
height: 28
|
|
||||||
radius: 14
|
|
||||||
color: Theme.surface
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
y: 2
|
|
||||||
x: Settings.settings.useWallpaperTheme ? wallpaperThemeSwitch.width - width - 2 : 2
|
|
||||||
|
|
||||||
Behavior on x {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: 200
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
Settings.settings.useWallpaperTheme = !Settings.settings.useWallpaperTheme;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
spacing: 12
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 8
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Wallpaper Interval (seconds)"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: Settings.settings.wallpaperInterval
|
|
||||||
font.pixelSize: 13
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Slider {
|
|
||||||
id: intervalSlider
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
from: 10
|
|
||||||
to: 900
|
|
||||||
stepSize: 10
|
|
||||||
value: Settings.settings.wallpaperInterval
|
|
||||||
snapMode: Slider.SnapAlways
|
|
||||||
onMoved: {
|
|
||||||
Settings.settings.wallpaperInterval = Math.round(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
x: intervalSlider.leftPadding
|
|
||||||
y: intervalSlider.topPadding + intervalSlider.availableHeight / 2 - height / 2
|
|
||||||
implicitWidth: 200
|
|
||||||
implicitHeight: 4
|
|
||||||
width: intervalSlider.availableWidth
|
|
||||||
height: implicitHeight
|
|
||||||
radius: 2
|
|
||||||
color: Theme.surfaceVariant
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: intervalSlider.visualPosition * parent.width
|
|
||||||
height: parent.height
|
|
||||||
color: Theme.accentPrimary
|
|
||||||
radius: 2
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
handle: Rectangle {
|
|
||||||
x: intervalSlider.leftPadding + intervalSlider.visualPosition * (intervalSlider.availableWidth - width)
|
|
||||||
y: intervalSlider.topPadding + intervalSlider.availableHeight / 2 - height / 2
|
|
||||||
implicitWidth: 20
|
|
||||||
implicitHeight: 20
|
|
||||||
radius: 10
|
|
||||||
color: intervalSlider.pressed ? Theme.surfaceVariant : Theme.surface
|
|
||||||
border.color: Theme.accentPrimary
|
|
||||||
border.width: 2
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
spacing: 8
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 8
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Use SWWW"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom Material 3 Switch
|
|
||||||
Rectangle {
|
|
||||||
id: swwwSwitch
|
|
||||||
|
|
||||||
width: 52
|
|
||||||
height: 32
|
|
||||||
radius: 16
|
|
||||||
color: Settings.settings.useSWWW ? Theme.accentPrimary : Theme.surfaceVariant
|
|
||||||
border.color: Settings.settings.useSWWW ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 2
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: swwwThumb
|
|
||||||
|
|
||||||
width: 28
|
|
||||||
height: 28
|
|
||||||
radius: 14
|
|
||||||
color: Theme.surface
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
y: 2
|
|
||||||
x: Settings.settings.useSWWW ? swwwSwitch.width - width - 2 : 2
|
|
||||||
|
|
||||||
Behavior on x {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: 200
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
Settings.settings.useSWWW = !Settings.settings.useSWWW;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
spacing: 12
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
visible: Settings.settings.useSWWW
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Resize Mode"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
ComboBox {
|
|
||||||
id: resizeComboBox
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: 40
|
|
||||||
model: ["no", "crop", "fit", "stretch"]
|
|
||||||
currentIndex: model.indexOf(Settings.settings.wallpaperResize)
|
|
||||||
onActivated: {
|
|
||||||
Settings.settings.wallpaperResize = model[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
implicitWidth: 120
|
|
||||||
implicitHeight: 40
|
|
||||||
color: Theme.surfaceVariant
|
|
||||||
border.color: resizeComboBox.activeFocus ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
radius: 16
|
|
||||||
}
|
|
||||||
|
|
||||||
contentItem: Text {
|
|
||||||
leftPadding: 12
|
|
||||||
rightPadding: resizeComboBox.indicator.width + resizeComboBox.spacing
|
|
||||||
text: resizeComboBox.displayText
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: 13
|
|
||||||
color: Theme.textPrimary
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
elide: Text.ElideRight
|
|
||||||
}
|
|
||||||
|
|
||||||
indicator: Text {
|
|
||||||
x: resizeComboBox.width - width - 12
|
|
||||||
y: resizeComboBox.topPadding + (resizeComboBox.availableHeight - height) / 2
|
|
||||||
text: "arrow_drop_down"
|
|
||||||
font.family: "Material Symbols Outlined"
|
|
||||||
font.pixelSize: 24
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
popup: Popup {
|
|
||||||
y: resizeComboBox.height
|
|
||||||
width: resizeComboBox.width
|
|
||||||
implicitHeight: contentItem.implicitHeight
|
|
||||||
padding: 1
|
|
||||||
|
|
||||||
contentItem: ListView {
|
|
||||||
clip: true
|
|
||||||
implicitHeight: contentHeight
|
|
||||||
model: resizeComboBox.popup.visible ? resizeComboBox.delegateModel : null
|
|
||||||
currentIndex: resizeComboBox.highlightedIndex
|
|
||||||
|
|
||||||
ScrollIndicator.vertical: ScrollIndicator {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
color: Theme.surfaceVariant
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
radius: 16
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate: ItemDelegate {
|
|
||||||
width: resizeComboBox.width
|
|
||||||
highlighted: resizeComboBox.highlightedIndex === index
|
|
||||||
|
|
||||||
contentItem: Text {
|
|
||||||
text: modelData
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: 13
|
|
||||||
color: Theme.textPrimary
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
elide: Text.ElideRight
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
color: highlighted ? Theme.accentPrimary.toString().replace(/#/, "#1A") : "transparent"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
spacing: 12
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
visible: Settings.settings.useSWWW
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Transition Type"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
ComboBox {
|
|
||||||
id: transitionTypeComboBox
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: 40
|
|
||||||
model: ["none", "simple", "fade", "left", "right", "top", "bottom", "wipe", "wave", "grow", "center", "any", "outer", "random"]
|
|
||||||
currentIndex: model.indexOf(Settings.settings.transitionType)
|
|
||||||
onActivated: {
|
|
||||||
Settings.settings.transitionType = model[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
implicitWidth: 120
|
|
||||||
implicitHeight: 40
|
|
||||||
color: Theme.surfaceVariant
|
|
||||||
border.color: transitionTypeComboBox.activeFocus ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
radius: 16
|
|
||||||
}
|
|
||||||
|
|
||||||
contentItem: Text {
|
|
||||||
leftPadding: 12
|
|
||||||
rightPadding: transitionTypeComboBox.indicator.width + transitionTypeComboBox.spacing
|
|
||||||
text: transitionTypeComboBox.displayText
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: 13
|
|
||||||
color: Theme.textPrimary
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
elide: Text.ElideRight
|
|
||||||
}
|
|
||||||
|
|
||||||
indicator: Text {
|
|
||||||
x: transitionTypeComboBox.width - width - 12
|
|
||||||
y: transitionTypeComboBox.topPadding + (transitionTypeComboBox.availableHeight - height) / 2
|
|
||||||
text: "arrow_drop_down"
|
|
||||||
font.family: "Material Symbols Outlined"
|
|
||||||
font.pixelSize: 24
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
popup: Popup {
|
|
||||||
y: transitionTypeComboBox.height
|
|
||||||
width: transitionTypeComboBox.width
|
|
||||||
implicitHeight: contentItem.implicitHeight
|
|
||||||
padding: 1
|
|
||||||
|
|
||||||
contentItem: ListView {
|
|
||||||
clip: true
|
|
||||||
implicitHeight: contentHeight
|
|
||||||
model: transitionTypeComboBox.popup.visible ? transitionTypeComboBox.delegateModel : null
|
|
||||||
currentIndex: transitionTypeComboBox.highlightedIndex
|
|
||||||
|
|
||||||
ScrollIndicator.vertical: ScrollIndicator {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
color: Theme.surfaceVariant
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
radius: 16
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate: ItemDelegate {
|
|
||||||
width: transitionTypeComboBox.width
|
|
||||||
highlighted: transitionTypeComboBox.highlightedIndex === index
|
|
||||||
|
|
||||||
contentItem: Text {
|
|
||||||
text: modelData
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: 13
|
|
||||||
color: Theme.textPrimary
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
elide: Text.ElideRight
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
color: highlighted ? Theme.accentPrimary.toString().replace(/#/, "#1A") : "transparent"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
spacing: 12
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
visible: Settings.settings.useSWWW
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Transition FPS"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: Settings.settings.transitionFps
|
|
||||||
font.pixelSize: 13
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Slider {
|
|
||||||
id: fpsSlider
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
from: 30
|
|
||||||
to: 500
|
|
||||||
stepSize: 5
|
|
||||||
value: Settings.settings.transitionFps
|
|
||||||
snapMode: Slider.SnapAlways
|
|
||||||
onMoved: {
|
|
||||||
Settings.settings.transitionFps = Math.round(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
x: fpsSlider.leftPadding
|
|
||||||
y: fpsSlider.topPadding + fpsSlider.availableHeight / 2 - height / 2
|
|
||||||
implicitWidth: 200
|
|
||||||
implicitHeight: 4
|
|
||||||
width: fpsSlider.availableWidth
|
|
||||||
height: implicitHeight
|
|
||||||
radius: 2
|
|
||||||
color: Theme.surfaceVariant
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: fpsSlider.visualPosition * parent.width
|
|
||||||
height: parent.height
|
|
||||||
color: Theme.accentPrimary
|
|
||||||
radius: 2
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
handle: Rectangle {
|
|
||||||
x: fpsSlider.leftPadding + fpsSlider.visualPosition * (fpsSlider.availableWidth - width)
|
|
||||||
y: fpsSlider.topPadding + fpsSlider.availableHeight / 2 - height / 2
|
|
||||||
implicitWidth: 20
|
|
||||||
implicitHeight: 20
|
|
||||||
radius: 10
|
|
||||||
color: fpsSlider.pressed ? Theme.surfaceVariant : Theme.surface
|
|
||||||
border.color: Theme.accentPrimary
|
|
||||||
border.width: 2
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
spacing: 12
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
visible: Settings.settings.useSWWW
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Transition Duration (seconds)"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: Settings.settings.transitionDuration.toFixed(3)
|
|
||||||
font.pixelSize: 13
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Slider {
|
|
||||||
id: durationSlider
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
from: 0.25
|
|
||||||
to: 10
|
|
||||||
stepSize: 0.05
|
|
||||||
value: Settings.settings.transitionDuration
|
|
||||||
snapMode: Slider.SnapAlways
|
|
||||||
onMoved: {
|
|
||||||
Settings.settings.transitionDuration = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
x: durationSlider.leftPadding
|
|
||||||
y: durationSlider.topPadding + durationSlider.availableHeight / 2 - height / 2
|
|
||||||
implicitWidth: 200
|
|
||||||
implicitHeight: 4
|
|
||||||
width: durationSlider.availableWidth
|
|
||||||
height: implicitHeight
|
|
||||||
radius: 2
|
|
||||||
color: Theme.surfaceVariant
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: durationSlider.visualPosition * parent.width
|
|
||||||
height: parent.height
|
|
||||||
color: Theme.accentPrimary
|
|
||||||
radius: 2
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
handle: Rectangle {
|
|
||||||
x: durationSlider.leftPadding + durationSlider.visualPosition * (durationSlider.availableWidth - width)
|
|
||||||
y: durationSlider.topPadding + durationSlider.availableHeight / 2 - height / 2
|
|
||||||
implicitWidth: 20
|
|
||||||
implicitHeight: 20
|
|
||||||
radius: 10
|
|
||||||
color: durationSlider.pressed ? Theme.surfaceVariant : Theme.surface
|
|
||||||
border.color: Theme.accentPrimary
|
|
||||||
border.width: 2
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,275 +0,0 @@
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import qs.Settings
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: weatherSettingsCard
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: 320
|
|
||||||
color: Theme.surface
|
|
||||||
radius: 18
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: 18
|
|
||||||
spacing: 12
|
|
||||||
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
spacing: 12
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "wb_sunny"
|
|
||||||
font.family: "Material Symbols Outlined"
|
|
||||||
font.pixelSize: 20
|
|
||||||
color: Theme.accentPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Weather Settings"
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: 16
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
spacing: 8
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "City"
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: 40
|
|
||||||
radius: 16
|
|
||||||
color: Theme.surfaceVariant
|
|
||||||
border.color: cityInput.activeFocus ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
TextInput {
|
|
||||||
id: cityInput
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.leftMargin: 12
|
|
||||||
anchors.rightMargin: 12
|
|
||||||
anchors.topMargin: 6
|
|
||||||
anchors.bottomMargin: 6
|
|
||||||
text: Settings.settings.weatherCity
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: 13
|
|
||||||
color: Theme.textPrimary
|
|
||||||
verticalAlignment: TextInput.AlignVCenter
|
|
||||||
clip: true
|
|
||||||
focus: true
|
|
||||||
selectByMouse: true
|
|
||||||
activeFocusOnTab: true
|
|
||||||
inputMethodHints: Qt.ImhNone
|
|
||||||
|
|
||||||
onTextChanged: {
|
|
||||||
Settings.settings.weatherCity = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.IBeamCursor
|
|
||||||
onClicked: {
|
|
||||||
cityInput.forceActiveFocus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
spacing: 12
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Temperature Unit"
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom Material 3 Switch
|
|
||||||
Rectangle {
|
|
||||||
id: customSwitch
|
|
||||||
width: 52
|
|
||||||
height: 32
|
|
||||||
radius: 16
|
|
||||||
color: Theme.accentPrimary
|
|
||||||
border.color: Theme.accentPrimary
|
|
||||||
border.width: 2
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: thumb
|
|
||||||
width: 28
|
|
||||||
height: 28
|
|
||||||
radius: 14
|
|
||||||
color: Theme.surface
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
y: 2
|
|
||||||
x: Settings.settings.useFahrenheit ? customSwitch.width - width - 2 : 2
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: Settings.settings.useFahrenheit ? "\u00b0F" : "\u00b0C"
|
|
||||||
font.family: Theme.fontFamily
|
|
||||||
font.pixelSize: 12
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on x {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: 200
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
Settings.settings.useFahrenheit = !Settings.settings.useFahrenheit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
spacing: 8
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 8
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Use 12 Hour Clock"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom Material 3 Switch
|
|
||||||
Rectangle {
|
|
||||||
id: use12HourClockSwitch
|
|
||||||
width: 52
|
|
||||||
height: 32
|
|
||||||
radius: 16
|
|
||||||
color: Settings.settings.use12HourClock ? Theme.accentPrimary : Theme.surfaceVariant
|
|
||||||
border.color: Settings.settings.use12HourClock ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 2
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: randomWallpaperThumb
|
|
||||||
width: 28
|
|
||||||
height: 28
|
|
||||||
radius: 14
|
|
||||||
color: Theme.surface
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
y: 2
|
|
||||||
x: Settings.settings.use12HourClock ? use12HourClockSwitch.width - width - 2 : 2
|
|
||||||
|
|
||||||
Behavior on x {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: 200
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
Settings.settings.use12HourClock = !Settings.settings.use12HourClock;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
spacing: 8
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 8
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "US Style Date"
|
|
||||||
font.pixelSize: 13
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom Material 3 Switch
|
|
||||||
Rectangle {
|
|
||||||
id: reverseDayMonthSwitch
|
|
||||||
width: 52
|
|
||||||
height: 32
|
|
||||||
radius: 16
|
|
||||||
color: Settings.settings.reverseDayMonth ? Theme.accentPrimary : Theme.surfaceVariant
|
|
||||||
border.color: Settings.settings.reverseDayMonth ? Theme.accentPrimary : Theme.outline
|
|
||||||
border.width: 2
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: reverseDayMonthThumb
|
|
||||||
width: 28
|
|
||||||
height: 28
|
|
||||||
radius: 14
|
|
||||||
color: Theme.surface
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
y: 2
|
|
||||||
x: Settings.settings.reverseDayMonth ? reverseDayMonthSwitch.width - width - 2 : 2
|
|
||||||
|
|
||||||
Behavior on x {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: 200
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
Settings.settings.reverseDayMonth = !Settings.settings.reverseDayMonth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -4,11 +4,22 @@ import Quickshell
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import qs.Settings
|
import qs.Settings
|
||||||
import qs.Widgets.Sidebar.Config
|
import qs.Widgets.SettingsWindow
|
||||||
import qs.Components
|
import qs.Components
|
||||||
|
|
||||||
PanelWithOverlay {
|
PanelWithOverlay {
|
||||||
id: sidebarPopup
|
id: sidebarPopup
|
||||||
|
property var shell: null
|
||||||
|
|
||||||
|
// Trigger initial weather loading when component is completed
|
||||||
|
Component.onCompleted: {
|
||||||
|
// Load initial weather data after a short delay to ensure all components are ready
|
||||||
|
Qt.callLater(function() {
|
||||||
|
if (weather && weather.fetchCityWeather) {
|
||||||
|
weather.fetchCityWeather();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function showAt() {
|
function showAt() {
|
||||||
sidebarPopupRect.showAt();
|
sidebarPopupRect.showAt();
|
||||||
|
|
@ -56,17 +67,17 @@ PanelWithOverlay {
|
||||||
}
|
}
|
||||||
|
|
||||||
function hidePopup() {
|
function hidePopup() {
|
||||||
if (sidebarPopupRect.settingsModal && sidebarPopupRect.settingsModal.visible) {
|
if (shell && shell.settingsWindow && shell.settingsWindow.visible) {
|
||||||
sidebarPopupRect.settingsModal.visible = false;
|
shell.settingsWindow.visible = false;
|
||||||
}
|
}
|
||||||
if (wallpaperPanel && wallpaperPanel.visible) {
|
if (wallpaperPanelLoader.active && wallpaperPanelLoader.item && wallpaperPanelLoader.item.visible) {
|
||||||
wallpaperPanel.visible = false;
|
wallpaperPanelLoader.item.visible = false;
|
||||||
}
|
}
|
||||||
if (sidebarPopupRect.wifiPanelModal && sidebarPopupRect.wifiPanelModal.visible) {
|
if (wifiPanelLoader.active && wifiPanelLoader.item && wifiPanelLoader.item.visible) {
|
||||||
sidebarPopupRect.wifiPanelModal.visible = false;
|
wifiPanelLoader.item.visible = false;
|
||||||
}
|
}
|
||||||
if (sidebarPopupRect.bluetoothPanelModal && sidebarPopupRect.bluetoothPanelModal.visible) {
|
if (bluetoothPanelLoader.active && bluetoothPanelLoader.item && bluetoothPanelLoader.item.visible) {
|
||||||
sidebarPopupRect.bluetoothPanelModal.visible = false;
|
bluetoothPanelLoader.item.visible = false;
|
||||||
}
|
}
|
||||||
if (sidebarPopup.visible) {
|
if (sidebarPopup.visible) {
|
||||||
slideAnim.from = 0;
|
slideAnim.from = 0;
|
||||||
|
|
@ -124,11 +135,44 @@ PanelWithOverlay {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
property alias settingsModal: settingsModal
|
// Access the shell's SettingsWindow instead of creating a new one
|
||||||
property alias wifiPanelModal: wifiPanel.panel
|
|
||||||
property alias bluetoothPanelModal: bluetoothPanel.panel
|
// LazyLoader for WifiPanel
|
||||||
SettingsModal {
|
LazyLoader {
|
||||||
|
id: wifiPanelLoader
|
||||||
|
loading: false
|
||||||
|
component: WifiPanel {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LazyLoader for BluetoothPanel
|
||||||
|
LazyLoader {
|
||||||
|
id: bluetoothPanelLoader
|
||||||
|
loading: false
|
||||||
|
component: BluetoothPanel {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LazyLoader for WallpaperPanel
|
||||||
|
LazyLoader {
|
||||||
|
id: wallpaperPanelLoader
|
||||||
|
loading: false
|
||||||
|
component: WallpaperPanel {
|
||||||
|
Component.onCompleted: {
|
||||||
|
if (parent) {
|
||||||
|
anchors.top = parent.top;
|
||||||
|
anchors.right = parent.right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SettingsIcon component
|
||||||
|
SettingsIcon {
|
||||||
id: settingsModal
|
id: settingsModal
|
||||||
|
onWeatherRefreshRequested: {
|
||||||
|
if (weather && weather.fetchCityWeather) {
|
||||||
|
weather.fetchCityWeather();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
|
@ -226,7 +270,14 @@ PanelWithOverlay {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: wifiPanel.showAt()
|
onClicked: {
|
||||||
|
if (!wifiPanelLoader.active) {
|
||||||
|
wifiPanelLoader.loading = true;
|
||||||
|
}
|
||||||
|
if (wifiPanelLoader.item) {
|
||||||
|
wifiPanelLoader.item.showAt();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledTooltip {
|
StyledTooltip {
|
||||||
|
|
@ -261,7 +312,14 @@ PanelWithOverlay {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: bluetoothPanel.showAt()
|
onClicked: {
|
||||||
|
if (!bluetoothPanelLoader.active) {
|
||||||
|
bluetoothPanelLoader.loading = true;
|
||||||
|
}
|
||||||
|
if (bluetoothPanelLoader.item) {
|
||||||
|
bluetoothPanelLoader.item.showAt();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledTooltip {
|
StyledTooltip {
|
||||||
|
|
@ -274,16 +332,6 @@ PanelWithOverlay {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hidden panel components for modal functionality
|
|
||||||
WifiPanel {
|
|
||||||
id: wifiPanel
|
|
||||||
visible: false
|
|
||||||
}
|
|
||||||
BluetoothPanel {
|
|
||||||
id: bluetoothPanel
|
|
||||||
visible: false
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
}
|
}
|
||||||
|
|
@ -310,10 +358,18 @@ PanelWithOverlay {
|
||||||
}
|
}
|
||||||
|
|
||||||
onSettingsRequested: {
|
onSettingsRequested: {
|
||||||
settingsModal.visible = true;
|
// Use the SettingsModal's openSettings function
|
||||||
|
if (typeof settingsModal !== 'undefined' && settingsModal && settingsModal.openSettings) {
|
||||||
|
settingsModal.openSettings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onWallpaperRequested: {
|
onWallpaperRequested: {
|
||||||
wallpaperPanel.visible = true;
|
if (!wallpaperPanelLoader.active) {
|
||||||
|
wallpaperPanelLoader.loading = true;
|
||||||
|
}
|
||||||
|
if (wallpaperPanelLoader.item) {
|
||||||
|
wallpaperPanelLoader.item.visible = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -408,15 +464,5 @@ PanelWithOverlay {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WallpaperPanel {
|
|
||||||
id: wallpaperPanel
|
|
||||||
Component.onCompleted: {
|
|
||||||
if (parent) {
|
|
||||||
anchors.top = parent.top;
|
|
||||||
anchors.right = parent.right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
80
Widgets/Sidebar/Panel/SettingsIcon.qml
Normal file
80
Widgets/Sidebar/Panel/SettingsIcon.qml
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Controls
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Wayland
|
||||||
|
import qs.Settings
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets.SettingsWindow
|
||||||
|
import qs.Components
|
||||||
|
|
||||||
|
PanelWindow {
|
||||||
|
id: settingsModal
|
||||||
|
implicitWidth: 480
|
||||||
|
implicitHeight: 780
|
||||||
|
visible: false
|
||||||
|
color: "transparent"
|
||||||
|
anchors.top: true
|
||||||
|
anchors.right: true
|
||||||
|
margins.right: 0
|
||||||
|
margins.top: 0
|
||||||
|
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
|
||||||
|
|
||||||
|
// Signal to request weather refresh
|
||||||
|
signal weatherRefreshRequested()
|
||||||
|
|
||||||
|
// Property to track the settings window instance
|
||||||
|
property var settingsWindow: null
|
||||||
|
|
||||||
|
// Function to open the modal and initialize temp values
|
||||||
|
function openSettings() {
|
||||||
|
if (!settingsWindow) {
|
||||||
|
// Create new window
|
||||||
|
settingsWindow = settingsComponent.createObject(null); // No parent to avoid dependency issues
|
||||||
|
if (settingsWindow) {
|
||||||
|
settingsWindow.visible = true;
|
||||||
|
// Handle window closure
|
||||||
|
settingsWindow.visibleChanged.connect(function() {
|
||||||
|
if (settingsWindow && !settingsWindow.visible) {
|
||||||
|
// Trigger weather refresh when settings close
|
||||||
|
weatherRefreshRequested();
|
||||||
|
var windowToDestroy = settingsWindow;
|
||||||
|
settingsWindow = null;
|
||||||
|
windowToDestroy.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (settingsWindow.visible) {
|
||||||
|
// Close and destroy window
|
||||||
|
var windowToDestroy = settingsWindow;
|
||||||
|
settingsWindow = null;
|
||||||
|
windowToDestroy.visible = false;
|
||||||
|
windowToDestroy.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to close the modal and release focus
|
||||||
|
function closeSettings() {
|
||||||
|
if (settingsWindow) {
|
||||||
|
var windowToDestroy = settingsWindow;
|
||||||
|
settingsWindow = null;
|
||||||
|
windowToDestroy.visible = false;
|
||||||
|
windowToDestroy.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: settingsComponent
|
||||||
|
SettingsWindow {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up on destruction
|
||||||
|
Component.onDestruction: {
|
||||||
|
if (settingsWindow) {
|
||||||
|
var windowToDestroy = settingsWindow;
|
||||||
|
settingsWindow = null;
|
||||||
|
windowToDestroy.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -15,13 +15,17 @@ Rectangle {
|
||||||
property var weatherData: null
|
property var weatherData: null
|
||||||
property string errorString: ""
|
property string errorString: ""
|
||||||
property bool isVisible: false
|
property bool isVisible: false
|
||||||
|
property int lastFetchTime: 0
|
||||||
|
property bool isLoading: false
|
||||||
|
|
||||||
// Auto-refetch weather when city changes
|
// Auto-refetch weather when city changes
|
||||||
Connections {
|
Connections {
|
||||||
target: Settings.settings
|
target: Settings.settings
|
||||||
function onWeatherCityChanged() {
|
function onWeatherCityChanged() {
|
||||||
if (isVisible && city !== "") {
|
if (isVisible && city !== "") {
|
||||||
fetchCityWeather()
|
// Force refresh when city changes
|
||||||
|
lastFetchTime = 0;
|
||||||
|
fetchCityWeather();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -33,20 +37,42 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchCityWeather() {
|
function fetchCityWeather() {
|
||||||
|
if (!city || city.trim() === "") {
|
||||||
|
errorString = "No city configured";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we should fetch new data (avoid fetching too frequently)
|
||||||
|
var currentTime = Date.now();
|
||||||
|
var timeSinceLastFetch = currentTime - lastFetchTime;
|
||||||
|
|
||||||
|
// Only skip if we have recent data AND lastFetchTime is not 0 (initial state)
|
||||||
|
if (lastFetchTime > 0 && timeSinceLastFetch < 60000) { // 1 minute
|
||||||
|
return; // Skip if last fetch was less than 1 minute ago
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading = true;
|
||||||
|
errorString = "";
|
||||||
|
|
||||||
WeatherHelper.fetchCityWeather(city,
|
WeatherHelper.fetchCityWeather(city,
|
||||||
function(result) {
|
function(result) {
|
||||||
weatherData = result.weather;
|
weatherData = result.weather;
|
||||||
|
lastFetchTime = currentTime;
|
||||||
errorString = "";
|
errorString = "";
|
||||||
|
isLoading = false;
|
||||||
},
|
},
|
||||||
function(err) {
|
function(err) {
|
||||||
errorString = err;
|
errorString = err;
|
||||||
|
isLoading = false;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function startWeatherFetch() {
|
function startWeatherFetch() {
|
||||||
isVisible = true
|
isVisible = true
|
||||||
fetchCityWeather()
|
// Force refresh when panel opens, regardless of time check
|
||||||
|
lastFetchTime = 0;
|
||||||
|
fetchCityWeather();
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopWeatherFetch() {
|
function stopWeatherFetch() {
|
||||||
|
|
@ -77,12 +103,21 @@ Rectangle {
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: weatherIcon
|
id: weatherIcon
|
||||||
text: weatherData && weatherData.current_weather ? materialSymbolForCode(weatherData.current_weather.weathercode) : "cloud"
|
text: isLoading ? "sync" : (weatherData && weatherData.current_weather ? materialSymbolForCode(weatherData.current_weather.weathercode) : "cloud")
|
||||||
font.family: "Material Symbols Outlined"
|
font.family: "Material Symbols Outlined"
|
||||||
font.pixelSize: 28
|
font.pixelSize: 28
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
color: Theme.accentPrimary
|
color: isLoading ? Theme.accentPrimary : Theme.accentPrimary
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
|
||||||
|
// Add rotation animation for loading state
|
||||||
|
RotationAnimation on rotation {
|
||||||
|
running: isLoading
|
||||||
|
from: 0
|
||||||
|
to: 360
|
||||||
|
duration: 1000
|
||||||
|
loops: Animation.Infinite
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
|
|
|
||||||
50
shell.qml
50
shell.qml
|
|
@ -9,6 +9,7 @@ import qs.Bar.Modules
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
import qs.Widgets.LockScreen
|
import qs.Widgets.LockScreen
|
||||||
import qs.Widgets.Notification
|
import qs.Widgets.Notification
|
||||||
|
import qs.Widgets.SettingsWindow
|
||||||
import qs.Settings
|
import qs.Settings
|
||||||
import qs.Helpers
|
import qs.Helpers
|
||||||
|
|
||||||
|
|
@ -19,9 +20,18 @@ Scope {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property alias appLauncherPanel: appLauncherPanel
|
property alias appLauncherPanel: appLauncherPanel
|
||||||
property var notificationHistoryWin: notificationHistoryWin
|
property var notificationHistoryWin: notificationHistoryLoader.active ? notificationHistoryLoader.item : null
|
||||||
|
property var settingsWindow: null
|
||||||
property bool pendingReload: false
|
property bool pendingReload: false
|
||||||
|
|
||||||
|
// Function to load notification history
|
||||||
|
function loadNotificationHistory() {
|
||||||
|
if (!notificationHistoryLoader.active) {
|
||||||
|
notificationHistoryLoader.loading = true;
|
||||||
|
}
|
||||||
|
return notificationHistoryLoader;
|
||||||
|
}
|
||||||
|
|
||||||
// Helper function to round value to nearest step
|
// Helper function to round value to nearest step
|
||||||
function roundToStep(value, step) {
|
function roundToStep(value, step) {
|
||||||
return Math.round(value / step) * step;
|
return Math.round(value / step) * step;
|
||||||
|
|
@ -50,7 +60,7 @@ Scope {
|
||||||
Bar {
|
Bar {
|
||||||
id: bar
|
id: bar
|
||||||
shell: root
|
shell: root
|
||||||
property var notificationHistoryWin: notificationHistoryWin
|
property var notificationHistoryWin: notificationHistoryLoader.active ? notificationHistoryLoader.item : null
|
||||||
}
|
}
|
||||||
|
|
||||||
Variants {
|
Variants {
|
||||||
|
|
@ -62,6 +72,9 @@ Scope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Background {}
|
||||||
|
Overview {}
|
||||||
|
|
||||||
Applauncher {
|
Applauncher {
|
||||||
id: appLauncherPanel
|
id: appLauncherPanel
|
||||||
visible: false
|
visible: false
|
||||||
|
|
@ -94,8 +107,8 @@ Scope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (notificationHistoryWin) {
|
if (notificationHistoryLoader.active && notificationHistoryLoader.item) {
|
||||||
notificationHistoryWin.addToHistory({
|
notificationHistoryLoader.item.addToHistory({
|
||||||
id: notification.id,
|
id: notification.id,
|
||||||
appName: notification.appName || "Notification",
|
appName: notification.appName || "Notification",
|
||||||
summary: notification.summary || "",
|
summary: notification.summary || "",
|
||||||
|
|
@ -111,8 +124,33 @@ Scope {
|
||||||
id: notificationPopup
|
id: notificationPopup
|
||||||
}
|
}
|
||||||
|
|
||||||
NotificationHistory {
|
// LazyLoader for NotificationHistory - only load when needed
|
||||||
id: notificationHistoryWin
|
LazyLoader {
|
||||||
|
id: notificationHistoryLoader
|
||||||
|
loading: false
|
||||||
|
component: NotificationHistory {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Centralized LazyLoader for SettingsWindow - prevents crashes on multiple opens
|
||||||
|
LazyLoader {
|
||||||
|
id: settingsWindowLoader
|
||||||
|
loading: false
|
||||||
|
component: SettingsWindow {
|
||||||
|
Component.onCompleted: {
|
||||||
|
root.settingsWindow = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to safely show/hide settings window
|
||||||
|
function toggleSettingsWindow() {
|
||||||
|
if (!settingsWindowLoader.active) {
|
||||||
|
settingsWindowLoader.loading = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settingsWindowLoader.item) {
|
||||||
|
settingsWindowLoader.item.visible = !settingsWindowLoader.item.visible;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reference to the default audio sink from Pipewire
|
// Reference to the default audio sink from Pipewire
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue