import QtQuick import QtQuick.Layouts import Quickshell import ZShell.Services import ZShell.Config import qs.Components import qs.Services CustomRect { id: root readonly property color accent: Colors.palette.m3secondary readonly property real percentage: Storage.primaryDisk?.perc ?? 0 color: Colors.tPalette.m3surfaceContainer implicitHeight: layout.implicitHeight + Tokens.padding.large * 2 implicitWidth: layout.implicitWidth + layout.anchors.margins * 2 radius: Tokens.rounding.largeIncreased ServiceRef { service: Storage } ColumnLayout { id: layout anchors.left: parent.left anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter spacing: 0 RowLayout { id: row Layout.alignment: Qt.AlignHCenter spacing: Tokens.spacing.largeIncreased CircularProgress { fgColor: root.accent implicitSize: usageColumn.implicitHeight + thickness + Tokens.padding.large * 2 startAngle: -225 sweepAngle: 270 value: root.percentage Behavior on clampedVal { Anim { } } ColumnLayout { id: usageColumn anchors.centerIn: parent spacing: 0 MaterialIcon { Layout.alignment: Qt.AlignHCenter color: root.accent font.pointSize: Tokens.font.size.large text: "hard_drive" } CustomText { Layout.alignment: Qt.AlignHCenter color: root.accent font.pointSize: Tokens.font.size.large text: Math.round(root.percentage * 100) + "%" } CustomText { Layout.alignment: Qt.AlignHCenter color: Colors.palette.m3onSurfaceVariant text: qsTr("Used") } } } ColumnLayout { spacing: Tokens.spacing.extraSmall CustomText { text: qsTr("Storage") } CustomText { color: root.accent text: { if (!Storage.primaryDisk) return qsTr("No disks detected"); const fmt = UsageFmt.formatKib(Storage.primaryDisk.used, Storage.primaryDisk.total); return `${fmt.value.toFixed(1)} / ${Math.floor(fmt.total)} ${fmt.unit}`; } } } } SplitButton { Layout.alignment: Qt.AlignHCenter active: menuItems.find(m => m.modelData === Storage.primaryDisk) ?? menuItems[0] ?? null enabled: Storage.disks.length fallbackIcon: "storage" fallbackText: qsTr("No disks") menuItems: disks.instances minLeftWidth: row.implicitWidth * 0.6 type: SplitButton.Tonal menu.onItemSelected: item => Storage.manualPrimaryDisk = (item as DiskItem).modelData Variants { id: disks model: Storage.disks DiskItem { } } } } component DiskItem: MenuItem { required property var modelData activeIcon: "storage" icon: modelData === Storage.primaryDisk ? "check" : "" text: modelData.mount } }