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
This commit is contained in:
12 files changed
+360
-23
No files matched your search
@@ -213,7 +213,10 @@ Rectangle {
|
||||
/// Park the select indicator bottom-right of the art instead of top-right.
|
||||
property bool selectMarkBottom: false
|
||||
property bool selected: false
|
||||
signal selectToggled()
|
||||
/// `modifiers` rides straight off the click: a grid host turns Shift into
|
||||
/// a range (controls/SelectionModel.qml). Every select-mode target on the
|
||||
/// card — artwork, title, artist line — emits it.
|
||||
signal selectToggled(int modifiers)
|
||||
|
||||
// Album blacklist ("Block this album") — LIVE since QbzBlacklist landed
|
||||
// (`blockAlbum(id, title, artist, coverUrl)`). Kept as a property, not
|
||||
@@ -561,7 +564,7 @@ Rectangle {
|
||||
}
|
||||
// .slint:169 — in select mode the card click TOGGLES.
|
||||
if (root.selectMode) {
|
||||
root.selectToggled()
|
||||
root.selectToggled(mouse.modifiers)
|
||||
return
|
||||
}
|
||||
if (root.pulledDead)
|
||||
@@ -993,7 +996,7 @@ Rectangle {
|
||||
// .slint:465 — the title carries the SAME target
|
||||
// as the artwork, select mode included.
|
||||
if (root.selectMode) {
|
||||
root.selectToggled()
|
||||
root.selectToggled(mouse.modifiers)
|
||||
return
|
||||
}
|
||||
if (root.pulledDead)
|
||||
@@ -1009,7 +1012,8 @@ Rectangle {
|
||||
width: parent.width
|
||||
height: 18
|
||||
text: root.artist
|
||||
color: (root.artistId !== "" || root.hostArtistLink)
|
||||
color: !root.selectMode
|
||||
&& (root.artistId !== "" || root.hostArtistLink)
|
||||
&& artistArea.containsMouse
|
||||
? theme.textPrimary : theme.textMuted
|
||||
font.pixelSize: theme.fontLink - 1
|
||||
@@ -1019,9 +1023,15 @@ Rectangle {
|
||||
id: artistArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: root.artistId !== "" || root.hostArtistLink
|
||||
cursorShape: root.selectMode || root.artistId !== "" || root.hostArtistLink
|
||||
? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
onClicked: {
|
||||
onClicked: function (mouse) {
|
||||
// In select mode the artist line is the card too:
|
||||
// opening the artist mid-selection would drop it.
|
||||
if (root.selectMode) {
|
||||
root.selectToggled(mouse.modifiers)
|
||||
return
|
||||
}
|
||||
if (root.artistId !== "")
|
||||
QbzArtist.openArtist(root.artistId)
|
||||
else if (root.hostArtistLink)
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
// QbzCheckbox (primitives/QbzCheckbox.slint) — 18px square, r4, accent fill
|
||||
// with an accent-text check when on, muted border when off. Emits toggled();
|
||||
// like the Slint original it never self-flips (the owner of the state does).
|
||||
// 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.
|
||||
@@ -15,7 +20,7 @@ Rectangle {
|
||||
id: root
|
||||
|
||||
property bool checked: false
|
||||
signal toggled()
|
||||
signal toggled(int modifiers)
|
||||
|
||||
QbzTheme { id: theme }
|
||||
|
||||
@@ -30,14 +35,14 @@ Rectangle {
|
||||
activeFocusOnTab: root.enabled
|
||||
Accessible.role: Accessible.CheckBox
|
||||
Accessible.checked: root.checked
|
||||
Accessible.onToggleAction: if (root.enabled) root.toggled()
|
||||
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()
|
||||
root.toggled(event.modifiers)
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
@@ -66,6 +71,6 @@ Rectangle {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onPressed: root.forceActiveFocus()
|
||||
onClicked: root.toggled()
|
||||
onClicked: function (mouse) { root.toggled(mouse.modifiers) }
|
||||
}
|
||||
}
|
||||
@@ -749,7 +749,10 @@ Rectangle {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.toggleSelect(Qt.NoModifier)
|
||||
// The disc is where a select-mode click most often lands,
|
||||
// so it hands over the modifiers exactly like the body:
|
||||
// a plain `NoModifier` here made Shift-click a toggle.
|
||||
onClicked: function (mouse) { root.toggleSelect(mouse.modifiers) }
|
||||
}
|
||||
}
|
||||
Text {
|
||||
@@ -969,6 +972,9 @@ Rectangle {
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
// Hover only: a tooltip must not eat the click the
|
||||
// row body (play, or a select-mode toggle) owns.
|
||||
acceptedButtons: Qt.NoButton
|
||||
ToolTip.visible: containsMouse
|
||||
ToolTip.delay: 300
|
||||
// NEW msgid — the one string this state needs and
|
||||
@@ -1078,7 +1084,12 @@ Rectangle {
|
||||
MouseArea {
|
||||
id: artistLinkArea
|
||||
anchors.fill: parent
|
||||
enabled: root.artistLink && (artistLine.linkMode || !!root.item.artistId)
|
||||
// In select mode the whole row is a selection target
|
||||
// (TrackRow.slint:174): the names stop being links so the
|
||||
// click — and its Shift / Ctrl — reaches the row body
|
||||
// instead of opening an artist page mid-selection.
|
||||
enabled: !root.selectMode
|
||||
&& root.artistLink && (artistLine.linkMode || !!root.item.artistId)
|
||||
hoverEnabled: true
|
||||
cursorShape: (artistLine.linkMode
|
||||
? (artistLine.hotSpan >= 0 && artistLine.spans[artistLine.hotSpan].href !== "")
|
||||
@@ -1088,6 +1099,9 @@ Rectangle {
|
||||
artistLine.hotSpan = artistLine.spanAt(mouse.x)
|
||||
}
|
||||
onExited: artistLine.hotSpan = -1
|
||||
// Entering select mode under the pointer disables the area
|
||||
// without an `exited`; the hot name must not stay lit.
|
||||
onEnabledChanged: if (!enabled) artistLine.hotSpan = -1
|
||||
// Same routing as the menu's "Go to artist" — Slint drives
|
||||
// both through one handler, so gating only the menu would
|
||||
// leave the LINK navigating to the track's own artist.
|
||||
@@ -1116,7 +1130,8 @@ Rectangle {
|
||||
MouseArea {
|
||||
id: albumArea
|
||||
anchors.fill: parent
|
||||
enabled: !!root.item.albumId && !root.releaseGone
|
||||
// Not a link in select mode, for the artist line's reason.
|
||||
enabled: !root.selectMode && !!root.item.albumId && !root.releaseGone
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
// The names ride along so a release the catalog lost can
|
||||
|
||||
@@ -304,8 +304,11 @@ Rectangle {
|
||||
id: artistArea
|
||||
anchors.fill: parent
|
||||
// Only a real artist id is clickable — otherwise the
|
||||
// pointer promises a page that cannot open.
|
||||
enabled: (root.item.artistId || "") !== ""
|
||||
// pointer promises a page that cannot open. In select
|
||||
// mode the whole row selects (Shift / Ctrl included), so
|
||||
// the name stops being a link and the click falls to the
|
||||
// row body underneath.
|
||||
enabled: !root.selectMode && (root.item.artistId || "") !== ""
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: QbzArtist.openArtist(root.item.artistId)
|
||||
@@ -331,7 +334,8 @@ Rectangle {
|
||||
MouseArea {
|
||||
id: labelArea
|
||||
anchors.fill: parent
|
||||
enabled: (root.item.labelId || "") !== ""
|
||||
// Not a link in select mode, for the artist name's reason.
|
||||
enabled: !root.selectMode && (root.item.labelId || "") !== ""
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: QbzHome.openLabel(root.item.labelId)
|
||||
|
||||
@@ -593,11 +593,14 @@ Item {
|
||||
selected: root.nativeActive
|
||||
? cardCell.slot.selected === true
|
||||
: root.selected[cardCell.slot.id] === true
|
||||
onSelectToggled: {
|
||||
// The card's modifiers, straight through: the
|
||||
// paged grid (299dcde5b) passed NoModifier here,
|
||||
// so a Shift-click on a card was a toggle.
|
||||
onSelectToggled: function (mods) {
|
||||
if (root.nativeActive)
|
||||
root.nativeToggleSelect(cardCell.slot.nativeIndex, Qt.NoModifier)
|
||||
root.nativeToggleSelect(cardCell.slot.nativeIndex, mods)
|
||||
else
|
||||
root.toggleSelect(cardCell.slot.id, Qt.NoModifier)
|
||||
root.toggleSelect(cardCell.slot.id, mods)
|
||||
}
|
||||
// Non-select mode only — the card routes a
|
||||
// select-mode click to `selectToggled` and never
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
// Slint declares this inline inside TreeRow; the Qt port also needs it on
|
||||
// the album cards and the track rows in multi-select, so it is its own file
|
||||
// (three call sites, one shape).
|
||||
//
|
||||
// `toggled` carries the click's modifiers: this disc IS a select-mode click
|
||||
// target, and one that dropped them turned every Shift-click on it into a
|
||||
// plain toggle (controls/SelectionModel.qml).
|
||||
|
||||
import QtQuick
|
||||
import com.blitzfc.qbz
|
||||
@@ -16,7 +20,7 @@ Rectangle {
|
||||
property bool on: false
|
||||
property bool partial: false
|
||||
property int diameter: 13
|
||||
signal toggled()
|
||||
signal toggled(int modifiers)
|
||||
|
||||
QbzTheme { id: theme }
|
||||
|
||||
@@ -52,6 +56,6 @@ Rectangle {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.toggled()
|
||||
onClicked: function (mouse) { root.toggled(mouse.modifiers) }
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user