Skip to content

feat: Use QScrollArea for components selection#1328

Open
Czaki wants to merge 14 commits intodevelopfrom
scroll_area_select_components
Open

feat: Use QScrollArea for components selection#1328
Czaki wants to merge 14 commits intodevelopfrom
scroll_area_select_components

Conversation

@Czaki
Copy link
Collaborator

@Czaki Czaki commented Oct 22, 2025

Summary by Sourcery

Make component selection scrollable and update ROI handling hooks to keep chosen components in sync with ROI changes.

New Features:

  • Allow scrolling through the list of selectable components using a scrollable container.

Enhancements:

  • Ensure selected components are automatically brought into view when toggled or changed.
  • Separate initialization of component checkboxes from updating their checked state via a dedicated setter.
  • Adjust the main ROI mask layout to use a splitter between algorithm selection and component selection panels.
  • Introduce a post-ROI-set hook for subclasses to perform additional updates after ROI changes.
  • Tighten type annotations for napari layer addition utility.

Summary by CodeRabbit

  • New Features

    • Component list supports vertical scrolling and auto-scrolls a toggled item into view
    • Component and algorithm selectors placed in a resizable split layout for better spacing
    • Settings now trigger an explicit post-ROI synchronization to keep component choices up to date
  • Refactor

    • Component-selection API reshaped for clearer, more efficient updates and partial state changes

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Oct 22, 2025

Reviewer's Guide

Wrap the components selection widget in a vertically scrollable QScrollArea, adjust its API to separate component list initialization from selection updates, and integrate it into the ROI/stack settings lifecycle while improving layout behavior and type hints.

Sequence diagram for ROI update and components list initialization

sequenceDiagram
    participant Client
    participant StackSettings
    participant BaseSettings
    participant ChosenComponents

    Client->>StackSettings: set_project_info(data)
    activate StackSettings
    StackSettings->>StackSettings: compute new_roi_info and selected_components
    StackSettings->>BaseSettings: roi = new_roi_info
    activate BaseSettings
    BaseSettings->>BaseSettings: set _roi_info
    BaseSettings->>BaseSettings: clear _additional_layers
    BaseSettings->>StackSettings: post_roi_set()
    deactivate BaseSettings
    activate StackSettings
    StackSettings->>ChosenComponents: set_chose(roi_info.bound_info.keys(), [])
    deactivate StackSettings
    Note over StackSettings,ChosenComponents: Later, when restoring selection
    StackSettings->>ChosenComponents: set_chosen(selected_components)
    deactivate StackSettings
Loading

Class diagram for updated ChosenComponents and settings integration

classDiagram
    class QScrollArea

    class ChosenComponents {
        +dict~int,ComponentCheckBox~ check_box
        +QPushButton check_all_btn
        +QPushButton uncheck_all_btn
        +FlowLayout check_layout
        +check_change_signal
        +mouse_enter
        +mouse_leave
        +ChosenComponents()
        +other_component_choose(num int)
        +check_all()
        +uncheck_all()
        +remove_components()
        +new_choose(num int, chosen_components Sequence_int_)
        +set_chose(components_index Sequence_int_, chosen_components Sequence_int_)
        +set_chosen(chosen_components Sequence_int_)
        +check_change()
        +change_state(num int, val bool)
        +get_state(num int) bool
        +get_chosen() list_int_
    }

    QScrollArea <|-- ChosenComponents

    class BaseSettings {
        -ROIInfo _roi_info
        -dict _additional_layers
        +roi ROIInfo
        +roi_changed
        +set_roi(val Union_np_ndarray_ROIInfo_)
        +post_roi_set()
    }

    class StackSettings {
        +ChosenComponents chosen_components_widget
        +set_project_info(data MaskProjectTuple_or_PointsInfo)
        +_set_roi_info(state, new_roi_info ROIInfo, segmentation_parameters dict, list_of_components list_int_, save_chosen bool)
        +post_roi_set()
    }

    BaseSettings <|-- StackSettings
    StackSettings --> ChosenComponents : manages_selection
Loading

File-Level Changes

Change Details Files
Make the components chooser a scrollable QScrollArea-based widget and adjust its internal layout/behavior.
  • Change ChosenComponents to inherit from QScrollArea instead of QWidget and embed an inner QWidget as its scrollable content.
  • Move the existing button and FlowLayout setup onto the inner widget’s layout and enable vertical-only scrolling with ScrollBarAsNeeded.
  • Automatically scroll to make a component’s checkbox visible when it is toggled via other_component_choose or change_state.
package/PartSeg/_roi_mask/main_window.py
Refine the ChosenComponents API to separate component list creation from selection updates and handle optional inputs safely.
  • Update set_chose to accept an optional chosen_components sequence, defaulting to an empty list when None is provided.
  • Add a new set_chosen method that only updates which components are checked without recreating the component list.
  • Use set_chosen wherever only selection needs updating, avoiding unnecessary recreation of checkboxes.
package/PartSeg/_roi_mask/main_window.py
package/PartSeg/_roi_mask/stack_settings.py
Integrate the scrollable chooser into the main UI layout using a splitter and hook chooser updates into the ROI lifecycle.
  • Replace direct stacking of algorithm_choose_widget and choose_components with a vertical QSplitter so both can share space and resize together.
  • Introduce post_roi_set in the settings base class and override it to repopulate the components chooser after ROI changes using set_chose.
  • Ensure ROI assignment calls post_roi_set after updating _roi_info so UI stays in sync.
package/PartSeg/_roi_mask/main_window.py
package/PartSeg/_roi_mask/stack_settings.py
package/PartSeg/common_backend/base_settings.py
Tighten typing for napari layer utility function.
  • Add explicit type annotations to _add_layer_util arguments and return type for better clarity and static checking.
package/PartSeg/common_gui/napari_image_view.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 22, 2025

📝 Walkthrough

Walkthrough

Converted the components chooser into a scrollable widget with updated selection API, added ImageSettings.post_roi_set hook invoked when ROI changes, adjusted StackSettings to use new chooser API and added post_roi_set synchronization, and refined a napari image view type signature; AlgorithmOptions now nests chooser in a vertical splitter.

Changes

Cohort / File(s) Summary
ChosenComponents UI & API
package/PartSeg/_roi_mask/main_window.py
Replaced ChosenComponents base QWidgetQScrollArea; enable vertical scrolling, disable horizontal, host prior content via widget(); handlers call ensureWidgetVisible(...). Renamed/reshaped API: set_chose(...)set_components(..., chosen_components: Union[Sequence[int], None]=None), added set_chosen(...). new_choose(...) now uses set_components(...). AlgorithmOptions now places chooser in a vertical QSplitter.
StackSettings integration
package/PartSeg/_roi_mask/stack_settings.py
Use set_chosen(selected_components) / set_components(...) directly instead of reconstructing keys from ROI params. Removed intermediate mapping in non-saving path. Added post_roi_set(self) to sync chooser via chosen_components_widget.set_components(...) with signals blocked.
Settings base hook
package/PartSeg/common_backend/base_settings.py
Added ImageSettings.post_roi_set(self) -> None and call it whenever ROI is set or cleared (before emitting roi_changed / roi_clean) so subclasses can react to ROI updates.
Type annotation refinements
package/PartSeg/common_gui/napari_image_view.py
Tightened ImageView._add_layer_util signature to index: int, layer: _NapariImage, filters: list[tuple[NoiseFilterType, float]] -> None (no runtime changes).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ImageSettings
    participant StackSettings
    participant ChosenComponents
    participant UI

    User->>ImageSettings: change/select ROI
    ImageSettings->>ImageSettings: set _roi_info, clear layers
    ImageSettings->>StackSettings: post_roi_set()
    StackSettings->>StackSettings: compute component lists (list_of_components)
    StackSettings->>ChosenComponents: set_components(component_keys, [])
    ChosenComponents->>UI: update checkboxes (no rebuild if possible)
    UI->>ChosenComponents: ensureWidgetVisible(toggled_checkbox)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I nudged the scroll, the checkboxes slide,

chosen bits tucked where they like to hide,
a gentle hook wakes when ROIs appear,
signals whisper, widgets steer,
I hop — the interface is bright and spry.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.04% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: wrapping components selection in a QScrollArea for vertical scrolling, which is the primary focus across multiple modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch scroll_area_select_components

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 OpenGrep (1.16.4)
package/PartSeg/_roi_mask/stack_settings.py

┌──────────────┐
│ Opengrep CLI │
└──────────────┘

�[32m✔�[39m �[1mOpengrep OSS�[0m
�[32m✔�[39m Basic security coverage for first-party code vulnerabilities.

�[1m Loading rules from local config...�[0m


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud
Copy link

@codecov
Copy link

codecov bot commented Oct 22, 2025

Codecov Report

❌ Patch coverage is 84.61538% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.13%. Comparing base (979f440) to head (aaf4ad1).

Files with missing lines Patch % Lines
package/PartSeg/_roi_mask/main_window.py 80.00% 5 Missing ⚠️
package/PartSeg/_roi_mask/stack_settings.py 90.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #1328      +/-   ##
===========================================
+ Coverage    93.12%   93.13%   +0.01%     
===========================================
  Files          211      211              
  Lines        33272    33297      +25     
===========================================
+ Hits         30983    31010      +27     
+ Misses        2289     2287       -2     

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Czaki Czaki added the skip check PR title skip spellcheking PR title label Dec 7, 2025
@Czaki Czaki added this to the 0.16.5 milestone Dec 7, 2025
@sonarqubecloud
Copy link

sonarqubecloud bot commented Dec 7, 2025

@Czaki Czaki marked this pull request as ready for review March 20, 2026 11:08
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="package/PartSeg/_roi_mask/stack_settings.py" line_range="303-311" />
<code_context>
         if save_chosen:
</code_context>
<issue_to_address>
**question (bug_risk):** set_chosen no longer constrains components to the available ROI parameters list.

Previously, the `save_chosen` path constrained components via `set_chosen(sorted(state2.roi_extraction_parameters.keys()))`. Now it uses only `state2.selected_components` and relies on `post_roi_set` / `bound_info.keys()`, so the component list is no longer tied to `roi_extraction_parameters`. If `roi_extraction_parameters` and `bound_info` diverge (e.g. params exist for components no longer in the ROI), some components with saved parameters may become unselectable. If that’s unintended, consider deriving the component list from the parameter keys, or intersecting `roi_extraction_parameters` and `bound_info` explicitly.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@package/PartSeg/_roi_mask/main_window.py`:
- Around line 473-476: The loop in set_chosen causes many stateChanged signals
and repeated image refreshes; wrap per-checkbox updates with signal blocking and
then trigger a single update at the end: in set_chosen (method name) call
check.blockSignals(True) before check.setChecked(...) and
check.blockSignals(False) after the loop (or for each check), then explicitly
emit the existing check_change_signal or call image_view.refresh_selected() once
after the loop to perform a single refresh; this prevents per-checkbox
stateChanged handlers from firing during the batch update invoked by
StackSettings.

In `@package/PartSeg/_roi_mask/stack_settings.py`:
- Around line 313-315: post_roi_set may be called before the UI widget exists
(chosen_components_widget is initialized to None), causing an AttributeError;
update post_roi_set to guard the call by checking that
self.chosen_components_widget is truthy (or hasattr/set to non-None) before
calling set_chose(self.roi_info.bound_info.keys(), []), so headless or pre-UI
usage of post_roi_set/setting self.roi doesn't raise.

In `@package/PartSeg/common_backend/base_settings.py`:
- Around line 158-163: The post_roi_set() hook is only called in one branch, so
ensure it runs on every ROI update path: call self.post_roi_set() before any
early returns in the ROI setter (so it executes even when ROI is set to None)
and add a call to self.post_roi_set() inside
BaseSettings.set_segmentation_result (the method referenced as
set_segmentation_result) after the internal ROI/state is updated; keep the
existing self.roi_changed.emit(self._roi_info) behavior but ensure
post_roi_set() is invoked consistently before or right after emitting so
subclasses are always synchronized.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 767af4e3-be73-433d-b152-e3afa0efc1f2

📥 Commits

Reviewing files that changed from the base of the PR and between 979f440 and 6278963.

📒 Files selected for processing (4)
  • package/PartSeg/_roi_mask/main_window.py
  • package/PartSeg/_roi_mask/stack_settings.py
  • package/PartSeg/common_backend/base_settings.py
  • package/PartSeg/common_gui/napari_image_view.py

Comment on lines +473 to +476
def set_chosen(self, chosen_components: Sequence[int]):
chosen_components = set(chosen_components)
for num, check in self.check_box.items():
check.setChecked(num in chosen_components)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Batch set_chosen() updates into a single refresh.

Each setChecked() here can emit stateChanged, which reaches check_change_signal and image_view.refresh_selected() via Line 544. Since StackSettings now calls set_chosen() after ROI loads at Line 174 and Line 306 in package/PartSeg/_roi_mask/stack_settings.py, loading a segmentation with many selected components will refresh the view once per component.

Proposed fix
     def set_chosen(self, chosen_components: Sequence[int]):
         chosen_components = set(chosen_components)
-        for num, check in self.check_box.items():
-            check.setChecked(num in chosen_components)
+        self.blockSignals(True)
+        try:
+            for num, check in self.check_box.items():
+                check.setChecked(num in chosen_components)
+        finally:
+            self.blockSignals(False)
+        self.check_change_signal.emit()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def set_chosen(self, chosen_components: Sequence[int]):
chosen_components = set(chosen_components)
for num, check in self.check_box.items():
check.setChecked(num in chosen_components)
def set_chosen(self, chosen_components: Sequence[int]):
chosen_components = set(chosen_components)
self.blockSignals(True)
try:
for num, check in self.check_box.items():
check.setChecked(num in chosen_components)
finally:
self.blockSignals(False)
self.check_change_signal.emit()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package/PartSeg/_roi_mask/main_window.py` around lines 473 - 476, The loop in
set_chosen causes many stateChanged signals and repeated image refreshes; wrap
per-checkbox updates with signal blocking and then trigger a single update at
the end: in set_chosen (method name) call check.blockSignals(True) before
check.setChecked(...) and check.blockSignals(False) after the loop (or for each
check), then explicitly emit the existing check_change_signal or call
image_view.refresh_selected() once after the loop to perform a single refresh;
this prevents per-checkbox stateChanged handlers from firing during the batch
update invoked by StackSettings.

Comment on lines +158 to +163
self.post_roi_set()
self.roi_changed.emit(self._roi_info)

def post_roi_set(self) -> None:
"""called after roi is set, for subclasses to override"""

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Make post_roi_set() run on every ROI update path.

Right now this hook only fires in the non-None branch here. The early return above and BaseSettings.set_segmentation_result() at Line 537 still bypass it, so subclasses overriding post_roi_set() will stay synchronized for some ROI updates but not others.

Proposed fix
     def roi(self, val: Union[np.ndarray, ROIInfo]):
         if val is None:
             self._roi_info = ROIInfo(val)
             self._additional_layers = {}
+            self.post_roi_set()
             self.roi_clean.emit()
             return
         try:
             if isinstance(val, np.ndarray):
                 self._roi_info = ROIInfo(self.image.fit_array_to_image(val))
@@
         if result.points is not None:
             self.points = result.points
         self._roi_info = roi_info
+        self.post_roi_set()
         self.roi_changed.emit(self._roi_info)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package/PartSeg/common_backend/base_settings.py` around lines 158 - 163, The
post_roi_set() hook is only called in one branch, so ensure it runs on every ROI
update path: call self.post_roi_set() before any early returns in the ROI setter
(so it executes even when ROI is set to None) and add a call to
self.post_roi_set() inside BaseSettings.set_segmentation_result (the method
referenced as set_segmentation_result) after the internal ROI/state is updated;
keep the existing self.roi_changed.emit(self._roi_info) behavior but ensure
post_roi_set() is invoked consistently before or right after emitting so
subclasses are always synchronized.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
package/PartSeg/_roi_mask/main_window.py (1)

473-477: ⚠️ Potential issue | 🟠 Major

Batch set_chosen() into one signal emission.

Because Line 545 wires check_change_signal to image_view.refresh_selected, each changed setChecked() here can still trigger a full refresh before the final explicit emit. On ROI loads with many selected components, that turns one sync into N+1 view refreshes.

💡 Proposed fix
     def set_chosen(self, chosen_components: Sequence[int]):
         chosen_components = set(chosen_components)
         for num, check in self.check_box.items():
-            check.setChecked(num in chosen_components)
+            check.blockSignals(True)
+            try:
+                check.setChecked(num in chosen_components)
+            finally:
+                check.blockSignals(False)
         self.check_change_signal.emit()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package/PartSeg/_roi_mask/main_window.py` around lines 473 - 477, Batch the
per-checkbox updates in set_chosen by temporarily blocking signals on each
QCheckBox while calling setChecked so intermediate stateChanged signals don't
trigger image_view.refresh_selected; for example, in set_chosen iterate
self.check_box.items(), call check.blockSignals(True) (or use
QSignalBlocker(check)), call check.setChecked(...), then unblock
(blockSignals(False)) and after the loop emit self.check_change_signal.emit()
once. Ensure you reference the set_chosen method and self.check_box and leave
the final explicit emit as the single notification.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@package/PartSeg/_roi_mask/main_window.py`:
- Around line 473-477: Batch the per-checkbox updates in set_chosen by
temporarily blocking signals on each QCheckBox while calling setChecked so
intermediate stateChanged signals don't trigger image_view.refresh_selected; for
example, in set_chosen iterate self.check_box.items(), call
check.blockSignals(True) (or use QSignalBlocker(check)), call
check.setChecked(...), then unblock (blockSignals(False)) and after the loop
emit self.check_change_signal.emit() once. Ensure you reference the set_chosen
method and self.check_box and leave the final explicit emit as the single
notification.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9b9be0c1-0617-4b8b-a660-58ac2fce6f04

📥 Commits

Reviewing files that changed from the base of the PR and between 6278963 and 6b3bc30.

📒 Files selected for processing (3)
  • package/PartSeg/_roi_mask/main_window.py
  • package/PartSeg/_roi_mask/stack_settings.py
  • package/PartSeg/common_backend/base_settings.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • package/PartSeg/common_backend/base_settings.py
  • package/PartSeg/_roi_mask/stack_settings.py

@sonarqubecloud
Copy link

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
package/PartSeg/_roi_mask/stack_settings.py (2)

306-311: Same null check concern applies here.

The set_chosen() calls at lines 306 and 310 lack the null guard that post_roi_set() has. For consistency, consider adding a similar check.

🛡️ Proposed defensive guard
             self.roi = state2.roi_info
-            self.chosen_components_widget.set_chosen(state2.selected_components)
+            if self.chosen_components_widget is not None:
+                self.chosen_components_widget.set_chosen(state2.selected_components)
             self.components_parameters_dict = state2.roi_extraction_parameters
         else:
             self.roi = new_roi_info
-            self.chosen_components_widget.set_chosen(list_of_components)
+            if self.chosen_components_widget is not None:
+                self.chosen_components_widget.set_chosen(list_of_components)
             self.components_parameters_dict = segmentation_parameters
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package/PartSeg/_roi_mask/stack_settings.py` around lines 306 - 311, The
calls to chosen_components_widget.set_chosen(...) in the conditional branches
(using state2.selected_components and list_of_components) lack a null guard like
the one used in post_roi_set(); update both usages to first check that
chosen_components_widget is not None (or is truthy) before calling set_chosen so
you don't call a method on a missing widget—apply the same defensive pattern
used in post_roi_set() around the set_chosen invocations and leave the rest of
the assignments (self.components_parameters_dict, self.roi) unchanged.

174-181: Consider adding null checks for chosen_components_widget for consistency.

Unlike post_roi_set() which guards against chosen_components_widget being None (line 314), these call sites don't have a similar guard. If set_project_info is invoked before the widget is attached, post_roi_set() will return early but the subsequent set_chosen() call will raise AttributeError.

🛡️ Proposed defensive guard
             self.roi = state2.roi_info
-            self.chosen_components_widget.set_chosen(state2.selected_components)
-
+            if self.chosen_components_widget is not None:
+                self.chosen_components_widget.set_chosen(state2.selected_components)
             self.components_parameters_dict = state2.roi_extraction_parameters
         else:
             self.set_history(data.history)
             self.roi = data.roi_info
-            self.chosen_components_widget.set_chosen(data.selected_components)
-
+            if self.chosen_components_widget is not None:
+                self.chosen_components_widget.set_chosen(data.selected_components)
             self.components_parameters_dict = data.roi_extraction_parameters
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package/PartSeg/_roi_mask/stack_settings.py` around lines 174 - 181, The
calls to self.chosen_components_widget.set_chosen in set_project_info lack a
null check and can raise AttributeError if the widget isn't attached; update
set_project_info to guard before calling set_chosen (e.g., if
self.chosen_components_widget is not None) in both branches where
state2.selected_components and data.selected_components are used, mirroring the
defensive check in post_roi_set so that when chosen_components_widget is None
the method returns or skips set_chosen safely while still setting
history/roi/components_parameters_dict.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@package/PartSeg/_roi_mask/stack_settings.py`:
- Around line 306-311: The calls to chosen_components_widget.set_chosen(...) in
the conditional branches (using state2.selected_components and
list_of_components) lack a null guard like the one used in post_roi_set();
update both usages to first check that chosen_components_widget is not None (or
is truthy) before calling set_chosen so you don't call a method on a missing
widget—apply the same defensive pattern used in post_roi_set() around the
set_chosen invocations and leave the rest of the assignments
(self.components_parameters_dict, self.roi) unchanged.
- Around line 174-181: The calls to self.chosen_components_widget.set_chosen in
set_project_info lack a null check and can raise AttributeError if the widget
isn't attached; update set_project_info to guard before calling set_chosen
(e.g., if self.chosen_components_widget is not None) in both branches where
state2.selected_components and data.selected_components are used, mirroring the
defensive check in post_roi_set so that when chosen_components_widget is None
the method returns or skips set_chosen safely while still setting
history/roi/components_parameters_dict.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 74abb391-3a08-49c5-bd38-19fc3b3f4a6b

📥 Commits

Reviewing files that changed from the base of the PR and between 590b71e and aaf4ad1.

📒 Files selected for processing (1)
  • package/PartSeg/_roi_mask/stack_settings.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip check PR title skip spellcheking PR title

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant