Skip to content

AnalyzeView: unify onboard-log download into single page with transport facade#14331

Open
HTRamsey wants to merge 1 commit into
mavlink:masterfrom
HTRamsey:refactor/onboard-logs-unified-transport
Open

AnalyzeView: unify onboard-log download into single page with transport facade#14331
HTRamsey wants to merge 1 commit into
mavlink:masterfrom
HTRamsey:refactor/onboard-logs-unified-transport

Conversation

@HTRamsey
Copy link
Copy Markdown
Collaborator

@HTRamsey HTRamsey commented May 5, 2026

Summary

Collapses the parallel Onboard Logs and Onboard Logs (FTP) AnalyzePages and their controllers into one. A new OnboardLogController facade picks the LOG protocol or MAVLink-FTP transport per active vehicle based on MAV_PROTOCOL_CAPABILITY_FTP, eliminating duplicate UI, controllers, and entry types.

Why

The two pages did the same job — list and download flight logs from the vehicle — over different transports. Users had to know which page their firmware supported. The QML pages and entry classes were ~95% duplicate; the controllers shared an identical state machine (refresh → list → download → cancel) and diverged only in transport.

Changes

New layout (everything under src/AnalyzeView/OnboardLogs/)

OnboardLogController.{h,cc}    # QML_SINGLETON facade (chooses + forwards)
OnboardLogTransport.{h,cc}     # abstract base — model/state/signals contract
LogProtocolTransport.{h,cc}    # MAVLink LOG_REQUEST_LIST/LOG_DATA implementation
FtpTransport.{h,cc}            # MAVLink FTP implementation
OnboardLogEntry.{h,cc}         # shared row item (id/time/size/status/selected/ftpPath)
OnboardLogDownloadData.{h,cc}  # LOG-protocol-only chunk-tracking helper
OnboardLogPage.qml             # single AnalyzePage entry
OnboardLogTable.qml            # shared row grid, parameterized on `controller`
OnboardLogIcon.svg

Architecture

  • OnboardLogController is now a thin QML_SINGLETON facade. It owns one LogProtocolTransport and one FtpTransport as children, picks one as _active, and forwards refresh/download/cancel/eraseAll plus the QML-facing properties (model, requestingList, downloadingLogs, canErase, transportName).
  • Transport selection runs on MultiVehicleManager::activeVehicleChanged, on Vehicle::capabilityBitsChanged (handles late-arriving caps), and when the user toggles the override Fact at runtime.
  • LogProtocolTransport (was OnboardLogController) and FtpTransport (was OnboardLogFtpController) are demoted from QML singletons. Their bodies are unchanged except for inheriting from OnboardLogTransport instead of QObject.
  • OnboardLogEntry (was QGCOnboardLogEntry) is the shared model item; FTP path stays empty for LOG-protocol entries.
  • OnboardLogPage.qml shows Erase All only when the active transport advertises canErase. Description text switches between LOG-protocol and MAVLink-FTP framings via transportName.
  • The second analyzePages() entry in QGCCorePlugin.cc and the OnboardLogsFtp/ subdirectory are removed.

FTP erase parity

FtpTransport overrides canErase()=true and implements eraseAll() via FTPManager::deleteFile(), processing the model sequentially. Successful deletes drop the entry from the model; failures leave it with an Error status. cancel() also tears down in-flight delete state.

Settings override

New MavlinkSettings.onboardLogTransport enum Fact (Auto / LOG protocol / MAVLink FTP, default Auto). The facade re-evaluates on Fact change so users can force a transport when capability detection is unreliable.

Folder cleanup

  • FtpTransport logging-category declaration moved out of the header (no external consumer).
  • Stale class QThread; forward decl removed from LogProtocolTransport.h.
  • Drive-by null-check fix in LogProtocolTransport's PX4 SYS_LOGGER parameter lookup (was already unsafe before this PR).

Compatibility

  • QML public API: OnboardLogController retains its singleton name; existing QML bindings continue to work, now resolved against the facade.
  • Custom builds: Downstream QGC_CUSTOM_BUILD plugins that listed both AnalyzePages or referenced OnboardLogFtpController will need a one-line update — the FTP class is now FtpTransport and is no longer a QML singleton.

Test plan

  • Builds clean (Linux, Ninja, Debug + Release)
  • All 14 AnalyzeView tests pass (ctest -L AnalyzeView)
  • OnboardLogDownloadTest integration test exercises the facade → LOG-transport path on a non-FTP mock vehicle
  • Tested manually against PX4 SITL (FTP transport, list + download + erase)
  • Tested manually against ArduPilot SITL (LOG transport, list + download + erase)
  • Tested the override Fact swap at runtime (Auto ↔ Log ↔ FTP) with a connected vehicle
  • Verified the Erase All button hides on a non-FTP vehicle when override = Auto and shows on a connected FTP vehicle
  • Verified pageDescription swaps text on transport change

Follow-ups (intentionally out of scope)

  1. Translation pass — both old tr() strings ("Log Refresh" / "Onboard Log Refresh", etc.) need consolidation in qgc_*.ts.
  2. Compression UI — LogProtocolTransport still exposes the compressLogs/compressing/compressionProgress Q_PROPERTYs, but the facade doesn't forward them. Wire them up if/when the UI lands.
  3. ArduPilot FTP RemoveFile robustness check — older ArduPilot firmware may not honor the delete request; consider falling back to LOG-protocol erase even when FTP is the listing transport.

…rt facade

Collapses the parallel "Onboard Logs" / "Onboard Logs (FTP)" pages and
controllers into one. A new OnboardLogController facade picks the LOG
protocol or MAVLink-FTP transport per active vehicle based on
MAV_PROTOCOL_CAPABILITY_FTP, eliminating duplicate UI and entry types.

Architecture
- New abstract OnboardLogTransport base in
  src/AnalyzeView/OnboardLogs/, owning model/requestingList/
  downloadingLogs Q_PROPERTYs plus the selection/erasure surface.
- LogProtocolTransport (was OnboardLogController) and FtpTransport
  (was OnboardLogFtpController) are demoted from QML singletons to
  facade-owned children.
- OnboardLogController is now a thin QML_SINGLETON facade. It
  delegates refresh/download/cancel/eraseAll to the active transport,
  re-emits its signals, and swaps transports on vehicle change, on
  late-arriving Vehicle::capabilityBitsChanged, and when the user
  toggles the override Fact.
- OnboardLogEntry (was QGCOnboardLogEntry) is the shared row item;
  LOG-protocol-only OnboardLogDownloadData split into its own pair.
- OnboardLogTable.qml is shared; OnboardLogPage.qml is the single
  AnalyzePage entry, hiding Erase All when the active transport
  reports canErase=false.
- OnboardLogsFtp/ subdirectory and the second analyzePages() entry
  removed.

FTP erase parity
- FtpTransport overrides canErase()=true and eraseAll(), processing
  the model sequentially via FTPManager::deleteFile(). Successful
  deletes drop entries from the model; failures leave them with an
  Error status. cancel() also tears down in-flight delete state.

Settings override
- New MavlinkSettings.onboardLogTransport Fact (Auto/LOG/FTP enum,
  default Auto) for forcing a transport when capability detection is
  unreliable.

Folder cleanup
- All OnboardLog sources live in src/AnalyzeView/OnboardLogs/.
- FtpTransport's logging-category declaration moved out of the
  header (no external consumer).
- Stale class QThread; forward decl removed from LogProtocolTransport.
- Drive-by null-check fix in LogProtocolTransport's PX4 SYS_LOGGER
  parameter lookup.
Copilot AI review requested due to automatic review settings May 5, 2026 19:26
@HTRamsey
Copy link
Copy Markdown
Collaborator Author

HTRamsey commented May 5, 2026

@julianoes just merging your FTP log stuff in to one tab

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR consolidates the AnalyzeView “Onboard Logs” UI and logic by introducing a single OnboardLogController facade which selects between the MAVLink LOG protocol and MAVLink FTP transports per active vehicle (or via a new user override setting), removing the duplicate FTP-specific Analyze page/controller.

Changes:

  • Introduces an OnboardLogTransport abstraction with concrete LogProtocolTransport and FtpTransport implementations, selected/forwarded by a singleton OnboardLogController.
  • Replaces the separate FTP Analyze page with a shared OnboardLogTable.qml, and updates the single OnboardLogPage.qml to adapt messaging and “Erase All” visibility by active transport.
  • Adds a new MavlinkSettings.onboardLogTransport enum setting (Auto/LOG protocol/MAVLink FTP) and updates the integration test to use the facade’s public API.

Reviewed changes

Copilot reviewed 26 out of 26 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test/AnalyzeView/OnboardLogDownloadTest.cc Updates the integration test to use the facade’s public accessors and renamed entry type.
src/Settings/MavlinkSettings.h Adds the onboardLogTransport SettingFact declaration.
src/Settings/MavlinkSettings.cc Registers the new onboardLogTransport SettingFact.
src/Settings/Mavlink.SettingsGroup.json Defines the new onboard-log transport override setting (enum).
src/API/QGCCorePlugin.cc Removes the separate “Onboard Logs (FTP)” analyze page entry.
src/AnalyzeView/OnboardLogsFtp/OnboardLogFtpPage.qml Removes the dedicated FTP onboard-log page (deleted).
src/AnalyzeView/OnboardLogsFtp/OnboardLogFtpEntry.{h,cc} Removes FTP-specific log entry type (deleted).
src/AnalyzeView/OnboardLogsFtp/OnboardLogFtpController.h Removes FTP-specific controller singleton header (deleted).
src/AnalyzeView/OnboardLogsFtp/CMakeLists.txt Removes the FTP submodule build file (deleted).
src/AnalyzeView/OnboardLogs/OnboardLogTransport.{h,cc} Adds common transport interface/base state shared by transports and facade.
src/AnalyzeView/OnboardLogs/OnboardLogTable.qml Adds shared QML table UI used by the unified onboard logs page.
src/AnalyzeView/OnboardLogs/OnboardLogPage.qml Switches to shared table component and adapts description/Erase button to active transport.
src/AnalyzeView/OnboardLogs/OnboardLogEntry.{h,cc} Renames/unifies the log entry type and moves LOG-only download tracking out.
src/AnalyzeView/OnboardLogs/OnboardLogDownloadData.{h,cc} Extracts LOG-protocol chunk tracking into its own helper.
src/AnalyzeView/OnboardLogs/OnboardLogController.{h,cc} Implements the singleton facade selecting/forwarding to the active transport + override setting integration.
src/AnalyzeView/OnboardLogs/LogProtocolTransport.{h,cc} Adds LOG-protocol transport implementation (previous controller logic moved here).
src/AnalyzeView/OnboardLogs/FtpTransport.{h,cc} Adds FTP transport implementation (previous FTP controller logic moved here) including “erase all” support.
src/AnalyzeView/OnboardLogs/CMakeLists.txt Updates the module sources to include new transport/facade classes and helper.
src/AnalyzeView/CMakeLists.txt Removes FTP subdir and registers OnboardLogTable.qml in the AnalyzeView QML module.
Comments suppressed due to low confidence (2)

src/AnalyzeView/OnboardLogs/FtpTransport.cc:53

  • On vehicle change, this disconnects list/download/progress signals but does not disconnect FTPManager::deleteComplete. If an erase is in progress and the vehicle changes, deleteComplete can still invoke _deleteComplete on this transport while its internal state (_currentEraseEntry/_eraseQueue/_vehicle) is being reset, which can lead to use-after-free or acting on the wrong vehicle. Disconnect deleteComplete here as well and/or call cancel() before swapping vehicles.
    src/AnalyzeView/OnboardLogs/FtpTransport.cc:60
  • On vehicle change this resets listing/download queues, but it does not reset the public busy flags (_requestingLogEntries/_downloadingLogs) nor the erase state (_erasing/_eraseQueue/_currentEraseEntry/_eraseFailureCount). If the user switches vehicles mid-refresh/download/erase, QML can remain stuck in a busy state and stale pointers may remain. Consider calling cancel() (which already cancels download/delete) and explicitly clearing erase state + calling _setListing(false)/_setDownloading(false) as part of the vehicle switch teardown.

}

_receivedAllEntries();
qCWarning(LogProtocolTransportLog) << "Too many errors retreiving log list. Giving up.";
Comment on lines +135 to +139
if (_vehicle) {
_logEntriesModel->clearAndDeleteContents();
(void)disconnect(_vehicle, &Vehicle::logEntry, this, &LogProtocolTransport::_logEntry);
(void)disconnect(_vehicle, &Vehicle::logData, this, &LogProtocolTransport::_logData);
}
@@ -0,0 +1,93 @@
#pragma once

@codecov
Copy link
Copy Markdown

codecov Bot commented May 5, 2026

Codecov Report

❌ Patch coverage is 29.34947% with 467 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (master@48cb54b). Learn more about missing BASE report.

Files with missing lines Patch % Lines
...rc/AnalyzeView/OnboardLogs/LogProtocolTransport.cc 30.67% 186 Missing and 83 partials ⚠️
src/AnalyzeView/OnboardLogs/FtpTransport.cc 5.42% 117 Missing and 5 partials ⚠️
...rc/AnalyzeView/OnboardLogs/OnboardLogController.cc 38.96% 21 Missing and 26 partials ⚠️
.../AnalyzeView/OnboardLogs/OnboardLogDownloadData.cc 60.00% 4 Missing and 4 partials ⚠️
src/AnalyzeView/OnboardLogs/OnboardLogEntry.h 68.18% 2 Missing and 5 partials ⚠️
src/AnalyzeView/OnboardLogs/LogProtocolTransport.h 16.66% 5 Missing ⚠️
src/AnalyzeView/OnboardLogs/FtpTransport.h 0.00% 3 Missing ⚠️
src/AnalyzeView/OnboardLogs/OnboardLogEntry.cc 66.66% 1 Missing and 1 partial ⚠️
src/AnalyzeView/OnboardLogs/OnboardLogTransport.h 60.00% 2 Missing ⚠️
src/AnalyzeView/OnboardLogs/OnboardLogTransport.cc 75.00% 0 Missing and 1 partial ⚠️
... and 1 more
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##             master   #14331   +/-   ##
=========================================
  Coverage          ?   25.52%           
=========================================
  Files             ?      745           
  Lines             ?    62373           
  Branches          ?    28827           
=========================================
  Hits              ?    15918           
  Misses            ?    35290           
  Partials          ?    11165           
Flag Coverage Δ
unittests 25.52% <29.34%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/API/QGCCorePlugin.cc 9.31% <ø> (ø)
src/AnalyzeView/OnboardLogs/OnboardLogTransport.cc 75.00% <75.00%> (ø)
src/Settings/MavlinkSettings.cc 4.00% <0.00%> (ø)
src/AnalyzeView/OnboardLogs/OnboardLogEntry.cc 54.54% <66.66%> (ø)
src/AnalyzeView/OnboardLogs/OnboardLogTransport.h 60.00% <60.00%> (ø)
src/AnalyzeView/OnboardLogs/FtpTransport.h 0.00% <0.00%> (ø)
src/AnalyzeView/OnboardLogs/LogProtocolTransport.h 16.66% <16.66%> (ø)
src/AnalyzeView/OnboardLogs/OnboardLogEntry.h 71.42% <68.18%> (ø)
.../AnalyzeView/OnboardLogs/OnboardLogDownloadData.cc 60.00% <60.00%> (ø)
...rc/AnalyzeView/OnboardLogs/OnboardLogController.cc 40.90% <38.96%> (ø)
... and 2 more

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 48cb54b...d91a4b1. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

Build Results

Platform Status

Platform Status Details
Linux Passed View
Windows Passed View
MacOS Passed View
Android Passed View

All builds passed.

Pre-commit

Check Status Details
pre-commit Failed (non-blocking) View

Pre-commit hooks: 4 passed, 36 failed, 7 skipped.

Test Results

linux-coverage: 88 passed, 0 skipped
Total: 88 passed, 0 skipped

Code Coverage

Coverage: 59.5%

No baseline available for comparison

Artifact Sizes

Artifact Size
QGroundControl 216.59 MB
QGroundControl-aarch64 176.55 MB
QGroundControl-installer-AMD64 134.62 MB
QGroundControl-installer-AMD64-ARM64 77.25 MB
QGroundControl-installer-ARM64 105.97 MB
QGroundControl-linux 336.30 MB
QGroundControl-mac 187.79 MB
QGroundControl-windows 187.81 MB
QGroundControl-x86_64 171.68 MB
No baseline available for comparison

Updated: 2026-05-05 20:21:32 UTC • Triggered by: Android

Copy link
Copy Markdown
Contributor

@julianoes julianoes left a comment

Choose a reason for hiding this comment

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

picks the LOG protocol or MAVLink-FTP transport per active vehicle based on MAV_PROTOCOL_CAPABILITY_FTP

You can't necessarily do that. I was told that ArduPilot boards without SD card but logs in flash, won't support this. We have to check whether they are setting MAV_PROTOCOL_CAPABILITY_FTP or not!

Also, download via FTP does not have date and time for ArduPilot (see discussion in ArduPilot/ardupilot#32860), so this feature needs to be opt-in or at least manually selectable which is the reason why I made it as a separate tab.

You can of course move it to the same tab and show a selector instead to select the backend.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants