Skip to content

feat(dialog): QDateTimeEdit event surface — datetime_iso event + onDateTimeChanged (0.18.0)#150

Merged
facontidavide merged 1 commit into
mainfrom
feat/dialog-datetime-event
Jul 18, 2026
Merged

feat(dialog): QDateTimeEdit event surface — datetime_iso event + onDateTimeChanged (0.18.0)#150
facontidavide merged 1 commit into
mainfrom
feat/dialog-datetime-event

Conversation

@facontidavide

Copy link
Copy Markdown
Contributor

Summary

The QDateTimeEdit setters (setDateTime / setDateTimeRange) shipped without an event direction, so a plugin's QDateTimeEdit could display a value but never report user edits — dead API against any host (found during an SDK↔host drift audit). This adds the missing surface, header-only and backward compatible (no C ABI change, PJ_DIALOG_PROTOCOL_VERSION unchanged):

  • WidgetEventBuilder::dateTimeChanged() — emits the datetime_iso key
  • WidgetEvent::dateTimeChanged() reader
  • DialogPluginTyped::onDateTimeChanged() typed handler + dispatch entry (placed with the other dedicated events, before the generic text() branch)

Contract clarifications folded in from review findings:

  • Datetimes are wall-clock local, exchanged verbatim; an explicit UTC offset is honored on parse.
  • Empty/unparsable strings are ignored — the widget keeps its current value (the old "clears any prior value" doc-comment described behavior no host implements; a QDateTimeEdit always displays a value).
  • QDateEdit/QTimeEdit subclasses share the binding; events always carry a full ISO datetime.
  • Fractional seconds appear only for ms-precision editors.

Docs: dialog-sdk-reference.md gains its previously missing QDateTimeEdit section; dialog-plugin-guide.md widget table row corrected; CHANGELOG entry added.

Versioning

MINOR → 0.18.0 (conanfile.py + CMakeLists.txt + recipe.yaml in sync). Header-only additions; already-built plugins are unaffected — an old DSO keeps its own compiled dispatcher and simply never sees the new event. Note: adding a virtual to DialogPluginTyped never crosses the DSO boundary (plugins talk to the host only via the C vtable), so this is the same MINOR pattern as every prior typed-handler addition (onDateRangeChanged, onMarkerTimelineChanged, …). Tagging/release is a separate step, not part of this PR.

Test plan

  • TDD: round-trip + missing-field + wrong-type tests in widget_event_builder_test.cpp, dispatch test in dialog_plugin_typed_test.cpp (all watched fail first).
  • Full SDK suite: 49/49 pass.
  • Companion host PR in PJ4 (fix/dialog-widget-drift) binds the widget and passes its suite against these headers.
  • Reviewed by Codex (6 findings, all addressed or rebutted above) + a 4-angle cleanup pass (clean).

🤖 Generated with Claude Code

…teTimeChanged (0.18.0)

The QDateTimeEdit setters (setDateTime / setDateTimeRange) shipped without an
event direction, so the widget could display but never report edits — dead API
against any host. Add the missing surface, all header-only and backward
compatible (no C ABI change, PJ_DIALOG_PROTOCOL_VERSION unchanged):

- WidgetEventBuilder::dateTimeChanged() emitting the "datetime_iso" key
- WidgetEvent::dateTimeChanged() reader
- DialogPluginTyped::onDateTimeChanged() typed handler + dispatch entry

Contract clarifications folded into the same change (review findings):
datetimes are wall-clock local, exchanged verbatim; empty/unparsable strings
are ignored (a QDateTimeEdit always displays a value — the old "clears" doc
was wrong); QDateEdit/QTimeEdit subclasses share the binding; fractional
seconds appear only for ms-precision editors.

dialog-sdk-reference.md gains its previously missing QDateTimeEdit section.
MINOR bump to 0.18.0 (conanfile.py + CMakeLists.txt + recipe.yaml + CHANGELOG).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@facontidavide
facontidavide merged commit 9c72f3a into main Jul 18, 2026
7 checks passed
@facontidavide
facontidavide deleted the feat/dialog-datetime-event branch July 18, 2026 08:08
facontidavide added a commit that referenced this pull request Jul 18, 2026
…ding rows (#152)

Large tables (10k+ rows) cost ~25 ms per full-state refresh (~1 MB JSON
round-trip); a live feed appending one row per event had no cheaper option
than resending the whole array. Add batch deltas (JSON-level, backward
compatible; no C ABI change):

- WidgetData::appendTableRows / updateTableCells / removeTableRows write a
  per-widget table_delta {seq, append, update_cells, remove_rows}. seq is
  plugin-owned; hosts apply a delta only when its seq differs from the last
  applied (restart-safe, no wraparound edge), as update_cells -> remove_rows
  -> append, all indexes addressing the pre-delta table. Ops of one refresh
  share one seq — a differing seq starts a fresh delta, so stale ops can
  never be relabeled. rows in the same refresh wins and consumes the delta.
- WidgetDataView::tableDelta() decodes strictly (a malformed op rejects the
  whole delta — partial application would consume the seq while diverging
  from the plugin's model) and normalizes remove_rows to descending unique;
  tableDeltaSeq() is the cheap staleness pre-check.
- dialog-plugin-guide.md gains a "Large tables" section: the
  omit-unchanged-fields pattern (every widget-data field is optional), the
  efficiency ladder, and the delta contract. SDK-side only: hosts apply
  table_delta from the companion PlotJuggler change onward; older hosts
  ignore the key (harmless no-op).

Rides the 0.18.0 release together with the QDateTimeEdit event PR (#150);
CHANGELOG entries merge under one heading on whichever lands second.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant