Files
asepharyana 1cdb82a76f Sync config from arch
- hypr/apps.lua
- hypr/autostart.lua
- hypr/envs.lua
- hypr/hyprland.lua
- hypr/hyprsunset.conf
- hypr/input.lua
- hypr/looknfeel.lua
- hypr/omasettings.lua
- hypr/xdph.conf
- omarchy/branding/about.txt
- omarchy/branding/screensaver.txt
- omarchy/extensions/omarchy-menu.jsonc
- omarchy/hooks/battery-low.d/play-warning-sound.sample
- omarchy/hooks/font-set.d/show-font-notification.sample
- omarchy/hooks/post-boot.d/weather.sample
- omarchy/hooks/post-update.d/install-voxtype.hook
- omarchy/hooks/post-update.d/setup-agent.hook
- omarchy/hooks/post-update.d/setup-fingerprint.hook
- omarchy/hooks/post-update.d/show-update-notification.sample
- omarchy/hooks/pre-refresh-pacman.d/add-custom-repo.sample
- omarchy/hooks/theme-set.d/show-theme-notification.sample
- omarchy/shell.json
- omarchy/shell.toml
- omarchy/theme.name
- omarchy/themes/azure-glow/README.md
- omarchy/themes/azure-glow/alacritty.toml
- omarchy/themes/azure-glow/btop.theme
- omarchy/themes/azure-glow/hyprland.conf
- omarchy/themes/azure-glow/hyprlock.conf
- omarchy/themes/azure-glow/icons.theme
- … 269 more
2026-09-23 15:19:12 +07:00

778 lines
26 KiB
QML

pragma ComponentBehavior: Bound
import QtQuick
import qs.Commons
import qs.Ui
// Latency in detail: window picker, the two-leg chart at full height, and
// the per-leg statistics table.
Column {
id: tab
required property var panel
spacing: Style.space(12)
// The stats-table vocabulary, declared once for every table in this tab.
// There were three identical copies of these three components, scoped
// inside their own Grid, plus three formatters differing only in which
// dash they printed for a missing value — the "fix it everywhere" trap
// readout.js already sprang once. A missing figure is the em dash
// throughout now, which is the panel's own grammar for "no value".
component StatHead: Text {
textFormat: Text.PlainText
color: tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
font.letterSpacing: 1
horizontalAlignment: Text.AlignRight
}
component StatName: Text {
textFormat: Text.PlainText
color: tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.bodySmall
}
component StatVal: Text {
textFormat: Text.PlainText
color: tab.panel.fg
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.bodySmall
horizontalAlignment: Text.AlignRight
}
function ms(v) {
return v === null || v === undefined ? "\u2014" : v.toFixed(1) + " ms"
}
function pct(v) {
return v === null || v === undefined ? "\u2014"
: (v * 100).toFixed(2) + " %"
}
Component.onCompleted: panel.requestTests()
// The last peak test that captured latency both ways.
readonly property var loadTest: {
var tests = panel.testsData && panel.testsData.tests ? panel.testsData.tests : []
for (var i = 0; i < tests.length; i++) {
var t = tests[i]
if (t.kind === "peak" && t.ok && t.ping_idle !== null && t.ping_loaded !== null)
return t
}
return null
}
// A peak test whose loaded latency came out BELOW its idle latency did
// not measure the link under load: a queue cannot make packets arrive
// sooner. The old code clamped the difference at zero, which graded that
// A+ and handed back the best possible verdict on an unusable
// measurement. Withhold it instead — the same wrong-direction rule the
// daemon applies to the loaded/idle ratio.
readonly property bool loadTestUsable: loadTest
&& loadTest.ping_idle > 0
&& loadTest.ping_loaded >= loadTest.ping_idle * 0.95
readonly property real addedMs: loadTestUsable
? Math.max(0, loadTest.ping_loaded - loadTest.ping_idle) : 0
// Waveform's grading of latency added under load.
readonly property string bloatGrade: {
if (!loadTestUsable) return ""
if (addedMs < 5) return "A+"
if (addedMs < 30) return "A"
if (addedMs < 60) return "B"
if (addedMs < 200) return "C"
if (addedMs < 400) return "D"
return "F"
}
readonly property color bloatTone: {
if (bloatGrade === "A+" || bloatGrade === "A") return panel.okTone
if (bloatGrade === "B" || bloatGrade === "C") return panel.warnTone
return Color.urgent
}
// The kernel's timing for the machine's own TCP connections, or null while
// too few qualify — the daemon publishes nothing rather than a
// distribution drawn from a handful of sockets.
readonly property var sockets: panel.live ? panel.live.sockets : null
readonly property string socketsNote: {
if (!sockets) return ""
var q = sockets.queue_p50
var head = "Measured from your own traffic, no probe. "
if (q === null || q === undefined) return head
// Deliberately a claim about the ABSOLUTE delay, not its share of the
// round trip: a socket to another continent is mostly distance, and
// saying "almost none of it is queueing" there would be false.
if (q < 10) return head + "Queueing is a few milliseconds at most, so "
+ "nothing on the path is holding your traffic up. The rest of each "
+ "round trip is distance to the servers themselves."
if (q < 30) return head + "There is real queueing on the path now \u2014 "
+ "enough for a video call to start feeling it while something else "
+ "is downloading."
return head + "Queueing dominates what your apps feel. Something on the "
+ "path is holding packets \u2014 the legs above say which side of the "
+ "router it is on."
}
// What the instruments line says when folded shut. A count is worth more
// than the word "instruments" on its own, so the collapsed state still
// carries the fact most worth knowing: how many are feeding the score.
readonly property string instrumentSummary: {
var ins = panel.live && panel.live.instruments ? panel.live.instruments : []
if (!ins.length) return "NOT YET MEASURED"
var scored = 0, quarantined = 0
for (var i = 0; i < ins.length; i++) {
if (ins[i].active) scored++
else if (ins[i].quarantined) quarantined++
}
var parts = [scored + " SCORED"]
var standby = ins.length - scored - quarantined
if (standby > 0) parts.push(standby + " STANDBY")
if (quarantined > 0) parts.push(quarantined + " QUARANTINED")
return parts.join(" \u00b7 ")
}
// The idle/loaded split, published on `lag`. Null until enough probes have
// landed on each side of it to be worth comparing.
readonly property var underLoad: {
var l = panel.live && panel.live.lag ? panel.live.lag : null
if (!l || l.loaded_p50 === null || l.loaded_p50 === undefined) return null
return l
}
// Collapsed, this line is the block: typical and worst while the link was
// actually carrying traffic, which is the pair the headline 30 s window
// averages away.
readonly property string underLoadSummary: {
var u = underLoad
if (!u) return "NOT YET MEASURED"
var p50 = u.loaded_p50 !== null && u.loaded_p50 !== undefined
? Math.round(u.loaded_p50) : null
var p95 = u.loaded_p95 !== null && u.loaded_p95 !== undefined
? Math.round(u.loaded_p95) : null
if (p50 === null) return "NOT YET MEASURED"
var out = p50 + " MS TYPICAL"
if (p95 !== null) out += " \u00b7 " + p95 + " WORST"
return out
}
readonly property string underLoadNote: {
var u = underLoad
if (!u) return ""
var parts = []
if (u.loaded_samples !== undefined)
parts.push(u.loaded_samples + " of "
+ (u.loaded_samples + (u.idle_samples || 0)) + " probes landed while "
+ "the link was carrying traffic")
// Depth is what everyone reports. Duration is what you feel after the
// download has finished, and it is the half nobody shows.
if (u.drain_ms !== null && u.drain_ms !== undefined) {
var secs = (u.drain_ms / 1000).toFixed(1)
parts.push(u.drain_settled
? "the queue drained " + secs + " s after traffic stopped"
: "still above its quiet level " + secs + " s after traffic stopped")
}
return parts.join(". ") + "."
}
readonly property var windows: ["5m", "30m", "6h", "24h", "7d"]
property string window: "30m"
// 5m/30m paint straight from recent.json; longer windows query history.
readonly property bool fromRecent: window === "5m" || window === "30m"
onWindowChanged: if (!fromRecent) panel.requestHistory(window)
readonly property var chartPoints: {
if (fromRecent) {
var pts = panel.recentPoints
if (window === "5m") {
var cut = Date.now() / 1000 - 300
pts = pts.filter(function(p) { return p.t >= cut })
}
return pts
}
var h = panel.history
if (!h || !h.rows || panel.historyWindow !== window) return []
return h.rows.map(function(r) {
return {
t: r.ts,
local: r.local_p50,
total: (r.local_p50 !== null && r.wan_p50 !== null)
? r.local_p50 + r.wan_p50 : null,
loss: ((r.local_loss || 0) + (r.wan_loss || 0)) > 0
? (r.local_loss || 0) + (r.wan_loss || 0) : null,
}
})
}
Row {
spacing: Style.space(5)
Repeater {
model: tab.windows
Rectangle {
id: pill
required property string modelData
readonly property bool selected: tab.window === modelData
width: pillLabel.implicitWidth + Style.space(22)
height: Style.space(22)
color: selected
? Style.selectedFillFor(tab.panel.fg, Color.accent)
: (pillHover.hovered
? Style.hoverFillFor(tab.panel.fg, Color.accent)
: Style.normalFillFor(tab.panel.fg, Color.accent))
border.width: selected ? 0 : Style.normalBorderWidth
border.color: Style.normalBorderFor(tab.panel.fg, Color.accent)
Text {
id: pillLabel
textFormat: Text.PlainText
anchors.centerIn: parent
text: pill.modelData.toUpperCase()
color: pill.selected ? tab.panel.fg : tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
}
HoverHandler { id: pillHover }
TapHandler { onTapped: tab.window = pill.modelData }
}
}
}
Text {
textFormat: Text.PlainText
visible: !tab.fromRecent && tab.panel.historyLoading
text: "loading…"
color: tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
}
LegChart {
width: parent.width
height: Style.space(140)
points: tab.chartPoints
wanColor: Color.accent
localColor: tab.panel.dim
minScaleMs: 10
showScale: true
fontFamily: tab.panel.fontFamily
}
Row {
spacing: Style.space(16)
component LegendEntry: Row {
property color tint: "white"
property string label: ""
spacing: Style.space(6)
Rectangle {
width: Style.space(10); height: 2
color: parent.tint
anchors.verticalCenter: parent.verticalCenter
}
Text {
textFormat: Text.PlainText
text: parent.label
color: tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
anchors.verticalCenter: parent.verticalCenter
}
}
LegendEntry { tint: Color.accent; label: "wan leg (router → internet)" }
LegendEntry { tint: tab.panel.dim; label: "local leg (you → router)" }
}
PanelSeparator { width: parent.width }
// Stats table: rows of metric, local, wan — from live.json's 30 s window.
Grid {
width: parent.width
columns: 3
columnSpacing: Style.space(14)
rowSpacing: Style.space(6)
readonly property real cell: (width - Style.space(14) * 2) / 3
readonly property var local: tab.panel.live ? tab.panel.live.local : null
readonly property var wan: tab.panel.live ? tab.panel.live.wan : null
StatHead { width: parent.cell; text: "LAST 30 S" ; horizontalAlignment: Text.AlignLeft }
StatHead { width: parent.cell; text: "LOCAL LEG" }
StatHead { width: parent.cell; text: "WAN LEG" }
StatName { width: parent.cell; text: "median" }
StatVal { width: parent.cell; text: tab.ms(parent.local ? parent.local.p50 : null) }
StatVal { width: parent.cell; text: tab.ms(parent.wan ? parent.wan.p50 : null) }
StatName { width: parent.cell; text: "p95" }
StatVal { width: parent.cell; text: tab.ms(parent.local ? parent.local.p95 : null) }
StatVal { width: parent.cell; text: tab.ms(parent.wan ? parent.wan.p95 : null) }
StatName { width: parent.cell; text: "worst" }
StatVal { width: parent.cell; text: tab.ms(parent.local ? parent.local.max : null) }
StatVal { width: parent.cell; text: tab.ms(parent.wan ? parent.wan.max : null) }
StatName { width: parent.cell; text: "jitter" }
StatVal { width: parent.cell; text: tab.ms(parent.local ? parent.local.jitter : null) }
StatVal { width: parent.cell; text: tab.ms(parent.wan ? parent.wan.jitter : null) }
StatName { width: parent.cell; text: "loss" }
StatVal {
width: parent.cell
text: tab.pct(parent.local ? parent.local.loss : null)
color: parent.local && parent.local.loss > 0 ? tab.panel.warnTone : tab.panel.fg
}
StatVal {
width: parent.cell
text: tab.pct(parent.wan ? parent.wan.loss : null)
color: parent.wan && parent.wan.loss > 0 ? tab.panel.warnTone : tab.panel.fg
}
}
PanelSeparator { width: parent.width }
// ---- what the machine's own connections are experiencing ----------------
// The table above is our probe. This is the kernel's own timing for the
// user's real TCP traffic to their real destinations: no probe, no
// privilege. `floor` is the lowest round trip each path has ever shown, so
// "queueing" is the delay left once distance is divided out — which is the
// only figure that compares a socket next door with one on another
// continent.
Text {
textFormat: Text.PlainText
text: "AS YOUR APPS SEE IT"
+ (tab.sockets ? " \u00b7 " + tab.sockets.sockets + " CONNECTIONS" : "")
color: tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
font.letterSpacing: 1
}
Text {
textFormat: Text.PlainText
visible: !tab.sockets
width: parent.width
wrapMode: Text.WordWrap
text: "Not enough measured connections yet. This fills in once a few "
+ "apps are talking over TCP."
color: tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
}
Grid {
width: parent.width
visible: !!tab.sockets
columns: 3
columnSpacing: Style.space(14)
rowSpacing: Style.space(6)
readonly property real cell: (width - Style.space(14) * 2) / 3
readonly property var s: tab.sockets
StatHead { width: parent.cell; text: "TCP, LIVE"; horizontalAlignment: Text.AlignLeft }
StatHead { width: parent.cell; text: "TYPICAL" }
StatHead { width: parent.cell; text: "WORST" }
StatName { width: parent.cell; text: "round trip" }
StatVal { width: parent.cell; text: tab.ms(parent.s ? parent.s.rtt_p50 : null) }
StatVal { width: parent.cell; text: tab.ms(parent.s ? parent.s.rtt_p95 : null) }
StatName { width: parent.cell; text: "path floor" }
StatVal { width: parent.cell; text: tab.ms(parent.s ? parent.s.floor_p50 : null) }
StatVal { width: parent.cell; text: "\u2014" }
StatName { width: parent.cell; text: "queueing" }
StatVal {
width: parent.cell
text: tab.ms(parent.s ? parent.s.queue_p50 : null)
color: parent.s && parent.s.queue_p50 > 30 ? tab.panel.warnTone : tab.panel.fg
}
StatVal {
width: parent.cell
text: tab.ms(parent.s ? parent.s.queue_p95 : null)
color: parent.s && parent.s.queue_p95 > 60 ? tab.panel.warnTone : tab.panel.fg
}
}
Text {
textFormat: Text.PlainText
visible: !!tab.sockets
width: parent.width
wrapMode: Text.WordWrap
text: tab.socketsNote
color: tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
}
PanelSeparator { width: parent.width }
// Folded shut by default: four rows and a paragraph is a lot of the tab's
// height for something that only matters when you are asking which probe
// produced the number. The header still reports the count, and the whole
// row is the control — no separate button, no extra line.
Item {
width: parent.width
height: instHeader.implicitHeight
Text {
id: instHeader
textFormat: Text.PlainText
text: "INSTRUMENTS \u00b7 " + (tab.panel.instrumentsExpanded
? "WHAT MEASURES THE INTERNET LEG" : tab.instrumentSummary)
color: instHover.hovered ? tab.panel.fg : tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
font.letterSpacing: 1
}
Text {
textFormat: Text.PlainText
anchors.right: parent.right
anchors.verticalCenter: instHeader.verticalCenter
// nf-md-chevron_down / nf-md-chevron_right
text: tab.panel.instrumentsExpanded ? "\u{f0140}" : "\u{f0142}"
color: instHover.hovered ? tab.panel.fg : tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
}
HoverHandler { id: instHover }
TapHandler {
onTapped: tab.panel.instrumentsExpanded = !tab.panel.instrumentsExpanded
}
}
// The bench: the two with the fewest losses and steadiest tails hold
// the seats and feed the score; the rest idle at a tenth of the rate.
Column {
width: parent.width
visible: tab.panel.instrumentsExpanded
height: visible ? implicitHeight : 0
spacing: Style.space(6)
Repeater {
model: tab.panel.live && tab.panel.live.instruments
? tab.panel.live.instruments : []
Row {
id: instRow
required property var modelData
width: parent.width
spacing: Style.space(8)
Rectangle {
width: Style.space(5)
height: Style.space(5)
color: instRow.modelData.active ? tab.panel.okTone : tab.panel.dim
anchors.verticalCenter: parent.verticalCenter
}
Text {
textFormat: Text.PlainText
width: parent.width - Style.space(5) - Style.space(60)
- Style.space(56) - Style.space(74) - Style.space(8) * 4
text: instRow.modelData.kind + " \u00b7 " + instRow.modelData.target
color: tab.panel.fg
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.bodySmall
elide: Text.ElideMiddle
}
Text {
textFormat: Text.PlainText
width: Style.space(60)
horizontalAlignment: Text.AlignRight
text: instRow.modelData.p50 !== null && instRow.modelData.p50 !== undefined
? instRow.modelData.p50.toFixed(1) + " ms" : "--"
color: tab.panel.fg
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.bodySmall
}
Text {
textFormat: Text.PlainText
width: Style.space(56)
horizontalAlignment: Text.AlignRight
text: {
var l = instRow.modelData.loss
return l !== null && l !== undefined ? (l * 100).toFixed(1) + "%" : "--"
}
color: instRow.modelData.loss ? tab.panel.warnTone : tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
}
Text {
textFormat: Text.PlainText
width: Style.space(74)
horizontalAlignment: Text.AlignRight
text: instRow.modelData.active ? "scored"
: instRow.modelData.quarantined ? "quarantined" : "standby"
color: instRow.modelData.active ? tab.panel.okTone : tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
}
}
}
}
Text {
textFormat: Text.PlainText
visible: tab.panel.instrumentsExpanded
height: visible ? implicitHeight : 0
width: parent.width
text: "Two instruments feed the score at a time, re-ranked every five "
+ "minutes on loss and tail stability \u2014 one bad anchor cannot "
+ "poison the number."
color: tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
wrapMode: Text.WordWrap
}
PanelSeparator { width: parent.width }
// ---- latency under load (bufferbloat) -----------------------------------
Item {
width: parent.width
height: loadLabel.implicitHeight
Text {
id: loadLabel
textFormat: Text.PlainText
text: "LATENCY UNDER LOAD"
color: tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
font.letterSpacing: 1
}
Text {
textFormat: Text.PlainText
anchors.right: parent.right
text: tab.loadTestUsable ? "measured during the last peak test" : ""
color: tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
}
}
PanelSeparator { width: parent.width }
Text {
textFormat: Text.PlainText
visible: !tab.loadTestUsable
width: parent.width
text: tab.loadTest && !tab.loadTestUsable
? "The last peak test read a lower latency under load than at rest, "
+ "which is not something a busy link can do — so it is not graded. "
+ "Run another and it should settle."
: "No measurement yet — run a peak test and the probes will time the "
+ "connection while it is saturated."
color: tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.bodySmall
wrapMode: Text.WordWrap
}
Row {
width: parent.width
visible: tab.loadTestUsable
spacing: Style.space(12)
Column {
width: parent.width - gradeCol.width - Style.space(12)
spacing: Style.space(6)
anchors.verticalCenter: parent.verticalCenter
readonly property real scaleMs: tab.loadTest
? Math.max(1, Math.max(tab.loadTest.ping_idle, tab.loadTest.ping_loaded) * 2.2)
: 1
component LoadBar: Row {
property string label: ""
property var ms: null
property color tint: tab.panel.okTone
width: parent.width
spacing: Style.space(9)
Text {
textFormat: Text.PlainText
width: Style.space(44)
text: parent.label
color: tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
width: parent.width - Style.space(44) - Style.space(52) - Style.space(9) * 2
height: Style.space(8)
color: Qt.rgba(tab.panel.fg.r, tab.panel.fg.g, tab.panel.fg.b, 0.10)
anchors.verticalCenter: parent.verticalCenter
Rectangle {
height: parent.height
width: parent.width * (parent.parent.ms !== null
? Math.min(1, parent.parent.ms / parent.parent.parent.scaleMs) : 0)
color: parent.parent.tint
}
}
Text {
textFormat: Text.PlainText
width: Style.space(52)
horizontalAlignment: Text.AlignRight
text: parent.ms !== null ? Math.round(parent.ms) + " ms" : "--"
color: tab.panel.fg
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.bodySmall
anchors.verticalCenter: parent.verticalCenter
}
}
LoadBar {
label: "idle"
ms: tab.loadTest ? tab.loadTest.ping_idle : null
tint: tab.panel.okTone
}
LoadBar {
label: "loaded"
ms: tab.loadTest ? tab.loadTest.ping_loaded : null
tint: tab.addedMs < 30 ? tab.panel.okTone : tab.panel.warnTone
}
}
Column {
id: gradeCol
width: Style.space(76)
spacing: Style.space(2)
anchors.verticalCenter: parent.verticalCenter
Text {
textFormat: Text.PlainText
anchors.horizontalCenter: parent.horizontalCenter
text: tab.bloatGrade
color: tab.bloatTone
font.family: tab.panel.fontFamily
font.pixelSize: Style.fontPx(1.7)
font.weight: Font.Bold
}
Text {
textFormat: Text.PlainText
anchors.horizontalCenter: parent.horizontalCenter
text: "BUFFERBLOAT"
color: tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
font.letterSpacing: 1
}
}
}
Text {
textFormat: Text.PlainText
visible: tab.loadTestUsable
width: parent.width
text: "+" + Math.round(tab.addedMs) + " ms added under full load. Below 30 ms "
+ "a video call stays clean while someone else is downloading."
color: tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
wrapMode: Text.WordWrap
}
// ---- under load, from the traffic you were already sending -------------
// The block above needs a peak test. This one needs nothing: every probe
// carries whether the link was busy when it landed, so the same samples
// answer both "how bad does it get while in use" and "how fast does it
// recover" without generating a byte.
PanelSeparator { width: parent.width; visible: !!tab.underLoad }
// Folded shut like the bench above it: adding a table and a note pushed
// the tab past the panel's height again, and the collapsed line already
// carries the two numbers worth reading.
Item {
width: parent.width
visible: !!tab.underLoad
height: visible ? ulHeader.implicitHeight : 0
Text {
id: ulHeader
textFormat: Text.PlainText
text: "WHILE YOU WERE USING IT \u00b7 " + (tab.panel.underLoadExpanded
? "LAST 5 MIN" : tab.underLoadSummary)
color: ulHover.hovered ? tab.panel.fg : tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
font.letterSpacing: 1
}
Text {
textFormat: Text.PlainText
anchors.right: parent.right
anchors.verticalCenter: ulHeader.verticalCenter
text: tab.panel.underLoadExpanded ? "\u{f0140}" : "\u{f0142}"
color: ulHover.hovered ? tab.panel.fg : tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
}
HoverHandler { id: ulHover }
TapHandler {
onTapped: tab.panel.underLoadExpanded = !tab.panel.underLoadExpanded
}
}
Grid {
width: parent.width
visible: !!tab.underLoad && tab.panel.underLoadExpanded
height: visible ? implicitHeight : 0
columns: 3
columnSpacing: Style.space(14)
rowSpacing: Style.space(6)
readonly property real cell: (width - Style.space(14) * 2) / 3
readonly property var u: tab.underLoad
StatHead { width: parent.cell; text: "PROBES"; horizontalAlignment: Text.AlignLeft }
StatHead { width: parent.cell; text: "TYPICAL" }
StatHead { width: parent.cell; text: "WORST" }
StatName { width: parent.cell; text: "while busy" }
StatVal {
width: parent.cell
text: tab.ms(parent.u ? parent.u.loaded_p50 : null)
}
// Scoped to the samples taken under load, so a short burst is not
// averaged away by the quiet either side of it — which is what the
// headline 30 s window does to it.
StatVal {
width: parent.cell
text: tab.ms(parent.u ? parent.u.loaded_p95 : null)
color: parent.u && parent.u.loaded_p95 > 100
? tab.panel.warnTone : tab.panel.fg
}
StatName { width: parent.cell; text: "while quiet" }
StatVal {
width: parent.cell
text: tab.ms(parent.u ? parent.u.idle_p50 : null)
}
StatVal { width: parent.cell; text: "\u2014" }
}
Text {
textFormat: Text.PlainText
visible: !!tab.underLoad && tab.panel.underLoadExpanded
height: visible ? implicitHeight : 0
width: parent.width
wrapMode: Text.WordWrap
text: tab.underLoadNote
color: tab.panel.dim
font.family: tab.panel.fontFamily
font.pixelSize: Style.font.caption
}
}