Add C++ ScriptConstructor to replace QML filter/computed-column drag-and-drop constructors - #6306
Draft
JorisGoosen wants to merge 19 commits into
Draft
Add C++ ScriptConstructor to replace QML filter/computed-column drag-and-drop constructors#6306JorisGoosen wants to merge 19 commits into
JorisGoosen wants to merge 19 commits into
Conversation
added 13 commits
August 26, 2026 08:58
…and-drop constructors Introduces a UI-agnostic model layer and a C++ QQuickItem view that together replace the JSON/QML/JS FilterConstructor and ComputedColumnsConstructor. Model (CommonData): - ScriptNode tree with JSON round-trip and R code generation matching the old QML output byte-for-byte (operators, functions, row-functions, columns, literals), including na.rm handling and ifelse return types. - ScriptConstructorRegistry as the single source of truth for available operators/functions per mode (filter / computed column / computed dataset). - ScriptConstructorModel owning the formula tree with drop-target resolution (including the gobble-left behaviour), completeness/boolean checks and snapshot-based undo. View (Desktop/qquick): - ScriptConstructorView (registered as ScriptConstructor) orchestrates layout, drag-and-drop, palettes, operator bar, inline literal editing and column type changes; leaf visuals are incubated QML (Text/Image/TextInput/CheckBox). Integration: - FilterWindow.qml now uses ScriptConstructor for the drag-and-drop filter. Tests: - Golden-R parity, 300-seed JSON round-trip fuzz, completeness, undo and DEFAULT_FILTER_JSON regression tests in testall.cpp.
- Column palette now falls back to ColumnsModel::singleton() (the columnsModel Q_PROPERTY shadowed the QML context property, so the palette was empty). - Add ScriptPalette with mouse-wheel and drag-to-scroll for the column and function palettes. - Drop spots accept inline typing: clicking an empty slot focuses a TextInput that parses number -> string -> boolean on edit-finish. - rebuild() now recursively renders child nodes into filled drop spots, and drop spots/leaves get explicit sizes so they are visible/clickable. - View implements ScriptColumnTypeProvider, resolving real column types from the columns model for R generation (previously always fell back to scale); columnTypeDrop is resolved on drop and re-resolved when the user changes a column's type while it sits in a slot. - Drag/drop hardening: scene->local coordinate mapping, skip filled and own-subtree drop spots, prefer deepest spot, clean up the dragged item. - Add hint text area, error markers on incomplete slots, trash icon, and filterErrorMsg property. - Add headless QML smoke test (tst_scriptconstructor.qml) verifying the view instantiates and the JSON->R/apply flow works.
- Wire the generated-R code display for computed columns (reserve bottom space, show/update on edit, hide in filter mode). - Add sqrt and ! to the operator bar as operator-bar-only functions. - Render function math symbols (sum/prod/sd/var and row variants) as images. - Wrap nested operator/function args in parentheses. - Fix operator "gobble left" on drop into empty space. - Integrate ScriptConstructor into ComputeColumnWindow. - Add engine-execution fuzz test that runs generated R through the engine.
- Right-clicking an element now rebuilds the view after removing the node, preventing a crash from dangling ScriptNode pointers in stale items. - Cycling a column's type now refreshes the whole view so the icon and parent layout update to the newly selected type.
- Column icons use the "transformed" variant (asterisk) when the column's effective type differs from its dataset type. - Clicking a column icon in a restrictive drop slot shows the allowed types instead of silently cycling to a type that would be reverted. - Row functions lay out their "row" text + symbol image correctly, and always keep a trailing free drop slot so more columns can be added.
Replace the modal MessageForwarder dialog with QToolTip::showText so the "Only <types> allowed" notice appears transiently near the clicked icon and does not block interaction. The message remains translatable via tr().
- Separate function and row-function arguments with commas. - Wrap function arguments in parentheses (single-arg math symbols like sum/SD omit them). - Centre the operator row within the top bar. - Autosize the column/function palettes to their widest entry (capped at a third of the view). - Show the column-type restriction tooltip ~10x longer.
- Pin image implicit size to blockDim so icon images no longer blow up the layout to their source resolution (this made sqrt extremely wide). - Render sqrt as a proper radical: a tall √ head plus an overline drawn above the argument; the operator bar shows the plain square-root symbol. - Add the faint centred background decoration (filter vs computed-column).
- Make ScriptConstructorRegistry a QObject and wrap every operator/function/ row-function tooltip in tr(), restoring the translatable strings. - Restore the mode-dependent "returns logicals..." suffix for comparison and logical operators (and the "!" function) via ScriptOperatorDef::toolTipForMode. - Add a ToolTip overlay (hover MouseArea, acceptedButtons: NoButton) to each ScriptNodeItem, showing the element's tooltip on hover without breaking drag & drop. - Columns show "Click icon to change column type" plus description and transformed-type preview; the trash shows its old "Dump unwanted snippets" tooltip.
Store the untranslated source strings (via QT_TRANSLATE_NOOP) in the registry and look them up with QCoreApplication::translate in toolTipForMode(), instead of freezing them with tr() at singleton-construction time. This makes the tooltips re-translate correctly after a live language change.
Distinguish the two division operators by making the operator lookup vertical-aware (operatorDef now resolves via the vertical flag), so the operator bar shows the fraction (\u00f7) and diagonal (/) distinctly instead of two identical images. Render vertical division as a stacked fraction (numerator over a horizontal bar over denominator) in the script area. Make the constructor background watermark resize reactively once its source image loads, fixing the filter constructor's missing watermark.
Remove the redundant white paint from ScriptConstructorView's updatePaintNode so the background watermark (filter/column) is no longer hidden behind it; both modes now show their image. Double-clicking the trash zone now clears the constructor (undoable), mirroring the old DropTrash.qml. Centre drop-spot placeholder text so the vertical-division dots line up under the fraction bar.
JorisGoosen
commented
Aug 27, 2026
Add local per-step undo to the constructor (own QUndoStack, focus-scoped Ctrl+Z/Shift+Z, cleared when re-seeded from another filter/column), so in-progress editing is undoable without touching the dataset stack. Route computed-column code application through SetComputedColumnCodeCommand and column creation through CreateComputedColumnCommand, so the data-mode undo/redo buttons cover computed columns the same way they already cover filters. Replace magic 1/2/3 column-type constants with columnType enum values, and drop the redundant columnTypeString in favour of the DECLARE_ENUM-generated columnTypeToString.
…ly show up and be smooth
JorisGoosen
force-pushed
the
filterConstructorCPP
branch
from
August 27, 2026 11:24
a7cde49 to
3d99479
Compare
Replace the setProperty("border.*") calls (which silently fail on QML
group properties) with QQmlProperty writes, restoring the green/red hover
outline, the red incomplete-check outline and the trash-zone border.
Cache the watermark image's natural size on load and use it for the
scaling ratio, so the background scales back up after shrinking instead
of staying stuck at its smallest size (the sourceSize = width*2 binding
was making implicitWidth follow width).
…timers - Fix ScriptConstructorToolTipArea TypeError by guarding null parent in the tooltip overlay binding (fired once per node item build) - Fix FilterWindow tab anchoring: anchor the Flickable content to its grandparent was dropped by Qt (parent/sibling only), so the RowLayout instead stretches via a width binding; use dataSetModel.columnsLabelFilteredCount instead of the stale workspace reference - Make column palette/tooltip builds O(N): cache column type/index/description per view (single pass via new ColumnsModel::provideInfoAt) and coalesce model-driven palette rebuilds through a 0ms timer - Add JASPTIMER scopes across the constructor pipeline (enabled with JASP_TIMER_USED=ON) and print all timers on exit
…nd incubation timers - Replace the per-item QtQuick ToolTip overlay with QToolTip::showText on hover (removes one QML incubation per node item and the tooltip-area component altogether) - Add deferUntilVisible so the computed-column constructor only builds its chrome/palettes when the tab becomes effectively visible (itemChange + requestBuild + singleShot re-check); FilterWindow keeps building eagerly - Add per-leaf-kind incubation timers (incubate <kind>, createSync <kind>, compile <kind>Component) to pinpoint whether first-use compilation or instantiation dominates constructor load time - Add quicktest for deferred build
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.
Introduces a UI-agnostic model layer and a C++ QQuickItem view that together
replace the JSON/QML/JS FilterConstructor and ComputedColumnsConstructor.
Model (CommonData):
QML output byte-for-byte (operators, functions, row-functions, columns,
literals), including na.rm handling and ifelse return types.
operators/functions per mode (filter / computed column / computed dataset).
(including the gobble-left behaviour), completeness/boolean checks and
snapshot-based undo.
View (Desktop/qquick):
drag-and-drop, palettes, operator bar, inline literal editing and column type
changes; leaf visuals are incubated QML (Text/Image/TextInput/CheckBox).
Integration:
Tests:
DEFAULT_FILTER_JSON regression tests in testall.cpp.