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>