Files
qbz/crates/qbz-qt/qml/controls/QbzCheckbox.qml
T
vicrodh 7c9bf8043f fix(qt): Shift and Ctrl work on every select-mode click target, not only the row body
Excel-style selection (750c59034) read the modifiers only where a row BODY
took the click. Every other target a select-mode surface draws dropped them,
so a Shift-click there was a plain toggle:

  - the track row's checkbox disc passed Qt.NoModifier;
  - QbzCheckbox and SelectCheck emitted toggled() with no argument, so the
    Library album rows, the local album rows and the folder rows, which
    already expected `function (mods)`, received undefined;
  - AlbumCard emitted selectToggled() with no argument, and the paged local
    albums grid (299dcde5b) spelled the drop out as Qt.NoModifier.

Some targets were never selection targets at all: in select mode the artist
and album names on a track row, the artist and label on a Library album row
and the artist line of an album card still navigated, leaving the page and
the selection mid-gesture. The row links stand down in select mode so the
click reaches the row body with its modifiers, and the card's artist line
toggles like its artwork and title. A hover-only tooltip on the pulled but
cached glyph no longer eats the row's click.

Reproduced on the release binary in a nested KWin with injected input: in
Local Library Tracks, the checkbox discs of rows 1, Shift 4 and Ctrl 6
selected 3 rows; the same clicks on the row bodies selected 5. No list
view, Flickable or wheel code changes; tst_wheel passes unchanged.

tst_multi_select clicks each of these targets through the real TrackRow,
AlbumListRow, AlbumCard, QbzCheckbox and SelectCheck.

cc
2026-09-14 10:30:34 -06:00

77 lines
2.9 KiB
QML

// QbzCheckbox (primitives/QbzCheckbox.slint) — 18px square, r4, accent fill
// with an accent-text check when on, muted border when off. Emits
// toggled(modifiers); like the Slint original it never self-flips (the owner of
// the state does).
//
// `modifiers` is the click's (or the key's), straight through: a multi-select
// host turns Shift into a range (controls/SelectionModel.qml). Hosts that only
// flip a flag keep a plain expression handler and never look at it.
//
// Used by Settings > Local Library (folder selection) and the Plex library
// picker, i.e. every place the Slint uses its own QbzCheckbox.
import QtQuick
import "../theme"
Rectangle {
// Explicit density opt-in; desktop geometry remains the default.
property bool kioskHost: false
id: root
property bool checked: false
signal toggled(int modifiers)
QbzTheme { id: theme }
width: kioskHost ? 44 : 18
height: kioskHost ? 44 : 18
radius: 4
color: root.checked ? theme.accent : "transparent"
border.width: root.activeFocus ? 2 : (root.checked ? 0 : 2)
border.color: root.activeFocus
? (root.checked ? theme.accentGlyphColor : theme.accent)
: theme.textMuted
activeFocusOnTab: root.enabled
Accessible.role: Accessible.CheckBox
Accessible.checked: root.checked
Accessible.onToggleAction: if (root.enabled) root.toggled(Qt.NoModifier)
Keys.onPressed: function (event) {
if (root.enabled && !event.isAutoRepeat
&& (event.key === Qt.Key_Space
|| event.key === Qt.Key_Return
|| event.key === Qt.Key_Enter)) {
root.toggled(event.modifiers)
event.accepted = true
}
}
QbzIcon {
anchors.centerIn: parent
visible: root.checked
name: "check"
// The glyph sits ON the accent fill. primitives/QbzCheckbox.slint:24
// says `tint: Theme.accent-text` and this was 1:1 with it; it now
// goes through the selector, which RETURNS accent-text on 34 of the
// 35 palettes — so this is not a divergence from :24 so much as a
// floor under it. The one row it changes is rose-pine-dawn, where
// accent-text #575279 on accent #d7827e is 2.56:1, under the 3:1
// non-text floor, and the selector hands back black at 7.38:1.
// Routing every on-accent glyph through one property is also what
// stops this control and views/local/SelectCheck.qml from drifting
// apart again — upstream contradicts itself between the two
// (SelectionCheckbox.slint:37 hardcodes #ffffff for the same job).
tintName: theme.accentGlyphTint
width: 12
height: 12
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onPressed: root.forceActiveFocus()
onClicked: function (mouse) { root.toggled(mouse.modifiers) }
}
}