feat(theme): add spanning tree branch lines to model tree view

Replace the simple open/closed disclosure arrows with full spanning
tree branch connectors that draw pipe-style lines between parent and
child items in the model tree.

New dark-theme SVGs created with Catppuccin colors:
- branch_vline_dark: vertical continuation line (#585b70)
- branch_more_dark: T-junction for mid-siblings
- branch_end_dark: L-junction for last sibling
- branch_more_closed_dark: T-junction + closed chevron (#a6adc8)
- branch_more_open_dark: T-junction + open chevron (#cdd6f4)
- branch_end_closed_dark: L-junction + closed chevron
- branch_end_open_dark: L-junction + open chevron

Updated QSS branch pseudo-selectors in KindredCreate.qss to map all
seven branch states (vline, more, end, more-closed, more-open,
end-closed, end-open) to the corresponding SVGs.

Updated ztools submodule with matching CatppuccinMocha.qss changes.
This commit is contained in:
forbes
2026-01-31 20:49:50 -06:00
parent 8ea3f141ff
commit 0d4545b7d6
9 changed files with 65 additions and 372 deletions

View File

@@ -788,14 +788,35 @@ QTreeView::branch:selected {
background-color: #45475a;
}
QTreeView::branch:has-children:!has-siblings:closed,
QTreeView::branch:closed:has-children:has-siblings {
image: url(qss:images_dark-light/branch_closed.svg);
/* Spanning tree branch lines */
QTreeView::branch:has-siblings:!adjoins-item {
image: url(qss:images_dark-light/branch_vline_dark.svg);
}
QTreeView::branch:open:has-children:!has-siblings,
QTreeView::branch:has-siblings:adjoins-item {
image: url(qss:images_dark-light/branch_more_dark.svg);
}
QTreeView::branch:!has-children:!has-siblings:adjoins-item {
image: url(qss:images_dark-light/branch_end_dark.svg);
}
/* Closed branches with children */
QTreeView::branch:closed:has-children:has-siblings {
image: url(qss:images_dark-light/branch_more_closed_dark.svg);
}
QTreeView::branch:closed:has-children:!has-siblings {
image: url(qss:images_dark-light/branch_end_closed_dark.svg);
}
/* Open branches with children */
QTreeView::branch:open:has-children:has-siblings {
image: url(qss:images_dark-light/branch_open.svg);
image: url(qss:images_dark-light/branch_more_open_dark.svg);
}
QTreeView::branch:open:has-children:!has-siblings {
image: url(qss:images_dark-light/branch_end_open_dark.svg);
}
/* =============================================================================

View File

@@ -1,55 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="20.000002"
height="20.000002"
id="svg2"
version="1.1"
viewBox="0 0 20.000002 20.000001"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs4" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>Pablo Gil</dc:title>
</cc:Agent>
</dc:creator>
<dc:subject>
<rdf:Bag>
<rdf:li>SVG</rdf:li>
<rdf:li>template</rdf:li>
</rdf:Bag>
</dc:subject>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(-1074.0663,-336.59799)">
<path
style="opacity:1;vector-effect:none;fill:none;fill-opacity:0.60093898;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.11764706"
d="m 1083.5663,336.59799 v 8 c 0,1.5 1,2.5 2.5,2.5 h 8"
id="path1536" />
<g
transform="translate(7.0000156,-5.4999999)"
id="layer1-4">
<path
id="path2474"
d="m 1075.0663,348.59798 3,3.50001 -3,3.49999"
style="opacity:1;vector-effect:none;fill:none;fill-opacity:0.34901961;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.34901961" />
</g>
</g>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<!-- L-junction with closed arrow: └▸ -->
<line x1="10" y1="0" x2="10" y2="10" stroke="#585b70" stroke-width="1"/>
<line x1="10" y1="10" x2="14" y2="10" stroke="#585b70" stroke-width="1"/>
<path d="M 14,6 18,10 14,14" fill="none" stroke="#a6adc8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 457 B

View File

@@ -1,47 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="20.000002"
height="20.000002"
id="svg2"
version="1.1"
viewBox="0 0 20.000002 20.000001"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs4" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>Pablo Gil</dc:title>
</cc:Agent>
</dc:creator>
<dc:subject>
<rdf:Bag>
<rdf:li>SVG</rdf:li>
<rdf:li>template</rdf:li>
</rdf:Bag>
</dc:subject>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(-1074.0663,-336.59799)">
<path
style="opacity:1;vector-effect:none;fill:none;fill-opacity:0.60093898;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.11764706"
d="m 1083.5663,336.59799 v 8 c 0,1.5 1,2.5 2.5,2.5 h 8"
id="path1536" />
</g>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<!-- L-junction (last sibling): └ -->
<line x1="10" y1="0" x2="10" y2="10" stroke="#585b70" stroke-width="1"/>
<line x1="10" y1="10" x2="20" y2="10" stroke="#585b70" stroke-width="1"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 323 B

View File

@@ -1,55 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="20.000002"
height="20.000002"
id="svg2"
version="1.1"
viewBox="0 0 20.000002 20.000001"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs4" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>Pablo Gil</dc:title>
</cc:Agent>
</dc:creator>
<dc:subject>
<rdf:Bag>
<rdf:li>SVG</rdf:li>
<rdf:li>template</rdf:li>
</rdf:Bag>
</dc:subject>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(-1074.0663,-336.59799)">
<path
style="opacity:1;vector-effect:none;fill:none;fill-opacity:0.60093898;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.11764706"
d="m 1083.5663,336.59799 v 8 c 0,1.5 1,2.5 2.5,2.5 h 8"
id="path1536" />
<g
transform="rotate(90,1082.5663,353.098)"
id="layer1-4">
<path
id="path2474"
d="m 1075.0663,348.59798 3,3.50001 -3,3.49999"
style="opacity:1;vector-effect:none;fill:none;fill-opacity:0.34901961;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.34901961" />
</g>
</g>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<!-- L-junction with open (down) arrow: └▾ -->
<line x1="10" y1="0" x2="10" y2="10" stroke="#585b70" stroke-width="1"/>
<line x1="10" y1="10" x2="14" y2="10" stroke="#585b70" stroke-width="1"/>
<path d="M 13,8 17,12 13,16" fill="none" stroke="#cdd6f4" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 462 B

View File

@@ -1,55 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="20.000002"
height="20.000002"
id="svg2"
version="1.1"
viewBox="0 0 20.000002 20.000001"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs4" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>Pablo Gil</dc:title>
</cc:Agent>
</dc:creator>
<dc:subject>
<rdf:Bag>
<rdf:li>SVG</rdf:li>
<rdf:li>template</rdf:li>
</rdf:Bag>
</dc:subject>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(-1074.0663,-336.59799)">
<path
style="opacity:1;vector-effect:none;fill:none;fill-opacity:0.60093898;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.11764706"
d="m 1094.0663,347.09799 h -10"
id="path1730" />
<path
style="opacity:1;vector-effect:none;fill:none;fill-opacity:0.60093898;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.11764706"
d="m 1083.5663,336.59799 v 20"
id="path1728" />
<path
style="opacity:1;vector-effect:none;fill:none;fill-opacity:0.34901961;stroke:#000000;stroke-width:1.99999996;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.34901961"
d="m 1082.0663,343.09798 3,3.50001 -3,3.49999"
id="path2474" />
</g>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<!-- T-junction with closed arrow: ├▸ -->
<line x1="10" y1="0" x2="10" y2="20" stroke="#585b70" stroke-width="1"/>
<line x1="10" y1="10" x2="14" y2="10" stroke="#585b70" stroke-width="1"/>
<path d="M 14,6 18,10 14,14" fill="none" stroke="#a6adc8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 457 B

View File

@@ -1,51 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="20.000002"
height="20.000002"
id="svg2"
version="1.1"
viewBox="0 0 20.000002 20.000001"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs4" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>Pablo Gil</dc:title>
</cc:Agent>
</dc:creator>
<dc:subject>
<rdf:Bag>
<rdf:li>SVG</rdf:li>
<rdf:li>template</rdf:li>
</rdf:Bag>
</dc:subject>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(-1074.0663,-336.59799)">
<path
style="opacity:1;vector-effect:none;fill:none;fill-opacity:0.60093898;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.11764706"
d="m 1094.0663,347.09799 h -10"
id="path1730" />
<path
style="opacity:1;vector-effect:none;fill:none;fill-opacity:0.60093898;stroke:#000000;stroke-width:0.99999998;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.11764706"
d="m 1083.5663,336.59799 v 20"
id="path1728" />
</g>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<!-- T-junction: ├ -->
<line x1="10" y1="0" x2="10" y2="20" stroke="#585b70" stroke-width="1"/>
<line x1="10" y1="10" x2="20" y2="10" stroke="#585b70" stroke-width="1"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 308 B

View File

@@ -1,63 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="20.000002"
height="20.000002"
id="svg2"
version="1.1"
viewBox="0 0 20.000002 20.000001"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs4" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>Pablo Gil</dc:title>
</cc:Agent>
</dc:creator>
<dc:subject>
<rdf:Bag>
<rdf:li>SVG</rdf:li>
<rdf:li>template</rdf:li>
</rdf:Bag>
</dc:subject>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(-1074.0663,-336.59799)">
<g
transform="rotate(90,1082.5663,353.098)"
id="layer1-4">
<path
id="path2474"
d="m 1075.0663,348.59798 3,3.50001 -3,3.49999"
style="opacity:1;vector-effect:none;fill:none;fill-opacity:0.34901961;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.34901961" />
</g>
<g
transform="translate(1.5420313e-5)"
id="layer1-6">
<path
id="path1730"
d="m 1094.0663,347.09799 h -10"
style="opacity:1;vector-effect:none;fill:none;fill-opacity:0.60093898;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.11764706" />
<path
id="path1728"
d="m 1083.5663,336.59799 v 20"
style="opacity:1;vector-effect:none;fill:none;fill-opacity:0.60093898;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.11764706" />
</g>
</g>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<!-- T-junction with open (down) arrow: ├▾ -->
<line x1="10" y1="0" x2="10" y2="20" stroke="#585b70" stroke-width="1"/>
<line x1="10" y1="10" x2="14" y2="10" stroke="#585b70" stroke-width="1"/>
<path d="M 13,8 17,12 13,16" fill="none" stroke="#cdd6f4" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 462 B

View File

@@ -1,47 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="20.000002"
height="20.000002"
id="svg2"
version="1.1"
viewBox="0 0 20.000002 20.000001"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs4" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>Pablo Gil</dc:title>
</cc:Agent>
</dc:creator>
<dc:subject>
<rdf:Bag>
<rdf:li>SVG</rdf:li>
<rdf:li>template</rdf:li>
</rdf:Bag>
</dc:subject>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(-1074.0663,-336.59799)">
<path
style="opacity:1;vector-effect:none;fill:none;fill-opacity:0.60093898;stroke:#000000;stroke-width:0.99999998;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.11764706"
d="m 1083.5663,336.59799 v 20"
id="path1728" />
</g>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<!-- Vertical line through center: │ -->
<line x1="10" y1="0" x2="10" y2="20" stroke="#585b70" stroke-width="1"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 250 B