pragma ComponentBehavior: Bound import QtQuick import QtQuick.Layouts import ZShell.Config import ZShell.Components import ZShell.Services import qs.Components import qs.Services Item { id: root required property int radius implicitHeight: layout.implicitHeight ServiceRef { service: Cpu } ServiceRef { service: Memory } RowLayout { id: layout anchors.fill: parent spacing: Tokens.spacing.medium UsageCard { accent: Colors.palette.m3primary buffer: ResourceUsage.cpuBuffer icon: "memory" label: qsTr("CPU") values: ResourceUsage.cpuInfo } UsageCard { accent: Colors.palette.m3tertiary buffer: ResourceUsage.memoryBuffer icon: "memory_alt" label: qsTr("Memory") values: ResourceUsage.memoryInfo } } component UsageCard: CustomRect { id: card property color accent required property var buffer property string icon property string label property list values color: Colors.tPalette.m3surfaceContainer radius: root.radius Layout.fillWidth: true Layout.fillHeight: true implicitHeight: mainLayout.implicitHeight + mainLayout.anchors.margins * 2 ColumnLayout { id: mainLayout anchors.fill: parent anchors.margins: Tokens.padding.large spacing: 0 RowLayout { spacing: Tokens.spacing.small MaterialIcon { color: card.accent text: card.icon } CustomText { text: card.label } } Item { id: graphWrapper Layout.fillHeight: true Layout.fillWidth: true implicitHeight: infoColumn.implicitHeight Item { anchors.left: parent.left anchors.top: parent.top anchors.bottom: parent.bottom anchors.right: infoColumn.left SparklineItem { id: sparkline anchors.fill: parent historyLength: ResourceUsage.historyLength line1: card.buffer line1Color: card.accent line1FillAlpha: 0.15 maxValue: 1.0 slideProgress: 1 Connections { function onValuesChanged(): void { slideAnim.restart(); } target: card.buffer } NumberAnimation { id: slideAnim duration: Config.dashboard.resourceUpdateInterval easing.type: Easing.Linear from: 0 property: "slideProgress" target: sparkline to: 1 } } // "Collecting data" placeholder CustomText { anchors.centerIn: parent color: Colors.palette.m3outline text: qsTr("Collecting data...") visible: card.buffer.count < 2 } } ColumnLayout { id: infoColumn anchors.right: parent.right anchors.bottom: parent.bottom width: { const prefWidth = graphWrapper.width / 3; const minWidth = graphWrapper.width / 4; if (prefWidth < implicitWidth) return implicitWidth; else if (prefWidth >= implicitWidth * 2) return minWidth; else return prefWidth; } Repeater { model: card.values Item { id: moreInfo required property var modelData Layout.leftMargin: Tokens.spacing.medium Layout.fillWidth: true implicitWidth: label.implicitWidth + value.implicitWidth + label.anchors.margins * 2 implicitHeight: label.implicitHeight CustomText { id: label anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter color: Colors.palette.m3onSurfaceVariant text: moreInfo.modelData.label } CustomText { id: value anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter color: card.accent text: moreInfo.modelData.value } } } } } } } }