Use Tab to switch bar panels

This commit is contained in:
David Heinemeier Hansson
2026-05-27 10:40:32 +02:00
parent 848499a76b
commit b03a7cc73c
8 changed files with 61 additions and 1 deletions
+4
View File
@@ -27,6 +27,10 @@ Item {
Qt.callLater(function() { popoutSwitchClosing = false })
}
function toggle() { opened ? close() : open() }
function switchPanel(direction) {
if (bar && typeof bar.switchPanelFrom === "function") return bar.switchPanelFrom(root, direction)
return false
}
// Read a single value from this panel's inline shell.json entry, with a
// fallback for missing/null values. Matches BarWidget.setting().
+51
View File
@@ -191,6 +191,57 @@ Item {
return Array.isArray(entries) ? entries : []
}
function panelNavigationSlots(region) {
var entries = layoutEntries(region)
var slots = []
for (var i = 0; i < entries.length; i++) {
var id = entryId(entries[i])
for (var j = 0; j < debugModuleSlots.length; j++) {
var slot = debugModuleSlots[j]
if (!slot || slot.region !== region || slot.moduleName !== id) continue
var item = slot.activeItem
if (!item || item.visible !== true || slot.visible !== true || slot.width <= 0 || slot.height <= 0) continue
if (typeof item.open !== "function" || typeof item.close !== "function" || item.opened === undefined) continue
slots.push(slot)
break
}
}
return slots
}
function switchPanelFrom(owner, direction) {
if (!owner) return false
var currentSlot = null
for (var i = 0; i < debugModuleSlots.length; i++) {
var slot = debugModuleSlots[i]
if (slot && slot.activeItem === owner) {
currentSlot = slot
break
}
}
if (!currentSlot) return false
var slots = panelNavigationSlots(currentSlot.region)
if (slots.length < 2) return false
var currentIndex = -1
for (var j = 0; j < slots.length; j++) {
if (slots[j] === currentSlot) {
currentIndex = j
break
}
}
if (currentIndex < 0) return false
var step = direction < 0 ? -1 : 1
var nextSlot = slots[(currentIndex + step + slots.length) % slots.length]
if (!nextSlot || !nextSlot.activeItem || nextSlot.activeItem === owner) return false
nextSlot.activeItem.open()
return true
}
function entrySettings(entry) {
return BarModel.entrySettings(entry)
}
+1 -1
View File
@@ -559,7 +559,7 @@ Panel {
}
onActivateRequested: if (root.cursorActive) root.activateCursor()
onCloseRequested: root.close()
onTabRequested: function(direction) { root.moveSection(direction) }
onTabRequested: function(direction) { root.switchPanel(direction) }
onTextKey: function(t) {
// 'm' mutes whatever the cursor is on: focused section's slider
// for output/input, the focused stream for streams.
+1
View File
@@ -434,6 +434,7 @@ Panel {
}
onActivateRequested: if (root.cursorActive) root.activateCursor()
onCloseRequested: root.close()
onTabRequested: function(direction) { root.switchPanel(direction) }
onDeleteRequested: if (root.cursorActive) root.deleteSelected()
Column {
+1
View File
@@ -372,6 +372,7 @@ Panel {
}
onActivateRequested: if (root.cursorActive) root.activateCursor()
onCloseRequested: root.close()
onTabRequested: function(direction) { root.switchPanel(direction) }
ScrollView {
id: scrollArea
+1
View File
@@ -664,6 +664,7 @@ Panel {
}
}
onCloseRequested: root.close()
onTabRequested: function(direction) { root.switchPanel(direction) }
onTextKey: function(t) {
if (t === "r" || t === "R") root.refresh()
}
+1
View File
@@ -279,6 +279,7 @@ Panel {
}
onActivateRequested: if (root.cursorActive) root.activateSelectedProfile()
onCloseRequested: root.close()
onTabRequested: function(direction) { root.switchPanel(direction) }
Column {
id: column
+1
View File
@@ -296,6 +296,7 @@ Panel {
}
onActivateRequested: if (root.cursorActive) root.activateCursor()
onCloseRequested: root.close()
onTabRequested: function(direction) { root.switchPanel(direction) }
onTextKey: function(t) {
if (t === "t" || t === "T") tailscale.toggleTailscale()
else if (t === "c" || t === "C") tailscale.copyPeerIp(root.selectedPeer())