6.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

// Table: one row per label set (several instant queries become one
// "Value #A" column each) or the frame's own columns, with the panel's
// overrides for names, units and coloured text. Click a header to sort.
Item {
    id: table

    property var frame: null

    readonly property var panel: frame ? frame.panel : ({})
    readonly property var tableData: frame && frame.result && frame.result.results ? G.tableFromResults(frame.result.results, panel) : { columns: [], rows: [] }

    // columns with their field config resolved through the overrides
    readonly property var columns: tableData.columns.map(function(c) {
        var cfg = G.fieldConfig(panel, { name: c.name, fieldName: c.field, column: c.name, refId: c.refId })
        var cell = (cfg.custom && cfg.custom.cellOptions) || {}
        return { name: cfg.displayName || c.name, type: c.type, cfg: cfg, cell: cell.type || "auto",
                 hidden: !!(cfg.custom && cfg.custom.hidden) }
    })
    readonly property var visibleCols: {
        var out = []
        for (var i = 0; i < columns.length; i++) if (!columns[i].hidden) out.push(i)
        return out
    }

    property int sortCol: -1
    property bool sortDesc: false
    readonly property var rows: {
        var r = tableData.rows.slice()
        if (sortCol >= 0) {
            var c = sortCol, desc = sortDesc
            r.sort(function(a, b) {
                var x = a[c], y = b[c]
                var d = typeof x === "number" && typeof y === "number" ? x - y : String(x).localeCompare(String(y))
                return desc ? -d : d
            })
        }
        return r
    }

    function cellText(col, v) {
        var c = columns[col]
        if (c.type === "time") return v ? G.fullTime(v) : ""
        if (typeof v === "number" || v === null) return v === null ? "" : G.format(v, c.cfg.unit, c.cfg.decimals)
        return String(v)
    }

    function cellColor(col, v) {
        var c = columns[col]
        if (typeof v !== "number" || (c.cell !== "color-text" && c.cell !== "color-background")) return ""
        var color = G.seriesColor(c.cfg.color && c.cfg.color.mode ? c.cfg : Object.assign({}, c.cfg, { color: { mode: "thresholds" } }),
                                  col, v, { min: c.cfg.min, max: c.cfg.max }, "")
        return color === "" ? "" : color
    }

    readonly property real colW: visibleCols.length ? width / visibleCols.length : width
    readonly property real rowH: fm.height + Kirigami.Units.smallSpacing

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

    ColumnLayout {
        anchors.fill: parent
        spacing: 0

        Row {
            visible: (table.panel.options || {}).showHeader !== false
            Layout.fillWidth: true

            Repeater {
                model: table.visibleCols
                delegate: MouseArea {
                    required property int modelData
                    width: table.colW
                    height: table.rowH
                    cursorShape: Qt.PointingHandCursor
                    onClicked: {
                        if (table.sortCol !== modelData) { table.sortCol = modelData; table.sortDesc = false }
                        else if (!table.sortDesc) table.sortDesc = true
                        else table.sortCol = -1
                    }
                    PlasmaComponents3.Label {
                        anchors.fill: parent
                        anchors.leftMargin: 4
                        verticalAlignment: Text.AlignVCenter
                        horizontalAlignment: table.columns[parent.modelData].type === "number" ? Text.AlignRight : Text.AlignLeft
                        rightPadding: 4
                        elide: Text.ElideRight
                        font.pointSize: Kirigami.Theme.smallFont.pointSize
                        font.bold: true
                        text: table.columns[parent.modelData].name
                              + (table.sortCol === parent.modelData ? (table.sortDesc ? " ↓" : " ↑") : "")
                    }
                }
            }
        }

        Rectangle {
            Layout.fillWidth: true
            height: 1
            color: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.2)
        }

        ListView {
            Layout.fillWidth: true
            Layout.fillHeight: true
            clip: true
            model: table.rows
            boundsBehavior: Flickable.StopAtBounds

            delegate: Rectangle {
                id: rowItem
                required property var modelData
                required property int index
                width: ListView.view.width
                height: table.rowH
                color: index % 2 ? Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.03) : "transparent"

                Row {
                    Repeater {
                        model: table.visibleCols
                        delegate: Item {
                            required property int modelData
                            readonly property var raw: rowItem.modelData[modelData]
                            readonly property string tint: table.cellColor(modelData, raw)
                            width: table.colW
                            height: table.rowH

                            Rectangle {
                                anchors.fill: parent
                                anchors.margins: 1
                                visible: parent.tint !== "" && table.columns[parent.modelData].cell === "color-background"
                                color: parent.tint || "transparent"
                                radius: 2
                            }

                            PlasmaComponents3.Label {
                                anchors.fill: parent
                                anchors.leftMargin: 4
                                rightPadding: 4
                                verticalAlignment: Text.AlignVCenter
                                horizontalAlignment: typeof parent.raw === "number" ? Text.AlignRight : Text.AlignLeft
                                elide: Text.ElideRight
                                font: Kirigami.Theme.smallFont
                                color: parent.tint !== "" && table.columns[parent.modelData].cell === "color-text" ? parent.tint : Kirigami.Theme.textColor
                                text: table.cellText(parent.modelData, parent.raw)
                                textFormat: Text.PlainText
                            }
                        }
                    }
                }
            }

            PlasmaComponents3.Label {
                anchors.centerIn: parent
                visible: table.rows.length === 0 && !!table.frame && table.frame.result !== null
                opacity: 0.6
                text: i18n("No data")
            }
        }
    }
}