Hi!
Thank you for your responses!
Unfortunately, the documentation for TreeView is not very detailed, and examples are quite scarce. I followed your advice and dug deeper into how the delegate works for TreeView. As a result, I managed to achieve exactly what I needed, as shown in the original screenshot.
To help others understand this topic more easily, I’ll share my code below.
Key ideas:
The entire view layout can be customized using the delegate. There’s no need to come up with complex solutions like DelegateChooser, which I had been trying earlier.
You can use the column and row variables to determine which row or column is being processed.
As mentioned earlier, to align text, you should use horizontalAlignment.
You need to align the row yourself (make indents depending on the nesting).
import QtQuick
import QtQuick.Controls
import Qt5Compat.GraphicalEffects
Item {
id: root
width: 260
height: 700
TreeView {
id: treeView
anchors.fill: parent
anchors.margins: 10
clip: true
model: assetModel
selectionModel: ItemSelectionModel {
model: treeView.model
}
delegate: Item {
implicitWidth: column === 0 ? root.width * 2/3 - padding * 2 : root.width * 1/3 - padding * 2
implicitHeight: label.implicitHeight * 1.5
readonly property real indentation: 20
readonly property real padding: 5
// Assigned to by TreeView:
required property TreeView treeView
required property bool isTreeNode
required property bool expanded
required property int hasChildren
required property int depth
required property int row
required property int column
required property bool current
property Animation indicatorAnimation: NumberAnimation {
target: indicator
property: "rotation"
from: expanded ? 0 : 90
to: expanded ? 90 : 0
duration: 100
easing.type: Easing.OutQuart
}
TableView.onPooled: indicatorAnimation.complete()
TableView.onReused: if (current) indicatorAnimation.start()
onExpandedChanged: indicator.rotation = expanded ? 90 : 0
Rectangle {
id: background
anchors.fill: parent
color: row === treeView.currentRow ? "#0085F8" : "transparent"
}
Label {
id: indicator
x: padding + (depth * indentation) + 5
anchors.verticalCenter: parent.verticalCenter
visible: isTreeNode && hasChildren
text: "▶"
color: "white"
TapHandler {
onSingleTapped: {
let index = treeView.index(row, column)
treeView.selectionModel.setCurrentIndex(index, ItemSelectionModel.NoUpdate)
treeView.toggleExpanded(row)
}
}
}
Image {
id: image
x: (isTreeNode ? (depth + 1) * indentation : 0)
anchors.verticalCenter: parent.verticalCenter
width: 13
height: 13
source: hasChildren ? "../../images/svg-folder.svg" : "../../images/svg-file.svg"
visible: column === 0 ? true : false
ColorOverlay {
source: image
anchors.fill: image
color: "white"
}
}
Label {
id: label
x: image.x + image.width + 5
anchors.verticalCenter: parent.verticalCenter
width: parent.width - padding - x
clip: true
text: model.display
color: column === 0 ? "white" : "#ABABAB"
font.pixelSize: column === 0 ? 14 : 10
horizontalAlignment: isTreeNode ? Text.AlignLeft : Text.AlignRight
rightPadding: 10
font.family: "Roboto Medium"
}
}
MouseArea {
id: menuMouseArea
anchors.fill: parent
acceptedButtons: Qt.RightButton
Connections {
target: menuMouseArea
onClicked: {
menu.open()
menu.x = menuMouseArea.mouseX
menu.y = menuMouseArea.mouseY
}
}
}
}
Menu {
id: menu
width: 150
leftPadding: 5
font.family: "Roboto Medium"
palette.window: "#1f1f1f"
palette.text: "white"
palette.windowText: "white"
palette.light: "#898989"
MenuItem {
text: "Rename"
icon.source: "../../images/svg-edit.svg"
icon.width: 14
icon.height: 14
}
MenuItem {
text: "Delete"
icon.source: "../../images/svg-trash.svg"
icon.width: 14
icon.height: 14
}
}
}
Now it looks like this:
[image: 4f7d83ed-313b-430f-b390-18116851959d.png]
Thank you all!