Skip to content

UI: platform profile picker for validation workflows (#370) - #715

Merged
fernandotonon merged 7 commits into
masterfrom
feat/ui-profile-picker-370
Jun 9, 2026
Merged

UI: platform profile picker for validation workflows (#370)#715
fernandotonon merged 7 commits into
masterfrom
feat/ui-profile-picker-370

Conversation

@fernandotonon

@fernandotonon fernandotonon commented Jun 5, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds Asset Folder Scan in Validation mode: platform profile picker (defaults to Modern Console), folder browse controls, and subprocess qtmesh scan --target execution that leaves the open scene untouched.
  • Introduces AssetScanController (QML singleton) + shared buildScanConfigWithPlatformProfile() used by CLI and GUI.
  • Hides example-* profiles from the GUI picker; short display names; Asset Folder Scan collapsed by default.

Test coverage

  • AssetScanController_test.cpp (11 tests): JSON parse success/failure, label sanitization, QSettings persistence/migration, profile list filtering, description, report ingestion, invalid scan path, CLI binary resolution
  • PlatformProfileScanSetupTest (3 tests): shared config builder matches loader, empty id, invalid id
  • Existing PlatformProfile_test.cpp unchanged for bundled profile loading

Review fixes

  • Subprocess scan timeout (10 min) to avoid stuck scanning state
  • Sentry breadcrumbs log folder name only, not absolute path
  • QML: keyboard activation + accessible names on browse/scan actions; hide stale findings while scanning; show failed scanFinished messages

Test plan

  • ./build_local/bin/UnitTests --gtest_filter="AssetScanController*:PlatformProfileScanSetup*"
  • Validation mode → expand Asset Folder Scan → Browse folder → Scan; results match qtmesh scan <dir> --target modern-console --json
  • Restart app: last non-example profile restored; fresh installs default to Modern Console

Closes #370

…).

Expose built-in scan profiles in the inspector with QSettings persistence, run scans via an isolated qtmesh subprocess (matching CLI --target), and share profile→ScanConfig merge through buildScanConfigWithPlatformProfile.

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

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces end-to-end asset folder scanning in Validation mode. A new AssetScanController singleton manages platform profile selection (via QSettings), invokes a CLI subprocess to scan a directory, parses JSON results, and emits state updates to QML. UI components in PropertiesPanel and BottomContextPanel display scan progress, results, and profile metadata. Helper struct PlatformProfileScanSetup and function buildScanConfigWithPlatformProfile centralize profile-to-ScanConfig construction, used by both AssetScanController and CLIPipeline::cmdScan.

Changes

Asset Folder Scanning Integration

Layer / File(s) Summary
Platform Profile Scanning Setup
src/PlatformProfile.h, src/PlatformProfile.cpp, src/AppSettingsKeys.h
PlatformProfileScanSetup struct and buildScanConfigWithPlatformProfile(...) helper centralize constructing a ScanConfig from an optional platform profile; validationPlatformProfileId() settings key enables persisting selected profile ID across sessions.
AssetScanController Declaration and Core Implementation
src/AssetScanController.h, src/AssetScanController.cpp
AssetScanController QML singleton declares properties for available profiles, selected profile, and scan state; implements singleton lifecycle helpers and constructor that loads profiles and restores last-selected profile from settings.
Profile Management and Persistence
src/AssetScanController.cpp
reloadProfiles() enumerates builtin profiles and filters UI-excluded IDs; setSelectedProfileId() persists selection to QSettings and emits Sentry breadcrumbs; updateProfileDescription() fetches and caches selected profile metadata.
JSON Report Parsing and Scan State Management
src/AssetScanController.cpp
parseScanJsonReport() parses scan JSON to extract summary counters and per-asset findings, filtering info-level severity; applyScanReport() applies parsed results to state and emits completion signals; setScanning() guards state transitions.
Subprocess Orchestration and Scan Execution
src/AssetScanController.cpp
resolveCliBinaryForTest() resolves CLI binary path for test/CI contexts; subprocess orchestration launches scan CLI with constructed arguments in worker thread, collects output, and applies async results.
CLI Pipeline Integration
src/CLIPipeline.cpp
cmdScan switches from old profile-load flow to buildScanConfigWithPlatformProfile(...) helper, propagating warnings and recording selected profile ID in scan breadcrumb.
Validation Mode UI Components
qml/PropertiesPanel.qml, qml/BottomContextPanel.qml
Asset Folder Scan section in PropertiesPanel with profile selector, directory browser, scan trigger, and results display; Asset Browser panel visibility extended to ValidationMode; BottomContextPanel validationSummary refactored to show scan context and restructured mesh validation rows.
QML Registration and Build Configuration
src/mainwindow.cpp, src/CMakeLists.txt, tests/CMakeLists.txt
AssetScanController registered as PropertiesPanel QML singleton; source and header added to CMake project and test build targets.
Unit and Integration Tests
src/AssetScanController_test.cpp
Tests verify JSON report parsing, QSettings persistence of profile selection, UI-exposed profile filtering and defaults, and platform profile scan config construction.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • fernandotonon/QtMeshEditor#370: Implements the requested GUI platform-profile picker, persisted QSettings key, profile descriptions, and Sentry breadcrumb integration for validation-mode asset folder scanning.

Possibly related PRs

  • fernandotonon/QtMeshEditor#455: Both PRs modify qml/BottomContextPanel.qml's validationSummary UI block; #455 introduced the initial structure while this PR extends it for asset-scan context and updated mesh status rows.
  • fernandotonon/QtMeshEditor#682: Both PRs use the same platform-profile plumbing (PlatformProfileLoader and buildScanConfigWithPlatformProfile) to construct ScanConfig with profile metadata; this PR adds the validation-mode consumer.
  • fernandotonon/QtMeshEditor#325: This PR's parseScanJsonReport consumer of the CLI's --json output is directly affected by PR #325's changes to the scan JSON schema and reporting fields.

Poem

🐰 A folder awaits a scan so bright,
Profiles selected, configs set right,
JSON threads dance in worker's care,
Summary counts float through the air,
Validation blooms—asset checks prepare! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.57% 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 PR title directly and clearly describes the main change: adding a platform profile picker UI for validation workflows, with the issue reference.
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.
Description check ✅ Passed The PR description covers all required template sections: Summary (with features), Technical Details (detailed changes), and Test coverage (manual and unit tests with specific commands).

✏️ 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 feat/ui-profile-picker-370

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 and others added 4 commits June 5, 2026 15:14
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…ole.

Add Browse/Open Asset Browser controls in the scan panel so the assets folder is easier to set.

Co-authored-by: Cursor <cursoragent@cursor.com>
Migrate stale QSettings on picker version bump, sort Modern Console first, strip validation suffixes from combo labels, and shorten bundled profile display names.

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

@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.

Actionable comments posted: 6

🧹 Nitpick comments (1)
src/AssetScanController.cpp (1)

295-300: ⚡ Quick win

Surface profile-setup warnings before launching the scan.

buildScanConfigWithPlatformProfile(...) returns setup.warnings, but they are discarded. That hides partial profile-parse problems from users and telemetry.

Suggested fix
     const PlatformProfileScanSetup setup = buildScanConfigWithPlatformProfile(m_selectedProfileId);
     if (!setup.ok) {
         emit error(setup.error);
         emit scanFinished(false, setup.error);
         return;
     }
+    for (const QString& w : setup.warnings) {
+        SentryReporter::addBreadcrumb(QStringLiteral("ui.action"),
+                                      QStringLiteral("asset scan profile warning: %1").arg(w),
+                                      QStringLiteral("warning"));
+    }
🤖 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/AssetScanController.cpp` around lines 295 - 300,
buildScanConfigWithPlatformProfile(m_selectedProfileId) returns
PlatformProfileScanSetup which includes setup.warnings but the current code
discards them; update the logic in the block that checks setup.ok to first check
if setup.warnings is non-empty and surface each warning (e.g., emit a warning
signal and/or log it to telemetry) before emitting error/scanFinished or
returning so partial profile-parse warnings are visible to users and telemetry;
reference PlatformProfileScanSetup, buildScanConfigWithPlatformProfile,
setup.warnings, m_selectedProfileId, and the existing emit error / emit
scanFinished calls when adding the warning handling.
🤖 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.

Inline comments:
In `@qml/PropertiesPanel.qml`:
- Around line 4411-4415: The findings Column currently remains visible during a
new scan; update its visible condition to also require that
AssetScanController.scanning is false so stale results are hidden during
in-flight scans—locate the Column block rendering findings (the Column with
width: parent.width - 16, spacing: 3) and change its visible expression from
AssetScanController.hasResults && AssetScanController.findings.length > 0 to
include !AssetScanController.scanning (matching the summary row gating).
- Around line 4449-4460: The onScanFinished handler currently updates
assetScanFeedback only when ok is true, dropping failure messages; update the
Connections handler for AssetScanController by adding an else branch (or
handling when ok is false) in function onScanFinished to set
assetScanFeedback.color to an error color (e.g. "`#c06060`") and
assetScanFeedback.text to message so failures surface to the UI; keep the
existing success branch for ok === true intact.
- Around line 4324-4387: The three MouseArea-only controls (folderBrowseMouse,
browserMouse, scanMouse) must support keyboard and assistive activation; update
each MouseArea to be focusable and expose Enter/Space handlers and accessibility
metadata: give the MouseArea a focus: true-able/tabbable target (wrap or set
focus on the parent Rectangle or add a FocusScope), add Keys.onPressed or
Keys.onReleased handlers for Qt.Key_Return and Qt.Key_Space that call the same
actions (AssetBrowserController.browseForDirectory(),
root.revealBottomTool("assetBrowser"), AssetScanController.scanFolder(...)), and
set accessible.role (Accessible.Button) and accessible.name (matching the Text)
so screen readers can announce them; ensure enabled respects
AssetScanController.scanning for scanMouse as before.

In `@src/AssetScanController_test.cpp`:
- Around line 55-65: The test reads persisted settings from a QSettings instance
created before calling AssetScanController::setSelectedProfileId(), which can
return stale data; after calling controller->setSelectedProfileId(id) create or
re-open a fresh QSettings (or call settings.sync()/settings.reload equivalent)
and then read AppSettingsKeys::validationPlatformProfileId() to assert
persistence. Locate the
AssetScanController::instance()/profileIds()/setSelectedProfileId()/selectedProfileId()
usage in the test and replace the final direct read from the original QSettings
with a newly constructed QSettings (or a synced one) before EXPECT_EQ to ensure
you assert the actual persisted value.

In `@src/AssetScanController.cpp`:
- Around line 302-303: The breadcrumb currently logs the full absolute path via
absRoot in SentryReporter::addBreadcrumb (in AssetScanController), which leaks
local directory paths; replace that usage with a non-sensitive identifier — e.g.
log only the profile id (m_selectedProfileId) and a sanitized path segment such
as QFileInfo(absRoot).fileName() or a hashed representation (use
QCryptographicHash::hash on absRoot) so breadcrumbs do not contain full absolute
paths; update the addBreadcrumb call to include the sanitized value instead of
absRoot and ensure any helper used for hashing/sanitizing is deterministic and
documented.
- Around line 253-254: Replace the blocking waitForFinished(-1) pattern with a
cancellable/timeout-aware approach: start the QProcess asynchronously (keep the
existing QProcess instance used where process.waitForFinished(-1) is called),
attach handlers for QProcess::finished and QProcess::errorOccurred to call
setScanning(false) and handle results, and add a QTimer watchdog (or use
waitForFinished(timeout) with a non-infinite timeout) that kills the process and
triggers setScanning(false) if the timeout expires; ensure the timeout/kill path
also emits the same finished/error handling so the controller/worker cannot
remain stuck in scanning state.

---

Nitpick comments:
In `@src/AssetScanController.cpp`:
- Around line 295-300: buildScanConfigWithPlatformProfile(m_selectedProfileId)
returns PlatformProfileScanSetup which includes setup.warnings but the current
code discards them; update the logic in the block that checks setup.ok to first
check if setup.warnings is non-empty and surface each warning (e.g., emit a
warning signal and/or log it to telemetry) before emitting error/scanFinished or
returning so partial profile-parse warnings are visible to users and telemetry;
reference PlatformProfileScanSetup, buildScanConfigWithPlatformProfile,
setup.warnings, m_selectedProfileId, and the existing emit error / emit
scanFinished calls when adding the warning handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: acc8a9c9-d72d-44dd-9a71-c9e416bf1da5

📥 Commits

Reviewing files that changed from the base of the PR and between 4754c96 and e1bc199.

📒 Files selected for processing (12)
  • qml/BottomContextPanel.qml
  • qml/PropertiesPanel.qml
  • src/AppSettingsKeys.h
  • src/AssetScanController.cpp
  • src/AssetScanController.h
  • src/AssetScanController_test.cpp
  • src/CLIPipeline.cpp
  • src/CMakeLists.txt
  • src/PlatformProfile.cpp
  • src/PlatformProfile.h
  • src/mainwindow.cpp
  • tests/CMakeLists.txt

Comment thread qml/PropertiesPanel.qml
Comment thread qml/PropertiesPanel.qml
Comment thread qml/PropertiesPanel.qml
Comment thread src/AssetScanController_test.cpp Outdated
Comment thread src/AssetScanController.cpp Outdated
Comment thread src/AssetScanController.cpp Outdated
fernandotonon and others added 2 commits June 8, 2026 22:26
Co-authored-by: Cursor <cursoragent@cursor.com>
Cover JSON parsing, profile picker state, scan validation, and shared scan-config builder; add subprocess timeout, sanitize Sentry breadcrumbs, and QML keyboard/feedback fixes.

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

sonarqubecloud Bot commented Jun 9, 2026

Copy link
Copy Markdown

@fernandotonon
fernandotonon merged commit c883f14 into master Jun 9, 2026
20 checks passed
@fernandotonon
fernandotonon deleted the feat/ui-profile-picker-370 branch June 9, 2026 03:00
fernandotonon added a commit that referenced this pull request Jun 9, 2026
Co-authored-by: Cursor <cursoragent@cursor.com>
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.

UI: platform profile picker for validation / batch workflows

1 participant