Skip to content

Add multi-selection to ImageGallery#3054

Merged
cbentejac merged 10 commits intodevelopfrom
copilot/add-multiselection-image-gallery
Apr 28, 2026
Merged

Add multi-selection to ImageGallery#3054
cbentejac merged 10 commits intodevelopfrom
copilot/add-multiselection-image-gallery

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 22, 2026

Adds multi-selection to the ImageGallery. The last clicked item continues to define selectedViewId for the viewer. Multiple images can be selected and removed together as a single undoable operation via right-click context menu or Delete key.

Description

Previously the ImageGallery only supported single-item selection. This adds standard multi-selection UX (Ctrl+Click to toggle, Shift+Click for range) and exposes a "Remove Selected Images" action for the selection.

Features list

  • Ctrl+Click toggles an item in/out of the selection
  • Shift+Click range-selects from the last clicked item to the target
  • Last clicked item still drives selectedViewId (viewer follows it)
  • Multi-selected items highlighted with semi-transparent accent (primary selection retains full highlight)
  • Right-click → "Remove Selected Images (N)" — enabled when N > 1
  • Delete removes all selected images when multiple are selected; falls back to single removal otherwise
  • Escape collapses multi-selection back to the current item
  • Multi-image removal is a single undoable operation (one undo step)

Implementation remarks

Selection state is tracked in two new sortedModel properties:

  • selectedIndex (existing) — the primary/last-clicked item, drives the viewer
  • selectedIndices: [] (new) — the full multi-selection set used for removal and highlighting

getObjectAt(filteredIndex) was added to SortFilterDelegateModel to let the gallery collect Python viewpoint attribute objects for all selected indices at removal time.

Multi-image removal is handled by a new removeImages(images) slot in graph.py that wraps individual removeImage() calls inside a single groupedGraphModification, so the entire batch undoes as one step. Nested macros in Qt's undo stack correctly aggregate into the outer macro.

The onCurrentItemChanged guard in grid/list views prevents keyboard navigation from incorrectly resetting selectedIndices by checking sortedModel.selectedIndex !== root.currentIndex before clearing selection state.

@fabiencastan fabiencastan added this to the Meshroom 2026.1.0 milestone Mar 22, 2026
@fabiencastan fabiencastan added the feature new feature (proposed as PR or issue planned by dev) label Mar 22, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 22, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.47%. Comparing base (b55440c) to head (444512c).
⚠️ Report is 14 commits behind head on develop.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #3054   +/-   ##
========================================
  Coverage    83.47%   83.47%           
========================================
  Files           81       81           
  Lines        10300    10301    +1     
========================================
+ Hits          8598     8599    +1     
  Misses        1702     1702           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@fabiencastan fabiencastan marked this pull request as ready for review April 1, 2026 21:27
Copilot AI and others added 2 commits April 24, 2026 15:10
- Add getObjectAt() to SortFilterDelegateModel for accessing filtered items
- Add selectedIndices, toggleIndex(), selectRange(), clearMultiSelection() to sortedModel
- Update ImageDelegate with isInMultiSelection property, removeSelectedRequest signal, visual highlight
- Update onPressed in ImageGallery.qml for Ctrl/Shift-click multi-selection
- Add sendRemoveSelectedRequest() and removeSelectedImagesRequest signal
- Add Escape key to clear multi-selection in grid/list views
- Add removeImages() slot in graph.py for single undo operation
- Connect onRemoveSelectedImagesRequest in WorkspaceView.qml

Co-authored-by: fabiencastan <153585+fabiencastan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/alicevision/Meshroom/sessions/afa03f78-9c73-481b-a448-8686e7ac4ed1
…nsistently

Co-authored-by: fabiencastan <153585+fabiencastan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/alicevision/Meshroom/sessions/afa03f78-9c73-481b-a448-8686e7ac4ed1
@cbentejac cbentejac force-pushed the copilot/add-multiselection-image-gallery branch from 26071a6 to a6940c8 Compare April 27, 2026 09:13
`removeSelectedRequest` was only used when the number of selected images
exceeded 1, but it is useless to go through a different pipe when there
is a single image or several, as the selection always remains available.

`removeSelectedRequest` is thus called everytime and is enabled as soon
as the selection is not empty.
…ection

Before sending the removal request for the selection of images, check
whether all the images are included in it. If so, we can use
`removeAllImages` straight away, which will be more efficient
computationally.
The `onRemoveSelectedImagesRequest` fully replaces the
`onRemoveImageRequest` slot.
This allows to process the removal of a selection of images as a single
operation rather than looping over each image and performing the same
checks everytime, thus improving the performance.
@cbentejac cbentejac force-pushed the copilot/add-multiselection-image-gallery branch from 8a4f01a to 07af4b8 Compare April 27, 2026 13:45
`sortedModel` may be destroyed before we reach the call to
`clearMultiSelection`. If this is the case, then that call raises some
errors, as `sortedModel` has become `undefined`. Capturing it in a variable
prior to performing any operation that may destroy it allows to still be
able to access the object itself.
If enabled, the index in the gallery will not be reset to -1 by default,
as it may cause a major move across the gallery.

The option is enabled when a selection of images is removed, as it makes
sense to remain close to where the last selected image was.
@cbentejac cbentejac force-pushed the copilot/add-multiselection-image-gallery branch from 4b2f2df to 576c34d Compare April 27, 2026 14:48
@cbentejac cbentejac force-pushed the copilot/add-multiselection-image-gallery branch from 99fdf3a to 444512c Compare April 28, 2026 13:38
@nicolas-lambert-tc nicolas-lambert-tc self-requested a review April 28, 2026 15:30
@cbentejac cbentejac merged commit 0ee8481 into develop Apr 28, 2026
8 checks passed
@cbentejac cbentejac deleted the copilot/add-multiselection-image-gallery branch April 28, 2026 15:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature new feature (proposed as PR or issue planned by dev)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants