summaryrefslogtreecommitdiffstats
path: root/docs/superpowers/plans
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-09 11:06:43 +0200
committerDanilo M. <danix@danix.xyz>2026-08-09 11:06:43 +0200
commit1f0179350f86300962a9ed1c6d54db10bfe7cd81 (patch)
tree199d816e58349171e611a2ec6290092faf35b4b4 /docs/superpowers/plans
parent751ca62940a21a9941e558de01f43e143c92492d (diff)
downloadqtmaildir-1f0179350f86300962a9ed1c6d54db10bfe7cd81.tar.gz
qtmaildir-1f0179350f86300962a9ed1c6d54db10bfe7cd81.zip
docs: record items 55 and 58, with their causes corrected
Both backlog entries stated a cause that measurement contradicted, and both would have misled the next reader into fixing the wrong thing. Item 55 blamed the thread view's size hint, computed as the sum of its fixed column widths, and placed the fault on first run. The hint is 256px, not 886: a QTableView does not put its column sum in its size hint, so that mechanism never applied. The trigger is the restore, in a window narrower than the one the position was saved in. Item 58 claimed the zoom range is unenforced and the first render unusable. MessageView::clampZoom() has always enforced exactly the README's 0.5 and 3.0; only the report was missing.
Diffstat (limited to 'docs/superpowers/plans')
-rw-r--r--docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md79
1 files changed, 43 insertions, 36 deletions
diff --git a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md
index f559bf1..159643f 100644
--- a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md
+++ b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md
@@ -112,10 +112,10 @@ taking that too literally.
| 52 | `test_querycompleter` fails under Wayland, passes offscreen | testing | XS | **done** |
| 53 | Message rows still read as a table, not as a conversation | presentation | ? | open, unspecified |
| 54 | A cron sync carries the edits but the count still says pending | correctness | S | **done** |
-| 55 | In a narrow window the message pane is invisible | presentation | XS | open |
+| 55 | In a narrow window the message pane is invisible | presentation | XS | **done** |
| 56 | No action carries an icon, so the toolbar reserves space for nothing | presentation | S | **done** |
| 57 | "Flag" would read better as "Important" or "Starred" | presentation | XS | **done** |
-| 58 | `message_zoom` documents a 0.5 to 3.0 range and enforces none of it | correctness | XS | open |
+| 58 | `message_zoom` documents a 0.5 to 3.0 range and enforces none of it | correctness | XS | **done** |
| 59 | Archive and Mark all read shipped with the same icon | presentation | XS | **done** |
Sizes are rough: XS under an hour, S a sitting, M a session.
@@ -3360,26 +3360,29 @@ Two notes on the verification, both worth more than the passing count:
**Observed (user, 2026-08-08):** "when opening in a squared window, the left
pane takes the whole width (right pane almost invisible)".
-**Cause, verified in code.** The splitter is built at
-`src/mainwindow.cpp:584` with `setStretchFactor(1, 2)` and **no**
-`setSizes()`, and neither pane carries a minimum width. A stretch factor only
-distributes space left over **after** every child's size hint is satisfied. The
-thread view's hint follows its columns, which are set to fixed widths at
-`src/mainwindow.cpp:557-561` and total roughly 886px (28 + 28 + 130 + 180 +
-520), every one of them `Interactive` with `setStretchLastSection(false)` at
-`src/mainwindow.cpp:513`. In a window narrower than that sum plus a usable
-message pane there is no leftover space at all, so the stretch factor never
-applies and the thread view takes essentially everything.
-
-This only bites on first run. Once a splitter position is saved it is restored
-from `window/splitter` (`src/mainwindow.cpp:120-123`), which is why the window
-behaves after the user has dragged it once. Item 1 built that persistence; it
-does not supply a sane starting point.
-
-**Approach.** Give the message view a minimum width so the splitter cannot
-collapse it, and set an initial `setSizes()` proportional to the window rather
-than letting the hints decide. Sizes only apply when nothing is restored, so it
-must go behind the same "no saved state" check as the geometry.
+**Cause, verified in code, and NOT what this item first recorded.** The
+original entry blamed the thread view's size hint, computed as the sum of its
+fixed column widths (~886px) against a `setStretchFactor(1, 2)` with no leftover
+space to distribute. Measured, the hint is **256px**: a `QTableView` does not
+put its column sum in its size hint, so that mechanism never applied and a
+freshly built window splits correctly.
+
+The real trigger is the **restore**, not the first run. A splitter position is
+saved in pixels (`window/splitter`, `src/mainwindow.cpp:120-124`), and the
+user's own state file held `1285/1252`, saved from a wide session. Reopened at
+1136px, `QSplitter::restoreState()` honours the first pane's 1285 verbatim and
+gives the second whatever is left, which is **29px**. That is the sliver in the
+screenshot. It gets worse the wider the window ever was, which is why item 1's
+persistence is where this comes from and why widening the default window would
+have changed nothing.
+
+**Approach, as built.** A `setMinimumWidth()` on the message view plus
+`setCollapsible(1, false)`, and nothing else. A restore-time repair was written
+first, running from `showEvent()` because the splitter has no laid-out width
+until the window is shown, and was then **deleted**: with the floor in place it
+was mutation-tested to be redundant, since the minimum width constrains
+`restoreState()` as much as it constrains a drag. Two mechanisms for one fault
+is one too many.
**Constraints.**
@@ -3550,20 +3553,24 @@ independent confirmation that `flagged` is load-bearing across the suite.
`toolbar_icon_size`, by reading `message_zoom` as the model for a bounded
numeric key and noticing it is not bounded.
-**Cause, verified in code.** `src/config.cpp:79-90` parses the value with
-`toDouble()` and assigns it on success. The parse failure is reported, but
-nothing checks the range. The README documents "0.5 to 3.0" (`README.md`, the
-`[general]` block), and `m_messageZoom` is never clamped anywhere else:
-`src/mainwindow.cpp:145` passes it straight to the saved-state default.
-
-So `message_zoom = 500` is accepted and applied. Unlike the toolbar icon size,
-this one is recoverable, since the zoom is adjustable from the UI and the
-adjusted value is what gets saved, but the first render is unusable.
-
-**Approach.** Clamp with a report, exactly as `toolbar_icon_size` does
-(`src/config.cpp`, the `kMinToolbarIconSize`/`kMaxToolbarIconSize` block). Both
-ends already have documented bounds, so this is applying the README's own
-numbers.
+**Cause, verified in code, and narrower than this item first recorded.** The
+entry claimed the value is applied unclamped and "the first render is
+unusable". It is not. `MessageView::clampZoom()` (`src/messageview.cpp:716`)
+bounds every value to `kMinZoom`/`kMaxZoom`, which are 0.5 and 3.0
+(`src/messageview.h:96-97`), exactly the README's numbers, and
+`MainWindow::restoreUiState()` routes the config value through
+`setZoomFactor()`, so `message_zoom = 500` renders at 3.0.
+
+What is genuinely missing is the **report**. `src/config.cpp` parses with
+`toDouble()` and, on success, assigns without comment, so nothing ever tells
+the user the 500 in their file is not what they are looking at. That silence is
+what the item's own Constraints section asks for.
+
+**Approach, as built.** Report only, no second clamp. `MessageView` owns the
+bounds and already enforces them; a copy in `Config` would be free to drift
+from the one that does the work, so `config.cpp` includes `messageview.h` and
+reports against `MessageView::kMinZoom`/`kMaxZoom`. This is where it differs
+from `toolbar_icon_size`, which has no widget-side enforcement to defer to.
**Constraints.**