7.9 KiB · text History 7a88816
import QtQuick
import QtQuick.Layouts
import org.kde.plasma.components as PlasmaComponents3
import org.kde.kirigami as Kirigami

import "../Grafana.js" as G

// Bar gauge: one bar per series between min and max, filled solid
// ("basic"), as a gradient up to the value's colour ("gradient"), or in
// segments ("lcd"), with the unfilled track shown faintly.
Item {
    id: bars

    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 string mode: options.displayMode || "gradient"
    readonly property bool vertical: options.orientation === "vertical" || (options.orientation === "auto" && false)
    readonly property bool showUnfilled: options.showUnfilled !== false
    readonly property string valueMode: options.valueMode || "color"

    readonly property var entries: {
        var out = []
        var list = frame ? frame.series : []
        var tc = Kirigami.Theme.textColor.toString()
        var defaults = (panel.fieldConfig && panel.fieldConfig.defaults) || {}
        var vals = []
        for (var i = 0; i < list.length; i++) vals.push(G.reduce(list[i].values, calc))
        var nums = vals.filter(function(v) { return v !== null })
        var autoMax = nums.length ? Math.max.apply(null, nums) : 1
        var autoMin = nums.length ? Math.min(0, Math.min.apply(null, nums)) : 0
        for (var j = 0; j < list.length; j++) {
            var cfg = G.fieldConfig(panel, list[j])
            var min = cfg.min !== undefined && cfg.min !== null ? cfg.min : autoMin
            var max = cfg.max !== undefined && cfg.max !== null ? cfg.max : autoMax
            var v = vals[j]
            var frac = max > min && v !== null ? Math.max(0, Math.min(1, (v - min) / (max - min))) : 0
            var rng = { min: min, max: max }
            out.push({
                name: G.displayName(list[j], cfg), value: v, frac: frac,
                text: G.format(v, cfg.unit, cfg.decimals),
                color: G.seriesColor(cfg, j, v, rng, tc),
                low: G.seriesColor(cfg, j, min, rng, tc)
            })
        }
        return out
    }

    // horizontal: name above each bar when there's room, beside it when not
    readonly property real rowH: entries.length ? height / entries.length : height
    readonly property bool nameAbove: rowH > fm.height * 2.4

    FontMetrics { id: fm; font: Kirigami.Theme.smallFont }

    ColumnLayout {
        anchors.fill: parent
        spacing: 2
        visible: !bars.vertical

        Repeater {
            model: bars.entries

            delegate: GridLayout {
                id: rowItem
                required property var modelData
                Layout.fillWidth: true
                Layout.fillHeight: true
                Layout.maximumHeight: Kirigami.Units.gridUnit * 3
                columns: bars.nameAbove ? 2 : 3
                rowSpacing: 0
                columnSpacing: Kirigami.Units.smallSpacing

                PlasmaComponents3.Label {
                    Layout.columnSpan: bars.nameAbove ? 2 : 1
                    Layout.fillWidth: bars.nameAbove
                    Layout.preferredWidth: bars.nameAbove ? -1 : Math.min(implicitWidth, bars.width * 0.3)
                    font: Kirigami.Theme.smallFont
                    elide: Text.ElideRight
                    text: rowItem.modelData.name
                    textFormat: Text.PlainText
                }

                Item {
                    id: track
                    Layout.fillWidth: true
                    Layout.fillHeight: true
                    Layout.minimumHeight: 6

                    Rectangle {
                        anchors.fill: parent
                        visible: bars.showUnfilled
                        radius: 2
                        color: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.08)
                    }

                    Rectangle {
                        visible: bars.mode !== "lcd"
                        height: parent.height
                        width: parent.width * rowItem.modelData.frac
                        radius: 2
                        color: rowItem.modelData.color
                        gradient: bars.mode === "gradient" ? g : null
                        Gradient {
                            id: g
                            orientation: Gradient.Horizontal
                            GradientStop { position: 0; color: G.withAlpha(rowItem.modelData.low, 0.35) }
                            GradientStop { position: 1; color: rowItem.modelData.color }
                        }
                    }

                    Row {
                        visible: bars.mode === "lcd"
                        anchors.fill: parent
                        spacing: 2
                        readonly property int count: Math.max(4, Math.floor(width / 10))
                        Repeater {
                            model: parent.count
                            delegate: Rectangle {
                                required property int index
                                width: (track.width - 2 * (parent.count - 1)) / parent.count
                                height: track.height
                                radius: 1
                                color: rowItem.modelData.color
                                opacity: (index + 0.5) / parent.count <= rowItem.modelData.frac ? 1 : 0.12
                            }
                        }
                    }
                }

                PlasmaComponents3.Label {
                    Layout.minimumWidth: implicitWidth
                    font.pixelSize: Math.max(9, Math.min(track.height * 0.9, fm.height * 1.3))
                    font.bold: true
                    color: bars.valueMode === "text" || rowItem.modelData.color === "transparent" ? Kirigami.Theme.textColor : rowItem.modelData.color
                    visible: bars.valueMode !== "hidden"
                    text: rowItem.modelData.text
                }
            }
        }
    }

    // vertical bars, side by side
    RowLayout {
        anchors.fill: parent
        spacing: Kirigami.Units.smallSpacing
        visible: bars.vertical

        Repeater {
            model: bars.vertical ? bars.entries : []

            delegate: ColumnLayout {
                required property var modelData
                Layout.fillWidth: true
                Layout.fillHeight: true
                spacing: 2

                PlasmaComponents3.Label {
                    Layout.alignment: Qt.AlignHCenter
                    font.bold: true
                    color: modelData.color === "transparent" ? Kirigami.Theme.textColor : modelData.color
                    text: modelData.text
                }

                Item {
                    Layout.fillWidth: true
                    Layout.fillHeight: true
                    Rectangle {
                        anchors.fill: parent
                        visible: bars.showUnfilled
                        radius: 2
                        color: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.08)
                    }
                    Rectangle {
                        anchors.bottom: parent.bottom
                        width: parent.width
                        height: parent.height * modelData.frac
                        radius: 2
                        color: modelData.color
                    }
                }

                PlasmaComponents3.Label {
                    Layout.fillWidth: true
                    horizontalAlignment: Text.AlignHCenter
                    elide: Text.ElideRight
                    font: Kirigami.Theme.smallFont
                    text: modelData.name
                }
            }
        }
    }
}