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

import "Grafana.js" as G

// A dashboard on Grafana's 24-column grid, one row unit `store.rowHeight`
// tall. Too narrow for that, panels stack full-width in reading order the
// way Grafana's own mobile layout does. Rows fold and unfold; a folded
// row's panels aren't queried until it opens.
PlasmaComponents3.ScrollView {
    id: view

    required property var store
    required property string uid

    readonly property var entry: (store.dashRev, store.dashboards[uid] || null)
    readonly property var vars: (store.dashRev, store.variablesFor(uid))
    readonly property var items: (store.dashRev, entry ? G.layout(entry.dashboard, store.folded[uid] || {}, vars) : [])

    readonly property real gap: Kirigami.Units.smallSpacing
    readonly property real unit: store.rowHeight
    // a fixed gutter for the scrollbar, rather than availableWidth: that
    // shrinks when the scrollbar appears, which re-lays out, which can
    // hide it again
    readonly property real gridWidth: Math.max(0, width - Kirigami.Units.gridUnit)
    readonly property bool stacked: gridWidth < Kirigami.Units.gridUnit * 30
    readonly property real col: gridWidth / 24

    // [{item, x, y, w, h}] in pixels
    readonly property var placed: {
        var out = []
        if (!stacked) {
            for (var i = 0; i < items.length; i++) {
                var it = items[i]
                out.push({ item: it, x: it.x * col, y: it.y * unit, w: it.w * col, h: it.kind === "row" ? unit : it.h * unit })
            }
            return out
        }
        var y = 0
        for (var j = 0; j < items.length; j++) {
            var s = items[j]
            var h = s.kind === "row" ? unit : Math.max(4, s.h) * unit
            out.push({ item: s, x: 0, y: y, w: gridWidth, h: h })
            y += h
        }
        return out
    }

    readonly property real contentBottom: {
        var b = 0
        for (var i = 0; i < placed.length; i++) b = Math.max(b, placed[i].y + placed[i].h)
        return b
    }

    contentWidth: gridWidth
    contentHeight: contentBottom

    Item {
        width: view.gridWidth
        height: view.contentBottom

        Repeater {
            model: view.placed

            delegate: Loader {
                id: cell

                required property var modelData
                readonly property var it: modelData.item

                x: modelData.x + view.gap / 2
                y: modelData.y + view.gap / 2
                width: Math.max(0, modelData.w - view.gap)
                height: Math.max(0, modelData.h - view.gap)

                sourceComponent: it.kind === "row" ? rowHeader : panelFrame

                Component {
                    id: rowHeader

                    PlasmaComponents3.ItemDelegate {
                        onClicked: view.store.toggleRow(view.uid, cell.it.panel.id, cell.it.collapsed)

                        contentItem: RowLayout {
                            spacing: Kirigami.Units.smallSpacing

                            Kirigami.Icon {
                                source: cell.it.collapsed ? "arrow-right" : "arrow-down"
                                Layout.preferredWidth: Kirigami.Units.iconSizes.small
                                Layout.preferredHeight: Kirigami.Units.iconSizes.small
                            }

                            Kirigami.Heading {
                                level: 4
                                text: G.panelTitle(cell.it.panel, view.vars)
                            }

                            PlasmaComponents3.Label {
                                visible: cell.it.collapsed
                                opacity: 0.6
                                font: Kirigami.Theme.smallFont
                                text: i18np("(%1 panel)", "(%1 panels)", cell.it.count)
                            }

                            Item { Layout.fillWidth: true }
                        }
                    }
                }

                Component {
                    id: panelFrame

                    PanelFrame {
                        store: view.store
                        uid: view.uid
                        panel: cell.it.panel
                        vars: view.vars
                    }
                }
            }
        }
    }

    PlasmaComponents3.BusyIndicator {
        anchors.centerIn: parent
        visible: !view.entry && view.uid !== ""
        running: visible
    }
}