3.0 KiB · text History 35c3541
import QtQuick
import QtQuick.Layouts
import org.kde.plasma.components as PlasmaComponents3
import org.kde.kirigami as Kirigami

import "../Grafana.js" as G

// Pie / donut: each series reduced to one slice, with a legend beside it.
Item {
    id: pie

    property var frame: null

    readonly property var panel: frame ? frame.panel : ({})
    readonly property var options: panel.options || {}
    readonly property string calc: ((options.reduceOptions && options.reduceOptions.calcs) || ["lastNotNull"])[0] || "lastNotNull"

    readonly property var slices: {
        var out = []
        var list = frame ? frame.series : []
        var tc = Kirigami.Theme.textColor.toString()
        for (var i = 0; i < list.length; i++) {
            var cfg = G.fieldConfig(panel, list[i])
            var v = G.reduce(list[i].values, calc)
            if (v === null || v <= 0) continue
            out.push({ name: G.displayName(list[i], cfg), value: v, text: G.format(v, cfg.unit, cfg.decimals),
                       color: G.seriesColor(cfg.color && cfg.color.mode === "thresholds" ? cfg : Object.assign({}, cfg, { color: { mode: "palette-classic" } }), i, v, null, tc) })
        }
        return out
    }
    readonly property real total: slices.reduce(function(a, s) { return a + s.value }, 0)

    onSlicesChanged: canvas.requestPaint()

    RowLayout {
        anchors.fill: parent
        spacing: Kirigami.Units.smallSpacing

        Canvas {
            id: canvas
            Layout.fillHeight: true
            Layout.preferredWidth: height
            onWidthChanged: requestPaint()
            onPaint: {
                var ctx = getContext("2d")
                ctx.reset()
                var r = Math.min(width, height) / 2 - 2
                if (r <= 0 || pie.total <= 0) return
                var a = -Math.PI / 2
                for (var i = 0; i < pie.slices.length; i++) {
                    var s = pie.slices[i]
                    var b = a + s.value / pie.total * Math.PI * 2
                    ctx.beginPath(); ctx.moveTo(width / 2, height / 2)
                    ctx.arc(width / 2, height / 2, r, a, b); ctx.closePath()
                    ctx.fillStyle = s.color
                    ctx.fill()
                    a = b
                }
                if (pie.options.pieType === "donut") {
                    ctx.globalCompositeOperation = "destination-out"
                    ctx.beginPath(); ctx.arc(width / 2, height / 2, r * 0.6, 0, Math.PI * 2); ctx.fill()
                }
            }
        }

        ListView {
            Layout.fillWidth: true
            Layout.fillHeight: true
            clip: true
            model: pie.slices
            delegate: Row {
                required property var modelData
                spacing: Kirigami.Units.smallSpacing
                Rectangle { width: 10; height: 10; radius: 2; color: modelData.color; anchors.verticalCenter: parent.verticalCenter }
                PlasmaComponents3.Label { font: Kirigami.Theme.smallFont; text: modelData.name + "  " + modelData.text }
            }
        }
    }
}