feat(sdk): typed table sort keys in the dialog protocol (0.18.0)#149
Merged
Conversation
Numeric table columns sorted lexicographically because the dialog protocol
carried cells as display text only ("720" < "7" < "65"). Sort keys now travel
beside the display text:
- PJ::TableItem{text, optional<NumericValue>} — the display string and the
ordering truth. NumericValue keeps the native width, so int64/uint64 keys
past 2^53 stay exact; TableItem(v, "display") expresses hidden keys (show a
date, sort on nanoseconds). long double is rejected up front instead of
failing deep inside std::variant.
- setTableRows(name, vector<vector<TableItem>>) — an overload BESIDE the
string one, which is kept verbatim for compatibility. Emits the unchanged
`rows` plus a sparse per-column `column_values` map; columns with no keys
are omitted, valueless cells are null. Old hosts keep reading `rows` as
before; old plugins keep compiling and running. The string overload now
erases stale column_values so alternating overloads can never pair fresh
rows with old keys.
- setTableSortIndicator(name, col, ascending) — draws the header arrow for a
table the plugin sorts via onHeaderClicked (Qt paints none while its own
sorting is off).
- WidgetDataView::tableColumnValues()/tableSortIndicator() for hosts, with
malformed-input rejection (count mismatch, bad keys); tableRows() keeps a
row's shape when a cell is not a string instead of mis-aligning the row.
- Non-finite keys (NaN, ±inf) do not survive JSON — documented and pinned:
they arrive keyless and sort in the text rank.
Additive JSON only: no C ABI change, PJ_DIALOG_PROTOCOL_VERSION unchanged,
abi/baseline.abi unchanged, abi_major stays 5. Version 0.17.0 -> 0.18.0
(MINOR). The dialog-plugin guide gains a sortable-tables section including
the authoring constraints (no sortingEnabled+onHeaderClicked mix, no item
drag/drop on sortable tables) and the braced-literal ambiguity note.
41 tests in widget_data_test / widget_data_view_test cover the wire
round-trip: int64/uint64/float exactness, sparsity, null cells, non-finite
degradation, sort indicator, malformed input.
This was referenced Jul 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Numeric table columns in plugin dialogs sort lexicographically ("720" < "7" < "65") because the dialog protocol carries cells as display text only. This release lets a plugin ship the value beside the text so the host can sort on it:
PJ::TableItem—{text, optional<NumericValue>}. Native widths survive exactly (int64/uint64 past 2⁵³ never round through a double);TableItem(v, "display")expresses hidden keys (show a date, sort on nanoseconds).setTableRows(name, vector<vector<TableItem>>)— an overload beside the string one, which is kept verbatim. Emits the unchangedrowsplus a sparse per-columncolumn_valuesmap (nullfor valueless cells, keyless columns omitted).setTableSortIndicator(name, col, asc)— the header arrow for tables the plugin sorts viaonHeaderClicked.WidgetDataView::tableColumnValues()/tableSortIndicator()for hosts, rejecting malformed input (count mismatch, bad keys);tableRows()now keeps a row's shape when a cell is not a string.column_values;long doubleis rejected at the constraint; non-finite keys are documented + test-pinned to degrade to keyless cells (JSON has no NaN/inf).Compatibility
rows, no keys → text fallbackcolumn_values→ todayAdditive JSON only — no C ABI change,
PJ_DIALOG_PROTOCOL_VERSIONunchanged,abi/baseline.abiunchanged,abi_majorstays 5. Version 0.17.0 → 0.18.0 (MINOR). One source-level sharp edge, documented in the guide: a braced literalsetTableRows("t", {{"a","b"}})becomes ambiguous (compile error on recompile only; no plugin writes that).Docs & tests
dialog-plugin-guide.mdgains a sortable-tables section with the authoring constraints (never combinesortingEnabledwithonHeaderClicked; no item drag/drop on sortable tables). 41 tests inwidget_data_test/widget_data_view_testcover the wire round-trip: exactness, sparsity, null cells, non-finite degradation, indicator, malformed input.Release
After merge this should be tagged
v0.18.0(version triple already aligned:conanfile.py,CMakeLists.txt,recipe.yaml) so PJ4 and pj-official-plugins can pin it — companion PRs in both repos.