fix merge conflict

This commit is contained in:
Brian Moran
2023-03-18 10:28:23 -07:00
164 changed files with 22335 additions and 4650 deletions
+431 -58
View File
@@ -185,13 +185,18 @@ extern "C" {
void save_dxbase_(char* dxbase, FCL len);
void indexx_(float arr[], int* n, int indx[]);
void get_q3list_(char* fname, bool* bDiskData, int* nlist, char* list, FCL len1, FCL len2);
void rm_q3list_(char* callsign, FCL len);
void jpl_setup_(char* fname, FCL len);
}
int volatile itone[MAX_NUM_SYMBOLS]; //Audio tones for all Tx symbols
int volatile itone0[MAX_NUM_SYMBOLS]; //Dummy array, data not actually used
int volatile icw[NUM_CW_SYMBOLS]; //Dits for CW ID
dec_data_t dec_data; // for sharing with Fortran
int outBufSize;
int rc;
qint32 g_iptt {0};
@@ -212,6 +217,17 @@ bool m_displayBand = false;
bool no_a7_decodes = false;
bool keep_frequency = false;
QSharedMemory mem_qmap("mem_qmap"); //Memory segment to be shared (optionally) with QMAP
struct {
int ndecodes; //Number of QMAP decodes available (so far)
int ncand; //Number of QMAP candidates considered for decoding
int nQDecoderDone; //QMAP decoder is finished (0 or 1)
int nWDecoderBusy; //WSJT-X decoder is busy (0 or 1)
int nWTransmitting; //WSJT-X is transmitting (0 or 1)
char result[50][60]; //Decodes as character*60 arrays
} qmapcom;
int* ipc_qmap;
namespace
{
Radio::Frequency constexpr default_frequency {14074000};
@@ -453,6 +469,19 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
m_optimizingProgress.setAutoReset (false);
m_optimizingProgress.setMinimumDuration (15000); // only show after 15s delay
//Attach or create a memory segment to be shared with QMAP.
int memSize=4096;
if(!mem_qmap.attach()) {
if(!mem_qmap.create(memSize)) {
MessageBox::information_message (this,
"Unable to create shared memory segment mem_qmap.");
}
}
ipc_qmap = (int*)mem_qmap.data();
mem_qmap.lock();
memset(ipc_qmap,0,memSize); //Zero all of QMAP shared memory
mem_qmap.unlock();
// Closedown.
connect (ui->actionExit, &QAction::triggered, this, &QMainWindow::close);
@@ -882,6 +911,10 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
ui->lh_decodes_headings_label->setText(t);
ui->rh_decodes_headings_label->setText(t);
readSettings(); //Restore user's setup parameters
if(m_mode=="Q65") {
m_score=0;
read_log();
}
m_audioThread.start (m_audioThreadPriority);
#ifdef WIN32
@@ -1051,12 +1084,16 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
ui->labDXped->setStyleSheet("QLabel {background-color: red; color: white;}");
ui->pbBestSP->setVisible(m_mode=="FT4");
QString jpleph = m_config.data_dir().absoluteFilePath("JPLEPH");
jpl_setup_(const_cast<char *>(jpleph.toLocal8Bit().constData()),256);
// this must be the last statement of constructor
if (!m_valid) throw std::runtime_error {"Fatal initialization exception"};
}
void MainWindow::not_GA_warning_message ()
{
/* ### TEMPORARY ###
MessageBox::critical_message (this,
"This is a pre-release version of WSJT-X 2.6.0 made\n"
"available for testing purposes. By design it will\n"
@@ -1065,6 +1102,7 @@ void MainWindow::not_GA_warning_message ()
if (now >= QDateTime {{2023, 03, 31}, {23, 59, 59, 999}, Qt::UTC}) {
Q_EMIT finished ();
}
*/
}
void MainWindow::initialize_fonts ()
@@ -1120,6 +1158,7 @@ MainWindow::~MainWindow()
m_audioThread.quit ();
m_audioThread.wait ();
remove_child_from_event_filter (this);
memset(ipc_qmap,0,4096); //Zero all of QMAP shared memory
}
//-------------------------------------------------------- writeSettings()
@@ -1378,10 +1417,7 @@ void MainWindow::readSettings()
if(displayMsgAvg) on_actionMessage_averaging_triggered();
if (displayFoxLog) on_fox_log_action_triggered ();
if (displayContestLog) on_contest_log_action_triggered ();
if(displayActiveStations) {
on_actionActiveStations_triggered();
// QFile f {m_config.writeable_data_dir ().absoluteFilePath ("activeCalls.txt")};
}
if(displayActiveStations) on_actionActiveStations_triggered();
}
void MainWindow::checkMSK144ContestType()
@@ -2042,6 +2078,7 @@ void MainWindow::on_actionSettings_triggered() //Setup Dialog
}
ui->labDXped->setVisible(SpecOp::NONE != m_specOp);
set_mode(m_mode);
configActiveStations();
}
}
@@ -2332,6 +2369,16 @@ void MainWindow::keyPressEvent (QKeyEvent * e)
}
break;
case Qt::Key_R:
if(m_mode=="Q65" and e->modifiers() & Qt::ShiftModifier and
e->modifiers() & Qt::ControlModifier) {
if(m_specOp==SpecOp::Q65_PILEUP) {
refreshPileupList();
} else {
m_fetched=0;
readWidebandDecodes();
}
return;
}
if(e->modifiers() & Qt::AltModifier) {
if(!m_send_RR73) on_txrb4_doubleClicked();
return;
@@ -2424,6 +2471,7 @@ void MainWindow::displayDialFrequency ()
void MainWindow::statusChanged()
{
if (m_specOp==SpecOp::Q65_PILEUP && m_mode != "Q65") on_actionQ65_triggered();
statusUpdate ();
QFile f {m_config.temp_dir ().absoluteFilePath ("wsjtx_status.txt")};
if(f.open(QFile::WriteOnly | QIODevice::Text)) {
@@ -2447,6 +2495,18 @@ void MainWindow::statusChanged()
.arg (f.fileName ()).arg (f.errorString ()));
}
on_dxGridEntry_textChanged(m_hisGrid);
if(m_specOp!=SpecOp::HOUND) {
ui->txb2->setEnabled(true);
ui->txrb2->setEnabled(true);
ui->txb4->setEnabled(true);
ui->txrb4->setEnabled(true);
ui->txb5->setEnabled(true);
ui->txrb5->setEnabled(true);
ui->txb6->setEnabled(true);
ui->txrb6->setEnabled(true);
ui->houndButton->setChecked(false);
ui->houndButton->setStyleSheet("");
}
}
bool MainWindow::eventFilter (QObject * object, QEvent * event)
@@ -2663,6 +2723,11 @@ void MainWindow::on_actionQSG_X250_M3_triggered()
QDesktopServices::openUrl (QUrl {"https://wsjt.sourceforge.io/WSJTX_2.5.0_MAP65_3.0_Quick_Start.pdf"});
}
void MainWindow::on_actionQuick_Start_Guide_to_WSJT_X_2_7_and_QMAP_triggered()
{
QDesktopServices::openUrl (QUrl {"https://wsjt.sourceforge.io/Quick_Start_WSJT-X_2.7_QMAP.pdf"});
}
void MainWindow::on_actionOnline_User_Guide_triggered() //Display manual
{
#if defined (CMAKE_BUILD)
@@ -2913,9 +2978,11 @@ void MainWindow::on_actionActiveStations_triggered()
m_ActiveStationsWidget->showNormal();
m_ActiveStationsWidget->raise();
m_ActiveStationsWidget->activateWindow();
configActiveStations();
connect(m_ActiveStationsWidget.data(), SIGNAL(callSandP(int)),this,SLOT(callSandP2(int)));
connect(m_ActiveStationsWidget.data(), SIGNAL(activeStationsDisplay()),this,SLOT(ARRL_Digi_Display()));
m_ActiveStationsWidget->setScore(m_score);
if(m_mode=="Q65") m_ActiveStationsWidget->setRate(m_score);
}
void MainWindow::on_actionOpen_triggered() //Open File
@@ -3136,6 +3203,7 @@ void MainWindow::on_actionKeyboard_shortcuts_triggered()
<tr><td><b>Alt+Q </b></td><td>Open "Log QSO" window</td></tr>
<tr><td><b>Ctrl+R </b></td><td>Set Tx4 message to RRR (not in FT4)</td></tr>
<tr><td><b>Alt+R </b></td><td>Set Tx4 message to RR73</td></tr>
<tr><td><b>Ctrl+Shift+R </b></td><td>Refresh Active Stations window</td></tr>
<tr><td><b>Alt+S </b></td><td>Stop monitoring</td></tr>
<tr><td><b>Alt+T </b></td><td>Toggle Tune status</td></tr>
<tr><td><b>Alt+Z </b></td><td>Clear hung decoder status</td></tr>
@@ -3233,6 +3301,7 @@ void MainWindow::msgAvgDecode2()
void MainWindow::decode() //decode()
{
if(m_decoderBusy) return; //Don't start decoder if it's already busy.
m_fetched=0;
QDateTime now = QDateTime::currentDateTimeUtc ();
if( m_dateTimeLastTX.isValid () ) {
qint64 isecs_since_tx = m_dateTimeLastTX.secsTo(now);
@@ -3285,7 +3354,9 @@ void MainWindow::decode() //decode()
dec_data.params.ndiskdat=0;
if(m_diskData) dec_data.params.ndiskdat=1;
dec_data.params.nfa=m_wideGraph->nStartFreq();
dec_data.params.nfSplit=m_wideGraph->Fmin();
dec_data.params.nfSplit=m_wideGraph->Fmin(); // Not used any more?
if(dec_data.params.nfSplit==8) dec_data.params.nfSplit=1;
dec_data.params.nfb=m_wideGraph->Fmax();
if(m_mode=="FT8" and SpecOp::HOUND == m_specOp and !ui->cbRxAll->isChecked()) dec_data.params.nfb=1000;
if(m_mode=="FT8" and SpecOp::FOX == m_specOp ) dec_data.params.nfqso=200;
@@ -3341,7 +3412,10 @@ void MainWindow::decode() //decode()
dec_data.params.emedelay=0.0;
if(m_config.decode_at_52s()) dec_data.params.emedelay=2.5;
dec_data.params.minSync=ui->syncSpinBox->isVisible () ? m_minSync : 0;
dec_data.params.nexp_decode = static_cast<int> (m_specOp);
dec_data.params.nexp_decode=int(m_specOp);
if(dec_data.params.nexp_decode==5) dec_data.params.nexp_decode=1; //NA VHF, WW Digi, ARRL Digi contests
if(dec_data.params.nexp_decode==8) dec_data.params.nexp_decode=1; //and Q65 Pileup all use 4-character
if(dec_data.params.nexp_decode==9) dec_data.params.nexp_decode=1; //grid exchange
if(m_config.single_decode()) dec_data.params.nexp_decode += 32;
if(m_config.enable_VHF_features()) dec_data.params.nexp_decode += 64;
if(m_mode.startsWith("FST4")) dec_data.params.nexp_decode += 256*(ui->sbNB->value()+3);
@@ -3410,7 +3484,9 @@ void MainWindow::decode() //decode()
}
}
if((m_mode=="FT4" or (m_mode=="FT8" and m_ihsym==41) or m_diskData) and
m_ActiveStationsWidget != NULL) m_ActiveStationsWidget->erase();
m_ActiveStationsWidget != NULL) {
if(m_mode!="Q65") m_ActiveStationsWidget->erase(); //TEMP
}
}
void::MainWindow::fast_decode_done()
@@ -3523,10 +3599,69 @@ void MainWindow::decodeDone ()
ARRL_Digi_Display(); // Update the ARRL_DIGI display
}
if(m_mode!="FT8" or dec_data.params.nzhsym==50) m_nDecodes=0;
if(m_mode=="Q65" and (m_specOp==SpecOp::NA_VHF or m_specOp==SpecOp::ARRL_DIGI
or m_specOp==SpecOp::WW_DIGI or m_specOp==SpecOp::Q65_PILEUP)
and m_ActiveStationsWidget!=NULL) {
refreshPileupList();
}
}
void MainWindow::refreshPileupList()
{
// Update the ActiveStations display for Q65 pileup situation...
int nlist=0;
char list[2000];
char line[36];
list[0]=0;
auto fname {QDir::toNativeSeparators(m_config.writeable_data_dir().absoluteFilePath("tsil.3q"))};
get_q3list_(const_cast<char *> (fname.toLatin1().constData()), &m_diskData, &nlist,
&list[0], (FCL)fname.length(), (FCL)2000);
QString t="";
QString t0="";
for(int i=0; i<nlist; i++) {
memcpy(line,&list[36*i],36);
t0=QString::fromLatin1(line)+"\n";
m_callers[i]=t0;
t+=t0;
}
m_ActiveStationsWidget->setClickOK(false);
m_ActiveStationsWidget->displayRecentStations("Q65-pileup",t);
m_ActiveStationsWidget->setClickOK(true);
}
void MainWindow::read_log()
{
static QFile f {QDir {QStandardPaths::writableLocation (QStandardPaths::DataLocation)}.absoluteFilePath ("wsjtx.log")};
f.open(QIODevice::ReadOnly);
if(f.isOpen()) {
QTextStream in(&f);
QString line,callsign;
for(int i=0; i<99999; i++) {
line=in.readLine();
if(line.length()<=0) break;
callsign=line.mid(40,6);
int n=callsign.indexOf(",");
if(n>0) callsign=callsign.left(n);
m_EMEworked[callsign]=true;
m_score++;
}
f.close();
}
if(m_ActiveStationsWidget!=NULL) {
m_ActiveStationsWidget->setScore(m_score);
if(m_mode=="Q65") m_ActiveStationsWidget->setRate(m_score);
}
}
void MainWindow::ARRL_Digi_Update(DecodedText dt)
{
if(m_mode=="Q65") {
m_fetched=0;
readWidebandDecodes();
return;
}
// Extract information relevant for the ARRL Digi contest
QString deCall;
QString deGrid;
@@ -3586,6 +3721,11 @@ void MainWindow::ARRL_Digi_Update(DecodedText dt)
void MainWindow::ARRL_Digi_Display()
{
if(m_mode=="Q65") {
m_fetched=0;
readWidebandDecodes();
return;
}
QMutableMapIterator<QString,RecentCall> icall(m_recentCall);
QString deCall,deGrid;
int age=0;
@@ -3656,23 +3796,65 @@ void MainWindow::ARRL_Digi_Display()
t += (t1 + list[k] + "\n");
if(i>=maxRecent) break;
}
if(m_ActiveStationsWidget!=NULL) m_ActiveStationsWidget->displayRecentStations(t);
if(m_ActiveStationsWidget!=NULL) m_ActiveStationsWidget->displayRecentStations(m_mode,t);
m_ActiveStationsWidget->setClickOK(true);
}
void MainWindow::callSandP2(int n)
{
if(m_ready2call[n]=="") return;
bool bCtrl = (n<0);
n=qAbs(n)-1;
if(m_mode!="Q65" and m_ready2call[n]=="") return;
QStringList w=m_ready2call[n].split(' ', SkipEmptyParts);
m_deCall=w[0];
m_deGrid=w[1];
if(m_mode=="Q65" and m_specOp==SpecOp::Q65_PILEUP and n < 40) {
// This code is for 6m EME DXpedition operator
w=m_callers[n].split(' ', SkipEmptyParts);
m_deCall=w[2];
if(bCtrl) {
// Remove this call from q3list.
rm_q3list_(const_cast<char *> (m_deCall.toLatin1().constData()), m_deCall.size());
refreshPileupList();
return;
}
m_deGrid=w[3];
m_bDoubleClicked=true; //### needed?
m_txFirst=true;
ui->dxCallEntry->setText(m_deCall);
ui->dxGridEntry->setText(m_deGrid);
ui->txFirstCheckBox->setChecked(m_txFirst);
genStdMsgs("-22");
setTxMsg(3);
if (!ui->autoButton->isChecked()) ui->autoButton->click(); // Enable Tx
if(m_transmitting) m_restart=true;
return;
}
if(m_mode=="Q65") {
if(!bCtrl) { //Do not reset m_freqNominal if CTRL was down
double kHz=w[1].toDouble();
int nMHz=m_freqNominal/1000000;
m_freqNominal=(nMHz*1000 + kHz)* 1000;
}
m_deCall=w[3];
m_deGrid=w[4];
m_txFirst=(w[5]=="0");
// ui->TxFreqSpinBox->setValue(1500);
} else {
m_deCall=w[0];
m_deGrid=w[1];
ui->RxFreqSpinBox->setValue(w[4].toInt());
m_txFirst = (w[5]=="0");
}
m_bDoubleClicked=true; //### needed?
ui->dxCallEntry->setText(m_deCall);
ui->dxGridEntry->setText(m_deGrid);
genStdMsgs(w[3]); //### real SNR would be better here?
ui->RxFreqSpinBox->setValue(w[4].toInt());
if(m_mode=="Q65") {
ui->rptSpinBox->setValue(w[2].toInt());
genStdMsgs(w[2]);
} else {
genStdMsgs(w[3]);
}
setTxMsg(1);
m_txFirst = (w[5]=="0");
ui->txFirstCheckBox->setChecked(m_txFirst);
if (!ui->autoButton->isChecked()) ui->autoButton->click(); // Enable Tx
if(m_transmitting) m_restart=true;
@@ -3734,6 +3916,8 @@ void MainWindow::readFromStdout() //readFromStdout
bool bAvgMsg=false;
int navg=0;
qint64 ms = QDateTime::currentMSecsSinceEpoch() % 86400000;
double fTR=float((ms%int(1000.0*m_TRperiod)))/int(1000.0*m_TRperiod);
if(line_read.indexOf("<DecodeFinished>") >= 0) {
m_bDecoded = line_read.mid(20).trimmed().toInt() > 0;
int n=line_read.trimmed().size();
@@ -3793,6 +3977,7 @@ void MainWindow::readFromStdout() //readFromStdout
}
m_tBlankLine = line_read.left(ntime);
}
if(m_mode=="FT8" && fTR>0.6 && fTR<0.75) decodeDone(); // Clear a hung decoder status
}
if ("FST4W" == m_mode)
{
@@ -4005,7 +4190,8 @@ void MainWindow::readFromStdout() //readFromStdout
hound_reply ();
}
} else {
QStringList w=decodedtext.string().mid(24).split(" ",SkipEmptyParts);
QString text = decodedtext.string().replace("<","").replace(">",""); // needed for MSHV multistream messages
QStringList w=text.mid(24).split(" ",SkipEmptyParts);
if(decodedtext.string().contains("/")) w.append(" +00"); //Add a dummy report
if(w.size()>=3) {
QString foxCall=w.at(1);
@@ -4020,7 +4206,8 @@ void MainWindow::readFromStdout() //readFromStdout
m_rptRcvd=w.at(2);
m_rptSent=decodedtext.string().mid(7,3);
m_nFoxFreq=decodedtext.string().mid(16,4).toInt();
hound_reply ();
} else {
if (text.contains(m_config.my_callsign() + " " + m_hisCall) && !text.contains("73 ")) processMessage(decodedtext0); // needed for MSHV multistream messages
}
}
}
@@ -4111,7 +4298,7 @@ void MainWindow::auto_sequence (DecodedText const& message, unsigned start_toler
|| message_words.contains (ui->dxCallEntry->text ())
|| message_words.contains (Radio::base_callsign (ui->dxCallEntry->text ()))
|| message_words.contains ("DE")))
|| !message.isStandardMessage ()); // free text 73/RR73
|| (!message.isStandardMessage () && m_mode != "MSK144")); // free text 73/RR73 except for MSK
auto const& w = msg_no_hash.split(" ",SkipEmptyParts);
QString w2;
@@ -4770,13 +4957,14 @@ void MainWindow::guiUpdate()
}
}
if(m_mode=="FT8" or m_mode=="MSK144" or m_mode=="FT4" || "Q65" == m_mode) {
if(m_mode=="FT8" or m_mode=="MSK144" or m_mode=="FT4" or m_mode=="Q65") {
if(ui->txrb1->isEnabled() and
(SpecOp::NA_VHF==m_specOp or
SpecOp::FIELD_DAY==m_specOp or
SpecOp::RTTY==m_specOp or
SpecOp::WW_DIGI==m_specOp or
SpecOp::ARRL_DIGI==m_specOp) ) {
SpecOp::ARRL_DIGI==m_specOp or
SpecOp::Q65_PILEUP==m_specOp)) {
//We're in a contest-like mode other than EU_VHF: start QSO with Tx2.
ui->tx1->setEnabled(false);
ui->txb1->setEnabled(false);
@@ -4789,16 +4977,34 @@ void MainWindow::guiUpdate()
}
if(m_mode=="Echo" and !m_monitoring and !m_auto and !m_diskData) m_echoRunning=false;
if(m_mode=="Q65") {
mem_qmap.lock();
int n=0;
if(m_decoderBusy) n=1;
ipc_qmap[3]=n;
n=0;
if(m_transmitting) n=1;
ipc_qmap[4]=n;
if(ipc_qmap[0] > 0) { //ndecodes
memcpy(&qmapcom, (char*)ipc_qmap, sizeof(qmapcom)); //Fetch the new decode(s)
readWidebandDecodes();
}
mem_qmap.unlock();
}
//Once per second (onesec)
if(nsec != m_sec0) {
// qDebug() << "AAA" << nsec << m_bFastMode << m_bFast9;
// qDebug() << "AAA" << nsec%60 << int(m_specOp);
if(m_mode=="FST4") chk_FST4_freq_range();
m_currentBand=m_config.bands()->find(m_freqNominal);
if( SpecOp::HOUND == m_specOp ) {
qint32 tHound=QDateTime::currentMSecsSinceEpoch()/1000 - m_tAutoOn;
//To keep calling Fox, Hound must reactivate Enable Tx at least once every 2 minutes
if(tHound >= 120 and m_ntx==1) auto_tx_mode(false);
if(tHound >= 120 and m_ntx==1) {
auto_tx_mode(false);
statusUpdate ();
}
}
progressBar.setVisible(true);
@@ -5402,7 +5608,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
or bEU_VHF_w2 or (m_QSOProgress==CALLING))) {
if(message_words.at(4).contains(grid_regexp) and SpecOp::EU_VHF!=m_specOp) {
if((SpecOp::NA_VHF==m_specOp or SpecOp::WW_DIGI==m_specOp or
SpecOp::ARRL_DIGI==m_specOp )
SpecOp::ARRL_DIGI==m_specOp or SpecOp::Q65_PILEUP==m_specOp)
and bContestOK) {
setTxMsg(3);
m_QSOProgress=ROGER_REPORT;
@@ -5766,7 +5972,7 @@ void MainWindow::genCQMsg ()
QString t=ui->tx6->text();
QStringList tlist=t.split(" ");
if((m_mode=="FT4" or m_mode=="FT8" or m_mode=="MSK144" || "Q65" == m_mode) and
SpecOp::NONE != m_specOp and
SpecOp::NONE != m_specOp and SpecOp::HOUND != m_specOp and SpecOp::Q65_PILEUP != m_specOp and
( tlist.at(1)==my_callsign or
tlist.at(2)==my_callsign ) and
stdCall(my_callsign)) {
@@ -5890,6 +6096,7 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
if(SpecOp::NA_VHF==m_specOp) sent=my_grid;
if(SpecOp::WW_DIGI==m_specOp) sent=my_grid;
if(SpecOp::ARRL_DIGI==m_specOp) sent=my_grid;
if(SpecOp::Q65_PILEUP==m_specOp) sent=my_grid;
if(SpecOp::FIELD_DAY==m_specOp) sent=m_config.Field_Day_Exchange();
if(SpecOp::RTTY==m_specOp) {
sent=rst + m_config.RTTY_Exchange();
@@ -6314,6 +6521,21 @@ void MainWindow::on_RoundRobin_currentTextChanged(QString text)
ui->sbTxPercent->setEnabled (text == tr ("Random"));
}
void MainWindow::mousePressEvent(QMouseEvent *event)
{
if(ui->q65Button->hasFocus() && (event->button() & Qt::RightButton)) {
m_specOp=m_config.special_op_id();
if (m_specOp==SpecOp::Q65_PILEUP) {
m_config.setSpecial_None();
ui->tx1->setEnabled(true);
ui->txb1->setEnabled(true);
} else {
m_config.setSpecial_Q65_Pileup();
}
m_specOp=m_config.special_op_id();
on_actionQ65_triggered();
}
}
void MainWindow::on_dxCallEntry_textChanged (QString const& call)
{
@@ -6481,16 +6703,26 @@ void MainWindow::acceptQSO (QDateTime const& QSO_date_off, QString const& call,
}
if(m_ActiveStationsWidget!=NULL) {
QString band=m_config.bands()->find(dial_freq);
activeWorked(call,band);
int points=m_activeCall[call].points;
m_score += points;
ARRL_logged al;
al.time=QDateTime::currentDateTimeUtc();
al.band=band;
al.points=points;
m_arrl_log.append(al);
updateRate();
if(m_mode=="Q65") {
m_score++;
m_EMEworked[call]=true;
if(m_specOp==SpecOp::Q65_PILEUP) {
rm_q3list_(const_cast<char *> (m_deCall.toLatin1().constData()), m_deCall.size());
refreshPileupList();
}
m_ActiveStationsWidget->setRate(m_score);
} else {
QString band=m_config.bands()->find(dial_freq);
activeWorked(call,band);
int points=m_activeCall[call].points;
m_score += points;
ARRL_logged al;
al.time=QDateTime::currentDateTimeUtc();
al.band=band;
al.points=points;
m_arrl_log.append(al);
updateRate();
}
}
m_xSent.clear ();
@@ -6599,6 +6831,7 @@ void MainWindow::displayWidgets(qint64 n)
b=m_mode.startsWith("FST4");
ui->sbNB->setVisible(b);
genStdMsgs (m_rpt, true);
configActiveStations();
}
void MainWindow::on_actionFST4_triggered()
@@ -6811,7 +7044,6 @@ void MainWindow::on_actionFT8_triggered()
} else {
if (!(keep_frequency)) switch_mode (Modes::FT8);
}
if(m_specOp != SpecOp::HOUND) {
ui->houndButton->setChecked(false);
ui->houndButton->setStyleSheet("");
@@ -6824,15 +7056,16 @@ void MainWindow::on_actionFT8_triggered()
if(SpecOp::EU_VHF==m_specOp) t0="EU VHF";
if(SpecOp::FIELD_DAY==m_specOp) t0="Field Day";
if(SpecOp::RTTY==m_specOp) t0="FT RU";
if(SpecOp::WW_DIGI==m_specOp) t0="WW_DIGI";
if(SpecOp::ARRL_DIGI==m_specOp) t0="ARRL_DIGI";
if(SpecOp::WW_DIGI==m_specOp) t0="WW Digi";
if(SpecOp::ARRL_DIGI==m_specOp) t0="ARRL Digi";
if(SpecOp::Q65_PILEUP==m_specOp) t0="Q65 Pileup";
if(t0=="") {
ui->labDXped->setVisible(false);
} else {
ui->labDXped->setVisible(true);
ui->labDXped->setText(t0);
}
on_contest_log_action_triggered();
if(m_specOp!=SpecOp::Q65_PILEUP) on_contest_log_action_triggered();
}
if((SpecOp::FOX==m_specOp or SpecOp::HOUND==m_specOp) and !m_config.split_mode() and !m_bWarnedSplit) {
@@ -6844,6 +7077,7 @@ void MainWindow::on_actionFT8_triggered()
m_bWarnedSplit=true;
}
statusChanged();
configActiveStations();
}
void MainWindow::on_actionJT4_triggered()
@@ -7051,7 +7285,6 @@ void MainWindow::on_actionQ65_triggered()
ui->rh_decodes_title_label->setText(tr ("Average Decodes"));
ui->lh_decodes_headings_label->setText("UTC dB DT Freq " + tr ("Message"));
ui->rh_decodes_headings_label->setText("UTC dB DT Freq " + tr ("Message"));
statusChanged();
m_specOp=m_config.special_op_id();
if(m_specOp!=SpecOp::NONE and m_specOp!=SpecOp::FOX and m_specOp!=SpecOp::HOUND) {
@@ -7060,17 +7293,24 @@ void MainWindow::on_actionQ65_triggered()
if(SpecOp::EU_VHF==m_specOp) t0="EU VHF";
if(SpecOp::FIELD_DAY==m_specOp) t0="Field Day";
if(SpecOp::RTTY==m_specOp) t0="FT RU";
if(SpecOp::WW_DIGI==m_specOp) t0="WW_DIGI";
if(SpecOp::ARRL_DIGI==m_specOp) t0="ARRL_DIGI";
if(SpecOp::WW_DIGI==m_specOp) t0="WW Digi";
if(SpecOp::ARRL_DIGI==m_specOp) t0="ARRL Digi";
if(SpecOp::Q65_PILEUP==m_specOp) t0="Q65 Pileup";
if(t0=="") {
ui->labDXped->setVisible(false);
} else {
ui->labDXped->setVisible(true);
ui->labDXped->setText(t0);
}
on_contest_log_action_triggered();
if(m_specOp!=SpecOp::Q65_PILEUP) {
on_contest_log_action_triggered();
} else {
if(ui->txrb1->isChecked()) on_txb2_clicked();
ui->tx1->setEnabled(true);
ui->txb1->setEnabled(true);
}
}
statusChanged();
}
void MainWindow::on_actionMSK144_triggered()
@@ -7246,6 +7486,12 @@ void MainWindow::on_actionFreqCal_triggered()
void MainWindow::switch_mode (Mode mode)
{
if (m_mode != "Q65" && m_specOp==SpecOp::Q65_PILEUP) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
ui->tx1->setEnabled(true);
ui->txb1->setEnabled(true);
}
m_fastGraph->setMode(m_mode);
m_config.frequencies ()->filter (m_config.region (), mode, true); // filter on current time
auto const& row = m_config.frequencies ()->best_working_frequency (m_freqNominal);
@@ -7438,6 +7684,17 @@ void MainWindow::on_actionErase_ALL_TXT_triggered() //Erase ALL.TXT
}
}
void MainWindow::on_actionErase_list_of_Q65_callers_triggered()
{
int ret = MessageBox::query_message (this, tr ("Confirm Erase"),
tr ("Are you sure you want to erase the list of Q65 callers?"));
if(ret==MessageBox::Yes) {
QFile f {m_config.writeable_data_dir ().absoluteFilePath ("tsil.3q")};
f.remove();
}
}
void MainWindow::on_reset_cabrillo_log_action_triggered ()
{
if (MessageBox::Yes == MessageBox::query_message (this, tr ("Confirm Reset"),
@@ -7449,8 +7706,12 @@ void MainWindow::on_reset_cabrillo_log_action_triggered ()
if(m_config.RTTY_Exchange()!="SCC") ui->sbSerialNumber->setValue(1);
m_logBook.contest_log ()->reset ();
m_activeCall.clear(); //Erase the QMap of active calls
m_EMECall.clear(); //ditto for EME calls
m_score=0;
if (m_ActiveStationsWidget) m_ActiveStationsWidget->setScore(0);
if (m_ActiveStationsWidget) {
m_ActiveStationsWidget->setScore(0);
if(m_mode=="Q65") m_ActiveStationsWidget->setRate(0);
}
}
}
@@ -7529,6 +7790,7 @@ void MainWindow::on_bandComboBox_activated (int index)
m_bandEdited = true;
band_changed (frequency);
m_wideGraph->setRxBand (m_config.bands ()->find (frequency));
auto_tx_mode(false);
}
void MainWindow::band_changed (Frequency f)
@@ -7824,7 +8086,7 @@ void MainWindow::handle_transceiver_update (Transceiver::TransceiverState const&
if(m_lastDialFreq != m_freqNominal and m_ActiveStationsWidget != NULL) {
m_recentCall.clear();
m_ActiveStationsWidget->erase();
if(m_mode!="Q65") m_ActiveStationsWidget->erase();
}
m_lastDialFreq = m_freqNominal;
@@ -9176,6 +9438,112 @@ void MainWindow::write_transmit_entry (QString const& file_name)
}
}
void MainWindow::readWidebandDecodes()
{
if(m_ActiveStationsWidget==NULL) return;
int nhr=0;
int nmin=0;
int nsnr=0;
while(m_fetched < qmapcom.ndecodes) {
QString line=QString::fromLatin1(qmapcom.result[m_fetched]);
m_fetched++;
nhr=line.mid(0,2).toInt();
nmin=line.mid(2,2).toInt();
double frx=line.mid(4,9).toDouble();
double fsked=line.mid(13,7).toDouble();
QString msg=line.mid(34,-1);
int i1=msg.indexOf(" ");
int i2=i1 +1 + msg.mid(i1+1,-1).indexOf(" ");
QString dxcall=msg.mid(i1+1,i2-i1-1);
if(stdCall(dxcall)) {
QString w3=msg.mid(i2+1,-1);
nsnr=line.mid(29,3).toInt();
m_EMECall[dxcall].frx=frx;
m_EMECall[dxcall].fsked=fsked;
m_EMECall[dxcall].nsnr=nsnr;
m_EMECall[dxcall].t=60*nhr + nmin;
if(w3.contains(grid_regexp)) m_EMECall[dxcall].grid4=w3;
bool bCQ=line.contains(" CQ ");
m_EMECall[dxcall].ready2call=(bCQ or line.contains(" 73") or line.contains(" RR73"));
Frequency frequency = (m_freqNominal/1000000) * 1000000 + int(fsked*1000.0);
bool bFromDisk=qmapcom.nQDecoderDone==2;
if(!bFromDisk and (m_EMECall[dxcall].grid4.contains(grid_regexp) or bCQ)) {
qDebug() << "To PSKreporter:" << dxcall << m_EMECall[dxcall].grid4 << frequency << m_mode << nsnr;
if (!m_psk_Reporter.addRemoteStation (dxcall, m_EMECall[dxcall].grid4, frequency, m_mode, nsnr)) {
showStatusMessage (tr ("Spotting to PSK Reporter unavailable"));
}
}
}
}
if (m_config.spot_to_psk_reporter ()) {
m_psk_Reporter.sendReport(); // Upload any queued spots
}
// Update "m_wEMECall" by reading qmap_decodes.txt
QMap<QString,EMECall>::iterator i;
QString t="";
QString t1;
QString dxcall;
QString dxgrid4;
QStringList list;
float f[100];
int indx[100];
int maxAge=m_ActiveStationsWidget->maxAge();
m_ActiveStationsWidget->setClickOK(false);
int k=0;
for(i=m_EMECall.begin(); i!=m_EMECall.end(); i++) {
bool bSkip=false;
if(m_ActiveStationsWidget->wantedOnly() and m_EMEworked[i.key()]) bSkip=true;
if(m_ActiveStationsWidget->readyOnly() and !i->ready2call) bSkip=true;
if(!bSkip) {
int snr=i->nsnr;
int odd=1 - (i->t)%2;
int age=60*nhr + nmin - (i->t);
char c2[3]={32,32,0};
if(age<0) age += 1440;
if(age<=maxAge) {
dxcall=(i.key()+" ").left(8);
dxgrid4=(i->grid4+"... ").left(4);
if(!m_EMEworked[dxcall.trimmed()]) c2[0]=35; //# for not in log
if(i->ready2call) c2[1]=42; //* for ready to call
t1=t1.asprintf("%7.3f %5.1f %+03d %8s %4s %3d %3d %2s\n",i->frx,i->fsked,snr,dxcall.toLatin1().constData(),
dxgrid4.toLatin1().constData(),odd,age,c2);
f[k]=i->fsked;
list.append(t1);
k++;
}
m_ActiveStationsWidget->setClickOK(true);
}
}
if(k>0) {
t1="";
int kz=k;
indexx_(f,&kz,indx);
for(int k=0; k<kz; k++) {
int j=indx[k]-1;
t1=t1.asprintf("%2d. ",k+1);
t1+=list[j];
m_ready2call[k]=list[j];
t+=t1;
}
}
if(m_ActiveStationsWidget != NULL) {
m_ActiveStationsWidget->erase();
m_ActiveStationsWidget->displayRecentStations(m_mode,t);
m_ActiveStationsWidget->setClickOK(true);
}
if(ipc_qmap[2]!=0) {
m_fetched=0;
ipc_qmap[0]=0;
ipc_qmap[2]=0;
}
}
// -------------------------- Code for FT8 DXpedition Mode ---------------------------
void MainWindow::hound_reply ()
@@ -10051,15 +10419,16 @@ void MainWindow::chkFT4()
if(SpecOp::EU_VHF==m_specOp) t0="EU VHF";
if(SpecOp::FIELD_DAY==m_specOp) t0="Field Day";
if(SpecOp::RTTY==m_specOp) t0="FT RU";
if(SpecOp::WW_DIGI==m_specOp) t0="WW_DIGI";
if(SpecOp::ARRL_DIGI==m_specOp) t0="ARRL_DIGI";
if(SpecOp::WW_DIGI==m_specOp) t0="WW Digi";
if(SpecOp::ARRL_DIGI==m_specOp) t0="ARRL Digi";
if(SpecOp::Q65_PILEUP==m_specOp) t0="Q65 Pileup";
if(t0=="") {
ui->labDXped->setVisible(false);
} else {
ui->labDXped->setVisible(true);
ui->labDXped->setText(t0);
}
on_contest_log_action_triggered();
if(m_specOp!=SpecOp::Q65_PILEUP) on_contest_log_action_triggered();
}
if (SpecOp::HOUND == m_specOp or SpecOp::FOX == m_specOp) {
ui->labDXped->setVisible(false);
@@ -10091,6 +10460,17 @@ void MainWindow::set_mode (QString const& mode)
else if ("Echo" == mode) on_actionEcho_triggered ();
}
void MainWindow::configActiveStations()
{
if(m_ActiveStationsWidget!=NULL and (m_mode=="Q65" or m_mode=="FT4" or m_mode=="FT8")) {
if(m_specOp==SpecOp::Q65_PILEUP) {
m_ActiveStationsWidget->displayRecentStations("Q65-pileup","");
} else {
m_ActiveStationsWidget->displayRecentStations(m_mode,"");
}
}
}
void MainWindow::remote_configure (QString const& mode, quint32 frequency_tolerance
, QString const& submode, bool fast_mode, quint32 tr_period, quint32 rx_df
, QString const& dx_call, QString const& dx_grid, bool generate_messages)
@@ -10205,6 +10585,9 @@ void MainWindow::on_houndButton_clicked (bool checked)
if (checked) {
ui->houndButton->setStyleSheet("background-color: #ff0000;");
m_config.setSpecial_Hound();
ui->tx1->setVisible(true);
ui->tx1->setEnabled(true);
ui->txb1->setEnabled(true);
} else {
ui->houndButton->setStyleSheet("");
m_config.setSpecial_None();
@@ -10217,8 +10600,6 @@ void MainWindow::on_houndButton_clicked (bool checked)
void MainWindow::on_ft8Button_clicked()
{
ui->houndButton->setChecked(false);
ui->houndButton->setStyleSheet("");
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
@@ -10228,8 +10609,6 @@ void MainWindow::on_ft8Button_clicked()
void MainWindow::on_ft4Button_clicked()
{
ui->houndButton->setChecked(false);
ui->houndButton->setStyleSheet("");
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
@@ -10239,8 +10618,6 @@ void MainWindow::on_ft4Button_clicked()
void MainWindow::on_msk144Button_clicked()
{
ui->houndButton->setChecked(false);
ui->houndButton->setStyleSheet("");
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
@@ -10250,8 +10627,6 @@ void MainWindow::on_msk144Button_clicked()
void MainWindow::on_q65Button_clicked()
{
ui->houndButton->setChecked(false);
ui->houndButton->setStyleSheet("");
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
@@ -10261,8 +10636,6 @@ void MainWindow::on_q65Button_clicked()
void MainWindow::on_jt65Button_clicked()
{
ui->houndButton->setChecked(false);
ui->houndButton->setStyleSheet("");
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();