pragma ComponentBehavior: Bound import QtQuick import "Util.js" as Util Flickable { id: root required property Theme theme required property Brightness brightnessService readonly property var panelState: brightnessService ? Util.parseJson(brightnessService.stateJson(), {}) : ({}) readonly property var displays: panelState.displays || [] readonly property var global: panelState.global || ({ "mode": "none", "level": 0, "levels": [] }) readonly property var setup: panelState.setup || ({ "needed": false, "available": false }) readonly property bool hasGlobal: global.mode !== "none" function setAllAt(x, width) { if (brightnessService && hasGlobal) brightnessService.setAll(Math.max(0, Math.min(1, x / Math.max(1, width)))); } function setDisplayAt(id, x, width) { if (brightnessService) brightnessService.setDisplay(id, Math.max(0, Math.min(1, x / Math.max(1, width)))); } width: parent ? parent.width : 0 contentWidth: width contentHeight: brightnessCol.height clip: true interactive: contentHeight > height boundsBehavior: Flickable.StopAtBounds flickableDirection: Flickable.VerticalFlick StableListModel { id: displayModel rows: root.displays } Column { id: brightnessCol width: root.width spacing: 12 PopupButton { visible: root.setup.needed theme: root.theme text: "setup ddc" role: "primary" enabled: root.setup.available tooltip: enabled ? "install ddc support for external displays" : "ddc setup unavailable" onClicked: if (root.brightnessService) root.brightnessService.setupDdc() } PopupCard { width: parent.width height: 48 visible: root.hasGlobal theme: root.theme PopupSlider { anchors.left: parent.left anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter theme: root.theme Accessible.name: "all displays brightness" value: Number(root.global.level || 0) onMoved: value => root.setAllAt(value, 1) } } Grid { id: presetGrid width: parent.width visible: root.hasGlobal columns: 4 columnSpacing: 8 Repeater { model: [0.25, 0.5, 0.75, 1] delegate: PopupButton { id: preset required property real modelData theme: root.theme width: Math.floor((presetGrid.width - presetGrid.columnSpacing * (presetGrid.columns - 1)) / presetGrid.columns) text: `${Math.round(preset.modelData * 100)}%` accessibleName: `all displays brightness ${text}` onClicked: root.setAllAt(preset.modelData, 1) } } } NuguText { theme: root.theme variant: "meta" visible: displayModel.count === 0 text: "no displays" } Repeater { model: displayModel delegate: PopupCard { id: displayRow required property var rowData readonly property bool controllable: !!rowData.controllable readonly property string issue: String(rowData.issue || "") readonly property real level: Math.max(0, Math.min(1, Number(rowData.level || 0))) theme: root.theme padding: 0 width: root.width height: 44 attention: issue.length > 0 Accessible.name: String(rowData.name || "display") Accessible.description: issue NuguText { id: displayName anchors.left: parent.left anchors.leftMargin: 10 anchors.verticalCenter: parent.verticalCenter width: Math.min(128, root.width * 0.28) theme: root.theme text: String(displayRow.rowData.name || "display") elide: Text.ElideRight } PopupSlider { id: displaySlider anchors.left: displayName.right anchors.leftMargin: 10 anchors.right: displayPercent.left anchors.rightMargin: 10 anchors.verticalCenter: parent.verticalCenter theme: root.theme enabled: displayRow.controllable Accessible.name: `${displayName.text} brightness` Accessible.description: displayRow.issue value: displayRow.level onMoved: value => root.setDisplayAt(String(displayRow.rowData.id), value, 1) } NuguText { id: displayPercent anchors.right: issueBadge.visible ? issueBadge.left : parent.right anchors.rightMargin: 10 anchors.verticalCenter: parent.verticalCenter width: 44 theme: root.theme variant: "meta" text: displayRow.controllable ? `${Math.round(displayRow.level * 100)}%` : "n/a" horizontalAlignment: Text.AlignRight } NuguText { id: issueBadge visible: displayRow.issue.length > 0 anchors.right: parent.right anchors.rightMargin: 10 anchors.verticalCenter: parent.verticalCenter width: 90 theme: root.theme variant: "meta" text: displayRow.issue.toLowerCase() color: root.theme.warning elide: Text.ElideRight horizontalAlignment: Text.AlignRight } } } } }