Skip to content

Filter inspector sections by editor mode - #435

Merged
fernandotonon merged 2 commits into
masterfrom
codex/inspector-tabs-filtering
May 8, 2026
Merged

Filter inspector sections by editor mode#435
fernandotonon merged 2 commits into
masterfrom
codex/inspector-tabs-filtering

Conversation

@fernandotonon

@fernandotonon fernandotonon commented May 8, 2026

Copy link
Copy Markdown
Owner

Summary

  • Makes the inspector tab/filter policy explicit through EditorModeController APIs.
  • Adds a compact Current / All filter inside the Mode Tools tab so current-mode tools are the default while non-current sections remain reachable.
  • Updates PropertiesPanel.qml to use tab constants and reusable section visibility helpers instead of hard-coded tab/mode checks.
  • Adds focused controller tests for tab defaults, explicit Scene/History preservation, and all-mode tool reachability.

Validation

  • qmllint qml/PropertiesPanel.qml
  • cmake --build build_local --target UnitTests -j"$(nproc)"
  • env QT_QPA_PLATFORM=offscreen build_local/bin/UnitTests --gtest_filter=EditorModeControllerTest.*:MainWindowTest.ModeBarLoadsAndModeChangeUpdatesStatusIndicator
  • cmake --build build_local --target QtMeshEditor -j"$(nproc)"

Tracker

Summary by CodeRabbit

  • New Features

    • Added "Current" vs "All" filters for Mode Tools section
    • Introduced mode-specific tools header displaying current mode name
  • Improvements

    • Enhanced tab routing logic with mode-aware tab selection
    • Improved inspector tab visibility to intelligently adapt based on editor mode
    • Refined Mode Tools section behavior for better contextual display

@coderabbitai

coderabbitai Bot commented May 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Rate limit exceeded

@fernandotonon has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 47 minutes and 7 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3b008f1b-cc24-4141-8237-8f27320d05dc

📥 Commits

Reviewing files that changed from the base of the PR and between 0f79d63 and 0f4fbf3.

📒 Files selected for processing (2)
  • qml/PropertiesPanel.qml
  • src/EditorModeController_test.cpp
📝 Walkthrough

Walkthrough

This PR introduces an inspector tab routing system by adding mode-aware enum definitions and helper methods to EditorModeController, exposing them to QML, and refactoring PropertiesPanel to use these identifiers for tab selection and section visibility instead of hardcoded indices. The "Mode Tools" UI gains a dedicated header with current/all filtering, and section visibility conditions are unified via a new helper function.

Changes

Inspector Tab Routing & Mode Tools System

Layer / File(s) Summary
Inspector Tab Enumeration
src/EditorModeController.h
Introduces InspectorTabId enum with four tab identifiers (InspectorTab, SceneTab, ModeToolsTab, HistoryTab) exposed to QML via Q_ENUM.
Mode & Tab Helper Implementation
src/EditorModeController.cpp
Adds internal isValidMode() validation and five new methods: modeHasModeTools(), defaultInspectorTabForMode(), shouldKeepExplicitInspectorTab(), modeToolMatches(), and modeToolMatchesCurrentMode() for mode/tool/tab decisions.
QML-Invokable API
src/EditorModeController.h
Exposes all new C++ helpers as Q_INVOKABLE methods for QML access.
QML Tab Identifiers & Properties
qml/PropertiesPanel.qml
Adds readonly tab identifier properties (inspectorTab, sceneTab, modeToolsTab, historyTab) and showAllModeTools boolean flag to root Rectangle.
QML Helper Functions
qml/PropertiesPanel.qml
Defines showModeToolsForMode(), defaultTabForMode(), shouldKeepExplicitTab(), modeToolMatches(), and modeToolSectionVisible() wrappers around EditorModeController methods.
Mode Change Handler & Tab Preservation
qml/PropertiesPanel.qml
Updates onModeChanged to conditionally preserve explicitly selected tabs or reset to mode-based defaults via shouldKeepExplicitTab() and defaultTabForMode().
Mode Tools Header & Filter UI
qml/PropertiesPanel.qml
Adds new header displaying EditorModeController.modeName + " Tools" with toggle buttons for "Current" vs "All" filtering, visible only when currentTab === modeToolsTab.
Section Visibility Updates
qml/PropertiesPanel.qml
Refactors visibility conditions for 10 sections (Edit Mode Tools, Scene, Transform, Snap Settings, Primitive, Animations, Animation Control, LOD Generation, Material Presets, Mesh Validation) to use tab identifiers and modeToolSectionVisible() helper.
Tests for Mode & Tab Helpers
src/EditorModeController_test.cpp
Adds three test cases: default inspector tab selection per mode, inspector tab retention rules for Scene/History tabs, and mode tool filtering under show-all conditions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • fernandotonon/QtMeshEditor#433: Both PRs expand EditorModeController's QML-facing API with mode/inspector/tab helpers and update PropertiesPanel/ModeBar integration.
  • fernandotonon/QtMeshEditor#432: Both PRs add/extend EditorModeController APIs (mode/tab/tool helpers and enums) and refactor PropertiesPanel to use inspector/tab/mode-tools routing.

Poem

🐰 Tab routes now dance with modes so clear,
No hardcoded numbers living here;
Inspector, Scene, and Tools unified,
With "show all" filters, sections alive!
A path through modes, preserved and bright.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Filter inspector sections by editor mode' clearly summarizes the main change: refactoring inspector section visibility/filtering based on editor mode, which is the core objective across all modified files.
Description check ✅ Passed The PR description covers all required sections from the template: a detailed Summary section listing key changes, and comprehensive Validation and Tracker information, though no explicit Features/Bugfixes subsections.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/inspector-tabs-filtering

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.

@fernandotonon
fernandotonon force-pushed the codex/inspector-tabs-filtering branch from e8111ae to 0f79d63 Compare May 8, 2026 13:13

Copy link
Copy Markdown
Owner Author

Updated the PR to fix Mode Tools live refresh while staying on the Mode Tools tab.

Root cause: the QML visibility binding called an invokable that read EditorModeController::m_currentMode internally, but the QML expression did not directly read the currentMode property. QML therefore did not know to reevaluate the binding on mode changes until another property, such as the tab index, changed.

Fix: PropertiesPanel.qml now passes EditorModeController.currentMode into a controller helper, making current mode an explicit binding dependency. Switching Animation -> Material -> Validation now invalidates the Mode Tools section visibility immediately.

Validation rerun:

  • qmllint qml/PropertiesPanel.qml
  • cmake --build build_local --target UnitTests -j"$(nproc)"
  • env QT_QPA_PLATFORM=offscreen build_local/bin/UnitTests --gtest_filter=EditorModeControllerTest.*:MainWindowTest.ModeBarLoadsAndModeChangeUpdatesStatusIndicator
  • cmake --build build_local --target QtMeshEditor -j"$(nproc)"

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
qml/PropertiesPanel.qml (1)

56-63: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Consider resetting showAllModeTools on mode change.

onModeChanged resets currentTab to the mode-appropriate default but leaves showAllModeTools sticky. A user who toggled "All" and then switches modes will land on the new mode's ModeToolsTab with all sections still expanded — contradicting the PR's stated default of "current-mode tools." If this is intentional (preserve explicit user preference), a brief comment would clarify the decision.

💡 If reset is desired
         function onModeChanged() {
             if (root.shouldKeepExplicitTab(root.currentTab))
                 return
             root.currentTab = root.defaultTabForMode(EditorModeController.currentMode)
+            root.showAllModeTools = false
         }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@qml/PropertiesPanel.qml` around lines 56 - 63, onModeChanged updates
root.currentTab but leaves the "All sections" toggle sticky (showAllModeTools),
so when switching modes users can end up on the new ModeToolsTab with everything
expanded; update onModeChanged (inside the branch where you retarget the
Inspector/Mode-Tools pair — i.e. after the shouldKeepExplicitTab check and
before/after setting root.currentTab) to reset showAllModeTools to the default
for the new mode (e.g., set showAllModeTools = false or call the existing
initializer for mode-tool state) so ModeToolsTab starts in the current-mode
view; reference showAllModeTools, onModeChanged, root.currentTab,
root.defaultTabForMode and EditorModeController.currentMode when making the
change.
🧹 Nitpick comments (2)
src/EditorModeController_test.cpp (1)

80-88: ⚡ Quick win

defaultInspectorTabForMode is not tested for EditMode or ValidationMode.

modeHasModeTools asserts all four non-object modes (lines 73–77), but defaultInspectorTabForMode is only exercised for ObjectMode, AnimationMode, MaterialMode, and an invalid ID. Adding the two missing modes would fully close the contract and guard against future modeHasModeTools changes not being reflected in defaultInspectorTabForMode.

✅ Proposed additions
     EXPECT_EQ(ctrl->defaultInspectorTabForMode(EditorModeController::AnimationMode),
               EditorModeController::ModeToolsTab);
     EXPECT_EQ(ctrl->defaultInspectorTabForMode(EditorModeController::MaterialMode),
               EditorModeController::ModeToolsTab);
+    EXPECT_EQ(ctrl->defaultInspectorTabForMode(EditorModeController::EditMode),
+              EditorModeController::ModeToolsTab);
+    EXPECT_EQ(ctrl->defaultInspectorTabForMode(EditorModeController::ValidationMode),
+              EditorModeController::ModeToolsTab);
     EXPECT_EQ(ctrl->defaultInspectorTabForMode(99),
               EditorModeController::InspectorTab);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/EditorModeController_test.cpp` around lines 80 - 88, Add assertions for
the two missing modes so defaultInspectorTabForMode is validated for all
non-object modes; specifically call
ctrl->defaultInspectorTabForMode(EditorModeController::EditMode) and
ctrl->defaultInspectorTabForMode(EditorModeController::ValidationMode) and
expect EditorModeController::ModeToolsTab for both, mirroring the existing
checks for AnimationMode and MaterialMode (keep the existing
invalid-ID/InspectorTab check unchanged).
qml/PropertiesPanel.qml (1)

85-117: ⚡ Quick win

Decouple Repeater tab labels from InspectorTabId enum values.

The model array ["Inspector", "Scene", "Mode Tools", "History"] is compared/assigned via its implicit index (0–3), which silently couples the label order to the InspectorTabId enum order. Reordering either without updating the other would silently mis-route every sectionVisible binding downstream. All other visibility checks already use root.inspectorTab / root.sceneTab / etc. — the Repeater should too.

♻️ Proposed fix
-                    model: [ "Inspector", "Scene", "Mode Tools", "History" ]
+                    model: [
+                        { label: "Inspector",  id: root.inspectorTab  },
+                        { label: "Scene",      id: root.sceneTab      },
+                        { label: "Mode Tools", id: root.modeToolsTab  },
+                        { label: "History",    id: root.historyTab    }
+                    ]

                     Rectangle {
                         ...
-                            color: root.currentTab === index
+                            color: root.currentTab === modelData.id
                             ...
-                            font.bold: root.currentTab === index
+                            font.bold: root.currentTab === modelData.id
                             ...
-                            text: modelData
+                            text: modelData.label
                             ...
-                            onClicked: root.currentTab = index
+                            onClicked: root.currentTab = modelData.id
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@qml/PropertiesPanel.qml` around lines 85 - 117, The Repeater currently relies
on the implicit numeric index (0–3) to match InspectorTabId values, which
couples label order to enum order; change the Repeater.model from a plain string
array to an array of objects that include an explicit id referencing the root
tab IDs (e.g. { label: "Inspector", id: root.inspectorTab }, { label: "Scene",
id: root.sceneTab }, { label: "Mode Tools", id: root.modeToolsTab }, { label:
"History", id: root.historyTab }), then update usages: use modelData.label for
the Text, compare root.currentTab === modelData.id for the Rectangle
color/font.bold logic, and set onClicked: root.currentTab = modelData.id so tab
selection no longer depends on the Repeater index.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@qml/PropertiesPanel.qml`:
- Around line 56-63: onModeChanged updates root.currentTab but leaves the "All
sections" toggle sticky (showAllModeTools), so when switching modes users can
end up on the new ModeToolsTab with everything expanded; update onModeChanged
(inside the branch where you retarget the Inspector/Mode-Tools pair — i.e. after
the shouldKeepExplicitTab check and before/after setting root.currentTab) to
reset showAllModeTools to the default for the new mode (e.g., set
showAllModeTools = false or call the existing initializer for mode-tool state)
so ModeToolsTab starts in the current-mode view; reference showAllModeTools,
onModeChanged, root.currentTab, root.defaultTabForMode and
EditorModeController.currentMode when making the change.

---

Nitpick comments:
In `@qml/PropertiesPanel.qml`:
- Around line 85-117: The Repeater currently relies on the implicit numeric
index (0–3) to match InspectorTabId values, which couples label order to enum
order; change the Repeater.model from a plain string array to an array of
objects that include an explicit id referencing the root tab IDs (e.g. { label:
"Inspector", id: root.inspectorTab }, { label: "Scene", id: root.sceneTab }, {
label: "Mode Tools", id: root.modeToolsTab }, { label: "History", id:
root.historyTab }), then update usages: use modelData.label for the Text,
compare root.currentTab === modelData.id for the Rectangle color/font.bold
logic, and set onClicked: root.currentTab = modelData.id so tab selection no
longer depends on the Repeater index.

In `@src/EditorModeController_test.cpp`:
- Around line 80-88: Add assertions for the two missing modes so
defaultInspectorTabForMode is validated for all non-object modes; specifically
call ctrl->defaultInspectorTabForMode(EditorModeController::EditMode) and
ctrl->defaultInspectorTabForMode(EditorModeController::ValidationMode) and
expect EditorModeController::ModeToolsTab for both, mirroring the existing
checks for AnimationMode and MaterialMode (keep the existing
invalid-ID/InspectorTab check unchanged).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f808167e-6629-4094-a7b3-0ee0b86d2f55

📥 Commits

Reviewing files that changed from the base of the PR and between 7499c3e and 0f79d63.

📒 Files selected for processing (4)
  • qml/PropertiesPanel.qml
  • src/EditorModeController.cpp
  • src/EditorModeController.h
  • src/EditorModeController_test.cpp

- PropertiesPanel.qml: reset `showAllModeTools` back to false when the
  editor mode changes. Otherwise toggling "All" in Animation and switching
  to Material would silently land on Material's ModeToolsTab with every
  section expanded — contradicting the "current-mode tools" default the
  filter advertises.
- PropertiesPanel.qml: change the top-level tab Repeater model from a
  plain `["Inspector", "Scene", "Mode Tools", "History"]` array (indexed
  via the Repeater's implicit `index`) to objects that carry an explicit
  `id` referencing `root.inspectorTab` / `sceneTab` / `modeToolsTab` /
  `historyTab`. Reordering either the array or the `InspectorTabId` enum
  no longer silently mis-routes every `sectionVisible` binding downstream.
- EditorModeController_test.cpp: extend
  `InspectorTabPolicyDefaultsByMode` to also assert
  `defaultInspectorTabForMode(EditMode)` and
  `defaultInspectorTabForMode(ValidationMode)` — closes the contract
  gap with `modeHasModeTools` already covering all four non-object modes.

Co-authored-by: Cursor <cursoragent@cursor.com>
@fernandotonon

Copy link
Copy Markdown
Owner Author

Addressed all three CodeRabbit findings in 0f4fbf3:

  • Sticky showAllModeTools across mode changes (qml/PropertiesPanel.qml ~L56-63) — onModeChanged now resets the filter back to Current so each mode lands on its own tools by default. Comment in the connection block documents the reasoning.
  • Tab Repeater coupled to enum index order (qml/PropertiesPanel.qml ~L85-117) — model is now [{ label, id }] objects pinning each tab to root.inspectorTab / root.sceneTab / root.modeToolsTab / root.historyTab. color, font.bold and onClicked all use modelData.id. Reordering either the array or InspectorTabId no longer silently mis-routes sectionVisible bindings.
  • defaultInspectorTabForMode test gap (src/EditorModeController_test.cpp) — added assertions for EditMode and ValidationMode so the contract matches modeHasModeTools's existing coverage.

Validation:

  • qmllint qml/PropertiesPanel.qml (clean)
  • cmake --build build_local --target QtMeshEditor UnitTests -j"$(nproc)" (clean)
  • Local GUI smoke test (app starts, no console errors)

@sonarqubecloud

sonarqubecloud Bot commented May 8, 2026

Copy link
Copy Markdown

@fernandotonon
fernandotonon merged commit 0bb60da into master May 8, 2026
19 checks passed
@fernandotonon
fernandotonon deleted the codex/inspector-tabs-filtering branch May 8, 2026 13:54
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