From b998cbd3e63ba7f4c0e49b9fcd20ad8ea71eb987 Mon Sep 17 00:00:00 2001 From: bbedward Date: Sun, 24 Aug 2025 10:30:46 -0400 Subject: [PATCH] display configs --- Common/SettingsData.qml | 19 +- Modals/SettingsModal.qml | 19 +- Modules/Settings/DisplaysTab.qml | 349 +++++++++++++++++++++++++++++++ Modules/WallpaperBackground.qml | 2 +- Services/NetworkService.qml | 2 +- shell.qml | 17 +- 6 files changed, 394 insertions(+), 14 deletions(-) create mode 100644 Modules/Settings/DisplaysTab.qml diff --git a/Common/SettingsData.qml b/Common/SettingsData.qml index 39fa63b5..2ea419c2 100644 --- a/Common/SettingsData.qml +++ b/Common/SettingsData.qml @@ -91,6 +91,7 @@ Singleton { property int notificationTimeoutLow: 5000 property int notificationTimeoutNormal: 5000 property int notificationTimeoutCritical: 0 + property var screenPreferences: ({}) readonly property string defaultFontFamily: "Inter Variable" readonly property string defaultMonoFontFamily: "Fira Code" readonly property string _homeUrl: StandardPaths.writableLocation( @@ -283,6 +284,8 @@ Singleton { !== undefined ? settings.topBarSquareCorners : false topBarNoBackground = settings.topBarNoBackground !== undefined ? settings.topBarNoBackground : false + screenPreferences = settings.screenPreferences + !== undefined ? settings.screenPreferences : ({}) applyStoredTheme() detectAvailableIconThemes() detectQtTools() @@ -369,7 +372,8 @@ Singleton { "topBarNoBackground": topBarNoBackground, "notificationTimeoutLow": notificationTimeoutLow, "notificationTimeoutNormal": notificationTimeoutNormal, - "notificationTimeoutCritical": notificationTimeoutCritical + "notificationTimeoutCritical": notificationTimeoutCritical, + "screenPreferences": screenPreferences }, null, 2)) } @@ -911,6 +915,19 @@ Singleton { saveSettings() } + function setScreenPreferences(prefs) { + screenPreferences = prefs + saveSettings() + } + + function getFilteredScreens(componentId) { + var prefs = screenPreferences && screenPreferences[componentId] || ["all"] + if (prefs.includes("all")) { + return Quickshell.screens + } + return Quickshell.screens.filter(screen => prefs.includes(screen.name)) + } + function _shq(s) { return "'" + String(s).replace(/'/g, "'\\''") + "'" } diff --git a/Modals/SettingsModal.qml b/Modals/SettingsModal.qml index 9279fa11..994543ac 100644 --- a/Modals/SettingsModal.qml +++ b/Modals/SettingsModal.qml @@ -361,6 +361,9 @@ DankModal { }, { "text": "Dock", "icon": "dock_to_bottom" + }, { + "text": "Displays", + "icon": "monitor" }, { "text": "Recent Apps", "icon": "history" @@ -508,12 +511,22 @@ DankModal { } Loader { - id: recentAppsLoader + id: displaysLoader anchors.fill: parent active: sidebarContainer.currentIndex === 6 visible: active asynchronous: true + sourceComponent: DisplaysTab {} + } + + Loader { + id: recentAppsLoader + + anchors.fill: parent + active: sidebarContainer.currentIndex === 7 + visible: active + asynchronous: true sourceComponent: RecentAppsTab {} } @@ -521,7 +534,7 @@ DankModal { id: themeColorsLoader anchors.fill: parent - active: sidebarContainer.currentIndex === 7 + active: sidebarContainer.currentIndex === 8 visible: active asynchronous: true sourceComponent: ThemeColorsTab {} @@ -531,7 +544,7 @@ DankModal { id: aboutLoader anchors.fill: parent - active: sidebarContainer.currentIndex === 8 + active: sidebarContainer.currentIndex === 9 visible: active asynchronous: true sourceComponent: AboutTab {} diff --git a/Modules/Settings/DisplaysTab.qml b/Modules/Settings/DisplaysTab.qml new file mode 100644 index 00000000..044a5748 --- /dev/null +++ b/Modules/Settings/DisplaysTab.qml @@ -0,0 +1,349 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell +import qs.Common +import qs.Services +import qs.Widgets + +Item { + id: displaysTab + + property var variantComponents: [{ + "id": "topBar", + "name": "Top Bar", + "description": "System bar with widgets and system information", + "icon": "toolbar" + }, { + "id": "notifications", + "name": "Notification Popups", + "description": "Notification toast popups", + "icon": "notifications" + }, { + "id": "wallpaper", + "name": "Wallpaper", + "description": "Desktop background images", + "icon": "wallpaper" + }, { + "id": "osd", + "name": "On-Screen Displays", + "description": "Volume, brightness, and other system OSDs", + "icon": "picture_in_picture" + }] + + function getScreenPreferences(componentId) { + return SettingsData.screenPreferences && SettingsData.screenPreferences[componentId] || ["all"]; + } + + function setScreenPreferences(componentId, screenNames) { + var prefs = SettingsData.screenPreferences || { + }; + prefs[componentId] = screenNames; + SettingsData.setScreenPreferences(prefs); + } + + DankFlickable { + anchors.fill: parent + anchors.topMargin: Theme.spacingL + anchors.bottomMargin: Theme.spacingS + clip: true + contentHeight: mainColumn.height + contentWidth: width + + Column { + id: mainColumn + + width: parent.width + spacing: Theme.spacingXL + + StyledRect { + width: parent.width + height: screensInfoSection.implicitHeight + Theme.spacingL * 2 + radius: Theme.cornerRadius + color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) + border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) + border.width: 1 + + Column { + id: screensInfoSection + + anchors.fill: parent + anchors.margins: Theme.spacingL + spacing: Theme.spacingM + + Row { + width: parent.width + spacing: Theme.spacingM + + DankIcon { + name: "monitor" + size: Theme.iconSize + color: Theme.primary + anchors.verticalCenter: parent.verticalCenter + } + + Column { + width: parent.width - Theme.iconSize - Theme.spacingM + spacing: Theme.spacingXS + anchors.verticalCenter: parent.verticalCenter + + StyledText { + text: "Connected Displays" + font.pixelSize: Theme.fontSizeLarge + font.weight: Font.Medium + color: Theme.surfaceText + } + + StyledText { + text: "Configure which displays show shell components" + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceVariantText + wrapMode: Text.WordWrap + width: parent.width + } + + } + + } + + Column { + width: parent.width + spacing: Theme.spacingS + + StyledText { + text: "Available Screens (" + Quickshell.screens.length + ")" + font.pixelSize: Theme.fontSizeMedium + font.weight: Font.Medium + color: Theme.surfaceText + } + + Repeater { + model: Quickshell.screens + + delegate: Rectangle { + width: parent.width + height: screenRow.implicitHeight + Theme.spacingS * 2 + radius: Theme.cornerRadius + color: Theme.surfaceContainerHigh + border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3) + border.width: 1 + + Row { + id: screenRow + + anchors.fill: parent + anchors.margins: Theme.spacingS + spacing: Theme.spacingM + + DankIcon { + name: "desktop_windows" + size: Theme.iconSize - 4 + color: Theme.primary + anchors.verticalCenter: parent.verticalCenter + } + + Column { + width: parent.width - Theme.iconSize - Theme.spacingM * 2 + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.spacingXS / 2 + + StyledText { + text: modelData.name + font.pixelSize: Theme.fontSizeMedium + font.weight: Font.Medium + color: Theme.surfaceText + } + + Row { + spacing: Theme.spacingS + + StyledText { + text: modelData.width + "×" + modelData.height + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceVariantText + } + + StyledText { + text: "•" + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceVariantText + } + + StyledText { + text: modelData.model || "Unknown Model" + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceVariantText + } + + } + + } + + } + + } + + } + + } + + } + + } + + Column { + width: parent.width + spacing: Theme.spacingL + + Repeater { + model: displaysTab.variantComponents + + delegate: StyledRect { + width: parent.width + height: componentSection.implicitHeight + Theme.spacingL * 2 + radius: Theme.cornerRadius + color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) + border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) + border.width: 1 + + Column { + id: componentSection + + anchors.fill: parent + anchors.margins: Theme.spacingL + spacing: Theme.spacingM + + Row { + width: parent.width + spacing: Theme.spacingM + + DankIcon { + name: modelData.icon + size: Theme.iconSize + color: Theme.primary + anchors.verticalCenter: parent.verticalCenter + } + + Column { + width: parent.width - Theme.iconSize - Theme.spacingM + spacing: Theme.spacingXS + anchors.verticalCenter: parent.verticalCenter + + StyledText { + text: modelData.name + font.pixelSize: Theme.fontSizeLarge + font.weight: Font.Medium + color: Theme.surfaceText + } + + StyledText { + text: modelData.description + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceVariantText + wrapMode: Text.WordWrap + width: parent.width + } + + } + + } + + Column { + width: parent.width + spacing: Theme.spacingS + + StyledText { + text: "Show on screens:" + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceText + font.weight: Font.Medium + } + + Column { + property string componentId: modelData.id + property var selectedScreens: displaysTab.getScreenPreferences(componentId) + + width: parent.width + spacing: Theme.spacingXS + + DankToggle { + width: parent.width + text: "All displays" + description: "Show on all connected displays" + checked: parent.selectedScreens.includes("all") + onToggled: (checked) => { + if (checked) + displaysTab.setScreenPreferences(parent.componentId, ["all"]); + else + displaysTab.setScreenPreferences(parent.componentId, []); + } + } + + Rectangle { + width: parent.width + height: 1 + color: Theme.outline + opacity: 0.2 + visible: !parent.selectedScreens.includes("all") + } + + Column { + width: parent.width + spacing: Theme.spacingXS + visible: !parent.selectedScreens.includes("all") + + Repeater { + model: Quickshell.screens + + delegate: DankToggle { + property string screenName: modelData.name + property string componentId: parent.parent.componentId + + width: parent.width + text: screenName + description: modelData.width + "×" + modelData.height + " • " + (modelData.model || "Unknown Model") + checked: { + var prefs = displaysTab.getScreenPreferences(componentId); + return !prefs.includes("all") && prefs.includes(screenName); + } + onToggled: (checked) => { + var currentPrefs = displaysTab.getScreenPreferences(componentId); + if (currentPrefs.includes("all")) + currentPrefs = []; + + var newPrefs = currentPrefs.slice(); + if (checked) { + if (!newPrefs.includes(screenName)) + newPrefs.push(screenName); + + } else { + var index = newPrefs.indexOf(screenName); + if (index > -1) + newPrefs.splice(index, 1); + + } + displaysTab.setScreenPreferences(componentId, newPrefs); + } + } + + } + + } + + } + + } + + } + + } + + } + + } + + } + + } + +} diff --git a/Modules/WallpaperBackground.qml b/Modules/WallpaperBackground.qml index abb7c144..32e0ae23 100644 --- a/Modules/WallpaperBackground.qml +++ b/Modules/WallpaperBackground.qml @@ -9,7 +9,7 @@ LazyLoader { active: SessionData.wallpaperPath !== "" Variants { - model: Quickshell.screens + model: SettingsData.getFilteredScreens("wallpaper") PanelWindow { id: wallpaperWindow diff --git a/Services/NetworkService.qml b/Services/NetworkService.qml index 07b33b83..a3452cd7 100644 --- a/Services/NetworkService.qml +++ b/Services/NetworkService.qml @@ -33,7 +33,7 @@ Singleton { property var wifiNetworks: [] property var savedConnections: [] property var wifiSignalIcon: { - if (currentWifiSSID == "" || !wifiEnabled) { + if (!wifiConnected || networkStatus !== "wifi") { return "signal_wifi_off" } // Use nmcli signal strength percentage diff --git a/shell.qml b/shell.qml index fb90da08..6b6334f9 100644 --- a/shell.qml +++ b/shell.qml @@ -18,6 +18,7 @@ import qs.Modules.Settings import qs.Modules.TopBar import qs.Modules.Dock import qs.Services +import qs.Common ShellRoot { id: root @@ -31,7 +32,7 @@ ShellRoot { } Variants { - model: Quickshell.screens + model: SettingsData.getFilteredScreens("topBar") delegate: TopBar { modelData: item @@ -39,7 +40,7 @@ ShellRoot { } Variants { - model: Quickshell.screens + model: SettingsData.getFilteredScreens("dock") delegate: Dock { modelData: item @@ -81,7 +82,7 @@ ShellRoot { } Variants { - model: Quickshell.screens + model: SettingsData.getFilteredScreens("notifications") delegate: NotificationPopupManager { modelData: item @@ -232,7 +233,7 @@ ShellRoot { } Variants { - model: Quickshell.screens + model: SettingsData.getFilteredScreens("toast") delegate: Toast { modelData: item @@ -241,7 +242,7 @@ ShellRoot { } Variants { - model: Quickshell.screens + model: SettingsData.getFilteredScreens("osd") delegate: VolumeOSD { modelData: item @@ -252,7 +253,7 @@ ShellRoot { Variants { - model: Quickshell.screens + model: SettingsData.getFilteredScreens("osd") delegate: MicMuteOSD { modelData: item @@ -260,7 +261,7 @@ ShellRoot { } Variants { - model: Quickshell.screens + model: SettingsData.getFilteredScreens("osd") delegate: BrightnessOSD { modelData: item @@ -268,7 +269,7 @@ ShellRoot { } Variants { - model: Quickshell.screens + model: SettingsData.getFilteredScreens("osd") delegate: IdleInhibitorOSD { modelData: item