avnd: support comboboxes with runtime-populated item lists#2110
Conversation
Lets an avendish object repopulate a combobox port's choices at run time (e.g. from the files it finds in a folder). Complements the avendish halp::dynamic_combobox port. - Process::ComboBox gains setAlternatives() + an alternativesChanged signal. setAlternatives refreshes the value domain and re-clamps the current value when the list shrinks. The alternatives were already serialized, so saved documents reopen with their last-known items. - The inspector and canvas combobox widgets read their item list live and rebuild on alternativesChanged. - The avnd executor injects the port's update_items callback, marshalling the object's runtime updates to the model inlet on the main thread (QPointer-guarded). Nodes with type-only inputs are skipped. Objects that don't use the feature are unaffected. Co-authored-by: Pia Baltazar <pia@baltazar.studio>
|
Depends on the avendish port: celtera/avendish#171 ( |
|
Closing for now — the avendish port this consumes (celtera/avendish#171) has no real consumer yet, so parking both until one exists rather than adding to the review queue. Kept on |
|
Reference, not an active review request — parked alongside the avendish port it consumes (celtera/avendish#171). Working example: We solved our own case (Granola's sound picker) with a custom widget rather than this binding, so nothing depends on it. Happy to revive both together if you think a runtime-populated combobox is worth having generally. |
|
eventually it's a feature we want though ! it's very useful in many cases |
Adds the host side of avendish's halp::folder_combobox: a combobox whose items are the files of a sibling folder/path port, listed at edit/load time. - Process::ComboBox gains folderPortName + fileExtensions and repopulateFromFolder(): lists a folder's matching files as the items. - The avnd binding (Concepts.hpp) stamps that metadata onto the ComboBox when the field is an avnd::folder_items_parameter. - ProcessModel wires each folder-combobox to its sibling folder port after port creation (i.e. after deserialization): populates immediately and refreshes on the folder's valueChanged. Populated at document load, no execution needed — unlike the executor-pushed dynamic_combobox, this is the right shape for file pickers in an editor (FluCoMa's folder file ports, Granola's sound picker). NOT yet compile-tested (needs a full score build). Co-authored-by: Pia Baltazar <pia@baltazar.studio>
|
OK then I'll reopen it and move this forward, as it's going to be useful for the flucoma port |
Make the folder-backed combobox string-valued (the selected file name) rather than an index, so an object consumes it directly like a file-name string — adopting it is then a pure port-type swap (lineedit -> folder_combobox) with no object-code change. The folder binding builds (name, name) alternatives. Co-authored-by: Pia Baltazar <pia@baltazar.studio>
folderPortName / fileExtensions were only set by the avnd port factory at creation; the deserializing ProcessModel constructor restores ports from the document instead of re-running the factory, so on load they were empty and init_folder_comboboxes skipped the combobox — no folder re-scan and no live refresh, only the stale saved alternatives. Serialize both fields with the port (extensions as one space-joined string, like FileChooser's filters; JSON reads guarded for older documents). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DDQaHG5FbEyH9D8VsjEyXe
The canvas combobox item's only interaction was an invisible drag-up/down-to-spin (InfiniteScroller); a plain click did nothing, so comboboxes looked read-only on the process panel while working fine in the inspector. The old popup attempt had been left commented out. Open a QMenu on mouse press instead, like a native combobox: items are the current alternatives, the selected one is checked, and QMenu natively supports both click-then-click and press-drag-release selection. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DDQaHG5FbEyH9D8VsjEyXe
|
Runtime-tested end-to-end now (populate at document load, save/reload round-trip, selection preserved). Two additions since last push:
celtera/avendish#171 should still land first. |
Folder-backed comboboxes now install a QFileSystemWatcher on their folder, so files created while the document is open (an upstream process writing its analysis, a recorder...) appear in the list without reloading. Also change the refresh policy for the current value: keep it when still listed, fall back to the port's init when that is listed, and otherwise leave it untouched instead of clamping to an arbitrary entry - it may name a file that simply does not exist yet, and becomes selected once the file appears. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DDQaHG5FbEyH9D8VsjEyXe
When the sibling port named by folder_port() holds a file path rather than a folder (e.g. a sound-file port), list the file's containing folder. Lets an object expose a picker next to an existing file port without adding a dedicated folder port. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DDQaHG5FbEyH9D8VsjEyXe
|
Follow-ups, all runtime-tested:
Exercised across ~45 processes in a FluCoMa addon: full analysis chain (onset slicing → corpus building → KD-tree fit/query) runs zero-config with the pickers. |
PR (ossia/score): runtime-populated comboboxes for avnd objects
Branch:
feature/dynamic-combobox(offmaster)Depends on: avendish
feature/dynamic-combobox(companion PR).Diff: 4 files, +119/-10.
What
Lets an avendish object repopulate a combobox port's item list at run time —
e.g. a "File" combobox that shows the audio files currently in a folder,
updating as the folder changes. Consumes the avendish
halp::dynamic_comboboxport.
Changes
Process::ComboBox(WidgetInlets.hpp/.cpp):setAlternatives()+alternativesChangedsignal.setAlternativesrefreshes the value domainand re-clamps the current value when the list shrinks. Alternatives were
already serialized, so documents reopen with their last-known items.
ControlWidgets.hpp): the inspector and canvas comboboxes readtheir items live and rebuild on
alternativesChanged(previously the listwas fixed at widget construction).
Crousti/Executor.hpp):connect_dynamic_itemsinjects theport's
update_itemscallback, marshalling runtime updates to the modelinlet on the main thread (
QPointer-guarded). Nodes with type-only inputsare skipped.
Compatibility
Purely additive. Objects and ports that don't use the feature are unaffected;
the widget/executor paths are guarded by
requires/if constexpron the newmembers.
Testing
A throwaway
DynComboTestobject (in the score-avnd-flucoma addon) lists afolder's audio files in a
dynamic_comboboxand follows folder changes live;verified in the running app. Not part of this PR.