feat: improve dash perf storage card
This commit is contained in:
parent
30878e3b51
commit
3ae676c040
5 changed files with 143 additions and 137 deletions
|
|
@ -19,14 +19,15 @@ Row {
|
|||
property bool menuOnTop
|
||||
property string fallbackIcon
|
||||
property string fallbackText
|
||||
property real minLeftWidth
|
||||
|
||||
property alias menuItems: menu.items
|
||||
property alias active: menu.active
|
||||
property alias expanded: menu.expanded
|
||||
property alias menu: menu
|
||||
property alias iconLabel: iconLabel
|
||||
property alias label: label
|
||||
property alias stateLayer: stateLayer
|
||||
readonly property alias menu: menu
|
||||
readonly property alias iconLabel: iconLabel
|
||||
readonly property alias label: label
|
||||
readonly property alias stateLayer: stateLayer
|
||||
|
||||
property color colour: type == SplitButton.Filled ? Colours.palette.m3primary : Colours.palette.m3secondaryContainer
|
||||
property color textColour: type == SplitButton.Filled ? Colours.palette.m3onPrimary : Colours.palette.m3onSecondaryContainer
|
||||
|
|
@ -41,14 +42,14 @@ Row {
|
|||
bottomRightRadius: Tokens.rounding.medium / 2
|
||||
color: root.disabled ? root.disabledColour : root.colour
|
||||
|
||||
implicitWidth: textRow.implicitWidth + root.horizontalPadding * 2
|
||||
implicitWidth: Math.max(root.minLeftWidth, textRow.implicitWidth + root.horizontalPadding * 2)
|
||||
implicitHeight: expandBtn.implicitHeight
|
||||
|
||||
StateLayer {
|
||||
id: stateLayer
|
||||
|
||||
rect.topRightRadius: parent.topRightRadius
|
||||
rect.bottomRightRadius: parent.bottomRightRadius
|
||||
topRightRadius: parent.topRightRadius
|
||||
bottomRightRadius: parent.bottomRightRadius
|
||||
color: root.textColour
|
||||
disabled: root.disabled
|
||||
onClicked: root.active?.clicked()
|
||||
|
|
|
|||
|
|
@ -125,10 +125,8 @@ Item {
|
|||
visible: Config.dashboard.performance.showMemory
|
||||
}
|
||||
|
||||
StorageGaugeCard {
|
||||
Layout.minimumWidth: 250
|
||||
Layout.preferredHeight: 220
|
||||
Layout.fillWidth: !Config.dashboard.performance.showNetwork
|
||||
StorageCard {
|
||||
Layout.fillHeight: true
|
||||
visible: Config.dashboard.performance.showStorage
|
||||
}
|
||||
|
||||
|
|
@ -385,132 +383,6 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
component StorageGaugeCard: StyledRect {
|
||||
id: storageGaugeCard
|
||||
|
||||
property int currentDiskIndex: 0
|
||||
readonly property var currentDisk: SystemUsage.disks.length > 0 ? SystemUsage.disks[currentDiskIndex] : null
|
||||
property int diskCount: 0
|
||||
readonly property real arcStartAngle: 0.75 * Math.PI
|
||||
readonly property real arcSweep: 1.5 * Math.PI
|
||||
property real animatedPercentage: 0
|
||||
property color accentColor: Colours.palette.m3secondary
|
||||
|
||||
color: Colours.tPalette.m3surfaceContainer
|
||||
radius: Tokens.rounding.extraLarge
|
||||
clip: true
|
||||
Component.onCompleted: {
|
||||
diskCount = SystemUsage.disks.length;
|
||||
if (currentDisk)
|
||||
animatedPercentage = currentDisk.perc;
|
||||
}
|
||||
onCurrentDiskChanged: {
|
||||
if (currentDisk)
|
||||
animatedPercentage = currentDisk.perc;
|
||||
}
|
||||
|
||||
// Update diskCount and animatedPercentage when disks data changes
|
||||
Connections {
|
||||
function onDisksChanged() {
|
||||
if (SystemUsage.disks.length !== storageGaugeCard.diskCount)
|
||||
storageGaugeCard.diskCount = SystemUsage.disks.length;
|
||||
|
||||
// Update animated percentage when disk data refreshes
|
||||
if (storageGaugeCard.currentDisk)
|
||||
storageGaugeCard.animatedPercentage = storageGaugeCard.currentDisk.perc;
|
||||
}
|
||||
|
||||
target: SystemUsage
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onWheel: wheel => {
|
||||
if (wheel.angleDelta.y > 0)
|
||||
storageGaugeCard.currentDiskIndex = (storageGaugeCard.currentDiskIndex - 1 + storageGaugeCard.diskCount) % storageGaugeCard.diskCount;
|
||||
else if (wheel.angleDelta.y < 0)
|
||||
storageGaugeCard.currentDiskIndex = (storageGaugeCard.currentDiskIndex + 1) % storageGaugeCard.diskCount;
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Tokens.padding.large
|
||||
spacing: Tokens.spacing.medium
|
||||
|
||||
CardHeader {
|
||||
icon: "hard_disk"
|
||||
title: {
|
||||
const base = qsTr("Storage");
|
||||
if (!storageGaugeCard.currentDisk)
|
||||
return base;
|
||||
|
||||
return `${base} - ${storageGaugeCard.currentDisk.mount}`;
|
||||
}
|
||||
accentColor: storageGaugeCard.accentColor
|
||||
|
||||
// Scroll hint icon
|
||||
MaterialIcon {
|
||||
text: "unfold_more"
|
||||
color: Colours.palette.m3onSurfaceVariant
|
||||
fontStyle: Tokens.font.icon.medium
|
||||
visible: storageGaugeCard.diskCount > 1
|
||||
opacity: 0.7
|
||||
ToolTip.visible: hintHover.hovered
|
||||
ToolTip.text: qsTr("Scroll to switch disks")
|
||||
ToolTip.delay: 500
|
||||
|
||||
HoverHandler {
|
||||
id: hintHover
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
ArcGauge {
|
||||
anchors.centerIn: parent
|
||||
width: Math.min(parent.width, parent.height)
|
||||
height: width
|
||||
percentage: storageGaugeCard.animatedPercentage
|
||||
accentColor: storageGaugeCard.accentColor
|
||||
trackColor: Colours.layer(Colours.palette.m3surfaceContainerHigh, 2)
|
||||
startAngle: storageGaugeCard.arcStartAngle
|
||||
sweepAngle: storageGaugeCard.arcSweep
|
||||
}
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: storageGaugeCard.currentDisk ? `${Math.round(storageGaugeCard.currentDisk.perc * 100)}%` : "—"
|
||||
font: Tokens.font.body.builders.large.size(28).weight(Font.Medium).build()
|
||||
color: storageGaugeCard.accentColor
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: {
|
||||
if (!storageGaugeCard.currentDisk)
|
||||
return "—";
|
||||
|
||||
const usedFmt = SystemUsage.formatKib(storageGaugeCard.currentDisk.used);
|
||||
const totalFmt = SystemUsage.formatKib(storageGaugeCard.currentDisk.total);
|
||||
return `${usedFmt.value.toFixed(1)} / ${Math.floor(totalFmt.value)} ${totalFmt.unit}`;
|
||||
}
|
||||
font: Tokens.font.body.small
|
||||
color: Colours.palette.m3onSurfaceVariant
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on animatedPercentage {
|
||||
Anim {
|
||||
type: Anim.StandardLarge
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component NetworkCard: StyledRect {
|
||||
id: networkCard
|
||||
|
||||
|
|
|
|||
130
modules/dashboard/performance/StorageCard.qml
Normal file
130
modules/dashboard/performance/StorageCard.qml
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Caelestia.Config
|
||||
import qs.components
|
||||
import qs.components.controls
|
||||
import qs.services
|
||||
|
||||
StyledRect {
|
||||
id: root
|
||||
|
||||
readonly property color accent: Colours.palette.m3secondary
|
||||
readonly property real percentage: SystemUsage.primaryDisk?.perc ?? 0
|
||||
|
||||
color: Colours.tPalette.m3surfaceContainer
|
||||
radius: Tokens.rounding.extraLarge
|
||||
|
||||
implicitWidth: layout.implicitWidth + layout.anchors.margins * 2
|
||||
implicitHeight: layout.implicitHeight + Tokens.padding.large * 2
|
||||
|
||||
ColumnLayout {
|
||||
id: layout
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.margins: Tokens.padding.extraLarge
|
||||
spacing: 0
|
||||
|
||||
RowLayout {
|
||||
id: row
|
||||
|
||||
spacing: Tokens.spacing.large
|
||||
|
||||
CircularProgress {
|
||||
fgColour: root.accent
|
||||
value: root.percentage
|
||||
implicitSize: usageColumn.implicitHeight + thickness + Tokens.padding.large * 2
|
||||
startAngle: -225
|
||||
sweepAngle: 270
|
||||
|
||||
Behavior on clampedVal {
|
||||
Anim {}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: usageColumn
|
||||
|
||||
anchors.centerIn: parent
|
||||
spacing: 0
|
||||
|
||||
MaterialIcon {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: "hard_drive"
|
||||
color: root.accent
|
||||
fontStyle: Tokens.font.icon.medium
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: Math.round(root.percentage * 100) + "%"
|
||||
font: Tokens.font.title.builders.large.width(90).build()
|
||||
color: root.accent
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: qsTr("Used")
|
||||
font: Tokens.font.body.small
|
||||
color: Colours.palette.m3onSurfaceVariant
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.minimumWidth: Tokens.sizes.dashboard.perfStorageTextWidth
|
||||
spacing: Tokens.spacing.extraSmall
|
||||
|
||||
StyledText {
|
||||
text: qsTr("Storage")
|
||||
font: Tokens.font.title.medium
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (!SystemUsage.primaryDisk)
|
||||
return qsTr("No disks detected");
|
||||
|
||||
const usedFmt = SystemUsage.formatKib(SystemUsage.primaryDisk.used);
|
||||
const totalFmt = SystemUsage.formatKib(SystemUsage.primaryDisk.total);
|
||||
return `${usedFmt.value.toFixed(1)} / ${Math.floor(totalFmt.value)} ${totalFmt.unit}`;
|
||||
}
|
||||
font: Tokens.font.body.large
|
||||
color: root.accent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SplitButton {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
type: SplitButton.Tonal
|
||||
disabled: !SystemUsage.disks.length
|
||||
fallbackIcon: "storage"
|
||||
fallbackText: qsTr("No disks")
|
||||
menuOnTop: true
|
||||
minLeftWidth: row.implicitWidth * 0.6
|
||||
|
||||
menuItems: disks.instances
|
||||
active: menuItems.find(m => m.modelData === SystemUsage.primaryDisk) ?? menuItems[0] ?? null
|
||||
menu.onItemSelected: item => SystemUsage.manualPrimaryDisk = (item as DiskItem).modelData
|
||||
|
||||
Variants {
|
||||
id: disks
|
||||
|
||||
model: SystemUsage.disks
|
||||
|
||||
DiskItem {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component DiskItem: MenuItem {
|
||||
required property var modelData
|
||||
|
||||
icon: modelData === SystemUsage.primaryDisk ? "check" : ""
|
||||
text: modelData.mount
|
||||
activeIcon: "storage"
|
||||
}
|
||||
}
|
||||
|
|
@ -191,6 +191,7 @@ class DashboardTokens : public ConfigObject {
|
|||
CONFIG_PROPERTY(int, mediaVisualiserSize, 80)
|
||||
CONFIG_PROPERTY(int, perfHeroCardWidth, 400)
|
||||
CONFIG_PROPERTY(int, perfUsageShapeSize, 100)
|
||||
CONFIG_PROPERTY(int, perfStorageTextWidth, 160)
|
||||
|
||||
public:
|
||||
explicit DashboardTokens(QObject* parent = nullptr)
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ Singleton {
|
|||
|
||||
// Individual disks: Array of { mount, used, total, free, perc }
|
||||
property var disks: []
|
||||
property var manualPrimaryDisk
|
||||
readonly property var primaryDisk: manualPrimaryDisk ?? disks[0] ?? null
|
||||
|
||||
property real lastCpuIdle
|
||||
property real lastCpuTotal
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue