Every feature GUI ran its own one second QTimer, read getState(), compared
it against a remembered m_lastFeatureState and restyled its start/stop
button when the two differed. The same twenty five lines appeared in each
of them.
Feature now keeps m_state private behind setState(), which emits
stateChanged() when it actually changes, and FeatureGUI grows a shared
updateStartStopButton() that restyles the button and reports an error
state. A GUI connects to the signal and calls that, so the state is
reflected as soon as it changes rather than up to a second later, and the
per feature timers and m_lastFeatureState members are gone.
FeatureUISet disconnects the feature from its GUI before the feature is
deleted: QObject emits destroyed() before dropping its connections, so a
stateChanged() emitted from the feature's destructor could otherwise reach
a GUI that has already deleted its ui object.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Server side for the spectrum paths added to the spec: GET spectrum/report
returns whichever measurement is switched on, POST spectrum/actions
carries autoscale, clearSpectrum, resetMeasurements, freeze and
gotoMarker, and GET spectrum/data returns the power values reduced to a
number of bins. The display actions reach the spectrum through new
GLSpectrumInterface methods that default to doing nothing, so an instance
without a GUI ignores them rather than every caller having to know.
The measurement results are kept as plain values behind a lock and
published once per displayed frame, so a report costs nothing until one is
asked for, and the figures match what is on screen.
Also completes the main spectrum settings, which were only partly carried
over the API, and adds reports that had no way to be read at all: vessels
for AIS, stations for APRS, sondes for Radiosonde, the programme list for
DAB, the RDS programme service name for BFM, and validity flags for the
ADS-B aircraft report so a caller can tell a missing position from one at
zero. Map settings are exposed through their generated setters.
Two fixes found while testing: the frequency scanner dropped the frequency
list because the API calls it "frequencies" and everything downstream
keys it as "frequencySettings", and the spectrum adapters bound a
reference to the error message before init() had allocated one, so every
error path returned no response at all.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The generated SWG setters overwrite the string pointer without deleting
what is already there, and every webapiSettingsGet and webapiReportGet
calls init() first, which has allocated one. Each call therefore leaked a
QString per string field. Measured at 117 bytes per settings GET for the
Satellite Tracker, over 20,000 requests.
Assign in place when the pointer is already set, which is what these same
functions have always done for title and reverseAPIAddress. 394 sites
across webapiFormatChannelSettings, webapiFormatDeviceSettings,
webapiFormatFeatureSettings and the three report equivalents.
The webapiReverseSend* functions are deliberately left alone: they build a
fresh SWG object whose constructor leaves the pointers null, so passing a
new QString is correct there.
After the change the same measurement is flat, at 7 bytes per GET.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Most plugins that use reverse API to PATCH settings updates to remote
server only do so when `useReverseAPI` is toggled, but not when the
relevant settings are being updated. So lets fix the precondition to
use the `m_useReverseAPI` flag instead.
Add left double click to add marker to 3D map.
Add support for alititudeReference for polygon and polyline.
Add support for plugins to set color of polygons.
Fix 3D map for Qt < 5.15.
Add 3D map label scale setting.
Add 3D map time to Web report.
Reduce height of display settings dialog to fit on smaller screens.