[Detail Bug] KNX GUI: Grid/Table blocks drop declared tail row labels when no cell references that row

Open Beginner friendly
#88 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
86/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
python
Domain
frontend

Research direction

Start in apps/knx-gui/src/knx_gui/plugins/project/ui/components/parameters_section.py, focusing on _render_grid_block and its max_row calculation. Check the existing GRID/TABLE rendering fixture or tests, then verify that declared trailing row_labels are iterated and rendered even without positioned cells or separators.

Written by the indexing model from the issue text.

Description

Detail Bug Report

https://app.detail.dev/org_62aa40f5-2c23-4914-a665-3bb2068af20e/bugs/bug_69a4fa86-c372-4a88-932c-2fe19a7656bf

Introduced in 7ccef9030d656479fb1e9dd6e559aa639d7c5dae by @kewde on Jun 17, 2026

Summary

  • Context: In _render_grid_block, the row loop is bounded by max_row derived only from cell/separator positions (parameters_section.py:209), not from len(block.row_labels).
  • Bug: A <Row> whose index no <ParameterRefRef>/<Separator> references is never iterated and its label is never rendered.
  • Actual vs. expected: Actual: rows are rendered only up to the last positioned cell/separator row. Expected: all declared row_labels should be iterated/rendered (parser preserves every <Row>).
  • Impact: Declared row labels can be silently dropped in GRID/TABLE rendering when there are trailing declared rows with no positioned content. In the only in-repo fixture this manifests as a single missing trailing row with an empty label (cosmetic), but synthetic repro shows non-empty labels can be lost.

Code with Bug

apps/knx-gui/src/knx_gui/plugins/project/ui/components/parameters_section.py:

all_rows = {r for r, _ in cells_by_pos} | {r for r, _ in labels_by_pos}
all_cols = {c for _, c in cells_by_pos} | {c for _, c in labels_by_pos}
max_row = max(all_rows, default=1)                       # <-- BUG 🔴 ignores declared row_labels length
max_col = max(all_cols, default=1)
...
declared_cols = max(max_col, len(block.column_headers))  # columns honour declared count
...
for row in range(1, max_row + 1):                        # <-- BUG 🔴 loop bound excludes declared tail rows
    imgui.table_next_row()
    if has_row_labels:
        imgui.table_set_column_index(0)
        label = block.row_labels[row - 1] if row - 1 < len(block.row_labels) else ""
        imgui.text_disabled(label)

Explanation

max_row is computed only from positioned cells/separators, so if len(block.row_labels) > max_row, trailing declared rows are never visited and their labels are never rendered. The existing bounds-check on row_labels indexing only prevents an IndexError; it cannot render labels for rows the loop never iterates.

The parser explicitly preserves all <Row> elements into row_labels, so the renderer’s truncation is an internal contract mismatch:

row_labels = (
    tuple(apply_text_args(r.text or r.name or "", arg_defaults) for r in rows.row)
    if rows else ()
)

Recommended Fix

Compute declared_rows symmetrically to declared_cols and iterate that instead of max_row:

declared_rows = max(max_row, len(block.row_labels))
...
for row in range(1, declared_rows + 1):
    ...

History

This bug was introduced in commit 7ccef90. The subsequent refactor 7158478 moved the logic into parameters_section.py without changing it.

Dominant language
Python
Stars
4
Forks
0
Avg merge
15h 38m
Merged PRs (30d)
37

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from XKNX/xknxtoolkit

All issues in XKNX/xknxtoolkit

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.