Watch
1
0
Fork
You've already forked souveraine
0
souveraine/surfaces/quickshell/ii-base/DeviceConnectNotification.qml

737 lines
35 KiB
QML

import "modules/common"
import "modules/common/widgets"
import "services"
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import Quickshell.Hyprland
Scope {
id: root
property bool active: false
property var focusedScreen: Quickshell.screens.find(s => s.name === Hyprland.focusedMonitor?.name) ?? null
// Dynamic properties passed via IPC
property string deviceType: "mouse" // "mouse", "pen_drive", "ssd", "hdd", "serial"
property string deviceName: ""
property string deviceSubtype: ""
property string devicePath: ""
function triggerPopup() {
root.active = true;
closeTimer.restart();
}
Timer {
id: closeTimer
interval: 4000 // 4 seconds
repeat: false
running: false
onTriggered: {
root.active = false;
}
}
IpcHandler {
target: "deviceConnectorService"
function showDeviceConnected(deviceType: string, deviceName: string, deviceSubtype: string, devicePath: string): void {
root.deviceType = deviceType;
root.deviceName = deviceName;
root.deviceSubtype = deviceSubtype;
root.devicePath = devicePath || "";
root.triggerPopup();
}
}
PanelWindow {
id: winRoot
color: "transparent"
screen: root.focusedScreen
visible: root.active || contentWrapper.opacity > 0.0
WlrLayershell.namespace: "quickshell:deviceConnectNotification"
WlrLayershell.layer: WlrLayer.Overlay
anchors {
top: !Config.options.bar.bottom
bottom: Config.options.bar.bottom
}
exclusionMode: ExclusionMode.Ignore
exclusiveZone: 0
margins {
top: !Config.options.bar.bottom ? (Appearance.sizes.barHeight + 6) : 0
bottom: Config.options.bar.bottom ? (Appearance.sizes.barHeight + 6) : 0
}
implicitWidth: contentWrapper.implicitWidth
implicitHeight: contentWrapper.implicitHeight
Item {
id: contentWrapper
// Make sure there's enough space for the shadow and rotation
implicitWidth: deviceContainer.width + 40
implicitHeight: deviceContainer.height + 40
opacity: root.active ? 1.0 : 0.0
Behavior on opacity {
NumberAnimation {
id: fadeOutAnim
duration: 300
easing.type: Easing.InOutQuad
}
}
property real animOffset: root.active ? 0 : (!Config.options.bar.bottom ? -30 : 30)
Behavior on animOffset {
NumberAnimation {
duration: 450
easing.type: Easing.OutCubic
}
}
StyledRectangularShadow {
target: deviceContainer
anchors.fill: deviceContainer
}
Rectangle {
id: deviceContainer
width: 280
height: 84
radius: Appearance.rounding.small
color: Appearance.m3colors.m3surfaceContainer
border.color: Appearance.colors.colLayer0Border
border.width: 1
anchors {
centerIn: parent
verticalCenterOffset: contentWrapper.animOffset
}
RowLayout {
anchors {
fill: parent
margins: 12
leftMargin: 20
rightMargin: 20
}
spacing: 18
// 3D-rotating graphic container
Item {
id: iconWrapper
Layout.preferredWidth: 38
Layout.preferredHeight: 56
Layout.alignment: Qt.AlignVCenter
Item {
id: rotatingIcon
anchors.fill: parent
// --- MOUSE GRAPHIC ---
Item {
anchors.fill: parent
visible: root.deviceType === "mouse"
Rectangle {
anchors.fill: parent
radius: width / 2
color: "transparent"
border.color: Appearance.colors.colPrimary
border.width: 2.5
// Button separator
Rectangle {
width: 2.5
height: parent.height * 0.45
color: Appearance.colors.colPrimary
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
}
// Scroll Wheel
Rectangle {
width: 4.5
height: 11
radius: 2
color: Appearance.colors.colSecondary
anchors.top: parent.top
anchors.topMargin: 7
anchors.horizontalCenter: parent.horizontalCenter
}
// DPI Button
Rectangle {
width: 4
height: 4
radius: 2
color: Appearance.colors.colPrimary
anchors.top: parent.top
anchors.topMargin: 20
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
// --- PEN DRIVE GRAPHIC ---
Item {
anchors.fill: parent
visible: root.deviceType === "pen_drive"
// USB Metal Connector
Rectangle {
width: 14
height: 12
color: "transparent"
border.color: Appearance.colors.colPrimary
border.width: 2.5
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
// USB Connector detailing
Rectangle {
width: 8
height: 3
color: Appearance.colors.colPrimary
anchors.bottom: parent.bottom
anchors.bottomMargin: 2
anchors.horizontalCenter: parent.horizontalCenter
}
}
// Pen Drive Body
Rectangle {
width: 22
height: 34
radius: 4
color: "transparent"
border.color: Appearance.colors.colPrimary
border.width: 2.5
anchors.top: parent.top
anchors.topMargin: 11
anchors.horizontalCenter: parent.horizontalCenter
// Stripe / grip line
Rectangle {
width: 10
height: 2
color: Appearance.colors.colSecondary
anchors.centerIn: parent
}
// Activity LED dot
Rectangle {
width: 3
height: 3
radius: 1.5
color: Appearance.colors.colSecondary
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
// --- SSD GRAPHIC ---
Item {
anchors.fill: parent
visible: root.deviceType === "ssd"
Rectangle {
width: 32
height: 48
radius: 6
color: "transparent"
border.color: Appearance.colors.colPrimary
border.width: 2.5
anchors.centerIn: parent
// USB-C port at the top
Rectangle {
width: 10
height: 2
radius: 1
color: Appearance.colors.colSecondary
anchors.top: parent.top
anchors.topMargin: 4
anchors.horizontalCenter: parent.horizontalCenter
}
// Modern speed stripes
Rectangle {
width: 18
height: 2
color: Appearance.colors.colPrimary
anchors.centerIn: parent
rotation: -45
}
Rectangle {
width: 12
height: 2
color: Appearance.colors.colSecondary
anchors.centerIn: parent
anchors.verticalCenterOffset: 6
anchors.horizontalCenterOffset: 6
rotation: -45
}
}
}
// --- HDD GRAPHIC ---
Item {
anchors.fill: parent
visible: root.deviceType === "hdd"
Rectangle {
width: 34
height: 50
radius: 4
color: "transparent"
border.color: Appearance.colors.colPrimary
border.width: 2.5
anchors.centerIn: parent
// Inner metal shield
Rectangle {
width: 26
height: 42
radius: 2
color: "transparent"
border.color: Appearance.colors.colSecondary
border.width: 1.5
anchors.centerIn: parent
// Disk Platter
Rectangle {
width: 20
height: 20
radius: 10
color: "transparent"
border.color: Appearance.colors.colPrimary
border.width: 2
anchors.centerIn: parent
// Spindle center
Rectangle {
width: 4
height: 4
radius: 2
color: Appearance.colors.colPrimary
anchors.centerIn: parent
}
}
// Actuator arm
Rectangle {
width: 2
height: 12
color: Appearance.colors.colPrimary
anchors.top: parent.top
anchors.topMargin: 6
anchors.right: parent.right
anchors.rightMargin: 6
rotation: -30
}
}
}
}
// --- CONTROLLER GRAPHICS ---
Item {
anchors.fill: parent
visible: root.deviceType === "controller_bluetooth" || root.deviceType === "controller_wired" || root.deviceType === "controller_dongle"
// Gamepad Base Body
Rectangle {
id: gpBody
width: 36
height: 24
radius: 8
color: "transparent"
border.color: Appearance.colors.colPrimary
border.width: 2.5
anchors.centerIn: parent
anchors.verticalCenterOffset: 2
// Left grip handle
Rectangle {
width: 10
height: 18
radius: 5
color: "transparent"
border.color: Appearance.colors.colPrimary
border.width: 2.5
anchors.left: parent.left
anchors.leftMargin: -2
anchors.bottom: parent.bottom
anchors.bottomMargin: -10
rotation: 20
}
// Right grip handle
Rectangle {
width: 10
height: 18
radius: 5
color: "transparent"
border.color: Appearance.colors.colPrimary
border.width: 2.5
anchors.right: parent.right
anchors.rightMargin: -2
anchors.bottom: parent.bottom
anchors.bottomMargin: -10
rotation: -20
}
// Left thumbstick
Rectangle {
width: 6
height: 6
radius: 3
color: Appearance.colors.colSecondary
anchors.left: parent.left
anchors.leftMargin: 8
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
}
// Right thumbstick
Rectangle {
width: 6
height: 6
radius: 3
color: Appearance.colors.colSecondary
anchors.right: parent.right
anchors.rightMargin: 8
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
}
// D-Pad
Item {
width: 8
height: 8
anchors.left: parent.left
anchors.leftMargin: 6
anchors.top: parent.top
anchors.topMargin: 4
// Horizontal bar
Rectangle {
width: 8
height: 2.5
color: Appearance.colors.colPrimary
anchors.centerIn: parent
}
// Vertical bar
Rectangle {
width: 2.5
height: 8
color: Appearance.colors.colPrimary
anchors.centerIn: parent
}
}
// Action buttons (A/B/X/Y)
Item {
width: 8
height: 8
anchors.right: parent.right
anchors.rightMargin: 6
anchors.top: parent.top
anchors.topMargin: 4
// Y button (top)
Rectangle { width: 2.5; height: 2.5; radius: 1.25; color: Appearance.colors.colPrimary; anchors.top: parent.top; anchors.horizontalCenter: parent.horizontalCenter }
// A button (bottom)
Rectangle { width: 2.5; height: 2.5; radius: 1.25; color: Appearance.colors.colPrimary; anchors.bottom: parent.bottom; anchors.horizontalCenter: parent.horizontalCenter }
// X button (left)
Rectangle { width: 2.5; height: 2.5; radius: 1.25; color: Appearance.colors.colPrimary; anchors.left: parent.left; anchors.verticalCenter: parent.verticalCenter }
// B button (right)
Rectangle { width: 2.5; height: 2.5; radius: 1.25; color: Appearance.colors.colPrimary; anchors.right: parent.right; anchors.verticalCenter: parent.verticalCenter }
}
}
// --- BLUETOOTH EMBLEM ---
Item {
visible: root.deviceType === "controller_bluetooth"
width: 12
height: 14
anchors.right: parent.right
anchors.rightMargin: -4
anchors.top: parent.top
anchors.topMargin: -4
// stylized bluetooth B using lines
Rectangle {
width: 2
height: 12
color: Appearance.colors.colSecondary
anchors.horizontalCenter: parent.horizontalCenter
}
// Bluetooth loops
Rectangle {
width: 5
height: 6
color: "transparent"
border.color: Appearance.colors.colSecondary
border.width: 1.5
radius: 3
anchors.top: parent.top
anchors.left: parent.horizontalCenter
}
Rectangle {
width: 5
height: 6
color: "transparent"
border.color: Appearance.colors.colSecondary
border.width: 1.5
radius: 3
anchors.bottom: parent.bottom
anchors.left: parent.horizontalCenter
}
}
// --- USB CABLE ---
Item {
visible: root.deviceType === "controller_wired"
anchors.fill: parent
// Cable line from top of controller to top of area
Rectangle {
width: 2
height: 12
color: Appearance.colors.colSecondary
anchors.bottom: gpBody.top
anchors.horizontalCenter: gpBody.horizontalCenter
}
}
// --- DONGLE AND WAVES ---
Item {
visible: root.deviceType === "controller_dongle"
anchors.fill: parent
// USB Dongle Receiver at the top
Rectangle {
id: dongleBody
width: 8
height: 6
radius: 1
color: "transparent"
border.color: Appearance.colors.colSecondary
border.width: 1.5
anchors.top: parent.top
anchors.topMargin: -2
anchors.horizontalCenter: parent.horizontalCenter
// metal part
Rectangle {
width: 4
height: 3
color: Appearance.colors.colSecondary
anchors.top: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
}
// Wireless wave arcs
// Wave 1
Rectangle {
width: 12
height: 4
radius: 2
color: Appearance.colors.colSecondary
opacity: 0.8
anchors.top: dongleBody.bottom
anchors.topMargin: 4
anchors.horizontalCenter: parent.horizontalCenter
}
// Wave 2
Rectangle {
width: 18
height: 4
radius: 2
color: Appearance.colors.colSecondary
opacity: 0.5
anchors.top: dongleBody.bottom
anchors.topMargin: 10
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
// --- SERIAL DEVICE / MICROCONTROLLER GRAPHIC ---
Item {
anchors.fill: parent
visible: root.deviceType === "serial"
// PCB Board Base
Rectangle {
id: pcbBase
width: 32
height: 48
radius: 4
color: "#1b2d24" // Dark forest green / PCB color
border.color: "#385e49" // Brighter green border
border.width: 1.5
anchors.centerIn: parent
// Left side pins (headers)
Column {
anchors.left: parent.left
anchors.leftMargin: 2
anchors.verticalCenter: parent.verticalCenter
spacing: 3
Repeater {
model: 6
Rectangle {
width: 3
height: 3
color: "#D4AF37" // Metallic Gold
radius: 0.5
}
}
}
// Right side pins (headers)
Column {
anchors.right: parent.right
anchors.rightMargin: 2
anchors.verticalCenter: parent.verticalCenter
spacing: 3
Repeater {
model: 6
Rectangle {
width: 3
height: 3
color: "#D4AF37" // Metallic Gold
radius: 0.5
}
}
}
// Metal Shielding Module (ESP32 SoC)
Rectangle {
width: 18
height: 18
radius: 2
color: "#8E9297" // Silver/Grey
border.color: "#B1B5BC"
border.width: 1
anchors.centerIn: parent
anchors.verticalCenterOffset: -4
// Silicon Chip detail (black square on metal)
Rectangle {
width: 8
height: 8
color: "#1e1e1e"
radius: 1
anchors.centerIn: parent
}
}
// USB-C Connector Port at the bottom
Rectangle {
width: 10
height: 4
color: "#CCCCCC"
border.color: "#888888"
border.width: 1
radius: 1
anchors.bottom: parent.bottom
anchors.bottomMargin: -1.5
anchors.horizontalCenter: parent.horizontalCenter
}
// Status/Power LED
Rectangle {
width: 3
height: 3
radius: 1.5
color: "#00E5FF" // Neon cyan glowing LED
anchors.top: parent.top
anchors.topMargin: 4
anchors.horizontalCenter: parent.horizontalCenter
SequentialAnimation on opacity {
loops: Animation.Infinite
running: root.active
NumberAnimation { from: 1.0; to: 0.2; duration: 500; easing.type: Easing.InOutQuad }
NumberAnimation { from: 0.2; to: 1.0; duration: 500; easing.type: Easing.InOutQuad }
}
}
}
}
transform: Rotation {
id: rotationY
origin.x: rotatingIcon.width / 2
origin.y: rotatingIcon.height / 2
axis { x: 0; y: 1; z: 0 }
angle: 0
}
NumberAnimation {
target: rotationY
property: "angle"
from: 0
to: 360
duration: 2500
loops: Animation.Infinite
running: root.active
}
}
}
// Labels
ColumnLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
spacing: 2
StyledText {
text: root.deviceName
font.pixelSize: Appearance.font.pixelSize.normal
font.bold: true
color: Appearance.colors.colOnLayer1
Layout.fillWidth: true
elide: Text.ElideRight
}
StyledText {
text: root.deviceSubtype
font.pixelSize: Appearance.font.pixelSize.smaller
color: Appearance.colors.colSubtext
Layout.fillWidth: true
elide: Text.ElideRight
}
}
}
MouseArea {
anchors.fill: parent
cursorShape: ((root.deviceType === "pen_drive" || root.deviceType === "ssd" || root.deviceType === "hdd") && root.devicePath !== "") ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
Quickshell.execDetached(["bash", "-c", "echo 'QML click detected! type=" + root.deviceType + " path=" + root.devicePath + "' >> /tmp/qml_click.log"]);
if (root.deviceType === "pen_drive" || root.deviceType === "ssd" || root.deviceType === "hdd") {
if (root.devicePath) {
Quickshell.execDetached(["bash", "-c", "if [ -f $HOME/.config/hypr/hyprland/scripts/open_storage_device.sh ]; then $HOME/.config/hypr/hyprland/scripts/open_storage_device.sh " + root.devicePath + "; else $HOME/.config/hypr/custom/scripts/open_storage_device.sh " + root.devicePath + "; fi"]);
root.active = false;
}
}
}
}
}
}
}
}