Four things the owner hit in Local Library. The context menu did nothing there — local rows and cards now mount the shared menu the rest of the app uses, with the action set Slint gives local and Plex items. Anything with no seam in this port (add-to-playlist, add-to-mixtape, the tag editor, local favourites) is hidden or visibly disabled rather than a row that silently does nothing. The per-view search fields did not open and collapse the way the header's does. That behaviour moved into the shared QbzLineEdit, so the Local toolbar, the queue and the tree rail all get it from one place instead of four copies. The queue's field also escaped its 300px column; it is width-bound now. Filter, sorting and grouping become icon-only buttons with an explanatory tooltip, which is what the owner asked for and what the crowding called for. Found on the way, and affecting Qobuz cards too: the album card's ⋯ menu had no "Play later" at all, and its "Add to queue" row dispatched play-later — the row lied about what it did. Both fixed, with Slint's icon set for the three. cc
141 lines
5.0 KiB
QML
141 lines
5.0 KiB
QML
// One row of the FLATTENED folder tree (LocalLibraryView.slint:444 TreeRow).
|
|
//
|
|
// 26px, radius 6, depth indent 8 + depth*16, select-mode checkbox (folder =
|
|
// tri-state from node.selectState 0/1/2, track = node.selected), an expand
|
|
// chevron with its OWN hit target (so toggling never selects), the folder /
|
|
// music glyph and the segment name. The selection cue is the 3px accent bar
|
|
// on the left edge — ADR-008: never a pill.
|
|
|
|
// Right-click opens a folder queue menu. DIVERGENCE: LocalLibraryView.slint
|
|
// gives the tree rail no per-row menu (only the detail pane's Play button and
|
|
// the bulk bar), but the owner asked for working context menus on the local
|
|
// rows and every entry here rides a seam that already exists
|
|
// (QbzLocal.playFolder / enqueue("folder", path, mode) — local_playback.rs
|
|
// `list_folder_tracks_recursive`). TRACK leaves get no menu: their `path` is
|
|
// a file path, not a track id, so no track arm accepts it.
|
|
|
|
import QtQuick
|
|
import com.blitzfc.qbz
|
|
import "../../controls"
|
|
import "../../theme"
|
|
|
|
Rectangle {
|
|
id: root
|
|
|
|
property var node: ({})
|
|
property bool selected: false
|
|
property bool selectMode: false
|
|
signal toggled()
|
|
signal activated()
|
|
signal toggleSelect()
|
|
|
|
QbzTheme { id: theme }
|
|
|
|
height: 26
|
|
radius: 6
|
|
color: selected ? theme.surfaceElevated
|
|
: rowArea.containsMouse ? theme.surfaceHover : "transparent"
|
|
|
|
// Row body — declared FIRST so the chevron / checkbox win their clicks.
|
|
MouseArea {
|
|
id: rowArea
|
|
anchors.fill: parent
|
|
hoverEnabled: true
|
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
cursorShape: root.node.isFolder ? Qt.PointingHandCursor : Qt.ArrowCursor
|
|
onClicked: function (mouse) {
|
|
if (mouse.button === Qt.RightButton) {
|
|
if (root.node.isFolder) folderMenu.openAtCursor(rowArea, mouse.x, mouse.y)
|
|
return
|
|
}
|
|
if (root.node.isFolder) root.activated()
|
|
}
|
|
}
|
|
|
|
CardMenu {
|
|
id: folderMenu
|
|
menuWidth: 200
|
|
entries: [
|
|
{ "label": QbzSession.tr("Play", QbzSession.trRev), "icon": "play-fill", "action": "play" },
|
|
{ "label": QbzSession.tr("Play next", QbzSession.trRev), "icon": "list-start", "action": "next" },
|
|
{ "label": QbzSession.tr("Play later", QbzSession.trRev), "icon": "list-plus", "action": "later" },
|
|
{ "label": QbzSession.tr("Add to queue", QbzSession.trRev), "icon": "list-end", "action": "queue" },
|
|
]
|
|
onPicked: function (a) {
|
|
if (a === "play") QbzLocal.playFolder(root.node.path)
|
|
else QbzLocal.enqueue("folder", root.node.path, a)
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
visible: root.selected
|
|
x: 0
|
|
y: 4
|
|
width: 3
|
|
height: parent.height - 8
|
|
radius: 1.5
|
|
color: theme.accent
|
|
}
|
|
|
|
Row {
|
|
anchors.fill: parent
|
|
anchors.leftMargin: 8 + (root.node.depth || 0) * 16
|
|
anchors.rightMargin: 10
|
|
spacing: 6
|
|
|
|
// Select-mode checkbox (folder tri-state / track boolean).
|
|
Item {
|
|
visible: root.selectMode
|
|
width: visible ? 13 : 0
|
|
height: parent.height
|
|
SelectCheck {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
on: root.node.isFolder ? root.node.selectState === 2
|
|
: root.node.selected === true
|
|
partial: root.node.isFolder === true && root.node.selectState === 1
|
|
onToggled: root.toggleSelect()
|
|
}
|
|
}
|
|
|
|
// Expand chevron — its own hit target.
|
|
Item {
|
|
width: 18
|
|
height: parent.height
|
|
QbzIcon {
|
|
visible: root.node.canExpand === true
|
|
name: root.node.expanded ? "chevron-down" : "chevron-right"
|
|
width: 11
|
|
height: 11
|
|
anchors.centerIn: parent
|
|
tintName: "muted"
|
|
}
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
enabled: root.node.canExpand === true
|
|
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
|
onClicked: root.toggled()
|
|
}
|
|
}
|
|
|
|
QbzIcon {
|
|
name: root.node.isFolder
|
|
? (root.node.expanded ? "folder-open" : "folder") : "music"
|
|
width: 14
|
|
height: 14
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
tintName: root.node.isFolder ? "accent" : "muted"
|
|
}
|
|
Text {
|
|
width: Math.max(0, parent.width - 50 - (root.node.depth || 0) * 16
|
|
- (root.selectMode ? 19 : 0))
|
|
height: parent.height
|
|
text: root.node.segment || ""
|
|
color: root.selected ? theme.textPrimary : theme.textSecondary
|
|
font.pixelSize: 13
|
|
font.weight: root.selected ? theme.weightSemibold : theme.weightRegular
|
|
verticalAlignment: Text.AlignVCenter
|
|
elide: Text.ElideRight
|
|
}
|
|
}
|
|
}
|