* @brief Handles connection transitions: recompiles transforms, reloads parser, fires * auto-actions. The latest-frame store clears on both edges so io.getLatestFrame can * never serve a previous connection's frame (the capture flag can stay on across the * cycle when the API server is enabled). */
| 832 | * cycle when the API server is enabled). |
| 833 | */ |
| 834 | void DataModel::FrameBuilder::onConnectedChanged() |
| 835 | { |
| 836 | Q_ASSERT(AppState::instance().operationMode() >= SerialStudio::ProjectFile |
| 837 | && AppState::instance().operationMode() <= SerialStudio::QuickPlot); |
| 838 | |
| 839 | const bool nowConnected = IO::ConnectionManager::instance().isConnected(); |
| 840 | if (nowConnected == m_lastConnectedState) |
| 841 | return; |
| 842 | |
| 843 | m_lastConnectedState = nowConnected; |
| 844 | m_quickPlotChannels = -1; |
| 845 | |
| 846 | invalidateFramePool(); |
| 847 | |
| 848 | parseBudgetReset(); |
| 849 | |
| 850 | if (!nowConnected) { |
| 851 | m_sourceFrames.clear(); |
| 852 | m_sourceFrameCounters.clear(); |
| 853 | m_latestFrames.clear(); |
| 854 | m_latestFrameSourceId = -1; |
| 855 | destroyTransformEngines(); |
| 856 | m_tableStore.clear(); |
| 857 | return; |
| 858 | } |
| 859 | |
| 860 | m_latestFrames.clear(); |
| 861 | m_latestFrameSourceId = -1; |
| 862 | |
| 863 | if (AppState::instance().operationMode() != SerialStudio::ProjectFile) |
| 864 | return; |
| 865 | |
| 866 | Q_ASSERT(!m_frame.title.isEmpty()); |
| 867 | initializeTableStore(); |
| 868 | DataModel::FrameParser::instance().readCode(); |
| 869 | compileTransforms(); |
| 870 | |
| 871 | const auto& actions = m_frame.actions; |
| 872 | for (const auto& action : actions) |
| 873 | if (action.autoExecuteOnConnect) { |
| 874 | const qint64 written = |
| 875 | IO::ConnectionManager::instance().writeDataToDevice(action.sourceId, get_tx_bytes(action)); |
| 876 | if (written < 0) [[unlikely]] |
| 877 | qWarning() << "[FrameBuilder] Auto-execute write failed for action:" << action.title; |
| 878 | } |
| 879 | |
| 880 | const auto& sources = DataModel::ProjectModel::instance().sources(); |
| 881 | if (sources.size() > 1) { |
| 882 | for (const auto& src : sources) |
| 883 | publishSourceTemplateFrame(src); |
| 884 | |
| 885 | return; |
| 886 | } |
| 887 | |
| 888 | const bool allImageGroups = |
| 889 | !m_frame.groups.empty() |
| 890 | && std::all_of(m_frame.groups.begin(), m_frame.groups.end(), [](const DataModel::Group& g) { |
| 891 | return g.widget == QLatin1String("image"); |
nothing calls this directly
no test coverage detected