Various main window and FreeDV Reporter UI improvements (#1132)
* Combine Locator and Distance columns. * Pop up tooltip to show SW version instead of using an entire column. * Add tooltip to better describe FreeDV Reporter tracking feature. * Hide ReSync button (missed from previous PR). * Move Assistance button to Help menu. * Shorten thread names in integrations to match main app. * Revert "Combine Locator and Distance columns." This reverts commitpull/1138/head1c41913f51. * Add PR #1132 to changelog. * Make sure TX globals are properly initialized during startup. * Allow Reporter columns to be moved by the user. Note: not persisting this yet. * WIP column ordering persistence. * Fix compiler error. * Preserve sort ordering on Linux. * Fix column sorting and naming bugs.: * Allow columns to be hidden. * Workaround due to previous bug, hopefully won't be necessary by merge. * Make sure legacy column visibility is handled properly. * Update changelog. * Fix spelling mistake. * Zero out waterfall when transmitting and not in full duplex. (#1136) * Zero out waterfall when transmitting and not in full duplex. * Add PR #1136 to changelog. * latest user manual PDF * Implement Windows specific column ordering save/restore. * Fix Windows build error. * Add additional debugging for Windows. * Revert Windows-specific changes. * Revert "Pop up tooltip to show SW version instead of using an entire column." This reverts commit55799509e1. * Revert "Revert Windows-specific changes." This reverts commitfa4bf18b8e. * Windows: we need to get the new ordering after event handler's called. * Forgot to allow Version column to be hidden. * Better handle migration for columns that get added or removed. * Fix most recent crash. * Fix startup crash in GH environment. * Fix Windows compiler error. * Windows: need to make sure all columns in control are in the order list. * Can't just push to a vector that's no longer in scope. * Mirror files needed for Windows tests. * Suppress possible cause of some of the Linux CI errors.
parent
c806ad3664
commit
612da148aa
|
|
@ -14,6 +14,10 @@ env:
|
|||
BUILD_TYPE: RelWithDebInfo
|
||||
TORCH_RELEASE: 2.9.1
|
||||
|
||||
# Needed to suppress possible cause of test errors.
|
||||
# See https://github.com/alexmurray/emacs-snap/issues/60
|
||||
NO_AT_BRIDGE: 1
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-24.04
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ jobs:
|
|||
- name: Install VB-Cable ("Radio" sound device)
|
||||
uses: LABSN/sound-ci-helpers@v1
|
||||
|
||||
- run: 'Invoke-WebRequest https://software.muzychenko.net/trials/vac464.zip -OutFile vac464.zip'
|
||||
- run: 'Invoke-WebRequest https://k6aq.net/freedv-build/vac464.zip -OutFile vac464.zip'
|
||||
- run: 'Expand-Archive -Path vac464.zip -DestinationPath vac464'
|
||||
- run: 'Import-Certificate -FilePath ${{github.workspace}}\test\vac464.cer -CertStoreLocation Cert:\LocalMachine\root'
|
||||
- run: 'Import-Certificate -FilePath ${{github.workspace}}\test\vac464.cer -CertStoreLocation Cert:\LocalMachine\TrustedPublisher'
|
||||
|
|
|
|||
|
|
@ -870,6 +870,8 @@ LDPC | Low Density Parity Check Codes - a family of powerful FEC codes
|
|||
* Flex: Report FreeDV SNR using SmartSDR Meter API. (PR #1119)
|
||||
* Add support for BBWENet bandwidth expander for received RADE audio. (PR #1113)
|
||||
* Reduce CPU usage rendering "scalar" plots (i.e. From Mic). (PR #1133)
|
||||
* FreeDV Reporter: Combine Version and Status columns to save horizontal space. (PR #1132)
|
||||
* FreeDV Reporter: Allow columns to be rearranged and/or made invisible. (PR #1132)
|
||||
|
||||
*Note: Legacy modes (700D, 700E, 1600) are now hidden by default. (PR #1108) You can show them
|
||||
again by going to Tools->Options->Modem and selecting "Enable Legacy Modes".*
|
||||
|
|
@ -887,6 +889,7 @@ again by going to Tools->Options->Modem and selecting "Enable Legacy Modes".*
|
|||
* OmniRig: Fix crash when using Test button in CAT config dialog. (PR #1126)
|
||||
* Fix hidden/clipped axis labels on plots. (PR #1110)
|
||||
* Work around deadlock bug in tty0tty. (PR #1134) - thanks @barjac!
|
||||
* Zero out waterfall when transmitting and not in full duplex. (PR #1136)
|
||||
2. Enhancements:
|
||||
* FreeDV Reporter: Sort empty user messages below non-empty ones. (PR #1105)
|
||||
* Linux: List /dev/rfcomm* serial devices when configuring. (PR #1106) - thanks @NespaLa!
|
||||
|
|
|
|||
|
|
@ -50,13 +50,16 @@ ReportingConfiguration::ReportingConfiguration()
|
|||
, freedvReporterBandFilterTracksExactFreq("/Reporting/FreeDV/BandFilterTracking/TracksExactFreq", false)
|
||||
, freedvReporterStatusText("/Reporting/FreeDV/StatusText", _(""))
|
||||
, freedvReporterRecentStatusTexts("/Reporting/FreeDV/RecentStatusTexts", {})
|
||||
|
||||
|
||||
, freedvReporterColumnOrder("/Reporting/FreeDV/ColumnOrder", { }) /* empty means default ordering */
|
||||
, freedvReporterColumnVisibility("/Reporting/FreeDV/ColumnVisibility", { })
|
||||
|
||||
, udpReportingEnabled("/Reporting/UDP/Enable", false)
|
||||
, udpReportingHostname("/Reporting/UDP/Hostname", _("127.0.0.1"))
|
||||
, udpReportingPort("/Reporting/UDP/Port", 2237)
|
||||
|
||||
, useUTCForReporting("/CallsignList/UseUTCTime", false)
|
||||
|
||||
|
||||
, reportingFrequencyList("/Reporting/FrequencyList", {
|
||||
_("1.8700"),
|
||||
_("3.6250"),
|
||||
|
|
@ -190,6 +193,9 @@ void ReportingConfiguration::load(wxConfigBase* config)
|
|||
load_(config, udpReportingHostname);
|
||||
load_(config, udpReportingPort);
|
||||
|
||||
load_(config, freedvReporterColumnOrder);
|
||||
load_(config, freedvReporterColumnVisibility);
|
||||
|
||||
load_(config, useUTCForReporting);
|
||||
|
||||
// Note: this needs to be loaded before the frequency list so that
|
||||
|
|
@ -235,6 +241,9 @@ void ReportingConfiguration::save(wxConfigBase* config)
|
|||
save_(config, freedvReporterStatusText);
|
||||
save_(config, freedvReporterRecentStatusTexts);
|
||||
|
||||
save_(config, freedvReporterColumnOrder);
|
||||
save_(config, freedvReporterColumnVisibility);
|
||||
|
||||
save_(config, udpReportingEnabled);
|
||||
save_(config, udpReportingHostname);
|
||||
save_(config, udpReportingPort);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,9 @@ public:
|
|||
ConfigurationDataElement<wxString> freedvReporterStatusText;
|
||||
ConfigurationDataElement<std::vector<wxString> > freedvReporterRecentStatusTexts;
|
||||
|
||||
ConfigurationDataElement<std::vector<int> > freedvReporterColumnOrder;
|
||||
ConfigurationDataElement<std::vector<bool> > freedvReporterColumnVisibility;
|
||||
|
||||
ConfigurationDataElement<bool> udpReportingEnabled;
|
||||
ConfigurationDataElement<wxString> udpReportingHostname;
|
||||
ConfigurationDataElement<int> udpReportingPort;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
//==========================================================================
|
||||
|
||||
#include <wx/tokenzr.h>
|
||||
#include <wx/numformatter.h>
|
||||
#include "WxWidgetsConfigStore.h"
|
||||
|
||||
template<>
|
||||
|
|
@ -30,6 +31,40 @@ void WxWidgetsConfigStore::load_<unsigned int>(wxConfigBase* config, Configurati
|
|||
configElement.setWithoutProcessing((unsigned int)val);
|
||||
}
|
||||
|
||||
template<>
|
||||
void WxWidgetsConfigStore::load_<std::vector<int> >(wxConfigBase* config, ConfigurationDataElement<std::vector<int> >& configElement)
|
||||
{
|
||||
wxString val;
|
||||
wxString defaultVal = generateStringFromArray_(configElement.getDefaultVal());
|
||||
|
||||
config->Read(configElement.getElementName(), &val, defaultVal);
|
||||
configElement.setWithoutProcessing(generateNumArrayFromString_(val));
|
||||
}
|
||||
|
||||
template<>
|
||||
void WxWidgetsConfigStore::save_<std::vector<int> >(wxConfigBase* config, ConfigurationDataElement<std::vector<int> >& configElement)
|
||||
{
|
||||
wxString val = generateStringFromArray_(configElement.getWithoutProcessing());
|
||||
config->Write(configElement.getElementName(), val);
|
||||
}
|
||||
|
||||
template<>
|
||||
void WxWidgetsConfigStore::load_<std::vector<bool> >(wxConfigBase* config, ConfigurationDataElement<std::vector<bool> >& configElement)
|
||||
{
|
||||
wxString val;
|
||||
wxString defaultVal = generateStringFromArray_(configElement.getDefaultVal());
|
||||
|
||||
config->Read(configElement.getElementName(), &val, defaultVal);
|
||||
configElement.setWithoutProcessing(generateBoolArrayFromString_(val));
|
||||
}
|
||||
|
||||
template<>
|
||||
void WxWidgetsConfigStore::save_<std::vector<bool> >(wxConfigBase* config, ConfigurationDataElement<std::vector<bool> >& configElement)
|
||||
{
|
||||
wxString val = generateStringFromArray_(configElement.getWithoutProcessing());
|
||||
config->Write(configElement.getElementName(), val);
|
||||
}
|
||||
|
||||
/* Note: for string arrays, we're treating them as a list of strings separated by commas. */
|
||||
|
||||
template<>
|
||||
|
|
@ -39,7 +74,7 @@ void WxWidgetsConfigStore::load_<std::vector<wxString> >(wxConfigBase* config, C
|
|||
wxString defaultVal = generateStringFromArray_(configElement.getDefaultVal());
|
||||
|
||||
config->Read(configElement.getElementName(), &val, defaultVal);
|
||||
configElement.setWithoutProcessing(generateArayFromString_(val));
|
||||
configElement.setWithoutProcessing(generateStrArrayFromString_(val));
|
||||
}
|
||||
|
||||
template<>
|
||||
|
|
@ -49,6 +84,67 @@ void WxWidgetsConfigStore::save_<std::vector<wxString> >(wxConfigBase* config, C
|
|||
config->Write(configElement.getElementName(), val);
|
||||
}
|
||||
|
||||
wxString WxWidgetsConfigStore::generateStringFromArray_(std::vector<int> const& vec)
|
||||
{
|
||||
wxString rv = "";
|
||||
|
||||
int count = vec.size();
|
||||
for (auto& item : vec)
|
||||
{
|
||||
wxString numAsString = wxNumberFormatter::ToString((long)item, wxNumberFormatter::Style_None);
|
||||
rv += numAsString;
|
||||
count--;
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
rv += ",";
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
wxString WxWidgetsConfigStore::generateStringFromArray_(std::vector<bool> const& vec)
|
||||
{
|
||||
std::vector<int> tmpVec;
|
||||
tmpVec.reserve(vec.size());
|
||||
for (auto v : vec)
|
||||
{
|
||||
tmpVec.push_back(v ? 1 : 0);
|
||||
}
|
||||
return generateStringFromArray_(tmpVec);
|
||||
}
|
||||
|
||||
std::vector<bool> WxWidgetsConfigStore::generateBoolArrayFromString_(wxString const& str)
|
||||
{
|
||||
std::vector<int> tmpVec = generateNumArrayFromString_(str);
|
||||
std::vector<bool> rv;
|
||||
|
||||
rv.reserve(tmpVec.size());
|
||||
for (auto& v : tmpVec)
|
||||
{
|
||||
rv.push_back(v == 1 ? true : false);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
std::vector<int> WxWidgetsConfigStore::generateNumArrayFromString_(wxString const& str)
|
||||
{
|
||||
std::vector<int> rv;
|
||||
|
||||
wxStringTokenizer tokenizer(str, ",");
|
||||
while ( tokenizer.HasMoreTokens() )
|
||||
{
|
||||
wxString token = tokenizer.GetNextToken();
|
||||
long tmp = 0;
|
||||
wxNumberFormatter::FromString(token, &tmp);
|
||||
rv.push_back((int)tmp);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
wxString WxWidgetsConfigStore::generateStringFromArray_(std::vector<wxString> const& vec)
|
||||
{
|
||||
wxString rv = "";
|
||||
|
|
@ -68,7 +164,7 @@ wxString WxWidgetsConfigStore::generateStringFromArray_(std::vector<wxString> co
|
|||
return rv;
|
||||
}
|
||||
|
||||
std::vector<wxString> WxWidgetsConfigStore::generateArayFromString_(wxString const& str)
|
||||
std::vector<wxString> WxWidgetsConfigStore::generateStrArrayFromString_(wxString const& str)
|
||||
{
|
||||
std::vector<wxString> rv;
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,13 @@ protected:
|
|||
void save_(wxConfigBase* config, ConfigurationDataElement<UnderlyingDataType>& configElement);
|
||||
|
||||
wxString generateStringFromArray_(std::vector<wxString> const& vec);
|
||||
std::vector<wxString> generateArayFromString_(wxString const& str);
|
||||
std::vector<wxString> generateStrArrayFromString_(wxString const& str);
|
||||
|
||||
wxString generateStringFromArray_(std::vector<int> const& vec);
|
||||
std::vector<int> generateNumArrayFromString_(wxString const& str);
|
||||
|
||||
wxString generateStringFromArray_(std::vector<bool> const& vec);
|
||||
std::vector<bool> generateBoolArrayFromString_(wxString const& str);
|
||||
};
|
||||
|
||||
template<typename UnderlyingDataType>
|
||||
|
|
@ -68,4 +74,16 @@ void WxWidgetsConfigStore::load_<std::vector<wxString> >(wxConfigBase* config, C
|
|||
template<>
|
||||
void WxWidgetsConfigStore::save_<std::vector<wxString> >(wxConfigBase* config, ConfigurationDataElement<std::vector<wxString> >& configElement);
|
||||
|
||||
// Special handling for loading and saving int arrays.
|
||||
template<>
|
||||
void WxWidgetsConfigStore::load_<std::vector<int> >(wxConfigBase* config, ConfigurationDataElement<std::vector<int> >& configElement);
|
||||
template<>
|
||||
void WxWidgetsConfigStore::save_<std::vector<int> >(wxConfigBase* config, ConfigurationDataElement<std::vector<int> >& configElement);
|
||||
|
||||
// Special handling for loading and saving bool arrays.
|
||||
template<>
|
||||
void WxWidgetsConfigStore::load_<std::vector<bool> >(wxConfigBase* config, ConfigurationDataElement<std::vector<bool> >& configElement);
|
||||
template<>
|
||||
void WxWidgetsConfigStore::save_<std::vector<bool> >(wxConfigBase* config, ConfigurationDataElement<std::vector<bool> >& configElement);
|
||||
|
||||
#endif // WXWIDGETS_CONFIG_STORE_H
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
#include <sstream>
|
||||
#include <math.h>
|
||||
#include <wx/datetime.h>
|
||||
#include <wx/display.h>
|
||||
|
|
@ -29,6 +30,10 @@
|
|||
#include <wx/uilocale.h>
|
||||
#endif // wxCHECK_VERSION(3,2,0)
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <wx/headerctrl.h>
|
||||
#endif // defined(WIN32)
|
||||
|
||||
#include "freedv_reporter.h"
|
||||
#include "freedv_interface.h"
|
||||
|
||||
|
|
@ -62,6 +67,115 @@ extern FreeDVInterface freedvInterface;
|
|||
|
||||
using namespace std::placeholders;
|
||||
|
||||
void FreeDVReporterDialog::createColumn_(int col, bool visible)
|
||||
{
|
||||
wxDataViewColumn* colObj = nullptr;
|
||||
int minWidth = 0;
|
||||
int alignment = wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL;
|
||||
wxString colName = "";
|
||||
bool ellipsize = false;
|
||||
|
||||
switch (col)
|
||||
{
|
||||
case CALLSIGN_COL:
|
||||
colName = wxT("Callsign");
|
||||
minWidth = 70;
|
||||
break;
|
||||
case GRID_SQUARE_COL:
|
||||
colName = wxT("Locator");
|
||||
minWidth = 65;
|
||||
break;
|
||||
case DISTANCE_COL:
|
||||
colName = wxT("km");
|
||||
minWidth = 60;
|
||||
alignment = wxALIGN_RIGHT | wxALIGN_CENTRE_VERTICAL;
|
||||
break;
|
||||
case HEADING_COL:
|
||||
colName = wxT("Hdg");
|
||||
minWidth = 60;
|
||||
alignment = wxALIGN_RIGHT | wxALIGN_CENTRE_VERTICAL;
|
||||
break;
|
||||
case VERSION_COL:
|
||||
colName = wxT("Version");
|
||||
minWidth = 70;
|
||||
break;
|
||||
case FREQUENCY_COL:
|
||||
colName = wxGetApp().appConfiguration.reportingConfiguration.reportingFrequencyAsKhz ? wxT("kHz") : wxT("MHz");
|
||||
minWidth = 60;
|
||||
alignment = wxALIGN_RIGHT | wxALIGN_CENTRE_VERTICAL;
|
||||
break;
|
||||
case TX_MODE_COL:
|
||||
colName = wxT("Mode");
|
||||
minWidth = 65;
|
||||
break;
|
||||
case STATUS_COL:
|
||||
colName = wxT("Status");
|
||||
minWidth = 60;
|
||||
break;
|
||||
case USER_MESSAGE_COL:
|
||||
// Note: there's Windows specific logic here, so we create the column
|
||||
// here rather than farther down.
|
||||
#if defined(WIN32)
|
||||
// Use ReportMessageRenderer only on Windows so that we can render emojis in color.
|
||||
colObj = new wxDataViewColumn(wxT("Msg"), new ReportMessageRenderer(), col, wxCOL_WIDTH_DEFAULT, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_REORDERABLE);
|
||||
m_listSpots->AppendColumn(colObj);
|
||||
#else
|
||||
colObj = m_listSpots->AppendTextColumn(wxT("Msg"), col, wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_DEFAULT, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_REORDERABLE);
|
||||
#endif // defined(WIN32)
|
||||
colObj->SetWidth(wxGetApp().appConfiguration.reportingUserMsgColWidth);
|
||||
minWidth = 130;
|
||||
ellipsize = true;
|
||||
break;
|
||||
case LAST_TX_DATE_COL:
|
||||
colName = wxT("Last TX");
|
||||
minWidth = 60;
|
||||
break;
|
||||
case LAST_RX_CALLSIGN_COL:
|
||||
colName = wxT("RX Call");
|
||||
minWidth = 65;
|
||||
break;
|
||||
case LAST_RX_MODE_COL:
|
||||
colName = wxT("Mode");
|
||||
minWidth = 60;
|
||||
break;
|
||||
case SNR_COL:
|
||||
colName = wxT("SNR");
|
||||
minWidth = 60;
|
||||
break;
|
||||
case LAST_UPDATE_DATE_COL:
|
||||
colName = wxT("Last Update");
|
||||
minWidth = 100;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (colObj == nullptr)
|
||||
{
|
||||
colObj = m_listSpots->AppendTextColumn(colName, col, wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_REORDERABLE);
|
||||
}
|
||||
auto renderer = colObj->GetRenderer();
|
||||
renderer->SetAlignment(alignment);
|
||||
if (ellipsize)
|
||||
{
|
||||
renderer->EnableEllipsize(wxELLIPSIZE_END);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderer->DisableEllipsize();
|
||||
}
|
||||
colObj->SetMinWidth(minWidth);
|
||||
if (col == wxGetApp().appConfiguration.reporterWindowCurrentSort)
|
||||
{
|
||||
colObj->SetSortOrder(wxGetApp().appConfiguration.reporterWindowCurrentSortDirection);
|
||||
}
|
||||
|
||||
if (!visible)
|
||||
{
|
||||
colObj->SetHidden(true);
|
||||
}
|
||||
}
|
||||
|
||||
FreeDVReporterDialog::FreeDVReporterDialog(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style)
|
||||
: wxFrame(parent, id, title, pos, size, style)
|
||||
, tipWindow_(nullptr)
|
||||
|
|
@ -90,151 +204,87 @@ FreeDVReporterDialog::FreeDVReporterDialog(wxWindow* parent, wxWindowID id, cons
|
|||
|
||||
// Main list box
|
||||
// =============================
|
||||
int col = 0;
|
||||
|
||||
m_listSpots = new wxDataViewCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_SINGLE);
|
||||
|
||||
// Associate data model.
|
||||
spotsDataModel_ = new FreeDVReporterDataModel(this);
|
||||
m_listSpots->AssociateModel(spotsDataModel_.get());
|
||||
|
||||
auto colObj = m_listSpots->AppendTextColumn(wxT("Callsign"), col++, wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
colObj->GetRenderer()->SetAlignment(wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
|
||||
colObj->GetRenderer()->DisableEllipsize();
|
||||
colObj->SetMinWidth(70);
|
||||
if ((col - 1) == wxGetApp().appConfiguration.reporterWindowCurrentSort)
|
||||
if (wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnOrder->size() != NUM_COLS)
|
||||
{
|
||||
colObj->SetSortOrder(wxGetApp().appConfiguration.reporterWindowCurrentSortDirection);
|
||||
// Generate default column ordering
|
||||
log_info("Generating missing column ordering");
|
||||
auto iter = wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnOrder->begin();
|
||||
while (iter != wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnOrder->end())
|
||||
{
|
||||
if (*iter >= RIGHTMOST_COL)
|
||||
{
|
||||
wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnOrder->erase(iter);
|
||||
iter = wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnOrder->begin();
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
auto maxIndex =
|
||||
wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnOrder->size() == 0 ?
|
||||
-1 :
|
||||
*std::max_element(
|
||||
wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnOrder->begin(),
|
||||
wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnOrder->end()
|
||||
);
|
||||
|
||||
for (auto index = maxIndex + 1; index < NUM_COLS; index++)
|
||||
{
|
||||
wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnOrder->push_back(index);
|
||||
}
|
||||
}
|
||||
|
||||
colObj = m_listSpots->AppendTextColumn(wxT("Locator"), col++, wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
colObj->GetRenderer()->DisableEllipsize();
|
||||
colObj->GetRenderer()->SetAlignment(wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
|
||||
colObj->SetMinWidth(65);
|
||||
if ((col - 1) == wxGetApp().appConfiguration.reporterWindowCurrentSort)
|
||||
|
||||
while (wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnVisibility->size() < NUM_COLS)
|
||||
{
|
||||
colObj->SetSortOrder(wxGetApp().appConfiguration.reporterWindowCurrentSortDirection);
|
||||
// Generate default column visibility
|
||||
wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnVisibility->push_back(true);
|
||||
}
|
||||
|
||||
colObj = m_listSpots->AppendTextColumn(wxT("km"), col++, wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
colObj->GetRenderer()->DisableEllipsize();
|
||||
colObj->GetRenderer()->SetAlignment(wxALIGN_RIGHT | wxALIGN_CENTRE_VERTICAL);
|
||||
colObj->SetMinWidth(60);
|
||||
if ((col - 1) == wxGetApp().appConfiguration.reporterWindowCurrentSort)
|
||||
{
|
||||
colObj->SetSortOrder(wxGetApp().appConfiguration.reporterWindowCurrentSortDirection);
|
||||
}
|
||||
|
||||
colObj = m_listSpots->AppendTextColumn(wxT("Hdg"), col++, wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
colObj->GetRenderer()->DisableEllipsize();
|
||||
colObj->GetRenderer()->SetAlignment(wxALIGN_RIGHT | wxALIGN_CENTRE_VERTICAL);
|
||||
colObj->SetMinWidth(60);
|
||||
if ((col - 1) == wxGetApp().appConfiguration.reporterWindowCurrentSort)
|
||||
{
|
||||
colObj->SetSortOrder(wxGetApp().appConfiguration.reporterWindowCurrentSortDirection);
|
||||
}
|
||||
|
||||
colObj = m_listSpots->AppendTextColumn(wxT("Version"), col++, wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
colObj->GetRenderer()->DisableEllipsize();
|
||||
colObj->GetRenderer()->SetAlignment(wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
|
||||
colObj->SetMinWidth(70);
|
||||
if ((col - 1) == wxGetApp().appConfiguration.reporterWindowCurrentSort)
|
||||
{
|
||||
colObj->SetSortOrder(wxGetApp().appConfiguration.reporterWindowCurrentSortDirection);
|
||||
}
|
||||
|
||||
colObj = m_listSpots->AppendTextColumn(
|
||||
wxGetApp().appConfiguration.reportingConfiguration.reportingFrequencyAsKhz ? wxT("kHz") : wxT("MHz"),
|
||||
col++, wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
colObj->GetRenderer()->DisableEllipsize();
|
||||
colObj->GetRenderer()->SetAlignment(wxALIGN_RIGHT | wxALIGN_CENTRE_VERTICAL);
|
||||
colObj->SetMinWidth(60);
|
||||
if ((col - 1) == wxGetApp().appConfiguration.reporterWindowCurrentSort)
|
||||
{
|
||||
colObj->SetSortOrder(wxGetApp().appConfiguration.reporterWindowCurrentSortDirection);
|
||||
}
|
||||
|
||||
colObj = m_listSpots->AppendTextColumn(wxT("Mode"), col++, wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
colObj->GetRenderer()->DisableEllipsize();
|
||||
colObj->GetRenderer()->SetAlignment(wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
|
||||
colObj->SetMinWidth(65);
|
||||
if ((col - 1) == wxGetApp().appConfiguration.reporterWindowCurrentSort)
|
||||
{
|
||||
colObj->SetSortOrder(wxGetApp().appConfiguration.reporterWindowCurrentSortDirection);
|
||||
}
|
||||
|
||||
colObj = m_listSpots->AppendTextColumn(wxT("Status"), col++, wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
colObj->GetRenderer()->DisableEllipsize();
|
||||
colObj->GetRenderer()->SetAlignment(wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
|
||||
colObj->SetMinWidth(60);
|
||||
if ((col - 1) == wxGetApp().appConfiguration.reporterWindowCurrentSort)
|
||||
{
|
||||
colObj->SetSortOrder(wxGetApp().appConfiguration.reporterWindowCurrentSortDirection);
|
||||
}
|
||||
|
||||
|
||||
// Windows seems to have the model column ID equal to the actual column ID regardless of the
|
||||
// actual ordering, so we just use wxHeaderCtrl to save/restore the column ordering.
|
||||
#if defined(WIN32)
|
||||
// Use ReportMessageRenderer only on Windows so that we can render emojis in color.
|
||||
colObj = new wxDataViewColumn(wxT("Msg"), new ReportMessageRenderer(), col++, wxCOL_WIDTH_DEFAULT, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
m_listSpots->AppendColumn(colObj);
|
||||
#else
|
||||
colObj = m_listSpots->AppendTextColumn(wxT("Msg"), col++, wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_DEFAULT, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
for (auto col = 0; col < NUM_COLS; col++)
|
||||
#else
|
||||
for (auto& col : wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnOrder.get())
|
||||
#endif // defined(WIN32)
|
||||
colObj->GetRenderer()->EnableEllipsize(wxELLIPSIZE_END);
|
||||
colObj->GetRenderer()->SetAlignment(wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
|
||||
colObj->SetMinWidth(130);
|
||||
if ((col - 1) == wxGetApp().appConfiguration.reporterWindowCurrentSort)
|
||||
{
|
||||
colObj->SetSortOrder(wxGetApp().appConfiguration.reporterWindowCurrentSortDirection);
|
||||
}
|
||||
colObj->SetWidth(wxGetApp().appConfiguration.reportingUserMsgColWidth);
|
||||
|
||||
colObj = m_listSpots->AppendTextColumn(wxT("Last TX"), col++, wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
colObj->GetRenderer()->DisableEllipsize();
|
||||
colObj->GetRenderer()->SetAlignment(wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
|
||||
colObj->SetMinWidth(60);
|
||||
if ((col - 1) == wxGetApp().appConfiguration.reporterWindowCurrentSort)
|
||||
{
|
||||
colObj->SetSortOrder(wxGetApp().appConfiguration.reporterWindowCurrentSortDirection);
|
||||
}
|
||||
|
||||
colObj = m_listSpots->AppendTextColumn(wxT("RX Call"), col++, wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
colObj->GetRenderer()->DisableEllipsize();
|
||||
colObj->GetRenderer()->SetAlignment(wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
|
||||
colObj->SetMinWidth(65);
|
||||
if ((col - 1) == wxGetApp().appConfiguration.reporterWindowCurrentSort)
|
||||
{
|
||||
colObj->SetSortOrder(wxGetApp().appConfiguration.reporterWindowCurrentSortDirection);
|
||||
}
|
||||
|
||||
colObj = m_listSpots->AppendTextColumn(wxT("Mode"), col++, wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
colObj->GetRenderer()->DisableEllipsize();
|
||||
colObj->GetRenderer()->SetAlignment(wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
|
||||
colObj->SetMinWidth(60);
|
||||
if ((col - 1) == wxGetApp().appConfiguration.reporterWindowCurrentSort)
|
||||
{
|
||||
colObj->SetSortOrder(wxGetApp().appConfiguration.reporterWindowCurrentSortDirection);
|
||||
}
|
||||
|
||||
colObj = m_listSpots->AppendTextColumn(wxT("SNR"), col++, wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
colObj->GetRenderer()->DisableEllipsize();
|
||||
colObj->GetRenderer()->SetAlignment(wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
|
||||
colObj->SetMinWidth(60);
|
||||
if ((col - 1) == wxGetApp().appConfiguration.reporterWindowCurrentSort)
|
||||
{
|
||||
colObj->SetSortOrder(wxGetApp().appConfiguration.reporterWindowCurrentSortDirection);
|
||||
}
|
||||
|
||||
colObj = m_listSpots->AppendTextColumn(wxT("Last Update"), col++, wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
colObj->GetRenderer()->DisableEllipsize();
|
||||
colObj->GetRenderer()->SetAlignment(wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
|
||||
colObj->SetMinWidth(100);
|
||||
if ((col - 1) == wxGetApp().appConfiguration.reporterWindowCurrentSort)
|
||||
{
|
||||
colObj->SetSortOrder(wxGetApp().appConfiguration.reporterWindowCurrentSortDirection);
|
||||
}
|
||||
if (col < NUM_COLS)
|
||||
{
|
||||
log_info("Creating col %d", col);
|
||||
auto visible = (bool)wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnVisibility->at(col);
|
||||
|
||||
m_listSpots->AppendTextColumn(wxT(" "), col++, wxDATAVIEW_CELL_INERT, 1, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE);
|
||||
// Hide RX Mode column if legacy modes aren't enabled
|
||||
if (col == LAST_RX_MODE_COL)
|
||||
{
|
||||
visible &= wxGetApp().appConfiguration.enableLegacyModes;
|
||||
}
|
||||
createColumn_(col, visible);
|
||||
}
|
||||
}
|
||||
m_listSpots->AppendTextColumn(wxT(" "), RIGHTMOST_COL, wxDATAVIEW_CELL_INERT, 1, wxALIGN_CENTER, wxDATAVIEW_COL_RESIZABLE);
|
||||
|
||||
#if defined(WIN32)
|
||||
auto headerCtrl = m_listSpots->GenericGetHeader();
|
||||
wxArrayInt wxColumnOrder;
|
||||
for (auto& col : wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnOrder.get())
|
||||
{
|
||||
if (col < NUM_COLS)
|
||||
{
|
||||
wxColumnOrder.Add(col);
|
||||
}
|
||||
}
|
||||
wxColumnOrder.Add(RIGHTMOST_COL); // All columns need to be in the list to actually take effect.
|
||||
headerCtrl->SetColumnsOrder(wxColumnOrder);
|
||||
#endif // defined(WIN32)
|
||||
|
||||
sectionSizer->Add(m_listSpots, 0, wxALL | wxEXPAND, 2);
|
||||
|
||||
// Bottom buttons
|
||||
|
|
@ -289,6 +339,7 @@ FreeDVReporterDialog::FreeDVReporterDialog(wxWindow* parent, wxWindowID id, cons
|
|||
bandFilterSizer->Add(m_bandFilter, 0, wxALL | wxALIGN_CENTER_VERTICAL, 2);
|
||||
|
||||
m_trackFrequency = new wxCheckBox(this, wxID_ANY, _("Track:"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE);
|
||||
m_trackFrequency->SetToolTip(_("Filters FreeDV Reporter list based on radio's current frequency or band."));
|
||||
bandFilterSizer->Add(m_trackFrequency, 0, wxALL | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, 5);
|
||||
|
||||
m_trackFreqBand = new wxRadioButton(this, wxID_ANY, _("band"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
|
||||
|
|
@ -322,6 +373,42 @@ FreeDVReporterDialog::FreeDVReporterDialog(wxWindow* parent, wxWindowID id, cons
|
|||
sectionSizer->Add(reportingSettingsSizer, 0, wxALL | wxEXPAND | wxFIXED_MINSIZE, 2);
|
||||
|
||||
this->SetMinSize(GetBestSize());
|
||||
|
||||
// Menu bar
|
||||
menuBar_ = new wxMenuBar();
|
||||
this->SetMenuBar(menuBar_);
|
||||
|
||||
showMenu_ = new wxMenu();
|
||||
menuBar_->Append(showMenu_, _("Show"));
|
||||
|
||||
std::vector<std::pair<int, wxString> > menus {
|
||||
{CALLSIGN_COL, _("Callsign")},
|
||||
{GRID_SQUARE_COL, _("Locator")},
|
||||
{DISTANCE_COL, _("Distance")},
|
||||
{VERSION_COL, _("Version")},
|
||||
{HEADING_COL, _("Heading")},
|
||||
{FREQUENCY_COL, _("Frequency")},
|
||||
{TX_MODE_COL, _("TX Mode")},
|
||||
{STATUS_COL, _("Status")},
|
||||
{USER_MESSAGE_COL, _("User Message")},
|
||||
{LAST_TX_DATE_COL, _("Last TX Date")},
|
||||
{LAST_RX_CALLSIGN_COL, _("Last RX Callsign")},
|
||||
{LAST_RX_MODE_COL, _("Last RX Mode")},
|
||||
{SNR_COL, _("SNR")},
|
||||
{LAST_UPDATE_DATE_COL, _("Last Update")},
|
||||
};
|
||||
|
||||
for (auto& item : menus)
|
||||
{
|
||||
auto menuItem = showMenu_->Append(wxID_HIGHEST + item.first, item.second, wxEmptyString, wxITEM_CHECK);
|
||||
menuItem->Check(wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnVisibility->at(item.first));
|
||||
this->Connect(wxID_HIGHEST + item.first, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(FreeDVReporterDialog::OnShowColumn));
|
||||
|
||||
if (item.first == LAST_RX_MODE_COL && !wxGetApp().appConfiguration.enableLegacyModes)
|
||||
{
|
||||
menuItem->Enable(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger auto-layout of window.
|
||||
// ==============================
|
||||
|
|
@ -440,6 +527,7 @@ FreeDVReporterDialog::FreeDVReporterDialog(wxWindow* parent, wxWindowID id, cons
|
|||
m_listSpots->Connect(wxEVT_MOTION, wxMouseEventHandler(FreeDVReporterDialog::AdjustToolTip), NULL, this);
|
||||
m_listSpots->Connect(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, wxDataViewEventHandler(FreeDVReporterDialog::OnItemRightClick), NULL, this);
|
||||
m_listSpots->Connect(wxEVT_DATAVIEW_COLUMN_HEADER_CLICK, wxDataViewEventHandler(FreeDVReporterDialog::OnColumnClick), NULL, this);
|
||||
m_listSpots->Connect(wxEVT_DATAVIEW_COLUMN_REORDERED, wxDataViewEventHandler(FreeDVReporterDialog::OnColumnReordered), NULL, this);
|
||||
|
||||
m_statusMessage->Connect(wxEVT_TEXT, wxCommandEventHandler(FreeDVReporterDialog::OnStatusTextChange), NULL, this);
|
||||
m_buttonSend->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FreeDVReporterDialog::OnStatusTextSend), NULL, this);
|
||||
|
|
@ -506,7 +594,8 @@ FreeDVReporterDialog::~FreeDVReporterDialog()
|
|||
m_listSpots->Disconnect(wxEVT_MOTION, wxMouseEventHandler(FreeDVReporterDialog::AdjustToolTip), NULL, this);
|
||||
m_listSpots->Disconnect(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, wxDataViewEventHandler(FreeDVReporterDialog::OnItemRightClick), NULL, this);
|
||||
m_listSpots->Disconnect(wxEVT_DATAVIEW_COLUMN_HEADER_CLICK, wxDataViewEventHandler(FreeDVReporterDialog::OnColumnClick), NULL, this);
|
||||
|
||||
m_listSpots->Disconnect(wxEVT_DATAVIEW_COLUMN_REORDERED, wxDataViewEventHandler(FreeDVReporterDialog::OnColumnReordered), NULL, this);
|
||||
|
||||
m_statusMessage->Disconnect(wxEVT_TEXT, wxCommandEventHandler(FreeDVReporterDialog::OnStatusTextChange), NULL, this);
|
||||
m_buttonSend->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FreeDVReporterDialog::OnStatusTextSend), NULL, this);
|
||||
m_buttonClear->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FreeDVReporterDialog::OnStatusTextClear), NULL, this);
|
||||
|
|
@ -525,6 +614,23 @@ bool FreeDVReporterDialog::isTextMessageFieldInFocus()
|
|||
return m_statusMessage->HasFocus();
|
||||
}
|
||||
|
||||
wxDataViewColumn* FreeDVReporterDialog::getColumnForModelColId_(unsigned int col)
|
||||
{
|
||||
wxDataViewColumn* item = nullptr;
|
||||
|
||||
for (unsigned int index = 0; index < m_listSpots->GetColumnCount(); index++)
|
||||
{
|
||||
item = m_listSpots->GetColumn(index);
|
||||
if (item->GetModelColumn() == col)
|
||||
{
|
||||
break;
|
||||
}
|
||||
item = nullptr;
|
||||
}
|
||||
assert(item != nullptr);
|
||||
return item;
|
||||
}
|
||||
|
||||
void FreeDVReporterDialog::refreshLayout()
|
||||
{
|
||||
// Update row colors
|
||||
|
|
@ -535,7 +641,7 @@ void FreeDVReporterDialog::refreshLayout()
|
|||
rxRowBackgroundColor = wxColour(wxGetApp().appConfiguration.reportingConfiguration.freedvReporterRxRowBackgroundColor);
|
||||
rxRowForegroundColor = wxColour(wxGetApp().appConfiguration.reportingConfiguration.freedvReporterRxRowForegroundColor);
|
||||
|
||||
wxDataViewColumn* item = m_listSpots->GetColumn(DISTANCE_COL);
|
||||
wxDataViewColumn* item = getColumnForModelColId_(DISTANCE_COL);
|
||||
|
||||
if (wxGetApp().appConfiguration.reportingConfiguration.useMetricDistances)
|
||||
{
|
||||
|
|
@ -547,7 +653,7 @@ void FreeDVReporterDialog::refreshLayout()
|
|||
}
|
||||
|
||||
// Refresh frequency units as appropriate.
|
||||
item = m_listSpots->GetColumn(FREQUENCY_COL);
|
||||
item = getColumnForModelColId_(FREQUENCY_COL);
|
||||
if (wxGetApp().appConfiguration.reportingConfiguration.reportingFrequencyAsKhz)
|
||||
{
|
||||
item->SetTitle("kHz");
|
||||
|
|
@ -558,7 +664,7 @@ void FreeDVReporterDialog::refreshLayout()
|
|||
}
|
||||
|
||||
// Change direction/heading column label based on preferences
|
||||
item = m_listSpots->GetColumn(HEADING_COL);
|
||||
item = getColumnForModelColId_(HEADING_COL);
|
||||
if (wxGetApp().appConfiguration.reportingConfiguration.reportingDirectionAsCardinal)
|
||||
{
|
||||
item->SetTitle("Dir");
|
||||
|
|
@ -570,9 +676,11 @@ void FreeDVReporterDialog::refreshLayout()
|
|||
item->SetAlignment(wxALIGN_RIGHT);
|
||||
}
|
||||
|
||||
// Hide RX Mode column if legacy modes aren't enabled
|
||||
auto rxModeColumn = m_listSpots->GetColumn(LAST_RX_MODE_COL);
|
||||
rxModeColumn->SetHidden(!wxGetApp().appConfiguration.enableLegacyModes);
|
||||
// Hide/show legacy columns
|
||||
item = getColumnForModelColId_(LAST_RX_MODE_COL);
|
||||
item->SetHidden(!wxGetApp().appConfiguration.enableLegacyModes || !wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnVisibility->at(LAST_RX_MODE_COL));
|
||||
auto menuItem = showMenu_->FindChildItem(wxID_HIGHEST + LAST_RX_MODE_COL);
|
||||
menuItem->Enable(wxGetApp().appConfiguration.enableLegacyModes);
|
||||
|
||||
// Refresh all data based on current settings and filters.
|
||||
FreeDVReporterDataModel* model = (FreeDVReporterDataModel*)spotsDataModel_.get();
|
||||
|
|
@ -596,6 +704,24 @@ void FreeDVReporterDialog::setReporter(std::shared_ptr<FreeDVReporter> const& re
|
|||
}
|
||||
}
|
||||
|
||||
void FreeDVReporterDialog::OnShowColumn(wxCommandEvent& event)
|
||||
{
|
||||
// Invert visibility value
|
||||
auto columnId = event.GetId() - wxID_HIGHEST;
|
||||
wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnVisibility->at(columnId) =
|
||||
!wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnVisibility->at(columnId);
|
||||
|
||||
auto newColValue =
|
||||
wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnVisibility->at(columnId);
|
||||
|
||||
wxMenuItem* menuItem = static_cast<wxMenuItem*>(event.GetEventObject());
|
||||
menuItem->Check(newColValue);
|
||||
|
||||
// Set column visibility in wxDataViewCtl.
|
||||
auto col = getColumnForModelColId_(columnId);
|
||||
col->SetHidden(!newColValue);
|
||||
}
|
||||
|
||||
void FreeDVReporterDialog::DeselectItem(wxMouseEvent& event)
|
||||
{
|
||||
DeselectItem();
|
||||
|
|
@ -682,17 +808,23 @@ void FreeDVReporterDialog::OnOK(wxCommandEvent&)
|
|||
// Preserve sort column/ordering
|
||||
for (unsigned int index = 0; index < m_listSpots->GetColumnCount(); index++)
|
||||
{
|
||||
auto colObj = m_listSpots->GetColumn(index);
|
||||
auto colObj = getColumnForModelColId_(index);
|
||||
if (colObj != nullptr && colObj->IsSortKey())
|
||||
{
|
||||
wxGetApp().appConfiguration.reporterWindowCurrentSort = index;
|
||||
wxGetApp().appConfiguration.reporterWindowCurrentSort = colObj->GetModelColumn();
|
||||
wxGetApp().appConfiguration.reporterWindowCurrentSortDirection = colObj->IsSortOrderAscending();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Preserve column ordering
|
||||
#if !defined(WIN32)
|
||||
wxDataViewEvent tmp;
|
||||
OnColumnReordered(tmp);
|
||||
#endif // !defined(WIN32)
|
||||
|
||||
// Preserve Msg column width
|
||||
auto userMsgCol = m_listSpots->GetColumn(USER_MESSAGE_COL);
|
||||
auto userMsgCol = getColumnForModelColId_(USER_MESSAGE_COL);
|
||||
wxGetApp().appConfiguration.reportingUserMsgColWidth = userMsgCol->GetWidth();
|
||||
|
||||
wxGetApp().appConfiguration.reporterWindowVisible = false;
|
||||
|
|
@ -727,11 +859,11 @@ void FreeDVReporterDialog::OnClose(wxCloseEvent&)
|
|||
bool found = false;
|
||||
for (unsigned int index = 0; index < m_listSpots->GetColumnCount(); index++)
|
||||
{
|
||||
auto colObj = m_listSpots->GetColumn(index);
|
||||
auto colObj = getColumnForModelColId_(index);
|
||||
if (colObj != nullptr && colObj->IsSortKey())
|
||||
{
|
||||
found = true;
|
||||
wxGetApp().appConfiguration.reporterWindowCurrentSort = index;
|
||||
wxGetApp().appConfiguration.reporterWindowCurrentSort = colObj->GetModelColumn();
|
||||
wxGetApp().appConfiguration.reporterWindowCurrentSortDirection = colObj->IsSortOrderAscending();
|
||||
break;
|
||||
}
|
||||
|
|
@ -743,8 +875,14 @@ void FreeDVReporterDialog::OnClose(wxCloseEvent&)
|
|||
wxGetApp().appConfiguration.reporterWindowCurrentSortDirection = true;
|
||||
}
|
||||
|
||||
// Preserve column ordering
|
||||
#if !defined(WIN32)
|
||||
wxDataViewEvent tmp;
|
||||
OnColumnReordered(tmp);
|
||||
#endif // !defined(WIN32)
|
||||
|
||||
// Preserve Msg column width
|
||||
auto userMsgCol = m_listSpots->GetColumn(USER_MESSAGE_COL);
|
||||
auto userMsgCol = getColumnForModelColId_(USER_MESSAGE_COL);
|
||||
wxGetApp().appConfiguration.reportingUserMsgColWidth = userMsgCol->GetWidth();
|
||||
|
||||
wxGetApp().appConfiguration.reporterWindowVisible = false;
|
||||
|
|
@ -1091,6 +1229,45 @@ void FreeDVReporterDialog::SkipMouseEvent(wxMouseEvent&)
|
|||
OnItemRightClick(contextEvent);
|
||||
}
|
||||
|
||||
void FreeDVReporterDialog::OnColumnReordered(wxDataViewEvent&)
|
||||
{
|
||||
// Preserve new column ordering
|
||||
// Note: Windows uses the same indices for model column and GetColumn()
|
||||
// so we need to use an alternate implementation for that platform.
|
||||
#if defined(WIN32)
|
||||
CallAfter([&]() {
|
||||
std::vector<int> newColPositions;
|
||||
std::stringstream ss;
|
||||
auto headerCtrl = m_listSpots->GenericGetHeader();
|
||||
wxArrayInt wxColumnOrder = headerCtrl->GetColumnsOrder();
|
||||
for (unsigned int index = 0; index < wxColumnOrder.GetCount(); index++)
|
||||
{
|
||||
auto col = wxColumnOrder.Item(index);
|
||||
if (col < NUM_COLS)
|
||||
{
|
||||
newColPositions.push_back(col);
|
||||
ss << col << " ";
|
||||
}
|
||||
}
|
||||
|
||||
wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnOrder = newColPositions;
|
||||
log_info("New column ordering: %s", ss.str().c_str());
|
||||
});
|
||||
#else
|
||||
std::stringstream ss;
|
||||
std::vector<int> newColPositions;
|
||||
for (unsigned int index = 0; index < NUM_COLS; index++)
|
||||
{
|
||||
auto dvc = m_listSpots->GetColumn(index);
|
||||
newColPositions.push_back(dvc->GetModelColumn());
|
||||
ss << dvc->GetModelColumn() << " ";
|
||||
}
|
||||
|
||||
wxGetApp().appConfiguration.reportingConfiguration.freedvReporterColumnOrder = newColPositions;
|
||||
log_info("New column ordering: %s", ss.str().c_str());
|
||||
#endif // defined(WIN32)
|
||||
}
|
||||
|
||||
void FreeDVReporterDialog::OnColumnClick(wxDataViewEvent& event)
|
||||
{
|
||||
DeselectItem();
|
||||
|
|
@ -1398,7 +1575,7 @@ void FreeDVReporterDialog::autosizeColumns()
|
|||
if (index != USER_MESSAGE_COL)
|
||||
{
|
||||
// USER_MESSAGE_COL width is preserved and should not be messed with.
|
||||
auto col = m_listSpots->GetColumn(index);
|
||||
auto col = getColumnForModelColId_(index);
|
||||
col->SetWidth(wxCOL_WIDTH_DEFAULT);
|
||||
col->SetWidth(wxCOL_WIDTH_AUTOSIZE);
|
||||
}
|
||||
|
|
@ -2526,8 +2703,8 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onFrequencyChangeFn_(std::st
|
|||
|
||||
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);
|
||||
(sortingColumn == parent_->getColumnForModelColId_(FREQUENCY_COL) && iter->second->frequency != frequencyHz) ||
|
||||
(sortingColumn == parent_->getColumnForModelColId_(LAST_UPDATE_DATE_COL) && iter->second->lastUpdate != lastUpdateTime);
|
||||
bool isDataChanged =
|
||||
(iter->second->frequency != frequencyHz ||
|
||||
iter->second->lastUpdate != lastUpdateTime);
|
||||
|
|
@ -2609,8 +2786,8 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onTransmitUpdateFn_(std::str
|
|||
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);
|
||||
(sortingColumn == parent_->getColumnForModelColId_(STATUS_COL) && iter->second->status != txStatus) ||
|
||||
(sortingColumn == parent_->getColumnForModelColId_(TX_MODE_COL) && iter->second->txMode != txMode);
|
||||
isDataChanged |=
|
||||
iter->second->status != txStatus ||
|
||||
iter->second->txMode != txMode;
|
||||
|
|
@ -2619,7 +2796,7 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onTransmitUpdateFn_(std::str
|
|||
iter->second->txMode = txMode;
|
||||
|
||||
auto lastTxTime = makeValidTime_(lastTxDate, iter->second->lastTxDate);
|
||||
isChanged |= (sortingColumn == parent_->m_listSpots->GetColumn(LAST_TX_DATE_COL) && iter->second->lastTx != lastTxTime);
|
||||
isChanged |= (sortingColumn == parent_->getColumnForModelColId_(LAST_TX_DATE_COL) && iter->second->lastTx != lastTxTime);
|
||||
isDataChanged |= iter->second->lastTx != lastTxTime;
|
||||
iter->second->lastTx = lastTxTime;
|
||||
}
|
||||
|
|
@ -2670,8 +2847,8 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onReceiveUpdateFn_(std::stri
|
|||
|
||||
auto sortingColumn = parent_->m_listSpots->GetSortingColumn();
|
||||
bool isChanged =
|
||||
(sortingColumn == parent_->m_listSpots->GetColumn(LAST_RX_CALLSIGN_COL) && iter->second->lastRxCallsign != receivedCallsignWx) ||
|
||||
(sortingColumn == parent_->m_listSpots->GetColumn(LAST_RX_MODE_COL) && iter->second->lastRxMode != rxModeWx);
|
||||
(sortingColumn == parent_->getColumnForModelColId_(LAST_RX_CALLSIGN_COL) && iter->second->lastRxCallsign != receivedCallsignWx) ||
|
||||
(sortingColumn == parent_->getColumnForModelColId_(LAST_RX_MODE_COL) && iter->second->lastRxMode != rxModeWx);
|
||||
bool isDataChanged =
|
||||
iter->second->lastRxCallsign != receivedCallsignWx ||
|
||||
iter->second->lastRxMode != rxModeWx;
|
||||
|
|
@ -2684,9 +2861,9 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onReceiveUpdateFn_(std::stri
|
|||
{
|
||||
// Frequency change--blank out SNR too.
|
||||
isChanged |=
|
||||
(sortingColumn == parent_->m_listSpots->GetColumn(LAST_RX_CALLSIGN_COL) && iter->second->lastRxCallsign != parent_->UNKNOWN_STR) ||
|
||||
(sortingColumn == parent_->m_listSpots->GetColumn(LAST_RX_MODE_COL) && iter->second->lastRxMode != parent_->UNKNOWN_STR) ||
|
||||
(sortingColumn == parent_->m_listSpots->GetColumn(SNR_COL) && iter->second->snr != parent_->UNKNOWN_STR) ||
|
||||
(sortingColumn == parent_->getColumnForModelColId_(LAST_RX_CALLSIGN_COL) && iter->second->lastRxCallsign != parent_->UNKNOWN_STR) ||
|
||||
(sortingColumn == parent_->getColumnForModelColId_(LAST_RX_MODE_COL) && iter->second->lastRxMode != parent_->UNKNOWN_STR) ||
|
||||
(sortingColumn == parent_->getColumnForModelColId_(SNR_COL) && iter->second->snr != parent_->UNKNOWN_STR) ||
|
||||
iter->second->lastRxDate.IsValid();
|
||||
isDataChanged |=
|
||||
iter->second->lastRxCallsign != parent_->UNKNOWN_STR ||
|
||||
|
|
@ -2703,7 +2880,7 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onReceiveUpdateFn_(std::stri
|
|||
else
|
||||
{
|
||||
isChanged |=
|
||||
(sortingColumn == parent_->m_listSpots->GetColumn(SNR_COL) && iter->second->snr != snrString);
|
||||
(sortingColumn == parent_->getColumnForModelColId_(SNR_COL) && iter->second->snr != snrString);
|
||||
isDataChanged |=
|
||||
iter->second->snr != snrString;
|
||||
|
||||
|
|
@ -2753,13 +2930,13 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onMessageUpdateFn_(std::stri
|
|||
bool isChanged = false;
|
||||
if (message.size() == 0)
|
||||
{
|
||||
isChanged |= (sortingColumn == parent_->m_listSpots->GetColumn(USER_MESSAGE_COL) && iter->second->userMessage != parent_->UNKNOWN_STR);
|
||||
isChanged |= (sortingColumn == parent_->getColumnForModelColId_(USER_MESSAGE_COL) && iter->second->userMessage != parent_->UNKNOWN_STR);
|
||||
iter->second->userMessage = parent_->UNKNOWN_STR;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto msgAsWxString = wxString::FromUTF8(message.c_str());
|
||||
isChanged |= (sortingColumn == parent_->m_listSpots->GetColumn(USER_MESSAGE_COL) && iter->second->userMessage != msgAsWxString);
|
||||
isChanged |= (sortingColumn == parent_->getColumnForModelColId_(USER_MESSAGE_COL) && iter->second->userMessage != msgAsWxString);
|
||||
iter->second->userMessage = msgAsWxString;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ class FreeDVReporterDialog : public wxFrame
|
|||
void OnColumnClick(wxDataViewEvent& event);
|
||||
void OnItemDoubleClick(wxDataViewEvent& event);
|
||||
void OnItemRightClick(wxDataViewEvent& event);
|
||||
void OnColumnReordered(wxDataViewEvent& event);
|
||||
|
||||
void OnTimer(wxTimerEvent& event);
|
||||
void DeselectItem();
|
||||
|
|
@ -122,6 +123,8 @@ class FreeDVReporterDialog : public wxFrame
|
|||
void SkipMouseEvent(wxMouseEvent& event);
|
||||
void AdjustMsgColWidth(wxListEvent& event);
|
||||
void OnRightClickSpotsList(wxContextMenuEvent& event);
|
||||
|
||||
void OnShowColumn(wxCommandEvent& event);
|
||||
|
||||
// Main list box that shows spots
|
||||
wxDataViewCtrl* m_listSpots;
|
||||
|
|
@ -156,6 +159,10 @@ class FreeDVReporterDialog : public wxFrame
|
|||
wxTimer* m_deleteTimer;
|
||||
|
||||
wxTipWindow* tipWindow_;
|
||||
|
||||
// Menu bar and menu options
|
||||
wxMenuBar* menuBar_;
|
||||
wxMenu* showMenu_;
|
||||
|
||||
private:
|
||||
const wxString UNKNOWN_STR;
|
||||
|
|
@ -372,6 +379,9 @@ class FreeDVReporterDialog : public wxFrame
|
|||
|
||||
bool isSelectionPossible_;
|
||||
|
||||
void createColumn_(int col, bool visible);
|
||||
wxDataViewColumn* getColumnForModelColId_(unsigned int col);
|
||||
|
||||
FilterFrequency getFilterForFrequency_(uint64_t freq);
|
||||
wxColour msgRowBackgroundColor;
|
||||
wxColour msgRowForegroundColor;
|
||||
|
|
|
|||
|
|
@ -122,8 +122,8 @@ void* MinimalTxRxThread::Entry()
|
|||
|
||||
#if defined(__linux__)
|
||||
const char* threadName = nullptr;
|
||||
if (m_tx) threadName = "FreeDV txThread";
|
||||
else threadName = "FreeDV rxThread";
|
||||
if (m_tx) threadName = "FDV txThread";
|
||||
else threadName = "FDV rxThread";
|
||||
pthread_setname_np(pthread_self(), threadName);
|
||||
#endif // defined(__linux__)
|
||||
|
||||
|
|
|
|||
35
src/main.cpp
35
src/main.cpp
|
|
@ -861,7 +861,9 @@ setDefaultMode:
|
|||
m_textSQ->Enable(isEnabled);
|
||||
m_btnCenterRx->Enable(isEnabled);
|
||||
m_btnCenterRx->Show(wxGetApp().appConfiguration.enableLegacyModes);
|
||||
|
||||
m_BtnReSync->Enable(isEnabled);
|
||||
m_BtnReSync->Show(wxGetApp().appConfiguration.enableLegacyModes);
|
||||
|
||||
if (!isEnabled)
|
||||
{
|
||||
m_textBits->SetLabel("Bits: unk");
|
||||
|
|
@ -953,6 +955,7 @@ setDefaultMode:
|
|||
|
||||
statsBox->Show(wxGetApp().appConfiguration.showDecodeStats);
|
||||
modeBox->Show(wxGetApp().appConfiguration.enableLegacyModes);
|
||||
m_BtnReSync->Show(wxGetApp().appConfiguration.enableLegacyModes);
|
||||
|
||||
// Initialize FreeDV Reporter as required
|
||||
CallAfter(&MainFrame::initializeFreeDVReporter_);
|
||||
|
|
@ -1180,6 +1183,7 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent, wxID_ANY, _("FreeDV ")
|
|||
g_TxFreqOffsetHz = 0.0;
|
||||
|
||||
g_tx.store(false, std::memory_order_release);
|
||||
g_voice_keyer_tx.store(false, std::memory_order_release);
|
||||
|
||||
// data states
|
||||
g_txDataInFifo.store(new GenericFIFO<short>(MAX_CALLSIGN*FREEDV_VARICODE_MAX_BITS), std::memory_order_release);
|
||||
|
|
@ -1416,6 +1420,7 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
|
|||
short speechOutPlotSamples[WAVEFORM_PLOT_BUF];
|
||||
short demodInPlotSamples[WAVEFORM_PLOT_BUF];
|
||||
bool txState = false;
|
||||
bool halfDuplexState = false;
|
||||
int syncState = 0;
|
||||
|
||||
auto& timer = evt.GetTimer();
|
||||
|
|
@ -1429,6 +1434,7 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
|
|||
if (timerId == ID_TIMER_UPDATE_OTHER)
|
||||
{
|
||||
txState = g_tx.load(std::memory_order_relaxed);
|
||||
halfDuplexState = g_half_duplex.load(std::memory_order_relaxed);
|
||||
syncState_ = freedvInterface.getSync();
|
||||
}
|
||||
syncState = syncState_;
|
||||
|
|
@ -1515,14 +1521,24 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
|
|||
// Update average magnitudes
|
||||
float rxSpectrum[MODEM_STATS_NSPEC];
|
||||
memset(rxSpectrum, 0, sizeof(float) * MODEM_STATS_NSPEC);
|
||||
while (g_avmag.numUsed() >= MODEM_STATS_NSPEC)
|
||||
bool txNotInFullDuplex = halfDuplexState && txState;
|
||||
if (!txNotInFullDuplex)
|
||||
{
|
||||
g_avmag.read(rxSpectrum, MODEM_STATS_NSPEC);
|
||||
for (int index = 0; index < MODEM_STATS_NSPEC; index++)
|
||||
while (g_avmag.numUsed() >= MODEM_STATS_NSPEC)
|
||||
{
|
||||
g_avmag_waterfall[index] = BETA * g_avmag_waterfall[index] + (1.0 - BETA) * rxSpectrum[index];
|
||||
}
|
||||
memcpy(g_avmag_spectrum, g_avmag_waterfall, sizeof(g_avmag_waterfall));
|
||||
g_avmag.read(rxSpectrum, MODEM_STATS_NSPEC);
|
||||
for (int index = 0; index < MODEM_STATS_NSPEC; index++)
|
||||
{
|
||||
g_avmag_waterfall[index] = BETA * g_avmag_waterfall[index] + (1.0 - BETA) * rxSpectrum[index];
|
||||
}
|
||||
memcpy(g_avmag_spectrum, g_avmag_waterfall, sizeof(g_avmag_waterfall));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume zero spectrum to avoid waterfall artifacts
|
||||
memset(g_avmag_waterfall, 0, sizeof(float) * MODEM_STATS_NSPEC);
|
||||
memcpy(g_avmag_spectrum, g_avmag_waterfall, sizeof(g_avmag_waterfall));
|
||||
}
|
||||
|
||||
// Synchronize changes with Filter dialog
|
||||
|
|
@ -2124,6 +2140,7 @@ void MainFrame::OnChangeTxMode( wxCommandEvent& event )
|
|||
m_ckboxSQ->Enable(isEnabled);
|
||||
m_textSQ->Enable(isEnabled);
|
||||
m_btnCenterRx->Enable(isEnabled);
|
||||
m_BtnReSync->Enable(isEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2132,6 +2149,8 @@ void MainFrame::performFreeDVOn_()
|
|||
log_debug("Start .....");
|
||||
g_queueResync = false;
|
||||
endingTx.store(false, std::memory_order_release);
|
||||
g_voice_keyer_tx.store(false, std::memory_order_release);
|
||||
g_tx.store(false, std::memory_order_release);
|
||||
|
||||
m_timeSinceSyncLoss = 0;
|
||||
|
||||
|
|
@ -2281,7 +2300,7 @@ void MainFrame::performFreeDVOn_()
|
|||
});
|
||||
|
||||
g_State.store(0, std::memory_order_release);
|
||||
g_prev_State.store(0, std::memory_order_release);;
|
||||
g_prev_State.store(0, std::memory_order_release);
|
||||
g_snr = 0.0;
|
||||
g_half_duplex.store(wxGetApp().appConfiguration.halfDuplexMode, std::memory_order_release);
|
||||
|
||||
|
|
|
|||
|
|
@ -224,6 +224,8 @@ void MainFrame::OnToolsOptions(wxCommandEvent& event)
|
|||
m_textSQ->Enable(isEnabled);
|
||||
m_btnCenterRx->Enable(isEnabled);
|
||||
m_btnCenterRx->Show(wxGetApp().appConfiguration.enableLegacyModes);
|
||||
m_BtnReSync->Enable(isEnabled);
|
||||
m_BtnReSync->Show(wxGetApp().appConfiguration.enableLegacyModes);
|
||||
|
||||
// XXX - with really short windows, wxWidgets sometimes doesn't size
|
||||
// the components properly until the user resizes the window (even if only
|
||||
|
|
@ -383,7 +385,7 @@ void MainFrame::OnHelpManual( wxCommandEvent& )
|
|||
//-------------------------------------------------------------------------
|
||||
void MainFrame::OnHelp( wxCommandEvent& )
|
||||
{
|
||||
wxLaunchDefaultBrowser("https://freedv.org/#gethelp");
|
||||
wxLaunchDefaultBrowser("https://freedv.org/#getting-help");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -414,6 +414,10 @@ TopFrame::TopFrame(wxWindow* parent, wxWindowID id, const wxString& title, const
|
|||
wxMenuItem* m_menuItemHelpManual;
|
||||
m_menuItemHelpManual = new wxMenuItem(help, wxID_ANY, wxString(_("&User Manual...")), _("Loads the user manual"), wxITEM_NORMAL);
|
||||
help->Append(m_menuItemHelpManual);
|
||||
|
||||
wxMenuItem* m_menuItemHelpGetAssistance;
|
||||
m_menuItemHelpGetAssistance = new wxMenuItem(help, wxID_ANY, wxString(_("&Get Assistance")), _("Gets assistance with FreeDV setup"), wxITEM_NORMAL);
|
||||
help->Append(m_menuItemHelpGetAssistance);
|
||||
|
||||
m_menubarMain->Append(help, _("&Help"));
|
||||
|
||||
|
|
@ -553,15 +557,6 @@ TopFrame::TopFrame(wxWindow* parent, wxWindowID id, const wxString& title, const
|
|||
|
||||
leftSizer->Add(sbSizer_ber,0, wxALL|wxEXPAND|wxFIXED_MINSIZE, 2);
|
||||
|
||||
//------------------------------
|
||||
// Help button: goes to Help page on website
|
||||
//------------------------------
|
||||
wxStaticBox* helpBox = new wxStaticBox(m_panel, wxID_ANY, _("Assistance"), wxDefaultPosition, wxSize(100,-1));
|
||||
wxStaticBoxSizer* helpSizer = new wxStaticBoxSizer(helpBox, wxVERTICAL);
|
||||
|
||||
m_btnHelp = new wxButton(helpBox, wxID_ANY, _("Get Help"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_btnHelp->SetToolTip(_("Get help with FreeDV."));
|
||||
helpSizer->Add(m_btnHelp, 0, wxALIGN_CENTER|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||
leftSizer->SetMinSize(wxSize(-1, 375));
|
||||
|
||||
#if !wxCHECK_VERSION(3,2,0)
|
||||
|
|
@ -569,7 +564,6 @@ TopFrame::TopFrame(wxWindow* parent, wxWindowID id, const wxString& title, const
|
|||
#else
|
||||
leftOuterSizer->Add(leftSizer, 2, wxALL | wxEXPAND | wxFIXED_MINSIZE, 1);
|
||||
#endif // !wxCHECK_VERSION(3,2,0)
|
||||
leftOuterSizer->Add(helpSizer, 0, wxFIXED_MINSIZE | wxALL | wxEXPAND, 1);
|
||||
|
||||
bSizer1->Add(leftOuterSizer, 0, wxALL|wxEXPAND, 5);
|
||||
|
||||
|
|
@ -851,6 +845,7 @@ TopFrame::TopFrame(wxWindow* parent, wxWindowID id, const wxString& title, const
|
|||
this->Connect(m_menuItemHelpUpdates->GetId(), wxEVT_UPDATE_UI, wxUpdateUIEventHandler(TopFrame::OnHelpCheckUpdatesUI));
|
||||
this->Connect(m_menuItemAbout->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnHelpAbout));
|
||||
this->Connect(m_menuItemHelpManual->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnHelpManual));
|
||||
this->Connect(m_menuItemHelpGetAssistance->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TopFrame::OnHelp));
|
||||
m_sliderSQ->Connect(wxEVT_SCROLL_TOP, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
|
||||
m_sliderSQ->Connect(wxEVT_SCROLL_BOTTOM, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
|
||||
m_sliderSQ->Connect(wxEVT_SCROLL_LINEUP, wxScrollEventHandler(TopFrame::OnCmdSliderScroll), NULL, this);
|
||||
|
|
@ -874,7 +869,6 @@ TopFrame::TopFrame(wxWindow* parent, wxWindowID id, const wxString& title, const
|
|||
m_togBtnVoiceKeyer->Connect(wxEVT_CONTEXT_MENU, wxContextMenuEventHandler(TopFrame::OnTogBtnVoiceKeyerRightClick), NULL, this);
|
||||
m_btnTogPTT->Connect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnPTT), NULL, this);
|
||||
m_btnTogPTT->Connect(wxEVT_CONTEXT_MENU, wxContextMenuEventHandler(TopFrame::OnTogBtnPTTRightClick), NULL, this);
|
||||
m_btnHelp->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnHelp), NULL, this);
|
||||
|
||||
m_BtnCallSignReset->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnCallSignReset), NULL, this);
|
||||
m_BtnBerReset->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnBerReset), NULL, this);
|
||||
|
|
@ -968,7 +962,6 @@ TopFrame::~TopFrame()
|
|||
m_togBtnVoiceKeyer->Disconnect(wxEVT_CONTEXT_MENU, wxContextMenuEventHandler(TopFrame::OnTogBtnVoiceKeyerRightClick), NULL, this);
|
||||
m_btnTogPTT->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnTogBtnPTT), NULL, this);
|
||||
m_btnTogPTT->Disconnect(wxEVT_CONTEXT_MENU, wxContextMenuEventHandler(TopFrame::OnTogBtnPTTRightClick), NULL, this);
|
||||
m_btnHelp->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnHelp), NULL, this);
|
||||
|
||||
m_btnCenterRx->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(TopFrame::OnCenterRx), NULL, this);
|
||||
|
||||
|
|
|
|||
|
|
@ -232,7 +232,6 @@ class TopFrame : public wxFrame
|
|||
wxToggleButton* m_togBtnAnalog;
|
||||
wxToggleButton* m_togBtnVoiceKeyer;
|
||||
wxToggleButton* m_btnTogPTT;
|
||||
wxButton* m_btnHelp;
|
||||
wxAuiNotebook* m_auiNbookCtrl;
|
||||
wxComboBox* m_cboReportFrequency;
|
||||
wxStaticBox* m_freqBox;
|
||||
|
|
|
|||
Loading…
Reference in New Issue