Only resort if we actually get new data from the server. (#915)

* Only resort if we actually get new data from the server.

* Further reduction in CPU usage by having highlights clear on a slightly longer time interval.

* Further CPU reductions by only re-sorting if data's actually changed.

* Further filter by current sorting column.

* Oops, sorting column should be the same as the modified column to trigger sorting.

* Fix crash when exiting FreeDV.

* Check IsValid() to avoid assertion on wxWidgets 3.0.

* Fix other wxWidgets 3.0 assertions discovered during testing.

* Reduce CPU load used by rendering frequency updates by only sending updates to the server when the frequency changes.

* Add PR #915 to changelog.
ms-gtk-assert-fix
Mooneer Salem 2025-06-10 08:54:20 -07:00 committed by GitHub
parent 405134f49c
commit 03a4d87970
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 74 additions and 14 deletions

View File

@ -800,6 +800,7 @@ LDPC | Low Density Parity Check Codes - a family of powerful FEC codes
* Unit tests: Increase sleep time before killing recording to resolve macOS test failures. (PR #917) * Unit tests: Increase sleep time before killing recording to resolve macOS test failures. (PR #917)
* Fix typo causing RX radio device to remain open. (PR #918) * Fix typo causing RX radio device to remain open. (PR #918)
* Fix WASAPI errors on some machines by supporting audio mix formats other than 16-bit integer. (PR #919) * Fix WASAPI errors on some machines by supporting audio mix formats other than 16-bit integer. (PR #919)
* Reduce CPU usage of FreeDV Reporter window by only re-sorting if we actually get new data from the server. (PR #915)
* FreeDV Reporter: Fix issue with first column not being aligned properly with other columns. (PR #922) * FreeDV Reporter: Fix issue with first column not being aligned properly with other columns. (PR #922)
2. Documentation: 2. Documentation:
* Add missing dependency for macOS builds to README. (PR #925; thanks @relistan!) * Add missing dependency for macOS builds to README. (PR #925; thanks @relistan!)

View File

@ -337,9 +337,12 @@ FreeDVReporterDialog::FreeDVReporterDialog(wxWindow* parent, wxWindowID id, cons
wxGetApp().appConfiguration.reporterWindowTop = actualPos.y; wxGetApp().appConfiguration.reporterWindowTop = actualPos.y;
SetPosition(actualPos); SetPosition(actualPos);
// Set up highlight clear timer // Set up timers. Highlight clear timer has a slightly longer interval
// to reduce CPU usage.
m_highlightClearTimer = new wxTimer(this); m_highlightClearTimer = new wxTimer(this);
m_highlightClearTimer->Start(100); m_highlightClearTimer->Start(250);
m_resortTimer = new wxTimer(this);
m_resortTimer->Start(100);
// Create Set popup menu // Create Set popup menu
setPopupMenu_ = new wxMenu(); setPopupMenu_ = new wxMenu();
@ -448,6 +451,9 @@ FreeDVReporterDialog::~FreeDVReporterDialog()
m_highlightClearTimer->Stop(); m_highlightClearTimer->Stop();
delete m_highlightClearTimer; delete m_highlightClearTimer;
m_resortTimer->Stop();
delete m_resortTimer;
m_trackFrequency->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FreeDVReporterDialog::OnFilterTrackingEnable), NULL, this); m_trackFrequency->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FreeDVReporterDialog::OnFilterTrackingEnable), NULL, this);
m_trackFreqBand->Disconnect(wxEVT_RADIOBUTTON, wxCommandEventHandler(FreeDVReporterDialog::OnFilterTrackingEnable), NULL, this); m_trackFreqBand->Disconnect(wxEVT_RADIOBUTTON, wxCommandEventHandler(FreeDVReporterDialog::OnFilterTrackingEnable), NULL, this);
m_trackExactFreq->Disconnect(wxEVT_RADIOBUTTON, wxCommandEventHandler(FreeDVReporterDialog::OnFilterTrackingEnable), NULL, this); m_trackExactFreq->Disconnect(wxEVT_RADIOBUTTON, wxCommandEventHandler(FreeDVReporterDialog::OnFilterTrackingEnable), NULL, this);
@ -789,8 +795,18 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::updateHighlights()
void FreeDVReporterDialog::OnTimer(wxTimerEvent& event) void FreeDVReporterDialog::OnTimer(wxTimerEvent& event)
{ {
FreeDVReporterDataModel* model = (FreeDVReporterDataModel*)spotsDataModel_.get(); FreeDVReporterDataModel* model = (FreeDVReporterDataModel*)spotsDataModel_.get();
if (event.GetTimer().GetId() == m_highlightClearTimer->GetId())
{
model->updateHighlights(); model->updateHighlights();
}
else
{
if (model->sortOnNextTimerInterval)
{
model->Resort(); model->Resort();
model->sortOnNextTimerInterval = false;
}
}
} }
void FreeDVReporterDialog::OnFilterTrackingEnable(wxCommandEvent& event) void FreeDVReporterDialog::OnFilterTrackingEnable(wxCommandEvent& event)
@ -1407,7 +1423,8 @@ wxString FreeDVReporterDialog::FreeDVReporterDataModel::GetCardinalDirection_(in
} }
FreeDVReporterDialog::FreeDVReporterDataModel::FreeDVReporterDataModel(FreeDVReporterDialog* parent) FreeDVReporterDialog::FreeDVReporterDataModel::FreeDVReporterDataModel(FreeDVReporterDialog* parent)
: isConnected_(false) : sortOnNextTimerInterval(false)
, isConnected_(false)
, parent_(parent) , parent_(parent)
, currentBandFilter_(FreeDVReporterDialog::BAND_ALL) , currentBandFilter_(FreeDVReporterDialog::BAND_ALL)
, filterSelfMessageUpdates_(false) , filterSelfMessageUpdates_(false)
@ -1861,6 +1878,7 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::refreshAllRows()
{ {
ItemDeleted(wxDataViewItem(nullptr), wxDataViewItem(kvp.second)); ItemDeleted(wxDataViewItem(nullptr), wxDataViewItem(kvp.second));
} }
sortOnNextTimerInterval = true;
} }
else if (updated && kvp.second->isVisible) else if (updated && kvp.second->isVisible)
{ {
@ -2029,6 +2047,7 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onUserConnectFn_(std::string
if (temp->isVisible) if (temp->isVisible)
{ {
ItemAdded(wxDataViewItem(nullptr), wxDataViewItem(temp)); ItemAdded(wxDataViewItem(nullptr), wxDataViewItem(temp));
sortOnNextTimerInterval = true;
} }
}); });
@ -2102,6 +2121,11 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onFrequencyChangeFn_(std::st
} }
auto lastUpdateTime = makeValidTime_(lastUpdate, iter->second->lastUpdateDate); auto lastUpdateTime = makeValidTime_(lastUpdate, iter->second->lastUpdateDate);
auto sortingColumn = parent_->m_listSpots->GetSortingColumn();
bool isChanged =
(sortingColumn == parent_->m_listSpots->GetColumn(FREQUENCY_COL) && iter->second->frequency != frequencyHz) ||
(sortingColumn == parent_->m_listSpots->GetColumn(LAST_UPDATE_DATE_COL) && iter->second->lastUpdate != lastUpdateTime);
iter->second->frequency = frequencyHz; iter->second->frequency = frequencyHz;
iter->second->freqString = frequencyString; iter->second->freqString = frequencyString;
iter->second->lastUpdate = lastUpdateTime; iter->second->lastUpdate = lastUpdateTime;
@ -2119,10 +2143,12 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onFrequencyChangeFn_(std::st
{ {
ItemDeleted(wxDataViewItem(nullptr), dvi); ItemDeleted(wxDataViewItem(nullptr), dvi);
} }
sortOnNextTimerInterval = true;
} }
else if (newVisibility) else if (newVisibility)
{ {
ItemChanged(dvi); ItemChanged(dvi);
sortOnNextTimerInterval |= isChanged;
} }
} }
}); });
@ -2139,8 +2165,10 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onTransmitUpdateFn_(std::str
auto iter = allReporterData_.find(sid); auto iter = allReporterData_.find(sid);
if (iter != allReporterData_.end()) if (iter != allReporterData_.end())
{ {
bool isChanged = iter->second->transmitting != transmitting;
iter->second->transmitting = transmitting; iter->second->transmitting = transmitting;
auto sortingColumn = parent_->m_listSpots->GetSortingColumn();
std::string txStatus = "RX"; std::string txStatus = "RX";
if (transmitting) if (transmitting)
{ {
@ -2149,20 +2177,27 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onTransmitUpdateFn_(std::str
if (iter->second->status != _(RX_ONLY_STATUS)) if (iter->second->status != _(RX_ONLY_STATUS))
{ {
isChanged |=
(sortingColumn == parent_->m_listSpots->GetColumn(STATUS_COL) && iter->second->status != txStatus) ||
(sortingColumn == parent_->m_listSpots->GetColumn(TX_MODE_COL) && iter->second->txMode != txMode);
iter->second->status = txStatus; iter->second->status = txStatus;
iter->second->txMode = txMode; iter->second->txMode = txMode;
auto lastTxTime = makeValidTime_(lastTxDate, iter->second->lastTxDate); auto lastTxTime = makeValidTime_(lastTxDate, iter->second->lastTxDate);
isChanged |= (sortingColumn == parent_->m_listSpots->GetColumn(LAST_TX_DATE_COL) && iter->second->lastTx != lastTxTime);
iter->second->lastTx = lastTxTime; iter->second->lastTx = lastTxTime;
} }
auto lastUpdateTime = makeValidTime_(lastUpdate, iter->second->lastUpdateDate); auto lastUpdateTime = makeValidTime_(lastUpdate, iter->second->lastUpdateDate);
isChanged |= (sortingColumn == parent_->m_listSpots->GetColumn(LAST_UPDATE_DATE_COL) && iter->second->lastUpdate != lastUpdateTime);
iter->second->lastUpdate = lastUpdateTime; iter->second->lastUpdate = lastUpdateTime;
if (iter->second->isVisible) if (iter->second->isVisible)
{ {
wxDataViewItem dvi(iter->second); wxDataViewItem dvi(iter->second);
ItemChanged(dvi); ItemChanged(dvi);
sortOnNextTimerInterval |= isChanged;
} }
} }
}); });
@ -2179,16 +2214,28 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onReceiveUpdateFn_(std::stri
auto iter = allReporterData_.find(sid); auto iter = allReporterData_.find(sid);
if (iter != allReporterData_.end()) if (iter != allReporterData_.end())
{ {
auto sortingColumn = parent_->m_listSpots->GetSortingColumn();
bool isChanged =
(sortingColumn == parent_->m_listSpots->GetColumn(LAST_RX_CALLSIGN_COL) && iter->second->lastRxCallsign != receivedCallsign) ||
(sortingColumn == parent_->m_listSpots->GetColumn(LAST_RX_MODE_COL) && iter->second->lastRxMode != rxMode);
iter->second->lastRxCallsign = receivedCallsign; iter->second->lastRxCallsign = receivedCallsign;
iter->second->lastRxMode = rxMode; iter->second->lastRxMode = rxMode;
auto lastUpdateTime = makeValidTime_(lastUpdate, iter->second->lastUpdateDate); auto lastUpdateTime = makeValidTime_(lastUpdate, iter->second->lastUpdateDate);
isChanged |= (sortingColumn == parent_->m_listSpots->GetColumn(LAST_UPDATE_DATE_COL) && iter->second->lastUpdate != lastUpdateTime);
iter->second->lastUpdate = lastUpdateTime; iter->second->lastUpdate = lastUpdateTime;
wxString snrString = wxString::Format(_("%.01f"), snr); wxString snrString = wxString::Format(_("%.01f"), snr);
if (receivedCallsign == "" && rxMode == "") if (receivedCallsign == "" && rxMode == "")
{ {
// Frequency change--blank out SNR too. // Frequency change--blank out SNR too.
isChanged |=
(sortingColumn == parent_->m_listSpots->GetColumn(LAST_RX_CALLSIGN_COL) && iter->second->lastRxCallsign != UNKNOWN_STR) ||
(sortingColumn == parent_->m_listSpots->GetColumn(LAST_RX_MODE_COL) && iter->second->lastRxMode != UNKNOWN_STR) ||
(sortingColumn == parent_->m_listSpots->GetColumn(SNR_COL) && iter->second->snr != UNKNOWN_STR) ||
iter->second->lastRxDate.IsValid();
iter->second->lastRxCallsign = UNKNOWN_STR; iter->second->lastRxCallsign = UNKNOWN_STR;
iter->second->lastRxMode = UNKNOWN_STR; iter->second->lastRxMode = UNKNOWN_STR;
iter->second->snr = UNKNOWN_STR; iter->second->snr = UNKNOWN_STR;
@ -2196,6 +2243,8 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onReceiveUpdateFn_(std::stri
} }
else else
{ {
isChanged |=
(sortingColumn == parent_->m_listSpots->GetColumn(SNR_COL) && iter->second->snr != snrString);
iter->second->snr = snrString; iter->second->snr = snrString;
iter->second->lastRxDate = wxDateTime::Now(); iter->second->lastRxDate = wxDateTime::Now();
} }
@ -2204,6 +2253,7 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onReceiveUpdateFn_(std::stri
{ {
wxDataViewItem dvi(iter->second); wxDataViewItem dvi(iter->second);
ItemChanged(dvi); ItemChanged(dvi);
sortOnNextTimerInterval |= isChanged;
} }
} }
}); });
@ -2220,16 +2270,21 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onMessageUpdateFn_(std::stri
auto iter = allReporterData_.find(sid); auto iter = allReporterData_.find(sid);
if (iter != allReporterData_.end()) if (iter != allReporterData_.end())
{ {
auto sortingColumn = parent_->m_listSpots->GetSortingColumn();
bool isChanged = false;
if (message.size() == 0) if (message.size() == 0)
{ {
isChanged |= (sortingColumn == parent_->m_listSpots->GetColumn(USER_MESSAGE_COL) && iter->second->userMessage != UNKNOWN_STR);
iter->second->userMessage = UNKNOWN_STR; iter->second->userMessage = UNKNOWN_STR;
} }
else else
{ {
isChanged |= (sortingColumn == parent_->m_listSpots->GetColumn(USER_MESSAGE_COL) && iter->second->userMessage != wxString::FromUTF8(message.c_str()));
iter->second->userMessage = wxString::FromUTF8(message.c_str()); iter->second->userMessage = wxString::FromUTF8(message.c_str());
} }
auto lastUpdateTime = makeValidTime_(lastUpdate, iter->second->lastUpdateDate); auto lastUpdateTime = makeValidTime_(lastUpdate, iter->second->lastUpdateDate);
isChanged |= (sortingColumn == parent_->m_listSpots->GetColumn(LAST_UPDATE_DATE_COL) && iter->second->lastUpdate != lastUpdateTime);
iter->second->lastUpdate = lastUpdateTime; iter->second->lastUpdate = lastUpdateTime;
// Only highlight on non-empty messages. // Only highlight on non-empty messages.
@ -2250,6 +2305,7 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onMessageUpdateFn_(std::stri
{ {
wxDataViewItem dvi(iter->second); wxDataViewItem dvi(iter->second);
ItemChanged(dvi); ItemChanged(dvi);
sortOnNextTimerInterval |= isChanged;
} }
} }
}); });

View File

@ -141,6 +141,7 @@ class FreeDVReporterDialog : public wxFrame
wxButton* m_buttonDisplayWebpage; wxButton* m_buttonDisplayWebpage;
// Timer to unhighlight RX rows after 10s (like with web-based Reporter) // Timer to unhighlight RX rows after 10s (like with web-based Reporter)
wxTimer* m_resortTimer;
wxTimer* m_highlightClearTimer; wxTimer* m_highlightClearTimer;
wxTipWindow* tipWindow_; wxTipWindow* tipWindow_;
@ -217,6 +218,8 @@ class FreeDVReporterDialog : public wxFrame
virtual wxString GetColumnType (unsigned int col) const override; virtual wxString GetColumnType (unsigned int col) const override;
#endif // !wxCHECK_VERSION(3,2,0) #endif // !wxCHECK_VERSION(3,2,0)
bool sortOnNextTimerInterval;
private: private:
struct ReporterData struct ReporterData
{ {

View File

@ -1238,14 +1238,14 @@ void MainFrame::OnChangeReportFrequency( wxCommandEvent& event )
m_cboReportFrequency->SetForegroundColour(wxColor(*wxRED)); m_cboReportFrequency->SetForegroundColour(wxColor(*wxRED));
} }
if (oldFreq != wxGetApp().appConfiguration.reportingConfiguration.reportingFrequency)
{
// Report current frequency to reporters // Report current frequency to reporters
for (auto& ptr : wxGetApp().m_reporters) for (auto& ptr : wxGetApp().m_reporters)
{ {
ptr->freqChange(wxGetApp().appConfiguration.reportingConfiguration.reportingFrequency); ptr->freqChange(wxGetApp().appConfiguration.reportingConfiguration.reportingFrequency);
} }
if (oldFreq != wxGetApp().appConfiguration.reportingConfiguration.reportingFrequency)
{
if (wxGetApp().rigFrequencyController != nullptr && if (wxGetApp().rigFrequencyController != nullptr &&
wxGetApp().appConfiguration.reportingConfiguration.reportingFrequency > 0 && wxGetApp().appConfiguration.reportingConfiguration.reportingFrequency > 0 &&
(wxGetApp().appConfiguration.rigControlConfiguration.hamlibEnableFreqModeChanges || wxGetApp().appConfiguration.rigControlConfiguration.hamlibEnableFreqChangesOnly)) (wxGetApp().appConfiguration.rigControlConfiguration.hamlibEnableFreqModeChanges || wxGetApp().appConfiguration.rigControlConfiguration.hamlibEnableFreqChangesOnly))