import QtQuick import QtQuick.Layouts import Quickshell import Quickshell.Services.SystemTray import "../../components" import "../../services" import "../../theme" GlassPanel { id: root implicitWidth: mainLayout.implicitWidth + 24 implicitHeight: 36 property var activeTrayItem: null property var activeTrayMenuOpener: null property real activeTrayX: 12 function getCleanAppName(item) { if (!item) return "Application" let title = item.title ? item.title.trim() : "" let idStr = item.id ? item.id.trim() : "" let raw = title if (!raw || raw.includes("_status_icon") || raw.includes(".desktop") || raw.includes("org.")) { raw = idStr } if (!raw) raw = idStr if (!raw) return "Application" raw = raw.replace(/(_status_icon_\d+|_tray_\d+|_\d+)$/i, "") if (raw.includes(".")) { let parts = raw.split(".") raw = parts[parts.length - 1] } raw = raw.replace(/[-_]/g, " ") raw = raw.replace(/([a-z])([A-Z])/g, "$1 $2") let words = raw.split(" ").filter(w => w.length > 0).map(w => w.charAt(0).toUpperCase() + w.slice(1)) let result = words.join(" ") if (result.toLowerCase() === "archupdate") return "Arch Update" return result || "Application" } RowLayout { id: mainLayout anchors.fill: parent anchors.leftMargin: 8 anchors.rightMargin: 8 spacing: 6 // System Tray Section (Active Background Apps) RowLayout { spacing: 4 Repeater { model: SystemTray.items Rectangle { id: trayItemRect width: 24 height: 24 radius: 5 color: trayMouse.containsMouse ? Theme.currentLine : "transparent" // Continuous Background QsMenuOpener (Caches DBus Menu Items for Instant Display) QsMenuOpener { id: itemMenuOpener menu: modelData.menu } Image { anchors.centerIn: parent width: 16 height: 16 source: modelData.icon fillMode: Image.PreserveAspectFit } MouseArea { id: trayMouse anchors.fill: parent hoverEnabled: true acceptedButtons: Qt.LeftButton | Qt.RightButton onClicked: (mouse) => { if (mouse.button === Qt.LeftButton) { modelData.activate() } else if (mouse.button === Qt.RightButton) { root.activeTrayItem = modelData root.activeTrayMenuOpener = itemMenuOpener var mapped = trayItemRect.mapToItem(root, 0, 0) root.activeTrayX = mapped.x PopupService.toggleTray() } } } } } } // Vertical Separator between Running Apps (System Tray) and Notification Center Rectangle { Layout.preferredWidth: 1 Layout.preferredHeight: 16 color: Theme.separator Layout.leftMargin: 4 Layout.rightMargin: 4 visible: true } // Notification Center Icon Snippet (Papirus Panel Icon & Dynamic Unread/DND SVG) Rectangle { id: notifBtn Layout.preferredWidth: 26 Layout.preferredHeight: 26 radius: 6 color: notifMouse.containsMouse ? Theme.currentLine : "transparent" Behavior on color { ColorAnimation { duration: 120 } } Image { anchors.centerIn: parent width: 16 height: 16 sourceSize.width: 16 sourceSize.height: 16 fillMode: Image.PreserveAspectFit source: { let base = "file:///usr/share/icons/" + Theme.panelIconDir + "/24x24/panel/" let hasUnread = NotificationService.notifications.length > 0 if (NotificationService.isDnd) { return hasUnread ? base + "indicator-notification-unread-dnd.svg" : base + "indicator-notification-read-dnd.svg" } else { return hasUnread ? base + "indicator-notification-unread.svg" : base + "indicator-notification-read.svg" } } } MouseArea { id: notifMouse anchors.fill: parent hoverEnabled: true onClicked: PopupService.toggleNotification() } } // Screenshot & Screen Recording Icon Snippet (Authentic Papirus Panel SVG) Rectangle { id: captureBtn Layout.preferredWidth: 26 Layout.preferredHeight: 26 radius: 6 color: captureMouse.containsMouse ? Theme.currentLine : "transparent" Behavior on color { ColorAnimation { duration: 120 } } Image { anchors.centerIn: parent width: 16 height: 16 sourceSize.width: 16 sourceSize.height: 16 fillMode: Image.PreserveAspectFit source: "file:///usr/share/icons/" + Theme.panelIconDir + "/24x24/panel/record-desktop-indicator.svg" } MouseArea { id: captureMouse anchors.fill: parent hoverEnabled: true onClicked: PopupService.toggleCapture() } } // Clipboard Manager Icon Snippet Rectangle { id: clipBtn Layout.preferredWidth: 26 Layout.preferredHeight: 26 radius: 6 color: clipMouse.containsMouse ? Theme.currentLine : "transparent" Behavior on color { ColorAnimation { duration: 120 } } Image { anchors.centerIn: parent width: 16 height: 16 sourceSize.width: 16 sourceSize.height: 16 fillMode: Image.PreserveAspectFit source: "file:///usr/share/icons/" + Theme.panelIconDir + "/24x24/panel/clipboard.svg" } MouseArea { id: clipMouse anchors.fill: parent hoverEnabled: true onClicked: { ClipboardService.scanClipboard() PopupService.toggleClipboard() } } } // Audio Icon Snippet (Icon-only, Scroll Wheel + Click Popup) Rectangle { id: audioBtn Layout.preferredWidth: 26 Layout.preferredHeight: 26 radius: 6 color: audioMouse.containsMouse ? Theme.currentLine : "transparent" Behavior on color { ColorAnimation { duration: 120 } } VolumeIcon { anchors.centerIn: parent volume: AudioService.volume isMuted: AudioService.isMuted width: 16 height: 16 } MouseArea { id: audioMouse anchors.fill: parent hoverEnabled: true onClicked: PopupService.toggleAudio() onWheel: (wheel) => { if (wheel.angleDelta.y > 0) { AudioService.volumeUp() } else if (wheel.angleDelta.y < 0) { AudioService.volumeDown() } } } } // Bluetooth Icon Snippet (Placed to the Right of Audio Control) Rectangle { id: btBtn Layout.preferredWidth: 26 Layout.preferredHeight: 26 radius: 6 color: btMouse.containsMouse ? Theme.currentLine : "transparent" Behavior on color { ColorAnimation { duration: 120 } } BluetoothIcon { anchors.centerIn: parent isPowered: BluetoothService.isPowered isConnected: BluetoothService.connectedDevices.length > 0 width: 16 height: 16 } MouseArea { id: btMouse anchors.fill: parent hoverEnabled: true onClicked: { BluetoothService.scanBluetooth() PopupService.toggleBluetooth() } } } // Screen Brightness Icon Snippet Rectangle { id: brightBtn Layout.preferredWidth: 26 Layout.preferredHeight: 26 radius: 6 color: brightMouse.containsMouse ? Theme.currentLine : "transparent" Behavior on color { ColorAnimation { duration: 120 } } BrightnessIcon { anchors.centerIn: parent brightness: BrightnessService.masterBrightness width: 16 height: 16 } MouseArea { id: brightMouse anchors.fill: parent hoverEnabled: true onClicked: { BrightnessService.scanDevices() PopupService.toggleBrightness() } onWheel: (wheel) => { if (wheel.angleDelta.y > 0) { BrightnessService.brightnessUp() } else if (wheel.angleDelta.y < 0) { BrightnessService.brightnessDown() } } } } // External Storage Mount Icon Snippet (Placed to the Right of Brightness) Rectangle { id: mountBtn Layout.preferredWidth: 26 Layout.preferredHeight: 26 radius: 6 color: mountMouse.containsMouse ? Theme.currentLine : "transparent" Behavior on color { ColorAnimation { duration: 120 } } Image { anchors.centerIn: parent width: 16 height: 16 sourceSize.width: 16 sourceSize.height: 16 fillMode: Image.PreserveAspectFit source: "file:///usr/share/icons/" + Theme.panelIconDir + "/24x24/panel/drive-removable-media-usb-panel.svg" } MouseArea { id: mountMouse anchors.fill: parent hoverEnabled: true onClicked: { MountService.scanDevices() PopupService.toggleMount() } } } // Network Icon Snippet (Ethernet & Wi-Fi Dynamic Badge) Rectangle { id: netBtn Layout.preferredWidth: 26 Layout.preferredHeight: 26 radius: 6 color: netMouse.containsMouse ? Theme.currentLine : "transparent" Behavior on color { ColorAnimation { duration: 120 } } NetworkIcon { anchors.centerIn: parent isConnected: NetworkService.isConnected signalPercent: NetworkService.signalPercent isEthernet: NetworkService.ethernetConnected isWifiPowered: NetworkService.isWifiPowered width: 16 height: 16 } MouseArea { id: netMouse anchors.fill: parent hoverEnabled: true onClicked: { NetworkService.scanWifi() PopupService.toggleNetwork() } } } // Battery Icon Snippet (Icon-only, Clickable) Rectangle { id: batBtn Layout.preferredWidth: 26 Layout.preferredHeight: 26 radius: 6 color: batMouse.containsMouse ? Theme.currentLine : "transparent" Behavior on color { ColorAnimation { duration: 120 } } BatteryIcon { anchors.centerIn: parent percentage: BatteryService.percentage isCharging: BatteryService.isCharging width: 16 height: 16 } MouseArea { id: batMouse anchors.fill: parent hoverEnabled: true onClicked: PopupService.toggleBattery() } } } // Screenshot & Screen Recording Control Detached Popup Window PopupWindow { id: captureMenu anchor.window: window anchor.rect.x: Math.round(root.x + root.width - implicitWidth) anchor.rect.y: 40 anchor.edges: Edges.Bottom | Edges.Right visible: PopupService.captureMenuOpen color: "transparent" implicitWidth: capGlass.implicitWidth implicitHeight: capGlass.implicitHeight GlassPanel { id: capGlass implicitWidth: 280 implicitHeight: Math.min(420, capCardLayout.implicitHeight + 24) anchors.fill: parent ColumnLayout { id: capCardLayout anchors.fill: parent anchors.margins: 12 spacing: 10 // Header Text { text: "Screen Capture & Recording" color: Theme.fg font.pixelSize: 12 font.weight: Font.Bold } // Solid Divider Rectangle { Layout.fillWidth: true Layout.preferredHeight: 1 color: Theme.currentLine } // Section 1: Screenshots Text { text: "TAKE SCREENSHOT" color: Theme.comment font.pixelSize: 9 font.weight: Font.Bold } ColumnLayout { Layout.fillWidth: true spacing: 4 // 1. Region / Selection Screenshot Rectangle { Layout.fillWidth: true Layout.preferredHeight: 28 radius: 5 color: regShotMouse.containsMouse ? Theme.currentLine : (Theme.isDark ? Theme.currentLine : Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.08)) border.color: Theme.currentLine border.width: 1 RowLayout { anchors.fill: parent anchors.leftMargin: 10 anchors.rightMargin: 10 spacing: 8 Text { text: "✂️"; font.pixelSize: 11; Layout.alignment: Qt.AlignVCenter } Text { text: "Region Screenshot"; color: Theme.fg; font.pixelSize: 10; font.weight: Font.Medium; Layout.fillWidth: true } Text { text: "Super+Shift+S"; color: Theme.comment; font.pixelSize: 8 } } MouseArea { id: regShotMouse anchors.fill: parent hoverEnabled: true onClicked: { PopupService.closeAll() CaptureService.captureRegion() } } } // 2. Fullscreen Screenshot Rectangle { Layout.fillWidth: true Layout.preferredHeight: 28 radius: 5 color: fullShotMouse.containsMouse ? Theme.currentLine : (Theme.isDark ? Theme.currentLine : Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.08)) border.color: Theme.currentLine border.width: 1 RowLayout { anchors.fill: parent anchors.leftMargin: 10 anchors.rightMargin: 10 spacing: 8 Text { text: "🖥️"; font.pixelSize: 11; Layout.alignment: Qt.AlignVCenter } Text { text: "Fullscreen Screenshot"; color: Theme.fg; font.pixelSize: 10; font.weight: Font.Medium; Layout.fillWidth: true } Text { text: "PrintScreen"; color: Theme.comment; font.pixelSize: 8 } } MouseArea { id: fullShotMouse anchors.fill: parent hoverEnabled: true onClicked: { PopupService.closeAll() CaptureService.captureFullscreen() } } } // 3. Active Window Screenshot Rectangle { Layout.fillWidth: true Layout.preferredHeight: 28 radius: 5 color: winShotMouse.containsMouse ? Theme.currentLine : (Theme.isDark ? Theme.currentLine : Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.08)) border.color: Theme.currentLine border.width: 1 RowLayout { anchors.fill: parent anchors.leftMargin: 10 anchors.rightMargin: 10 spacing: 8 Text { text: "🪟"; font.pixelSize: 11; Layout.alignment: Qt.AlignVCenter } Text { text: "Active Window"; color: Theme.fg; font.pixelSize: 10; font.weight: Font.Medium; Layout.fillWidth: true } Text { text: "Super+Print"; color: Theme.comment; font.pixelSize: 8 } } MouseArea { id: winShotMouse anchors.fill: parent hoverEnabled: true onClicked: { PopupService.closeAll() CaptureService.captureWindow() } } } } // Solid Divider Rectangle { Layout.fillWidth: true Layout.preferredHeight: 1 color: Theme.currentLine } // Section 2: Screen Recording Text { text: "RECORD VIDEO" color: Theme.comment font.pixelSize: 9 font.weight: Font.Bold } ColumnLayout { Layout.fillWidth: true spacing: 4 // 4. Region Screen Recording Rectangle { Layout.fillWidth: true Layout.preferredHeight: 28 radius: 5 color: regRecMouse.containsMouse ? Theme.currentLine : (Theme.isDark ? Theme.currentLine : Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.08)) border.color: Theme.currentLine border.width: 1 RowLayout { anchors.fill: parent anchors.leftMargin: 10 anchors.rightMargin: 10 spacing: 8 Text { text: "🎥"; font.pixelSize: 11; Layout.alignment: Qt.AlignVCenter } Text { text: "Record Region"; color: Theme.fg; font.pixelSize: 10; font.weight: Font.Medium; Layout.fillWidth: true } Text { text: "Super+Alt+R"; color: Theme.comment; font.pixelSize: 8 } } MouseArea { id: regRecMouse anchors.fill: parent hoverEnabled: true onClicked: { PopupService.closeAll() CaptureService.recordRegion() } } } // 5. Fullscreen Screen Recording Rectangle { Layout.fillWidth: true Layout.preferredHeight: 28 radius: 5 color: fullRecMouse.containsMouse ? Theme.currentLine : (Theme.isDark ? Theme.currentLine : Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.08)) border.color: Theme.currentLine border.width: 1 RowLayout { anchors.fill: parent anchors.leftMargin: 10 anchors.rightMargin: 10 spacing: 8 Text { text: "📽️"; font.pixelSize: 11; Layout.alignment: Qt.AlignVCenter } Text { text: "Record Screen"; color: Theme.fg; font.pixelSize: 10; font.weight: Font.Medium; Layout.fillWidth: true } Text { text: "Super+Alt+F"; color: Theme.comment; font.pixelSize: 8 } } MouseArea { id: fullRecMouse anchors.fill: parent hoverEnabled: true onClicked: { PopupService.closeAll() CaptureService.recordScreen() } } } } // Solid Divider Rectangle { Layout.fillWidth: true Layout.preferredHeight: 1 color: Theme.currentLine } // Section 3: Open Spectacle Full GUI Utility (Text Only) Rectangle { Layout.fillWidth: true Layout.preferredHeight: 28 radius: 5 color: guiBtnMouse.containsMouse ? Theme.currentLine : "transparent" border.color: Theme.accent border.width: 1 Text { anchors.centerIn: parent text: "Open Spectacle Studio" color: Theme.accent font.pixelSize: 10 font.weight: Font.Bold } MouseArea { id: guiBtnMouse anchors.fill: parent hoverEnabled: true onClicked: { PopupService.closeAll() Quickshell.execDetached(["spectacle", "-g"]) } } } } } } // Detached Notification Center Popup Window (Controlled by PopupService) PopupWindow { id: notifMenu anchor.window: window anchor.rect.x: root.x + (root.width / 2) - (implicitWidth / 2) anchor.rect.y: 42 anchor.edges: Edges.Bottom visible: PopupService.notificationMenuOpen color: "transparent" implicitWidth: notifGlass.implicitWidth implicitHeight: notifGlass.implicitHeight GlassPanel { id: notifGlass implicitWidth: 320 implicitHeight: notifLayout.implicitHeight + 20 anchors.fill: parent ColumnLayout { id: notifLayout anchors.fill: parent anchors.margins: 10 spacing: 8 // Header with DND Toggle & Clear All RowLayout { Layout.fillWidth: true Text { text: "Notifications" color: Theme.fg font.pixelSize: 12 font.weight: Font.Bold } Item { Layout.fillWidth: true } // DND Toggle Button Rectangle { width: 58; height: 20; radius: 4 color: NotificationService.isDnd ? Qt.rgba(Theme.subAccent.r, Theme.subAccent.g, Theme.subAccent.b, 0.2) : (dndBtnMouse.containsMouse ? Theme.currentLine : (Theme.isDark ? Theme.currentLine : Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.08))) border.color: NotificationService.isDnd ? Theme.subAccent : Theme.currentLine border.width: 1 Text { anchors.centerIn: parent text: NotificationService.isDnd ? "DND: ON" : "DND: OFF" color: NotificationService.isDnd ? Theme.subAccent : Theme.comment font.pixelSize: 9 font.weight: Font.Bold } MouseArea { id: dndBtnMouse anchors.fill: parent hoverEnabled: true onClicked: NotificationService.toggleDnd() } } Rectangle { width: 50; height: 20; radius: 4 color: clearNotifMouse.containsMouse ? Qt.rgba(255/255, 85/255, 85/255, 0.2) : "transparent" border.color: Theme.red border.width: 1 Text { anchors.centerIn: parent text: "Clear" color: Theme.red font.pixelSize: 9 font.weight: Font.Bold } MouseArea { id: clearNotifMouse anchors.fill: parent hoverEnabled: true onClicked: NotificationService.clearAll() } } } // Solid Divider Rectangle { Layout.fillWidth: true Layout.preferredHeight: 1 color: Theme.currentLine } // Scrollable List of Notifications Flickable { Layout.fillWidth: true Layout.preferredHeight: Math.min(380, notifListCol.implicitHeight) contentHeight: notifListCol.implicitHeight clip: true ColumnLayout { id: notifListCol width: parent.width spacing: 6 // Empty State Text { text: NotificationService.isDnd ? "Do Not Disturb is active" : "No new notifications" color: Theme.comment font.pixelSize: 10 font.italic: true visible: NotificationService.notifications.length === 0 Layout.alignment: Qt.AlignHCenter Layout.topMargin: 4 Layout.bottomMargin: 4 } Repeater { model: NotificationService.notifications Rectangle { Layout.fillWidth: true implicitHeight: notifItemCol.implicitHeight + 12 radius: 6 color: Theme.surface border.color: Theme.currentLine border.width: 1 ColumnLayout { id: notifItemCol anchors.fill: parent anchors.margins: 8 spacing: 4 RowLayout { Layout.fillWidth: true // Dynamically Sized App Source Badge Box Rectangle { implicitWidth: appText.implicitWidth + 12 implicitHeight: 18 radius: 4 color: Qt.rgba(Theme.accent.r, Theme.accent.g, Theme.accent.b, 0.18) border.color: Theme.accent border.width: 1 Text { id: appText anchors.centerIn: parent text: modelData.app.toUpperCase() color: Theme.accent font.pixelSize: 8 font.weight: Font.Bold } } Item { Layout.fillWidth: true } Text { text: modelData.time color: Theme.comment font.pixelSize: 9 } Text { text: "✕" color: delNotifMouse.containsMouse ? Theme.red : Theme.comment font.pixelSize: 10 MouseArea { id: delNotifMouse anchors.fill: parent hoverEnabled: true onClicked: NotificationService.dismissNotification(modelData.id) } } } Text { text: modelData.summary color: Theme.fg font.pixelSize: 11 font.weight: Font.Bold elide: Text.ElideRight Layout.fillWidth: true } Text { text: modelData.body color: Theme.comment font.pixelSize: 10 maximumLineCount: 3 wrapMode: Text.WrapAnywhere elide: Text.ElideRight visible: modelData.body !== "" Layout.fillWidth: true } } } } } } } } } // Clipboard Manager Detached Popup Window PopupWindow { id: clipboardMenu anchor.window: window anchor.rect.x: Math.round(root.x + root.width - implicitWidth) anchor.rect.y: 40 anchor.edges: Edges.Bottom | Edges.Right visible: PopupService.clipboardMenuOpen color: "transparent" implicitWidth: clipGlass.implicitWidth implicitHeight: clipGlass.implicitHeight GlassPanel { id: clipGlass implicitWidth: 320 implicitHeight: Math.min(500, clipCardLayout.implicitHeight + 24) anchors.fill: parent ColumnLayout { id: clipCardLayout anchors.fill: parent anchors.margins: 12 spacing: 10 // Header RowLayout { Layout.fillWidth: true Text { text: "Clipboard Manager" color: Theme.fg font.pixelSize: 12 font.weight: Font.Bold } Item { Layout.fillWidth: true } Rectangle { width: 54; height: 20; radius: 4 color: clearClipMouse.containsMouse ? Qt.rgba(255/255, 85/255, 85/255, 0.2) : "transparent" border.color: Theme.red border.width: 1 Text { anchors.centerIn: parent text: "Clear" color: Theme.red font.pixelSize: 9 font.weight: Font.Bold } MouseArea { id: clearClipMouse anchors.fill: parent hoverEnabled: true onClicked: ClipboardService.clearAll() } } } // Solid Divider Rectangle { Layout.fillWidth: true Layout.preferredHeight: 1 color: Theme.currentLine } // Scrollable List of Clipboard Items Flickable { Layout.fillWidth: true Layout.preferredHeight: Math.min(380, clipListCol.implicitHeight) contentHeight: clipListCol.implicitHeight clip: true ColumnLayout { id: clipListCol width: parent.width spacing: 6 // Empty State Text { text: "Clipboard is empty" color: Theme.comment font.pixelSize: 10 font.italic: true visible: ClipboardService.items.length === 0 Layout.alignment: Qt.AlignHCenter Layout.topMargin: 4 Layout.bottomMargin: 4 } Repeater { model: ClipboardService.items Rectangle { Layout.fillWidth: true implicitHeight: itemColLayout.implicitHeight + 12 radius: 6 color: clipItemMouse.containsMouse ? Theme.currentLine : Theme.surface border.color: Theme.currentLine border.width: 1 ColumnLayout { id: itemColLayout anchors.fill: parent anchors.margins: 8 spacing: 6 RowLayout { Layout.fillWidth: true Rectangle { width: 48; height: 16; radius: 3 color: modelData.type === "image" ? Qt.rgba(Theme.subAccent.r, Theme.subAccent.g, Theme.subAccent.b, 0.2) : Qt.rgba(Theme.accent.r, Theme.accent.g, Theme.accent.b, 0.2) Text { anchors.centerIn: parent text: modelData.type === "image" ? "IMAGE" : "TEXT" color: modelData.type === "image" ? Theme.subAccent : Theme.accent font.pixelSize: 8 font.weight: Font.Bold } } Text { text: modelData.type === "image" ? modelData.size : (modelData.length + " chars") color: Theme.comment font.pixelSize: 9 } Item { Layout.fillWidth: true } Text { text: modelData.time color: Theme.comment font.pixelSize: 9 } Text { text: "✕" color: delMouse.containsMouse ? Theme.red : Theme.comment font.pixelSize: 10 MouseArea { id: delMouse anchors.fill: parent hoverEnabled: true onClicked: ClipboardService.deleteEntry(modelData.id) } } } Image { visible: modelData.type === "image" source: modelData.type === "image" ? ("file://" + modelData.path) : "" Layout.fillWidth: true Layout.preferredHeight: 100 fillMode: Image.PreserveAspectFit horizontalAlignment: Image.AlignLeft } Text { visible: modelData.type === "text" text: modelData.type === "text" ? modelData.content : "" color: Theme.fg font.pixelSize: 10 maximumLineCount: 4 wrapMode: Text.WrapAnywhere elide: Text.ElideRight Layout.fillWidth: true } } MouseArea { id: clipItemMouse anchors.fill: parent hoverEnabled: true onClicked: { ClipboardService.copyEntry(modelData.id) PopupService.closeAll() } } } } } } } } } // Bluetooth Control Detached Popup Window PopupWindow { id: bluetoothMenu anchor.window: window anchor.rect.x: Math.round(root.x + root.width - implicitWidth) anchor.rect.y: 40 anchor.edges: Edges.Bottom | Edges.Right visible: PopupService.bluetoothMenuOpen color: "transparent" implicitWidth: btGlass.implicitWidth implicitHeight: btGlass.implicitHeight GlassPanel { id: btGlass implicitWidth: 300 implicitHeight: BluetoothService.isPowered ? 240 : 80 anchors.fill: parent ColumnLayout { id: btCardLayout anchors.fill: parent anchors.margins: 12 spacing: 10 // Header: Title + Power Toggle + Refresh Button RowLayout { Layout.fillWidth: true Text { text: "Bluetooth" color: Theme.fg font.pixelSize: 12 font.weight: Font.Bold } Item { Layout.fillWidth: true } // Power ON/OFF Button Rectangle { width: 50; height: 20; radius: 4 color: BluetoothService.isPowered ? (Theme.isDark ? Qt.rgba(80/255, 250/255, 123/255, 0.2) : Qt.rgba(34/255, 197/255, 94/255, 0.25)) : (Theme.isDark ? Qt.rgba(255/255, 85/255, 85/255, 0.2) : Qt.rgba(239/255, 68/255, 68/255, 0.25)) border.color: BluetoothService.isPowered ? (Theme.isDark ? Theme.green : "#15803d") : (Theme.isDark ? Theme.red : "#b91c1c") border.width: 1 Text { anchors.centerIn: parent text: BluetoothService.isPowered ? "ON" : "OFF" color: BluetoothService.isPowered ? (Theme.isDark ? Theme.green : "#15803d") : (Theme.isDark ? Theme.red : "#b91c1c") font.pixelSize: 9 font.weight: Font.Bold } MouseArea { id: btPwrMouse anchors.fill: parent hoverEnabled: true onClicked: BluetoothService.togglePower() } } Rectangle { width: 20; height: 20; radius: 4 color: refreshBtMouse.containsMouse ? Theme.currentLine : "transparent" Text { text: "↻"; color: Theme.comment; font.pixelSize: 12; anchors.centerIn: parent } MouseArea { id: refreshBtMouse anchors.fill: parent hoverEnabled: true onClicked: BluetoothService.scanBluetooth() } } } // Solid Divider Rectangle { Layout.fillWidth: true Layout.preferredHeight: 1 color: Theme.currentLine } // Off State Banner Item { Layout.fillWidth: true Layout.fillHeight: true visible: !BluetoothService.isPowered Text { anchors.centerIn: parent text: "Bluetooth is turned off" color: Theme.comment font.pixelSize: 11 font.italic: true } } Flickable { Layout.fillWidth: true Layout.fillHeight: true contentHeight: btScrollCol.implicitHeight clip: true visible: BluetoothService.isPowered ColumnLayout { id: btScrollCol width: parent.width spacing: 8 // Connected Devices Section Text { text: "CONNECTED DEVICES" color: Theme.comment font.pixelSize: 9 font.weight: Font.Bold } ColumnLayout { Layout.fillWidth: true spacing: 3 Text { text: "No connected devices" color: Theme.comment font.pixelSize: 10 font.italic: true visible: BluetoothService.connectedDevices.length === 0 } Repeater { model: BluetoothService.connectedDevices Rectangle { Layout.fillWidth: true Layout.preferredHeight: 28 radius: 5 color: Qt.rgba(Theme.accent.r, Theme.accent.g, Theme.accent.b, 0.18) border.color: Theme.accent border.width: 1 RowLayout { anchors.fill: parent anchors.leftMargin: 8 anchors.rightMargin: 8 spacing: 6 Rectangle { width: 6; height: 6; radius: 3; color: Theme.accent } Text { text: modelData.name color: Theme.accent font.pixelSize: 10 font.weight: Font.Bold elide: Text.ElideRight Layout.fillWidth: true } Rectangle { width: 58; height: 18; radius: 3 color: disconnMouse.containsMouse ? Theme.currentLine : "transparent" border.color: Theme.red border.width: 1 Text { anchors.centerIn: parent text: "Disconnect" color: Theme.red font.pixelSize: 8 font.weight: Font.Bold } MouseArea { id: disconnMouse anchors.fill: parent hoverEnabled: true onClicked: BluetoothService.disconnectDevice(modelData.mac) } } } } } } // Available / Paired Devices Section Text { text: "AVAILABLE / PAIRED DEVICES" color: Theme.comment font.pixelSize: 9 font.weight: Font.Bold } ColumnLayout { Layout.fillWidth: true spacing: 3 Text { text: "No available devices" color: Theme.comment font.pixelSize: 10 font.italic: true visible: BluetoothService.availableDevices.length === 0 } Repeater { model: BluetoothService.availableDevices Rectangle { Layout.fillWidth: true Layout.preferredHeight: 28 radius: 5 color: btDevMouse.containsMouse ? Theme.currentLine : "transparent" RowLayout { anchors.fill: parent anchors.leftMargin: 8 anchors.rightMargin: 8 spacing: 6 Rectangle { width: 6; height: 6; radius: 3; color: Theme.comment } Text { text: modelData.name color: Theme.fg font.pixelSize: 10 elide: Text.ElideRight Layout.fillWidth: true } Rectangle { width: 46; height: 18; radius: 3 color: connMouse.containsMouse ? Qt.rgba(Theme.accent.r, Theme.accent.g, Theme.accent.b, 0.2) : "transparent" border.color: Theme.accent border.width: 1 Text { anchors.centerIn: parent text: "Connect" color: Theme.accent font.pixelSize: 8 font.weight: Font.Bold } MouseArea { id: connMouse anchors.fill: parent hoverEnabled: true onClicked: BluetoothService.connectDevice(modelData.mac) } } } MouseArea { id: btDevMouse anchors.fill: parent hoverEnabled: true } } } } } } } } } // Audio Control & Device Selector Detached Popup Window PopupWindow { id: audioMenu anchor.window: window anchor.rect.x: Math.round(root.x + root.width - implicitWidth) anchor.rect.y: 40 anchor.edges: Edges.Bottom | Edges.Right visible: PopupService.audioMenuOpen color: "transparent" implicitWidth: audioGlass.implicitWidth implicitHeight: audioGlass.implicitHeight GlassPanel { id: audioGlass implicitWidth: 300 implicitHeight: Math.min(480, audioCardLayout.implicitHeight + 24) anchors.fill: parent ColumnLayout { id: audioCardLayout anchors.fill: parent anchors.margins: 12 spacing: 10 // Card Header: Volume Title + Percentage RowLayout { Layout.fillWidth: true Text { text: "Master Volume" color: Theme.fg font.pixelSize: 12 font.weight: Font.Bold } Item { Layout.fillWidth: true } Text { text: AudioService.volumeStr color: Theme.accent font.pixelSize: 11 font.weight: Font.Bold } } // Volume Slider Track Item { id: volSliderTrack Layout.fillWidth: true Layout.preferredHeight: 16 property bool isDragging: volSliderMouse.pressed Rectangle { anchors.centerIn: parent width: parent.width height: 4 radius: 2 color: Theme.currentLine Rectangle { width: Math.max(4, parent.width * (AudioService.volume / 100.0)) height: parent.height radius: 2 color: AudioService.isMuted ? Theme.red : Theme.accent } } // Circle Slider Knob Handle Rectangle { width: volSliderMouse.containsMouse || volSliderTrack.isDragging ? 12 : 8 height: width radius: width / 2 color: AudioService.isMuted ? Theme.red : Theme.accent border.color: Theme.bg border.width: 1 anchors.verticalCenter: parent.verticalCenter x: Math.max(0, Math.min(volSliderTrack.width - width, (volSliderTrack.width * (AudioService.volume / 100.0)) - (width / 2))) } MouseArea { id: volSliderMouse anchors.fill: parent hoverEnabled: true onPositionChanged: (mouse) => { if (pressed) { var ratio = Math.max(0.0, Math.min(1.0, mouse.x / width)) AudioService.setVolume(ratio * 100) } } onPressed: (mouse) => { var ratio = Math.max(0.0, Math.min(1.0, mouse.x / width)) AudioService.setVolume(ratio * 100) } } } // Mute Toggle Button Rectangle { Layout.fillWidth: true Layout.preferredHeight: 26 radius: 5 color: muteBtnMouse.containsMouse ? Theme.currentLine : (Theme.isDark ? Theme.currentLine : Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.08)) border.color: Theme.currentLine border.width: 1 RowLayout { anchors.centerIn: parent spacing: 6 VolumeIcon { volume: AudioService.volume isMuted: AudioService.isMuted width: 14 height: 14 } Text { text: AudioService.isMuted ? "Unmute Audio" : "Mute Audio" color: AudioService.isMuted ? Theme.red : Theme.fg font.pixelSize: 10 font.weight: Font.Medium } } MouseArea { id: muteBtnMouse anchors.fill: parent hoverEnabled: true onClicked: AudioService.toggleMute() } } // Solid Divider Rectangle { Layout.fillWidth: true Layout.preferredHeight: 1 color: Theme.currentLine } Flickable { Layout.fillWidth: true Layout.preferredHeight: Math.min(320, audioScrollCol.implicitHeight) contentHeight: audioScrollCol.implicitHeight clip: true ColumnLayout { id: audioScrollCol width: parent.width spacing: 8 // Output Devices Section Text { text: "OUTPUT DEVICES" color: Theme.comment font.pixelSize: 9 font.weight: Font.Bold } ColumnLayout { Layout.fillWidth: true spacing: 3 Repeater { model: AudioService.sinks Rectangle { Layout.fillWidth: true Layout.preferredHeight: 24 radius: 4 color: modelData.isActive ? Qt.rgba(Theme.accent.r, Theme.accent.g, Theme.accent.b, 0.18) : (sinkItemMouse.containsMouse ? Theme.surface : "transparent") border.color: modelData.isActive ? Theme.accent : "transparent" border.width: 1 RowLayout { anchors.fill: parent anchors.leftMargin: 6 anchors.rightMargin: 6 spacing: 6 Rectangle { width: 6; height: 6; radius: 3 color: modelData.isActive ? Theme.accent : Theme.comment } Text { text: modelData.name color: modelData.isActive ? (Theme.isDark ? Theme.accent : Theme.fg) : Theme.fg font.pixelSize: 10 font.weight: modelData.isActive ? Font.Bold : Font.Normal elide: Text.ElideRight Layout.fillWidth: true } } MouseArea { id: sinkItemMouse anchors.fill: parent hoverEnabled: true onClicked: AudioService.setDefaultDevice(modelData.id) } } } } // Solid Divider Rectangle { Layout.fillWidth: true Layout.preferredHeight: 1 color: Theme.currentLine } // Input Devices Section Text { text: "INPUT DEVICES" color: Theme.comment font.pixelSize: 9 font.weight: Font.Bold } ColumnLayout { Layout.fillWidth: true spacing: 3 Repeater { model: AudioService.sources Rectangle { Layout.fillWidth: true Layout.preferredHeight: 24 radius: 4 color: modelData.isActive ? Qt.rgba(Theme.accent.r, Theme.accent.g, Theme.accent.b, 0.18) : (srcItemMouse.containsMouse ? Theme.surface : "transparent") border.color: modelData.isActive ? Theme.accent : "transparent" border.width: 1 RowLayout { anchors.fill: parent anchors.leftMargin: 6 anchors.rightMargin: 6 spacing: 6 Rectangle { width: 6; height: 6; radius: 3 color: modelData.isActive ? Theme.accent : Theme.comment } Text { text: modelData.name color: modelData.isActive ? Theme.accent : Theme.fg font.pixelSize: 10 font.weight: modelData.isActive ? Font.Bold : Font.Normal elide: Text.ElideRight Layout.fillWidth: true } } MouseArea { id: srcItemMouse anchors.fill: parent hoverEnabled: true onClicked: AudioService.setDefaultDevice(modelData.id) } } } } } } } } } // Screen & Backlight Brightness Control Detached Popup Window PopupWindow { id: brightMenu anchor.window: window anchor.rect.x: Math.round(root.x + root.width - implicitWidth) anchor.rect.y: 40 anchor.edges: Edges.Bottom | Edges.Right visible: PopupService.brightnessMenuOpen color: "transparent" implicitWidth: brightGlass.implicitWidth implicitHeight: brightGlass.implicitHeight GlassPanel { id: brightGlass implicitWidth: 300 implicitHeight: Math.min(400, brightCardLayout.implicitHeight + 24) anchors.fill: parent ColumnLayout { id: brightCardLayout anchors.fill: parent anchors.margins: 12 spacing: 12 // Card Header: Title + Refresh Button RowLayout { Layout.fillWidth: true Text { text: "Brightness Controls" color: Theme.fg font.pixelSize: 12 font.weight: Font.Bold } Item { Layout.fillWidth: true } Rectangle { width: 20; height: 20; radius: 4 color: refreshBrightMouse.containsMouse ? Theme.currentLine : "transparent" Text { text: "↻"; color: Theme.comment; font.pixelSize: 12; anchors.centerIn: parent } MouseArea { id: refreshBrightMouse anchors.fill: parent hoverEnabled: true onClicked: BrightnessService.scanDevices() } } } // Solid Divider Rectangle { Layout.fillWidth: true Layout.preferredHeight: 1 color: Theme.currentLine } Flickable { Layout.fillWidth: true Layout.preferredHeight: Math.min(300, brightScrollCol.implicitHeight) contentHeight: brightScrollCol.implicitHeight clip: true ColumnLayout { id: brightScrollCol width: parent.width spacing: 12 Repeater { model: BrightnessService.devices ColumnLayout { Layout.fillWidth: true spacing: 4 // Device Label & Percentage Readout RowLayout { Layout.fillWidth: true BrightnessIcon { brightness: Math.round(devSliderTrack.currentPct) width: 14 height: 14 } Text { text: modelData.name color: Theme.fg font.pixelSize: 10 font.weight: Font.Bold elide: Text.ElideRight Layout.fillWidth: true } Text { text: Math.round(devSliderTrack.currentPct) + "%" color: modelData.type === "kbd" ? Theme.subAccent : Theme.accent font.pixelSize: 10 font.weight: Font.Bold } } // Independent Device Brightness Slider Track Item { id: devSliderTrack Layout.fillWidth: true Layout.preferredHeight: 16 property real currentPct: modelData.brightness Component.onCompleted: { currentPct = modelData.brightness } Rectangle { anchors.centerIn: parent width: parent.width height: 4 radius: 2 color: Theme.currentLine Rectangle { width: Math.max(4, parent.width * (devSliderTrack.currentPct / 100.0)) height: parent.height radius: 2 color: modelData.type === "kbd" ? Theme.subAccent : Theme.accent } } // Slider Knob Handle Rectangle { width: devSliderMouse.containsMouse || devSliderMouse.pressed ? 12 : 8 height: width radius: width / 2 color: modelData.type === "kbd" ? Theme.subAccent : Theme.accent border.color: Theme.bg border.width: 1 anchors.verticalCenter: parent.verticalCenter x: Math.max(0, Math.min(devSliderTrack.width - width, (devSliderTrack.width * (devSliderTrack.currentPct / 100.0)) - (width / 2))) } MouseArea { id: devSliderMouse anchors.fill: parent hoverEnabled: true function updatePos(mx) { var ratio = Math.max(0.0, Math.min(1.0, mx / width)) var val = Math.round(ratio * 100) devSliderTrack.currentPct = val BrightnessService.setDeviceBrightness(modelData.id, val) } onPressed: (mouse) => updatePos(mouse.x) onPositionChanged: (mouse) => { if (pressed) updatePos(mouse.x) } } } } } } } } } } // External Storage Mount Control Detached Popup Window PopupWindow { id: mountMenu anchor.window: window anchor.rect.x: Math.round(root.x + root.width - implicitWidth) anchor.rect.y: 40 anchor.edges: Edges.Bottom | Edges.Right visible: PopupService.mountMenuOpen color: "transparent" implicitWidth: mountGlass.implicitWidth implicitHeight: mountGlass.implicitHeight GlassPanel { id: mountGlass implicitWidth: 320 implicitHeight: Math.min(480, mountCardLayout.implicitHeight + 24) anchors.fill: parent ColumnLayout { id: mountCardLayout anchors.fill: parent anchors.margins: 12 spacing: 10 // Header RowLayout { Layout.fillWidth: true Text { text: "External Storage" color: Theme.fg font.pixelSize: 12 font.weight: Font.Bold } Item { Layout.fillWidth: true } Rectangle { width: 20; height: 20; radius: 4 color: refreshMountMouse.containsMouse ? Theme.currentLine : "transparent" Text { text: "↻"; color: Theme.comment; font.pixelSize: 12; anchors.centerIn: parent } MouseArea { id: refreshMountMouse anchors.fill: parent hoverEnabled: true onClicked: MountService.scanDevices() } } } // Solid Divider Rectangle { Layout.fillWidth: true Layout.preferredHeight: 1 color: Theme.currentLine } Flickable { Layout.fillWidth: true Layout.preferredHeight: Math.min(360, mountScrollCol.implicitHeight) contentHeight: mountScrollCol.implicitHeight clip: true ColumnLayout { id: mountScrollCol width: parent.width spacing: 8 Repeater { model: MountService.devices Rectangle { Layout.fillWidth: true implicitHeight: devItemCol.implicitHeight + 14 radius: 6 color: modelData.isMounted ? (Theme.isDark ? Qt.rgba(80/255, 250/255, 123/255, 0.1) : Qt.rgba(80/255, 250/255, 123/255, 0.18)) : Theme.surface border.color: modelData.isMounted ? (Theme.isDark ? Theme.green : "#15803d") : Theme.currentLine border.width: 1 ColumnLayout { id: devItemCol anchors.fill: parent anchors.margins: 7 spacing: 6 // Device Title & Mounted Status Dot RowLayout { Layout.fillWidth: true Rectangle { width: 6; height: 6; radius: 3 color: modelData.isMounted ? (Theme.isDark ? Theme.green : "#15803d") : Theme.comment } Text { text: modelData.label + " (" + modelData.size + ")" color: modelData.isMounted ? (Theme.isDark ? Theme.green : "#15803d") : Theme.fg font.pixelSize: 10 font.weight: Font.Bold elide: Text.ElideRight Layout.fillWidth: true } Text { text: modelData.isMounted ? "Mounted" : "Unmounted" color: modelData.isMounted ? (Theme.isDark ? Theme.green : "#15803d") : Theme.comment font.pixelSize: 9 } } Text { text: modelData.vendor color: Theme.comment font.pixelSize: 9 elide: Text.ElideRight visible: modelData.vendor !== "" } // 3 Action Buttons: [ Mount / Unmount ] | [ Mount & Open ] | [ Auto-Mount ] RowLayout { Layout.fillWidth: true spacing: 4 // Button 1: Mount / Unmount Rectangle { Layout.fillWidth: true Layout.preferredHeight: 22 radius: 4 color: mntBtnMouse.containsMouse ? Theme.currentLine : (Theme.isDark ? Theme.currentLine : Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.08)) border.color: Theme.currentLine border.width: 1 Text { anchors.centerIn: parent text: modelData.isMounted ? "Unmount" : "Mount" color: modelData.isMounted ? Theme.red : Theme.accent font.pixelSize: 9 font.weight: Font.Bold } MouseArea { id: mntBtnMouse anchors.fill: parent hoverEnabled: true onClicked: MountService.toggleMount(modelData.dev, modelData.isMounted) } } // Button 2: Mount & Open Rectangle { Layout.fillWidth: true Layout.preferredHeight: 22 radius: 4 color: openBtnMouse.containsMouse ? Theme.currentLine : (Theme.isDark ? Theme.currentLine : Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.08)) border.color: Theme.currentLine border.width: 1 Text { anchors.centerIn: parent text: "Mount & Open" color: Theme.subAccent font.pixelSize: 9 font.weight: Font.Bold } MouseArea { id: openBtnMouse anchors.fill: parent hoverEnabled: true onClicked: MountService.mountAndOpen(modelData.dev) } } // Button 3: Auto-Mount Toggle Rectangle { id: autoToggleBtn Layout.fillWidth: true Layout.preferredHeight: 22 radius: 4 property bool autoOn: MountService.autoMountMap[modelData.dev] === true color: autoOn ? Qt.rgba(80/255, 250/255, 123/255, 0.2) : (autoBtnMouse.containsMouse ? Theme.currentLine : (Theme.isDark ? Theme.currentLine : Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.08))) border.color: autoOn ? (Theme.isDark ? Theme.green : "#15803d") : Theme.currentLine border.width: 1 Text { anchors.centerIn: parent text: autoToggleBtn.autoOn ? "Auto: ON" : "Auto: OFF" color: autoToggleBtn.autoOn ? (Theme.isDark ? Theme.green : "#15803d") : Theme.comment font.pixelSize: 9 font.weight: Font.Bold } MouseArea { id: autoBtnMouse anchors.fill: parent hoverEnabled: true onClicked: MountService.toggleAutoMount(modelData.dev) } } } } } } } } } } } // Network Details Popup Window PopupWindow { id: netMenu anchor.window: window anchor.rect.x: Math.round(root.x + root.width - implicitWidth) anchor.rect.y: 40 anchor.edges: Edges.Bottom | Edges.Right visible: PopupService.networkMenuOpen color: "transparent" implicitWidth: netGlass.implicitWidth implicitHeight: netGlass.implicitHeight GlassPanel { id: netGlass implicitWidth: 300 implicitHeight: NetworkService.isWifiPowered ? 240 : 80 anchors.fill: parent ColumnLayout { id: netCardLayout anchors.fill: parent anchors.margins: 12 spacing: 8 // Header RowLayout { Layout.fillWidth: true Text { text: "Wi-Fi Networks" color: Theme.fg font.pixelSize: 12 font.weight: Font.Bold } Item { Layout.fillWidth: true } // Wi-Fi Power ON/OFF Toggle Button Rectangle { width: 50; height: 20; radius: 4 color: NetworkService.isWifiPowered ? (Theme.isDark ? Qt.rgba(80/255, 250/255, 123/255, 0.2) : Qt.rgba(34/255, 197/255, 94/255, 0.25)) : (Theme.isDark ? Qt.rgba(255/255, 85/255, 85/255, 0.2) : Qt.rgba(239/255, 68/255, 68/255, 0.25)) border.color: NetworkService.isWifiPowered ? (Theme.isDark ? Theme.green : "#15803d") : (Theme.isDark ? Theme.red : "#b91c1c") border.width: 1 Text { anchors.centerIn: parent text: NetworkService.isWifiPowered ? "ON" : "OFF" color: NetworkService.isWifiPowered ? (Theme.isDark ? Theme.green : "#15803d") : (Theme.isDark ? Theme.red : "#b91c1c") font.pixelSize: 9 font.weight: Font.Bold } MouseArea { id: wifiPwrMouse anchors.fill: parent hoverEnabled: true onClicked: NetworkService.toggleWifiPower() } } Rectangle { width: 20; height: 20; radius: 4 color: refreshNetMouse.containsMouse ? Theme.currentLine : "transparent" Text { text: "↻"; color: Theme.comment; font.pixelSize: 12; anchors.centerIn: parent } MouseArea { id: refreshNetMouse anchors.fill: parent hoverEnabled: true onClicked: NetworkService.scanWifi() } } } // Solid Divider Rectangle { Layout.fillWidth: true Layout.preferredHeight: 1 color: Theme.currentLine } // 1. Ethernet Card Rectangle { Layout.fillWidth: true implicitHeight: ethColLayout.implicitHeight + 12 radius: 6 color: NetworkService.ethernetConnected ? (Theme.isDark ? Qt.rgba(80/255, 250/255, 123/255, 0.15) : Qt.rgba(80/255, 250/255, 123/255, 0.22)) : Theme.surface border.color: NetworkService.ethernetConnected ? (Theme.isDark ? Theme.green : "#15803d") : Theme.currentLine border.width: 1 RowLayout { id: ethColLayout anchors.fill: parent anchors.leftMargin: 8 anchors.rightMargin: 8 spacing: 6 Rectangle { width: 6; height: 6; radius: 3; color: NetworkService.ethernetConnected ? Theme.green : Theme.comment } Text { text: "Ethernet (" + (NetworkService.ethernetConnected ? "Connected" : "Disconnected") + ")" color: NetworkService.ethernetConnected ? Theme.green : Theme.fg font.pixelSize: 10 font.weight: NetworkService.ethernetConnected ? Font.Bold : Font.Normal Layout.fillWidth: true } } } // Off State Banner Item { Layout.fillWidth: true Layout.fillHeight: true visible: !NetworkService.isWifiPowered Text { anchors.centerIn: parent text: "Wi-Fi is turned off" color: Theme.comment font.pixelSize: 11 font.italic: true } } Flickable { Layout.fillWidth: true Layout.fillHeight: true contentHeight: netScrollCol.implicitHeight clip: true visible: NetworkService.isWifiPowered ColumnLayout { id: netScrollCol width: parent.width spacing: 3 Text { text: "Wi-Fi is turned off" color: Theme.comment font.pixelSize: 10 font.italic: true visible: !NetworkService.isWifiPowered } Repeater { model: NetworkService.networks Rectangle { Layout.fillWidth: true Layout.preferredHeight: 26 radius: 5 color: modelData.inUse ? Qt.rgba(Theme.accent.r, Theme.accent.g, Theme.accent.b, 0.18) : (netItemMouse.containsMouse ? Theme.currentLine : "transparent") border.color: modelData.inUse ? Theme.accent : "transparent" border.width: 1 RowLayout { anchors.fill: parent anchors.leftMargin: 8 anchors.rightMargin: 8 spacing: 6 NetworkIcon { isConnected: true signalPercent: parseInt(modelData.signal) width: 14 height: 14 } Text { text: modelData.ssid color: modelData.inUse ? Theme.accent : Theme.fg font.pixelSize: 10 font.weight: modelData.inUse ? Font.Bold : Font.Normal elide: Text.ElideRight Layout.fillWidth: true } Text { text: modelData.inUse ? "Connected" : modelData.signal + "%" color: modelData.inUse ? Theme.accent : Theme.comment font.pixelSize: 9 } } MouseArea { id: netItemMouse anchors.fill: parent hoverEnabled: true onClicked: { if (!modelData.inUse) { NetworkService.connectNetwork(modelData.ssid, "") } } } } } } } } } } // Battery & Power Control Detached Popup Window PopupWindow { id: batMenu anchor.window: window anchor.rect.x: Math.round(root.x + root.width - implicitWidth) anchor.rect.y: 40 anchor.edges: Edges.Bottom | Edges.Right visible: PopupService.batteryMenuOpen color: "transparent" implicitWidth: batGlass.implicitWidth implicitHeight: batGlass.implicitHeight GlassPanel { id: batGlass implicitWidth: 300 implicitHeight: Math.min(450, batCardLayout.implicitHeight + 24) anchors.fill: parent ColumnLayout { id: batCardLayout anchors.fill: parent anchors.margins: 12 spacing: 10 // Header Text { text: "Battery & Power" color: Theme.fg font.pixelSize: 12 font.weight: Font.Bold } // Battery Status & Health Stats Card Rectangle { Layout.fillWidth: true implicitHeight: 54 radius: 6 color: Theme.surface border.color: Theme.currentLine border.width: 1 RowLayout { anchors.centerIn: parent spacing: 10 BatteryIcon { percentage: BatteryService.percentage isCharging: BatteryService.isCharging width: 22 height: 14 Layout.alignment: Qt.AlignVCenter } ColumnLayout { spacing: 2 Layout.alignment: Qt.AlignVCenter Text { text: BatteryService.percentage + "% (" + (BatteryService.isCharging ? "Charging" : "Discharging") + ")" color: Theme.fg font.pixelSize: 11 font.weight: Font.Bold } Text { text: "Battery Health: " + BatteryService.healthPercent + "%" color: Theme.isDark ? Theme.green : "#15803d" font.pixelSize: 10 } } } } // Solid Divider Rectangle { Layout.fillWidth: true Layout.preferredHeight: 1 color: Theme.currentLine } // Power Profile 3-Point Stepped Slider Section ColumnLayout { Layout.fillWidth: true spacing: 6 RowLayout { Layout.fillWidth: true Text { text: "POWER PROFILE" color: Theme.comment font.pixelSize: 9 font.weight: Font.Bold } Item { Layout.fillWidth: true } Text { text: BatteryService.activeProfile === "power-saver" ? "Power Saver" : (BatteryService.activeProfile === "performance" ? "Performance" : "Balanced") color: BatteryService.activeProfile === "power-saver" ? (Theme.isDark ? Theme.green : "#15803d") : (BatteryService.activeProfile === "performance" ? Theme.subAccent : Theme.accent) font.pixelSize: 10 font.weight: Font.Bold } } // Stepped 3-Point Slider Container Item { id: profileSliderTrack Layout.fillWidth: true Layout.preferredHeight: 20 property int activeIndex: BatteryService.activeProfile === "power-saver" ? 0 : (BatteryService.activeProfile === "performance" ? 2 : 1) // Track Line Rectangle { anchors.centerIn: parent width: parent.width - 16 height: 4 radius: 2 color: Theme.currentLine // Active Fill Rectangle { width: Math.max(0, (parent.width * (profileSliderTrack.activeIndex / 2.0))) height: parent.height radius: 2 color: profileSliderTrack.activeIndex === 0 ? Theme.green : (profileSliderTrack.activeIndex === 2 ? Theme.subAccent : Theme.accent) Behavior on width { NumberAnimation { duration: 150; easing.type: Easing.OutCubic } } } } // 3 Snap Point Dots Repeater { model: 3 Rectangle { required property int index width: 8 height: 8 radius: 4 color: index <= profileSliderTrack.activeIndex ? (profileSliderTrack.activeIndex === 0 ? Theme.green : (profileSliderTrack.activeIndex === 2 ? Theme.subAccent : Theme.accent)) : Theme.currentLine anchors.verticalCenter: parent.verticalCenter x: 8 + ((profileSliderTrack.width - 24) * (index / 2.0)) - 4 Behavior on color { ColorAnimation { duration: 120 } } } } // Stepped Handle Knob Rectangle { id: profileKnob width: 14 height: 14 radius: 7 color: profileSliderTrack.activeIndex === 0 ? Theme.green : (profileSliderTrack.activeIndex === 2 ? Theme.subAccent : Theme.accent) border.color: Theme.bg border.width: 2 anchors.verticalCenter: parent.verticalCenter x: 8 + ((profileSliderTrack.width - 24) * (profileSliderTrack.activeIndex / 2.0)) - 7 Behavior on x { NumberAnimation { duration: 180; easing.type: Easing.OutCubic } } Behavior on color { ColorAnimation { duration: 120 } } } // Mouse Drag / Snap Handler MouseArea { id: profileSliderMouse anchors.fill: parent hoverEnabled: true function applySnap(mouseX) { var ratio = Math.max(0.0, Math.min(1.0, (mouseX - 8) / (width - 24))) var snapIdx = Math.round(ratio * 2.0) var profiles = ["power-saver", "balanced", "performance"] var targetProfile = profiles[snapIdx] if (BatteryService.activeProfile !== targetProfile) { BatteryService.setProfile(targetProfile) } } onPositionChanged: (mouse) => { if (pressed) applySnap(mouse.x) } onPressed: (mouse) => { applySnap(mouse.x) } } } // 3 Point Labels Row (Power Saver, Balanced, Performance) RowLayout { Layout.fillWidth: true Text { text: "Power Saver" color: profileSliderTrack.activeIndex === 0 ? Theme.green : Theme.comment font.pixelSize: 9 font.weight: profileSliderTrack.activeIndex === 0 ? Font.Bold : Font.Normal } Item { Layout.fillWidth: true } Text { text: "Balanced" color: profileSliderTrack.activeIndex === 1 ? Theme.accent : Theme.comment font.pixelSize: 9 font.weight: profileSliderTrack.activeIndex === 1 ? Font.Bold : Font.Normal } Item { Layout.fillWidth: true } Text { text: "Performance" color: profileSliderTrack.activeIndex === 2 ? Theme.subAccent : Theme.comment font.pixelSize: 9 font.weight: profileSliderTrack.activeIndex === 2 ? Font.Bold : Font.Normal } } } // Solid Divider Rectangle { Layout.fillWidth: true Layout.preferredHeight: 1 color: Theme.currentLine } // Block PC Sleep Toggle Button (Caffeine Mode) Rectangle { Layout.fillWidth: true Layout.preferredHeight: 30 radius: 6 color: BatteryService.isSleepBlocked ? Qt.rgba(255/255, 184/255, 108/255, 0.2) : (sleepMouse.containsMouse ? Theme.currentLine : (Theme.isDark ? Theme.currentLine : Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.08))) border.color: BatteryService.isSleepBlocked ? Theme.orange : Theme.currentLine border.width: 1 RowLayout { anchors.centerIn: parent spacing: 8 Rectangle { width: 8; height: 8; radius: 4 color: BatteryService.isSleepBlocked ? Theme.orange : Theme.comment } Text { text: BatteryService.isSleepBlocked ? "Block PC Sleep: ACTIVE" : "Block PC from Falling Asleep" color: BatteryService.isSleepBlocked ? Theme.orange : Theme.fg font.pixelSize: 10 font.weight: Font.Bold } } MouseArea { id: sleepMouse anchors.fill: parent hoverEnabled: true onClicked: BatteryService.toggleSleepBlock() } } } } } // Running Applications System Tray Context Menu Detached Popup Window PopupWindow { id: trayContextMenu anchor.window: window anchor.rect.x: Math.round(Math.max(10, Math.min(window.width - 175, root.x + root.activeTrayX + 12 - 87))) anchor.rect.y: 40 anchor.edges: Edges.Bottom | Edges.Left visible: PopupService.trayMenuOpen color: "transparent" implicitWidth: trayGlass.implicitWidth implicitHeight: trayGlass.implicitHeight GlassPanel { id: trayGlass implicitWidth: 170 implicitHeight: trayCol.implicitHeight + 16 anchors.fill: parent ColumnLayout { id: trayCol anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top anchors.margins: 8 spacing: 4 // Sleek & Uniform App Header (Fixed 22px Height & Clean App Name) RowLayout { Layout.fillWidth: true Layout.preferredHeight: 22 spacing: 6 Item { width: 14 height: 14 Layout.alignment: Qt.AlignVCenter Image { anchors.fill: parent sourceSize.width: 14 sourceSize.height: 14 source: root.activeTrayItem ? (root.activeTrayItem.icon || "") : "" fillMode: Image.PreserveAspectFit visible: root.activeTrayItem ? (root.activeTrayItem.icon ? true : false) : false } } Text { text: root.getCleanAppName(root.activeTrayItem) color: Theme.accent font.pixelSize: 10 font.weight: Font.Bold elide: Text.ElideRight Layout.fillWidth: true Layout.alignment: Qt.AlignVCenter } } // Solid Divider (Only visible if app has menu items underneath) Rectangle { Layout.fillWidth: true Layout.preferredHeight: 1 color: Theme.currentLine visible: (root.activeTrayItem && root.activeTrayItem.hasMenu && root.activeTrayMenuOpener && root.activeTrayMenuOpener.children && root.activeTrayMenuOpener.children.length > 0) } // Render Pure Native DBus App Menu Items (Pre-Cached Real Time Model) Repeater { model: (root.activeTrayItem && root.activeTrayItem.hasMenu && root.activeTrayMenuOpener && root.activeTrayMenuOpener.children) ? root.activeTrayMenuOpener.children : 0 ColumnLayout { Layout.fillWidth: true spacing: 0 // Separator Item Rectangle { Layout.fillWidth: true Layout.preferredHeight: 1 color: Theme.currentLine visible: modelData.isSeparator === true Layout.topMargin: 2 Layout.bottomMargin: 2 } // Normal Native Menu Item Button Rectangle { Layout.fillWidth: true Layout.preferredHeight: 22 radius: 4 visible: modelData.isSeparator !== true && (modelData.text ? true : false) color: (menuItemMouse.containsMouse && modelData.enabled) ? Theme.currentLine : "transparent" RowLayout { anchors.fill: parent anchors.leftMargin: 6 anchors.rightMargin: 6 spacing: 6 Image { width: 12; height: 12 sourceSize.width: 12; sourceSize.height: 12 source: modelData.icon || "" visible: modelData.icon && modelData.icon !== "" fillMode: Image.PreserveAspectFit } Text { text: modelData.text ? modelData.text.replace(/&/g, "") : "" color: modelData.enabled ? Theme.fg : Theme.comment font.pixelSize: 10 font.weight: modelData.enabled ? Font.Medium : Font.Normal elide: Text.ElideRight Layout.fillWidth: true } } MouseArea { id: menuItemMouse anchors.fill: parent hoverEnabled: true enabled: modelData.enabled onClicked: { modelData.triggered() PopupService.closeAll() } } } } } } } } }