From e129f9ee94c160e25e4815a76e3c2dc96490189d Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Thu, 1 Oct 2026 08:50:52 +0200 Subject: [PATCH] Fix overlapping text in OutlineView - Replace manual Item+anchoring with ColumnLayout for proper height calc - Remove redundant bodyMeasure Text and bodyWidth property - Add proper top/bottom margins using rowPad constant - Body row now uses RowLayout with Layout.fillWidth --- ui/qml/OutlineView.qml | 89 ++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 59 deletions(-) diff --git a/ui/qml/OutlineView.qml b/ui/qml/OutlineView.qml index 0c3397b..08d7050 100644 --- a/ui/qml/OutlineView.qml +++ b/ui/qml/OutlineView.qml @@ -40,48 +40,20 @@ TreeView { readonly property string sectionBody: (model.body ?? "").trim() readonly property int bodyIndent: 12 - // The horizontal space available to the body text. The base delegate - // reserves (depth+1)*indentation on the left for the tree structure; - // the content region occupies the rest, minus our body indent and a - // right margin. Computing this explicitly (rather than via anchors) - // gives the body Text a concrete width, so contentHeight resolves - // deterministically and the row height below is correct. - readonly property real bodyWidth: - Math.max(1, tree.width - (depth + 1) * indentation - - bodyIndent - 12) - implicitWidth: tree.width - // Row height = headline + body (if any) + padding. bodyMeasure is a - // non-visible Text with the same font/width as the body, used purely - // to measure wrapped height without depending on the laid-out item. - implicitHeight: headlineRow.implicitHeight - + (sectionBody !== "" ? bodyMeasure.implicitHeight + 4 : 0) - + tree.rowPad * 2 - background: Rectangle { color: del.current ? "#2f3540" : "transparent" radius: 4 } - // Off-screen measurement of the wrapped body height. - Text { - id: bodyMeasure - visible: false - width: del.bodyWidth - text: del.sectionBody - font.pixelSize: 12 - lineHeight: 1.15 - wrapMode: Text.WordWrap - textFormat: Text.PlainText - } + contentItem: ColumnLayout { + spacing: 4 - contentItem: Item { RowLayout { id: headlineRow - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top + Layout.fillWidth: true + Layout.topMargin: tree.rowPad spacing: 8 // TODO keyword pill. @@ -156,34 +128,33 @@ TreeView { } } - // Left rule marking the body region. - Rectangle { - visible: bodyLabel.visible - width: 2 - color: "#3b4252" - anchors.top: bodyLabel.top - anchors.bottom: bodyLabel.bottom - anchors.left: parent.left - anchors.leftMargin: 2 - } - - // Section body, always visible inline beneath the headline. - // Given an explicit width (matching bodyMeasure) so wrapping and - // height are consistent with the reserved row height. - Text { - id: bodyLabel - anchors.top: headlineRow.bottom - anchors.topMargin: 4 - anchors.left: parent.left - anchors.leftMargin: del.bodyIndent - width: del.bodyWidth + // Body row with left rule. + RowLayout { visible: del.sectionBody !== "" - text: del.sectionBody - color: tree.dimColor - font.pixelSize: 12 - lineHeight: 1.15 - wrapMode: Text.WordWrap - textFormat: Text.PlainText + Layout.fillWidth: true + Layout.bottomMargin: tree.rowPad + spacing: 8 + + // Left rule marking the body region. + Rectangle { + width: 2 + Layout.fillHeight: true + Layout.leftMargin: 2 + color: "#3b4252" + } + + // Section body text. + Text { + id: bodyLabel + Layout.fillWidth: true + Layout.leftMargin: del.bodyIndent - 10 + text: del.sectionBody + color: tree.dimColor + font.pixelSize: 12 + lineHeight: 1.15 + wrapMode: Text.WordWrap + textFormat: Text.PlainText + } } } }