Unified look
This commit is contained in:
@@ -616,11 +616,11 @@ Panel {
|
|||||||
width: scrollArea.availableWidth
|
width: scrollArea.availableWidth
|
||||||
spacing: Style.space(14)
|
spacing: Style.space(14)
|
||||||
|
|
||||||
// ---------- Hero: speaker icon · mood · % ----------
|
// ---------- Hero: speaker icon · title/status · % ----------
|
||||||
Item {
|
Item {
|
||||||
id: heroItem
|
id: heroItem
|
||||||
width: parent.width
|
width: parent.width
|
||||||
implicitHeight: Math.max(heroIcon.implicitHeight, heroPercent.implicitHeight)
|
implicitHeight: Math.max(heroIcon.implicitHeight, heroLabels.implicitHeight, heroPercent.implicitHeight)
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: heroIcon
|
id: heroIcon
|
||||||
@@ -639,23 +639,39 @@ Panel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Column {
|
||||||
id: heroLabel
|
id: heroLabels
|
||||||
text: root.outputVolumeName(
|
|
||||||
outputSlider.dragging ? outputSlider.liveValue : root.outputVolume,
|
|
||||||
root.outputMuted
|
|
||||||
).toUpperCase()
|
|
||||||
color: Qt.darker(root.bar.foreground, 1.4)
|
|
||||||
font.family: root.bar.fontFamily
|
|
||||||
font.pixelSize: Style.font.caption
|
|
||||||
font.bold: true
|
|
||||||
font.letterSpacing: 1.2
|
|
||||||
anchors.left: heroIcon.right
|
anchors.left: heroIcon.right
|
||||||
anchors.leftMargin: Style.space(14)
|
anchors.leftMargin: Style.space(14)
|
||||||
anchors.right: heroPercent.left
|
anchors.right: heroPercent.left
|
||||||
anchors.rightMargin: Style.space(10)
|
anchors.rightMargin: Style.space(10)
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
elide: Text.ElideRight
|
spacing: Style.space(2)
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Audio"
|
||||||
|
color: root.bar.foreground
|
||||||
|
font.family: root.bar.fontFamily
|
||||||
|
font.pixelSize: Style.font.title
|
||||||
|
font.bold: true
|
||||||
|
elide: Text.ElideRight
|
||||||
|
width: parent.width
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: heroLabel
|
||||||
|
text: root.outputVolumeName(
|
||||||
|
outputSlider.dragging ? outputSlider.liveValue : root.outputVolume,
|
||||||
|
root.outputMuted
|
||||||
|
).toUpperCase()
|
||||||
|
color: Qt.darker(root.bar.foreground, 1.4)
|
||||||
|
font.family: root.bar.fontFamily
|
||||||
|
font.pixelSize: Style.font.caption
|
||||||
|
font.bold: true
|
||||||
|
font.letterSpacing: 1.2
|
||||||
|
elide: Text.ElideRight
|
||||||
|
width: parent.width
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
|||||||
+117
-113
@@ -88,19 +88,34 @@ Panel {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property int phraseIndex: 0
|
||||||
|
readonly property var activePhrases: [
|
||||||
|
"Untangling wires",
|
||||||
|
"Streaming vikings",
|
||||||
|
"Pairing mysteries",
|
||||||
|
"Herding headsets",
|
||||||
|
"Taming radios",
|
||||||
|
"Summoning speakers",
|
||||||
|
"Wrangling codecs",
|
||||||
|
"Polishing packets"
|
||||||
|
]
|
||||||
|
readonly property bool rotatingPhrases: adapter && adapter.enabled
|
||||||
|
readonly property string heroStatusText: {
|
||||||
|
if (!adapter) return "No adapter"
|
||||||
|
if (!adapter.enabled) return "Bluetooth off"
|
||||||
|
return activePhrases[phraseIndex % activePhrases.length]
|
||||||
|
}
|
||||||
|
|
||||||
// Single cursor model shared by keyboard and mouse. Sections:
|
// Single cursor model shared by keyboard and mouse. Sections:
|
||||||
// "header" — 2 action pills (scan, toggle); h/l moves between
|
|
||||||
// them, Enter activates.
|
|
||||||
// "connected" — currently connected devices; Enter disconnects.
|
// "connected" — currently connected devices; Enter disconnects.
|
||||||
// "known" — remembered devices; Enter connects.
|
// "known" — remembered devices; Enter connects.
|
||||||
// "discovered" — unremembered devices visible while scanning; Enter connects.
|
// "discovered" — unremembered devices visible while scanning; Enter connects.
|
||||||
// Visuals always come from CursorSurface (hasCursor / current),
|
// Visuals always come from CursorSurface (hasCursor / current),
|
||||||
// never from containsMouse. Mouse hover updates root cursor state too,
|
// never from containsMouse. Mouse hover updates root cursor state too,
|
||||||
// guaranteeing one highlight on screen.
|
// guaranteeing one highlight on screen.
|
||||||
property string focusSection: "header"
|
property string focusSection: "connected"
|
||||||
property int selectedIndex: 1 // default = toggle pill once the cursor is revealed
|
property int selectedIndex: 0
|
||||||
property bool cursorActive: false
|
property bool cursorActive: false
|
||||||
readonly property int headerPillCount: 2
|
|
||||||
|
|
||||||
// Stable identity for the focused device. Devices move between sections as
|
// Stable identity for the focused device. Devices move between sections as
|
||||||
// they connect, disconnect, pair, or get forgotten, so follow the BlueZ
|
// they connect, disconnect, pair, or get forgotten, so follow the BlueZ
|
||||||
@@ -115,7 +130,6 @@ Panel {
|
|||||||
: "transparent"
|
: "transparent"
|
||||||
|
|
||||||
function sectionCount(section) {
|
function sectionCount(section) {
|
||||||
if (section === "header") return headerPillCount
|
|
||||||
if (section === "connected") return connectedDevices.length
|
if (section === "connected") return connectedDevices.length
|
||||||
if (section === "known") return knownDevices.length
|
if (section === "known") return knownDevices.length
|
||||||
if (section === "discovered") return discoveredDevices.length
|
if (section === "discovered") return discoveredDevices.length
|
||||||
@@ -123,7 +137,6 @@ Panel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function sectionVisible(section) {
|
function sectionVisible(section) {
|
||||||
if (section === "header") return true
|
|
||||||
if (section === "connected") return connectedDevices.length > 0
|
if (section === "connected") return connectedDevices.length > 0
|
||||||
if (section === "known") return knownDevices.length > 0
|
if (section === "known") return knownDevices.length > 0
|
||||||
if (section === "discovered") return adapter && adapter.discovering && discoveredDevices.length > 0
|
if (section === "discovered") return adapter && adapter.discovering && discoveredDevices.length > 0
|
||||||
@@ -131,7 +144,7 @@ Panel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readonly property var visibleSections: {
|
readonly property var visibleSections: {
|
||||||
var list = ["header"]
|
var list = []
|
||||||
if (sectionVisible("connected")) list.push("connected")
|
if (sectionVisible("connected")) list.push("connected")
|
||||||
if (sectionVisible("known")) list.push("known")
|
if (sectionVisible("known")) list.push("known")
|
||||||
if (sectionVisible("discovered")) list.push("discovered")
|
if (sectionVisible("discovered")) list.push("discovered")
|
||||||
@@ -228,10 +241,7 @@ Panel {
|
|||||||
if (changed) pendingActions = next
|
if (changed) pendingActions = next
|
||||||
}
|
}
|
||||||
|
|
||||||
// j/k navigates between sections row-by-row. The header is treated as a
|
// j/k navigates between device sections row-by-row.
|
||||||
// SINGLE row (its pills sit on one horizontal line), so j/k from devices
|
|
||||||
// jumps to/from the header as a unit, and h/l moves between the three
|
|
||||||
// pills inside it. This matches wifi's DNS-pill behaviour.
|
|
||||||
function moveCursor(delta) {
|
function moveCursor(delta) {
|
||||||
var sections = visibleSections
|
var sections = visibleSections
|
||||||
if (!sections || sections.length === 0) return
|
if (!sections || sections.length === 0) return
|
||||||
@@ -239,48 +249,21 @@ Panel {
|
|||||||
if (sIdx < 0) { focusSection = sections[0]; selectedIndex = 0; return }
|
if (sIdx < 0) { focusSection = sections[0]; selectedIndex = 0; return }
|
||||||
|
|
||||||
var idx = selectedIndex
|
var idx = selectedIndex
|
||||||
var inHeader = focusSection === "header"
|
var max = sectionCount(focusSection) - 1
|
||||||
var max = inHeader ? 0 : sectionCount(focusSection) - 1
|
|
||||||
|
|
||||||
if (delta > 0) {
|
if (delta > 0) {
|
||||||
if (!inHeader && idx < max) { selectedIndex = idx + 1; return }
|
if (idx < max) { selectedIndex = idx + 1; return }
|
||||||
if (sIdx < sections.length - 1) {
|
if (sIdx < sections.length - 1) {
|
||||||
focusSection = sections[sIdx + 1]
|
focusSection = sections[sIdx + 1]
|
||||||
// Entering the header from below shouldn't happen (header is first),
|
|
||||||
// but other entries start at 0.
|
|
||||||
selectedIndex = 0
|
selectedIndex = 0
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!inHeader && idx > 0) { selectedIndex = idx - 1; return }
|
if (idx > 0) { selectedIndex = idx - 1; return }
|
||||||
if (sIdx > 0) {
|
if (sIdx > 0) { focusSection = sections[sIdx - 1]; selectedIndex = sectionCount(focusSection) - 1 }
|
||||||
focusSection = sections[sIdx - 1]
|
|
||||||
// Entering the header always lands on the toggle pill — the most
|
|
||||||
// common action and consistent with the on-open default. h/l from
|
|
||||||
// there moves to scan.
|
|
||||||
selectedIndex = focusSection === "header" ? 1 : sectionCount(focusSection) - 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// h/l: only meaningful in the header. In device sections it's a no-op
|
|
||||||
// — j/k is the canonical row navigator there.
|
|
||||||
function moveCursorH(delta) {
|
|
||||||
if (focusSection !== "header") return
|
|
||||||
var next = selectedIndex + delta
|
|
||||||
if (next < 0) next = 0
|
|
||||||
if (next > headerPillCount - 1) next = headerPillCount - 1
|
|
||||||
selectedIndex = next
|
|
||||||
}
|
|
||||||
|
|
||||||
function activateCursor() {
|
function activateCursor() {
|
||||||
if (focusSection === "header") {
|
|
||||||
if (selectedIndex === 0) {
|
|
||||||
if (adapter && adapter.enabled) adapter.discovering = !adapter.discovering
|
|
||||||
} else if (selectedIndex === 1) {
|
|
||||||
if (adapter) adapter.enabled = !adapter.enabled
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (focusSection === "connected" || focusSection === "known") {
|
if (focusSection === "connected" || focusSection === "known") {
|
||||||
var dev = deviceAt(focusSection, selectedIndex)
|
var dev = deviceAt(focusSection, selectedIndex)
|
||||||
if (!dev) return
|
if (!dev) return
|
||||||
@@ -313,16 +296,12 @@ Panel {
|
|||||||
if (adapter && adapter.enabled && !adapter.discovering) adapter.discovering = true
|
if (adapter && adapter.enabled && !adapter.discovering) adapter.discovering = true
|
||||||
if (connectedDevices.length > 0) { focusSection = "connected"; selectedIndex = 0 }
|
if (connectedDevices.length > 0) { focusSection = "connected"; selectedIndex = 0 }
|
||||||
else if (knownDevices.length > 0) { focusSection = "known"; selectedIndex = 0 }
|
else if (knownDevices.length > 0) { focusSection = "known"; selectedIndex = 0 }
|
||||||
else { focusSection = "header"; selectedIndex = 1 }
|
else if (discoveredDevices.length > 0) { focusSection = "discovered"; selectedIndex = 0 }
|
||||||
cursorActive = false
|
cursorActive = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateFocusedAddress() {
|
function updateFocusedAddress() {
|
||||||
if (focusSection === "header") {
|
|
||||||
focusedDeviceAddress = ""
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var d = deviceAt(focusSection, selectedIndex)
|
var d = deviceAt(focusSection, selectedIndex)
|
||||||
focusedDeviceAddress = d ? (d.address || "") : ""
|
focusedDeviceAddress = d ? (d.address || "") : ""
|
||||||
}
|
}
|
||||||
@@ -376,7 +355,10 @@ Panel {
|
|||||||
|
|
||||||
function clampCursor() {
|
function clampCursor() {
|
||||||
var sections = visibleSections
|
var sections = visibleSections
|
||||||
if (!sections || !sections.length) return
|
if (!sections || !sections.length) {
|
||||||
|
selectedIndex = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
if (sections.indexOf(focusSection) < 0) {
|
if (sections.indexOf(focusSection) < 0) {
|
||||||
focusSection = sections[0]
|
focusSection = sections[0]
|
||||||
selectedIndex = 0
|
selectedIndex = 0
|
||||||
@@ -413,13 +395,54 @@ Panel {
|
|||||||
onTriggered: root.pendingActions = ({})
|
onTriggered: root.pendingActions = ({})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: phraseTimer
|
||||||
|
interval: 2800
|
||||||
|
running: root.opened && root.rotatingPhrases
|
||||||
|
repeat: true
|
||||||
|
onTriggered: phraseSwap.restart()
|
||||||
|
}
|
||||||
|
|
||||||
|
SequentialAnimation {
|
||||||
|
id: phraseSwap
|
||||||
|
PropertyAnimation {
|
||||||
|
target: heroStatus; property: "opacity"
|
||||||
|
to: 0.0; duration: 180; easing.type: Easing.OutQuad
|
||||||
|
}
|
||||||
|
ScriptAction {
|
||||||
|
script: root.phraseIndex = (root.phraseIndex + 1) % root.activePhrases.length
|
||||||
|
}
|
||||||
|
PropertyAnimation {
|
||||||
|
target: heroStatus; property: "opacity"
|
||||||
|
to: 1.0; duration: 260; easing.type: Easing.InQuad
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root
|
||||||
|
function onRotatingPhrasesChanged() {
|
||||||
|
if (!root.rotatingPhrases) {
|
||||||
|
phraseSwap.stop()
|
||||||
|
heroStatus.opacity = 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleBluetooth() {
|
||||||
|
if (!adapter) return
|
||||||
|
adapter.enabled = !adapter.enabled
|
||||||
|
if (adapter.enabled) Qt.callLater(function() {
|
||||||
|
if (root.adapter) root.adapter.discovering = true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
WidgetButton {
|
WidgetButton {
|
||||||
id: button
|
id: button
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
bar: root.bar
|
bar: root.bar
|
||||||
text: root.icon
|
text: root.icon
|
||||||
onPressed: function(b) {
|
onPressed: function(b) {
|
||||||
if (b === Qt.RightButton && root.adapter) root.adapter.enabled = !root.adapter.enabled
|
if (b === Qt.RightButton) root.toggleBluetooth()
|
||||||
else if (b === Qt.MiddleButton) root.bar.run("omarchy-launch-bluetooth")
|
else if (b === Qt.MiddleButton) root.bar.run("omarchy-launch-bluetooth")
|
||||||
else root.toggle()
|
else root.toggle()
|
||||||
}
|
}
|
||||||
@@ -441,7 +464,6 @@ Panel {
|
|||||||
onMoveRequested: function(dx, dy) {
|
onMoveRequested: function(dx, dy) {
|
||||||
if (!root.cursorActive) { root.cursorActive = true; return }
|
if (!root.cursorActive) { root.cursorActive = true; return }
|
||||||
if (dy !== 0) root.moveCursor(dy)
|
if (dy !== 0) root.moveCursor(dy)
|
||||||
else if (dx !== 0) root.moveCursorH(dx)
|
|
||||||
}
|
}
|
||||||
onActivateRequested: if (root.cursorActive) root.activateCursor()
|
onActivateRequested: if (root.cursorActive) root.activateCursor()
|
||||||
onCloseRequested: root.close()
|
onCloseRequested: root.close()
|
||||||
@@ -452,54 +474,65 @@ Panel {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
spacing: Style.space(10)
|
spacing: Style.space(10)
|
||||||
|
|
||||||
// Header: title left, on/off toggle + actions right.
|
// ---------- Hero: Bluetooth icon · status ----------
|
||||||
Item {
|
Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: titleText.implicitHeight
|
implicitHeight: Math.max(heroIcon.implicitHeight, heroLabels.implicitHeight)
|
||||||
|
|
||||||
Row {
|
Text {
|
||||||
|
id: heroIcon
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
spacing: Style.space(8)
|
text: root.icon
|
||||||
|
color: root.bar.foreground
|
||||||
|
font.family: root.bar.fontFamily
|
||||||
|
font.pixelSize: Style.font.display
|
||||||
|
opacity: root.adapter && root.adapter.enabled ? 1.0 : 0.5
|
||||||
|
|
||||||
PanelSectionHeader {
|
MouseArea {
|
||||||
id: titleText
|
id: heroIconMouse
|
||||||
text: "Bluetooth"
|
anchors.fill: parent
|
||||||
foreground: root.bar.foreground
|
hoverEnabled: true
|
||||||
fontFamily: root.bar.fontFamily
|
cursorShape: root.adapter ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||||
fontSize: Style.font.bodySmall
|
enabled: !!root.adapter
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
onClicked: root.toggleBluetooth()
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
PanelToolTip {
|
||||||
text: "· " + (root.adapter && root.adapter.enabled ? "On" : "Off")
|
visible: heroIconMouse.containsMouse
|
||||||
color: Qt.darker(root.bar.foreground, 1.8)
|
text: root.adapter && root.adapter.enabled ? "Turn Bluetooth off" : "Turn Bluetooth on"
|
||||||
font.family: root.bar.fontFamily
|
fontFamily: root.bar.fontFamily
|
||||||
font.pixelSize: Style.font.bodySmall
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Column {
|
||||||
|
id: heroLabels
|
||||||
|
anchors.left: heroIcon.right
|
||||||
|
anchors.leftMargin: Style.space(14)
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
spacing: Style.space(4)
|
spacing: Style.space(2)
|
||||||
|
|
||||||
HeaderPill {
|
Text {
|
||||||
pillIndex: 0
|
text: "Bluetooth"
|
||||||
iconText: ""
|
color: root.bar.foreground
|
||||||
iconSpinning: root.adapter && root.adapter.discovering
|
font.family: root.bar.fontFamily
|
||||||
tooltipText: !root.adapter ? "" : !root.adapter.enabled ? "Bluetooth is off"
|
font.pixelSize: Style.font.title
|
||||||
: root.adapter.discovering ? "Stop scanning" : "Scan for devices"
|
font.bold: true
|
||||||
pillEnabled: root.adapter !== null && root.adapter.enabled
|
elide: Text.ElideRight
|
||||||
onActivated: if (root.adapter) root.adapter.discovering = !root.adapter.discovering
|
width: parent.width
|
||||||
}
|
}
|
||||||
|
|
||||||
HeaderPill {
|
Text {
|
||||||
pillIndex: 1
|
id: heroStatus
|
||||||
iconText: root.adapter && root.adapter.enabled ? "" : ""
|
text: root.heroStatusText.toUpperCase()
|
||||||
tooltipText: root.adapter && root.adapter.enabled ? "Turn Bluetooth off" : "Turn Bluetooth on"
|
color: Qt.darker(root.bar.foreground, 1.4)
|
||||||
onActivated: if (root.adapter) root.adapter.enabled = !root.adapter.enabled
|
font.family: root.bar.fontFamily
|
||||||
|
font.pixelSize: Style.font.caption
|
||||||
|
font.bold: true
|
||||||
|
font.letterSpacing: 1.2
|
||||||
|
elide: Text.ElideRight
|
||||||
|
width: parent.width
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -592,7 +625,7 @@ Panel {
|
|||||||
text: !root.adapter ? "No Bluetooth adapter"
|
text: !root.adapter ? "No Bluetooth adapter"
|
||||||
: !root.adapter.enabled ? "Turn Bluetooth on to scan"
|
: !root.adapter.enabled ? "Turn Bluetooth on to scan"
|
||||||
: root.adapter.discovering ? "Scanning for devices…"
|
: root.adapter.discovering ? "Scanning for devices…"
|
||||||
: "No paired devices. Tap the scan icon to find new ones."
|
: "No paired devices. Reopen this panel to scan again."
|
||||||
color: Qt.darker(root.bar.foreground, 1.5)
|
color: Qt.darker(root.bar.foreground, 1.5)
|
||||||
font.family: root.bar.fontFamily
|
font.family: root.bar.fontFamily
|
||||||
font.pixelSize: Style.font.bodySmall
|
font.pixelSize: Style.font.bodySmall
|
||||||
@@ -605,35 +638,6 @@ Panel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header pill: a Button bound into the panel's "header" cursor
|
|
||||||
// section. Button collapses what used to be a Button subclass +
|
|
||||||
// overlay MouseArea into one component; we keep the pillIndex / activated
|
|
||||||
// shim here so the three header pill instantiations stay readable.
|
|
||||||
component HeaderPill: Button {
|
|
||||||
id: pill
|
|
||||||
required property int pillIndex
|
|
||||||
property bool pillEnabled: true
|
|
||||||
signal activated()
|
|
||||||
|
|
||||||
foreground: root.bar.foreground
|
|
||||||
fontFamily: root.bar.fontFamily
|
|
||||||
horizontalPadding: Style.spacing.md
|
|
||||||
verticalPadding: Style.spacing.labelGap
|
|
||||||
iconSize: 14
|
|
||||||
enabled: pillEnabled
|
|
||||||
opacity: pillEnabled ? 1 : 0.4
|
|
||||||
|
|
||||||
hasCursor: root.cursorActive && root.focusSection === "header" && root.selectedIndex === pillIndex
|
|
||||||
|
|
||||||
onClicked: pill.activated()
|
|
||||||
onHovered: function(isHovered) {
|
|
||||||
if (!isHovered) return
|
|
||||||
root.cursorActive = true
|
|
||||||
root.focusSection = "header"
|
|
||||||
root.selectedIndex = pill.pillIndex
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Two-line device row showing name + live status. Pending state is owned
|
// Two-line device row showing name + live status. Pending state is owned
|
||||||
// by the panel so it survives rows moving between sections.
|
// by the panel so it survives rows moving between sections.
|
||||||
component DeviceRow: CursorSurface {
|
component DeviceRow: CursorSurface {
|
||||||
|
|||||||
@@ -399,11 +399,11 @@ Panel {
|
|||||||
width: scrollArea.availableWidth
|
width: scrollArea.availableWidth
|
||||||
spacing: Style.space(14)
|
spacing: Style.space(14)
|
||||||
|
|
||||||
// ---------- Hero: sun icon · BRIGHTNESS · percentage ----------
|
// ---------- Hero: display icon · title/status · percentage ----------
|
||||||
Item {
|
Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
visible: root.brightnessAvailable
|
visible: root.brightnessAvailable
|
||||||
implicitHeight: Math.max(heroIcon.implicitHeight, heroPercent.implicitHeight)
|
implicitHeight: Math.max(heroIcon.implicitHeight, heroLabels.implicitHeight, heroPercent.implicitHeight)
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: heroIcon
|
id: heroIcon
|
||||||
@@ -415,20 +415,36 @@ Panel {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Column {
|
||||||
id: heroLabel
|
id: heroLabels
|
||||||
text: root.brightnessName(brightnessSlider.dragging ? brightnessSlider.liveValue : root.brightnessPercent).toUpperCase()
|
|
||||||
color: Qt.darker(root.bar.foreground, 1.4)
|
|
||||||
font.family: root.bar.fontFamily
|
|
||||||
font.pixelSize: Style.font.caption
|
|
||||||
font.bold: true
|
|
||||||
font.letterSpacing: 1.2
|
|
||||||
anchors.left: heroIcon.right
|
anchors.left: heroIcon.right
|
||||||
anchors.leftMargin: Style.space(14)
|
anchors.leftMargin: Style.space(14)
|
||||||
anchors.right: heroPercent.left
|
anchors.right: heroPercent.left
|
||||||
anchors.rightMargin: Style.space(10)
|
anchors.rightMargin: Style.space(10)
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
elide: Text.ElideRight
|
spacing: Style.space(2)
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Display"
|
||||||
|
color: root.bar.foreground
|
||||||
|
font.family: root.bar.fontFamily
|
||||||
|
font.pixelSize: Style.font.title
|
||||||
|
font.bold: true
|
||||||
|
elide: Text.ElideRight
|
||||||
|
width: parent.width
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: heroLabel
|
||||||
|
text: root.brightnessName(brightnessSlider.dragging ? brightnessSlider.liveValue : root.brightnessPercent).toUpperCase()
|
||||||
|
color: Qt.darker(root.bar.foreground, 1.4)
|
||||||
|
font.family: root.bar.fontFamily
|
||||||
|
font.pixelSize: Style.font.caption
|
||||||
|
font.bold: true
|
||||||
|
font.letterSpacing: 1.2
|
||||||
|
elide: Text.ElideRight
|
||||||
|
width: parent.width
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
|||||||
@@ -749,10 +749,10 @@ Panel {
|
|||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: heroSsid
|
id: heroSsid
|
||||||
visible: root.info.type !== "ethernet"
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
text: {
|
text: {
|
||||||
if (root.info.type === "wifi") return root.info.ssid || "Wi-Fi"
|
if (root.info.type === "wifi") return root.info.ssid || "Wi-Fi"
|
||||||
|
if (root.info.type === "ethernet") return "Ethernet"
|
||||||
return root.info.iface || (root.kind === "disconnected" ? "Disconnected" : "No connection")
|
return root.info.iface || (root.kind === "disconnected" ? "Disconnected" : "No connection")
|
||||||
}
|
}
|
||||||
color: root.bar.foreground
|
color: root.bar.foreground
|
||||||
|
|||||||
@@ -293,10 +293,10 @@ Panel {
|
|||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
spacing: Style.space(14)
|
spacing: Style.space(14)
|
||||||
|
|
||||||
// ---------- Hero: battery icon · status · percentage ----------
|
// ---------- Hero: battery icon · title/status · percentage ----------
|
||||||
Item {
|
Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
implicitHeight: Math.max(heroIcon.implicitHeight, heroPercent.implicitHeight)
|
implicitHeight: Math.max(heroIcon.implicitHeight, heroLabels.implicitHeight, heroPercent.implicitHeight)
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: heroIcon
|
id: heroIcon
|
||||||
@@ -310,20 +310,36 @@ Panel {
|
|||||||
Behavior on color { ColorAnimation { duration: 200 } }
|
Behavior on color { ColorAnimation { duration: 200 } }
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Column {
|
||||||
id: heroStatus
|
id: heroLabels
|
||||||
text: root.heroStatusText.toUpperCase()
|
|
||||||
color: Qt.darker(root.bar.foreground, 1.4)
|
|
||||||
font.family: root.bar.fontFamily
|
|
||||||
font.pixelSize: Style.font.caption
|
|
||||||
font.bold: true
|
|
||||||
font.letterSpacing: 1.2
|
|
||||||
anchors.left: heroIcon.right
|
anchors.left: heroIcon.right
|
||||||
anchors.leftMargin: Style.space(14)
|
anchors.leftMargin: Style.space(14)
|
||||||
anchors.right: heroPercent.left
|
anchors.right: heroPercent.left
|
||||||
anchors.rightMargin: Style.space(10)
|
anchors.rightMargin: Style.space(10)
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
elide: Text.ElideRight
|
spacing: Style.space(2)
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Battery"
|
||||||
|
color: root.bar.foreground
|
||||||
|
font.family: root.bar.fontFamily
|
||||||
|
font.pixelSize: Style.font.title
|
||||||
|
font.bold: true
|
||||||
|
elide: Text.ElideRight
|
||||||
|
width: parent.width
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: heroStatus
|
||||||
|
text: root.heroStatusText.toUpperCase()
|
||||||
|
color: Qt.darker(root.bar.foreground, 1.4)
|
||||||
|
font.family: root.bar.fontFamily
|
||||||
|
font.pixelSize: Style.font.caption
|
||||||
|
font.bold: true
|
||||||
|
font.letterSpacing: 1.2
|
||||||
|
elide: Text.ElideRight
|
||||||
|
width: parent.width
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
|||||||
Reference in New Issue
Block a user