import QtQuick import QtQuick.Layouts import QtQuick.Shapes import qs.Components import qs.Config Item { id: root property color accentColor: DynamicColors.palette.m3primary property real animatedPercentage: 0 readonly property real arcStartAngle: 0.75 * Math.PI readonly property real arcSweep: 1.5 * Math.PI property color borderColor: warning ? DynamicColors.palette.m3onError : mainColor property string icon required property color mainColor required property double percentage property bool shown: true property string subtitle property string title property color usageColor: warning ? DynamicColors.palette.m3error : mainColor property bool warning: percentage * 100 >= warningThreshold property int warningThreshold: 100 clip: true implicitHeight: root.parent.height implicitWidth: root.parent.width percentage: 0 visible: width > 0 && height > 0 Canvas { id: gaugeCanvas anchors.centerIn: parent height: width width: Math.min(parent.width, parent.height) Component.onCompleted: requestPaint() onPaint: { const ctx = getContext("2d"); ctx.reset(); const cx = width / 2; const cy = height / 2; const radius = (Math.min(width, height) - 12) / 2; const lineWidth = 3; ctx.beginPath(); ctx.arc(cx, cy, radius, root.arcStartAngle, root.arcStartAngle + root.arcSweep); ctx.lineWidth = lineWidth; ctx.lineCap = "round"; ctx.strokeStyle = DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHigh, 2); ctx.stroke(); if (root.animatedPercentage > 0) { ctx.beginPath(); ctx.arc(cx, cy, radius, root.arcStartAngle, root.arcStartAngle + root.arcSweep * root.animatedPercentage); ctx.lineWidth = lineWidth; ctx.lineCap = "round"; ctx.strokeStyle = root.accentColor; ctx.stroke(); } } Connections { function onAnimatedPercentageChanged() { gaugeCanvas.requestPaint(); } target: root } Connections { function onPaletteChanged() { gaugeCanvas.requestPaint(); } target: DynamicColors } } }