Files
Panama/config/dot/quickshell/modules/settings/SettingRow.qml
Gabriel Brown 2bc12e6022 Add wallpaper, power, date, accessibility, and real search
Continues the settings expansion toward replacing GNOME Settings for
everything Panama actually owns.

Wallpaper. A thumbnail grid rather than a path field: the value of this
setting is the picture, so typing a path to something you cannot see is
the worst version of it. Two things about hyprpaper 0.8 shaped this. Its
IPC is much smaller than older documentation suggests -- preload,
listloaded, unload, and reload all answer "invalid hyprpaper request",
so setting is a single call with no preload. And the "<empty>,<path>"
form that used to mean every output is silently ignored, so a wallpaper
set that way appears to succeed and never changes; outputs are walked
explicitly instead. hyprpaper.conf lives in the repo through the
~/.config/hypr symlink and so cannot hold machine state, which is why
the choice lives in the shared settings store and is re-applied at
startup.

Power & Lock. hypridle has no IPC for reconfiguration and its config is
hyprlang rather than the shared JSON, so scripts/panama-idle generates a
config from the settings store and restarts the daemon. The generated
file lives under XDG_STATE_HOME for the same symlink reason, with a
systemd drop-in pointing hypridle at it. Management is a real state and
the page says which one you are in rather than showing sliders that
quietly do nothing. Zero means never for all three timers, which a naive
template would render as "immediately".

Date & Time. Deliberately not stored in Panama's settings: the timezone
and network time belong to the machine and are shared with sessions that
never see this file. Storing a copy would create a second answer to a
question the system already answers. Reads and writes timedatectl
directly; a cancelled polkit prompt surfaces as an error rather than as
a value that appears to have been accepted.

Accessibility. Pointer size and text scale have to agree across three
consumers with no shared configuration -- the compositor, GTK, and the
shell -- so the store is the source of truth and the values are pushed
outward to gsettings and hyprctl setcursor.

Search now indexes the schema instead of the twelve page labels. "gaps",
"wallpaper", and "screenshot" previously found nothing on an app that
has all three, which is the clearest way a settings app feels smaller
than it is. Shortcuts are indexed by what they do. A contract asserts
every non-internal schema label is reachable, so a new setting cannot be
added in an undiscoverable state.

The GNOME delegation allow-list was widened to the panel names
gnome-control-center actually reports; the previous list contained
"users", which is not one of them and so opened nothing.

Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
2026-08-18 00:42:13 -04:00

118 lines
3.2 KiB
QML

import QtQuick
import qs.config
Item {
id: root
default property alias trailingData: trailing.data
property string icon: ""
property string label: ""
property string detail: ""
property string value: ""
property bool divider: true
property int controlWidth: 150
// Rows are inert by default. A row that represents a choice -- picking a
// timezone from a list, say -- opts into being clickable across its whole
// width, which is a much larger target than the trailing control alone.
property bool activatable: false
signal activated
width: parent ? parent.width : 620
implicitHeight: Math.max(56, copy.implicitHeight + 20)
Text {
id: iconLabel
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: root.icon === "" ? 0 : 28
visible: root.icon !== ""
text: root.icon
color: Theme.accent
font.family: Theme.fontMono
font.pixelSize: 17
horizontalAlignment: Text.AlignHCenter
}
Column {
id: copy
anchors.left: iconLabel.visible ? iconLabel.right : parent.left
anchors.leftMargin: iconLabel.visible ? 10 : 0
anchors.right: trailing.left
anchors.rightMargin: 16
anchors.verticalCenter: parent.verticalCenter
spacing: 3
Text {
width: parent.width
text: root.label
color: Theme.fg
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSize
font.weight: Font.Medium
elide: Text.ElideRight
}
Text {
width: parent.width
visible: root.detail !== ""
text: root.detail
color: Theme.fgDim
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
wrapMode: Text.WordWrap
}
}
Item {
id: trailing
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
width: root.controlWidth
height: 32
Text {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
visible: root.value !== ""
text: root.value
color: Theme.fgDim
font.family: Theme.fontFamily
font.features: Theme.tabularFigures
font.pixelSize: Theme.fontSize
}
}
Rectangle {
anchors.left: copy.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: 1
visible: root.divider
color: Theme.alpha(Theme.fg, 0.065)
}
// Declared in this component's own body, so it is a child of the row rather
// than of the trailing slot that `trailingData` routes external children to.
Rectangle {
anchors.fill: parent
anchors.bottomMargin: 1
radius: 8
z: -1
visible: root.activatable && rowHover.hovered
color: Theme.alpha(Theme.fg, 0.05)
border.width: 0
}
HoverHandler {
id: rowHover
enabled: root.activatable
cursorShape: Qt.PointingHandCursor
}
TapHandler {
enabled: root.activatable
onTapped: root.activated()
}
}