mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-19 10:32:02 -05:00
3fbf5a5686
The filter used for 4 times down-sampling cannot handle sample streams where the hardware or drivers deliver chunks of data that are not multiples of 4 frames long. This seems to be prevalent on some Linux platforms. Also de-interleaving of single channel audio from stereo streams was no longer supported. I have changed the input strategy to de-interleave the incoming sample stream into an intermediate buffer large enough to hold all the samples required for a single unit of processing (one basic waterfall interval) and apply the down-sampling filter to the whole intermediate buffer just prior dispatch to the FFT generator. This now means that we are now using the ubiquitous 48kHz hardware sample rate for both input and output of audio across all platforms and decoding a single channel of a stereo stream is again supported. The down-sampling to 12kHz is done with a high quality FIR 49-tap low pass filter specifically designed by Joe (K1JT) for operation in a 4kHz bandwidth. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@3585 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
3038 lines
91 KiB
C++
3038 lines
91 KiB
C++
//--------------------------------------------------------------- MainWindow
|
|
#include "mainwindow.h"
|
|
#include "ui_mainwindow.h"
|
|
|
|
#include <QThread>
|
|
#include <QColorDialog>
|
|
|
|
#include "soundout.h"
|
|
#include "devsetup.h"
|
|
#include "plotter.h"
|
|
#include "about.h"
|
|
#include "widegraph.h"
|
|
#include "sleep.h"
|
|
#include "getfile.h"
|
|
#include "logqso.h"
|
|
|
|
|
|
|
|
#ifdef QT5
|
|
#include <QtConcurrent/QtConcurrentRun>
|
|
#endif
|
|
|
|
int itone[NUM_JT65_SYMBOLS]; //Audio tones for all Tx symbols
|
|
int icw[NUM_CW_SYMBOLS]; //Dits for CW ID
|
|
|
|
int outBufSize;
|
|
int rc;
|
|
qint32 g_COMportOpen;
|
|
qint32 g_iptt;
|
|
static int nc1=1;
|
|
wchar_t buffer[256];
|
|
|
|
|
|
Rig* rig = NULL;
|
|
QTextEdit* pShortcuts;
|
|
QTcpSocket* commanderSocket = new QTcpSocket(0);
|
|
|
|
QString rev="$Rev$";
|
|
QString Program_Title_Version=" WSJT-X v1.2, r" + rev.mid(6,4) +
|
|
" by K1JT";
|
|
|
|
//-------------------------------------------------- MainWindow constructor
|
|
// Multiple instances: new arg *thekey
|
|
MainWindow::MainWindow(QSettings * settings, QSharedMemory *shdmem, QString *thekey,
|
|
qint32 fontSize2, qint32 fontWeight2,
|
|
QWidget *parent) :
|
|
QMainWindow(parent),
|
|
m_settings (settings),
|
|
ui(new Ui::MainWindow),
|
|
m_wideGraph (new WideGraph (settings)),
|
|
m_logDlg (new LogQSO (settings, this)),
|
|
m_detector (RX_SAMPLE_RATE, NTMAX / 2, 6912 / 2),
|
|
m_audioInputDevice (QAudioDeviceInfo::defaultInputDevice ()), // start with default
|
|
m_modulator (TX_SAMPLE_RATE, NTMAX / 2),
|
|
m_audioOutputDevice (QAudioDeviceInfo::defaultOutputDevice ()), // start with default
|
|
m_soundOutput (&m_modulator),
|
|
psk_Reporter (new PSK_Reporter (this)),
|
|
m_msAudioOutputBuffered (0u),
|
|
m_framesAudioInputBuffered (RX_SAMPLE_RATE / 10),
|
|
m_audioThreadPriority (QThread::HighPriority)
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
connect (this, &MainWindow::finished, this, &MainWindow::close);
|
|
|
|
// start audio thread and hook up slots & signals for shutdown management
|
|
|
|
// these objects need to be in the audio thread so that invoking
|
|
// their slots is done in a thread safe way
|
|
m_soundOutput.moveToThread (&m_audioThread);
|
|
m_modulator.moveToThread (&m_audioThread);
|
|
m_soundInput.moveToThread (&m_audioThread);
|
|
m_detector.moveToThread (&m_audioThread);
|
|
|
|
connect (this, &MainWindow::finished, &m_audioThread, &QThread::quit); // quit thread event loop
|
|
connect (&m_audioThread, &QThread::finished, &m_audioThread, &QThread::deleteLater); // disposal
|
|
|
|
// hook up sound output stream slots & signals
|
|
connect (this, SIGNAL (startAudioOutputStream (QAudioDeviceInfo const&, unsigned, unsigned)), &m_soundOutput, SLOT (startStream (QAudioDeviceInfo const&, unsigned, unsigned)));
|
|
connect (this, SIGNAL (stopAudioOutputStream ()), &m_soundOutput, SLOT (stopStream ()));
|
|
connect (&m_soundOutput, &SoundOutput::error, this, &MainWindow::showSoundOutError);
|
|
// connect (&m_soundOutput, &SoundOutput::status, this, &MainWindow::showStatusMessage);
|
|
connect (this, SIGNAL (outAttenuationChanged (qreal)), &m_soundOutput, SLOT (setAttenuation (qreal)));
|
|
|
|
// hook up Modulator slots
|
|
connect (this, SIGNAL (muteAudioOutput (bool)), &m_modulator, SLOT (mute (bool)));
|
|
connect (this, SIGNAL(transmitFrequency (unsigned)), &m_modulator, SLOT (setFrequency (unsigned)));
|
|
connect (this, SIGNAL (endTransmitMessage ()), &m_modulator, SLOT (close ()));
|
|
connect (this, SIGNAL (tune (bool)), &m_modulator, SLOT (tune (bool)));
|
|
connect (this, SIGNAL (sendMessage (unsigned, double, unsigned, AudioDevice::Channel, bool, double))
|
|
, &m_modulator, SLOT (open (unsigned, double, unsigned, AudioDevice::Channel, bool, double)));
|
|
|
|
// hook up the audio input stream
|
|
connect (this, SIGNAL (startAudioInputStream (QAudioDeviceInfo const&, unsigned, int, QIODevice *))
|
|
, &m_soundInput, SLOT (start (QAudioDeviceInfo const&, unsigned, int, QIODevice *)));
|
|
connect (this, SIGNAL (stopAudioInputStream ()), &m_soundInput, SLOT (stop ()));
|
|
|
|
connect(&m_soundInput, SIGNAL (error (QString)), this, SLOT (showSoundInError (QString)));
|
|
// connect(&m_soundInput, SIGNAL(status(QString)), this, SLOT(showStatusMessage(QString)));
|
|
|
|
// hook up the detector
|
|
connect (this, SIGNAL (startDetector (AudioDevice::Channel)), &m_detector, SLOT (open (AudioDevice::Channel)));
|
|
connect (this, SIGNAL (detectorSetMonitoring (bool)), &m_detector, SLOT (setMonitoring (bool)));
|
|
connect (this, SIGNAL (detectorClose ()), &m_detector, SLOT (close ()));
|
|
|
|
connect(&m_detector, SIGNAL (framesWritten (qint64)), this, SLOT (dataSink (qint64)));
|
|
|
|
// setup the waterfall
|
|
connect(m_wideGraph.data (), SIGNAL(freezeDecode2(int)),this,
|
|
SLOT(freezeDecode(int)));
|
|
connect(m_wideGraph.data (), SIGNAL(f11f12(int)),this,
|
|
SLOT(bumpFqso(int)));
|
|
connect(m_wideGraph.data (), SIGNAL(setXIT2(int)),this,
|
|
SLOT(setXIT(int)));
|
|
// connect(m_wideGraph.data (), SIGNAL(dialFreqChanged(double)),this,
|
|
// SLOT(dialFreqChanged2(double)));
|
|
connect (this, &MainWindow::finished, m_wideGraph.data (), &WideGraph::close);
|
|
|
|
|
|
// setup the log QSO dialog
|
|
connect (m_logDlg.data (), SIGNAL (acceptQSO (bool)), this, SLOT (acceptQSO2 (bool)));
|
|
|
|
|
|
on_EraseButton_clicked();
|
|
|
|
QActionGroup* modeGroup = new QActionGroup(this);
|
|
ui->actionJT9_1->setActionGroup(modeGroup);
|
|
ui->actionJT65->setActionGroup(modeGroup);
|
|
ui->actionJT9_JT65->setActionGroup(modeGroup);
|
|
|
|
|
|
QActionGroup* saveGroup = new QActionGroup(this);
|
|
ui->actionNone->setActionGroup(saveGroup);
|
|
ui->actionSave_decoded->setActionGroup(saveGroup);
|
|
ui->actionSave_all->setActionGroup(saveGroup);
|
|
|
|
QActionGroup* DepthGroup = new QActionGroup(this);
|
|
ui->actionQuickDecode->setActionGroup(DepthGroup);
|
|
ui->actionMediumDecode->setActionGroup(DepthGroup);
|
|
ui->actionDeepestDecode->setActionGroup(DepthGroup);
|
|
|
|
QButtonGroup* txMsgButtonGroup = new QButtonGroup;
|
|
txMsgButtonGroup->addButton(ui->txrb1,1);
|
|
txMsgButtonGroup->addButton(ui->txrb2,2);
|
|
txMsgButtonGroup->addButton(ui->txrb3,3);
|
|
txMsgButtonGroup->addButton(ui->txrb4,4);
|
|
txMsgButtonGroup->addButton(ui->txrb5,5);
|
|
txMsgButtonGroup->addButton(ui->txrb6,6);
|
|
connect(txMsgButtonGroup,SIGNAL(buttonClicked(int)),SLOT(set_ntx(int)));
|
|
connect(ui->decodedTextBrowser2,SIGNAL(selectCallsign(bool,bool)),this,
|
|
SLOT(doubleClickOnCall(bool,bool)));
|
|
connect(ui->decodedTextBrowser,SIGNAL(selectCallsign(bool,bool)),this,
|
|
SLOT(doubleClickOnCall2(bool,bool)));
|
|
|
|
|
|
setWindowTitle(Program_Title_Version);
|
|
createStatusBar();
|
|
|
|
connect(&proc_jt9, SIGNAL(readyReadStandardOutput()),
|
|
this, SLOT(readFromStdout()));
|
|
|
|
connect(&proc_jt9, SIGNAL(error(QProcess::ProcessError)),
|
|
this, SLOT(jt9_error(QProcess::ProcessError)));
|
|
|
|
connect(&proc_jt9, SIGNAL(readyReadStandardError()),
|
|
this, SLOT(readFromStderr()));
|
|
|
|
ui->bandComboBox->setEditable(true);
|
|
ui->bandComboBox->lineEdit()->setReadOnly(true);
|
|
ui->bandComboBox->lineEdit()->setAlignment(Qt::AlignCenter);
|
|
for(int i = 0; i < ui->bandComboBox->count(); i++)
|
|
ui->bandComboBox->setItemData(i, Qt::AlignCenter, Qt::TextAlignmentRole);
|
|
|
|
ui->tx5->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
connect(ui->tx5, SIGNAL(customContextMenuRequested(const QPoint&)),
|
|
this, SLOT(showMacros(const QPoint&)));
|
|
|
|
ui->freeTextMsg->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
connect(ui->freeTextMsg, SIGNAL(customContextMenuRequested(const QPoint&)),
|
|
this, SLOT(showMacros(const QPoint&)));
|
|
|
|
QFont font=ui->decodedTextBrowser->font();
|
|
font.setPointSize(fontSize2);
|
|
font.setWeight(fontWeight2);
|
|
ui->decodedTextBrowser->setFont(font);
|
|
ui->decodedTextBrowser2->setFont(font);
|
|
|
|
font=ui->readFreq->font();
|
|
font.setFamily("helvetica");
|
|
font.setPointSize(9);
|
|
font.setWeight(75);
|
|
ui->readFreq->setFont(font);
|
|
|
|
connect(&m_guiTimer, SIGNAL(timeout()), this, SLOT(guiUpdate()));
|
|
m_guiTimer.start(100); //Don't change the 100 ms!
|
|
|
|
ptt0Timer = new QTimer(this);
|
|
ptt0Timer->setSingleShot(true);
|
|
connect (ptt0Timer, SIGNAL (timeout ()), &m_modulator, SLOT (close ()));
|
|
connect(ptt0Timer, SIGNAL(timeout()), this, SLOT(stopTx2()));
|
|
ptt1Timer = new QTimer(this);
|
|
ptt1Timer->setSingleShot(true);
|
|
connect(ptt1Timer, SIGNAL(timeout()), this, SLOT(startTx2()));
|
|
|
|
logQSOTimer = new QTimer(this);
|
|
logQSOTimer->setSingleShot(true);
|
|
connect(logQSOTimer, SIGNAL(timeout()), this, SLOT(on_logQSOButton_clicked()));
|
|
|
|
tuneButtonTimer= new QTimer(this);
|
|
tuneButtonTimer->setSingleShot(true);
|
|
connect (tuneButtonTimer, SIGNAL (timeout ()), &m_modulator, SLOT (close ()));
|
|
connect(tuneButtonTimer, SIGNAL(timeout()), this,
|
|
SLOT(on_stopTxButton_clicked()));
|
|
|
|
killFileTimer = new QTimer(this);
|
|
killFileTimer->setSingleShot(true);
|
|
connect(killFileTimer, SIGNAL(timeout()), this, SLOT(killFile()));
|
|
|
|
m_auto=false;
|
|
m_waterfallAvg = 1;
|
|
m_txFirst=false;
|
|
Q_EMIT muteAudioOutput (false);
|
|
m_btxMute=false;
|
|
m_btxok=false;
|
|
m_restart=false;
|
|
m_transmitting=false;
|
|
m_killAll=false;
|
|
m_widebandDecode=false;
|
|
m_ntx=1;
|
|
m_myCall="";
|
|
m_myGrid="FN20qi";
|
|
m_appDir = QApplication::applicationDirPath();
|
|
m_saveDir="/users/joe/wsjtx/install/save";
|
|
m_rxFreq=1500;
|
|
m_txFreq=1500;
|
|
m_setftx=0;
|
|
m_loopall=false;
|
|
m_startAnother=false;
|
|
m_saveDecoded=false;
|
|
m_saveAll=false;
|
|
m_sec0=-1;
|
|
m_palette="Linrad";
|
|
m_RxLog=1; //Write Date and Time to RxLog
|
|
m_nutc0=9999;
|
|
m_mode="JT9";
|
|
m_rpt="-15";
|
|
m_TRperiod=60;
|
|
m_inGain=0;
|
|
m_dataAvailable=false;
|
|
g_iptt=0;
|
|
g_COMportOpen=0;
|
|
m_secID=0;
|
|
m_promptToLog=false;
|
|
m_blankLine=false;
|
|
m_insertBlank=false;
|
|
m_displayDXCCEntity=false;
|
|
m_clearCallGrid=false;
|
|
m_bMiles=false;
|
|
m_decodedText2=false;
|
|
m_freeText=false;
|
|
m_msErase=0;
|
|
m_sent73=false;
|
|
m_watchdogLimit=5;
|
|
m_tune=false;
|
|
m_repeatMsg=0;
|
|
m_bRigOpen=false;
|
|
m_secBandChanged=0;
|
|
m_bMultipleOK=false;
|
|
m_dontReadFreq=false;
|
|
m_lockTxFreq=false;
|
|
ui->readFreq->setEnabled(false);
|
|
m_QSOText.clear();
|
|
m_CATerror=false;
|
|
decodeBusy(false);
|
|
|
|
signalMeter = new SignalMeter(ui->meterFrame);
|
|
signalMeter->resize(50, 160);
|
|
|
|
ui->labAz->setStyleSheet("border: 0px;");
|
|
ui->labDist->setStyleSheet("border: 0px;");
|
|
|
|
mem_jt9 = shdmem;
|
|
// Multiple instances:
|
|
mykey_jt9 = thekey;
|
|
|
|
//Band Settings
|
|
readSettings(); //Restore user's setup params
|
|
|
|
// start the audio thread
|
|
m_audioThread.start (m_audioThreadPriority);
|
|
|
|
#ifdef WIN32
|
|
if(!m_bMultipleOK) {
|
|
while(true) {
|
|
int iret=killbyname("jt9.exe");
|
|
if(iret == 603) break;
|
|
if(iret != 0) msgBox("KillByName return code: " +
|
|
QString::number(iret));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if(m_dFreq.length()<=1) { //Use the startup default frequencies and band descriptions
|
|
// default bands and JT65 frequencies
|
|
const double dFreq[]={0.13613,0.4742,1.838,3.576,5.357,7.076,10.138,14.076,
|
|
18.102,21.076,24.917,28.076,50.276,70.091,144.489,432.178};
|
|
const QStringList dBandDescription = QStringList() << "2200 m" << "630 m" << "160 m"
|
|
<< "80 m" << "60 m" << "40 m"
|
|
<< "30 m" << "20 m" << "17 m"
|
|
<< "15 m" << "12 m" << "10 m"
|
|
<< "6 m" << "4 m" << "2 m"
|
|
<< "other";
|
|
m_dFreq.clear();
|
|
m_antDescription.clear();
|
|
m_bandDescription.clear();
|
|
for(int i=0; i<16; i++) {
|
|
QString t;
|
|
t.sprintf("%f",dFreq[i]);
|
|
m_dFreq.append(t);
|
|
m_antDescription.append("");
|
|
m_bandDescription.append(dBandDescription[i]);
|
|
}
|
|
}
|
|
|
|
ui->bandComboBox->clear();
|
|
ui->bandComboBox->addItems(m_bandDescription);
|
|
ui->bandComboBox->setCurrentIndex(m_band);
|
|
|
|
QFile lockFile(m_appDir + "/.lock"); //Create .lock so jt9 will wait
|
|
lockFile.open(QIODevice::ReadWrite);
|
|
//QFile quitFile(m_appDir + "/.lock");
|
|
//quitFile.remove();
|
|
|
|
// Multiple instances: make the Qstring key into command line arg
|
|
// Multiple instances: start "jt9 -s <thekey>"
|
|
QByteArray ba = mykey_jt9->toLocal8Bit();
|
|
const char *bc = ba.data();
|
|
// proc_jt9.start(QDir::toNativeSeparators('"' + m_appDir + '"' + "/jt9 -s " + bc));
|
|
QByteArray lda = m_appDir.toLocal8Bit();
|
|
const char *ldir = lda.data();
|
|
proc_jt9.start(QDir::toNativeSeparators('"' + m_appDir + "\"/jt9 -s " + bc + " \"" + ldir + '"'));
|
|
|
|
m_pbdecoding_style1="QPushButton{background-color: cyan; \
|
|
border-style: outset; border-width: 1px; border-radius: 5px; \
|
|
border-color: black; min-width: 5em; padding: 3px;}";
|
|
m_pbmonitor_style="QPushButton{background-color: #00ff00; \
|
|
border-style: outset; border-width: 1px; border-radius: 5px; \
|
|
border-color: black; min-width: 5em; padding: 3px;}";
|
|
m_pbAutoOn_style="QPushButton{background-color: red; \
|
|
border-style: outset; border-width: 1px; border-radius: 5px; \
|
|
border-color: black; min-width: 5em; padding: 3px;}";
|
|
m_pbTune_style="QPushButton{background-color: red; \
|
|
border-style: outset; border-width: 1px; border-radius: 5px; \
|
|
border-color: black; min-width: 5em; padding: 3px;}";
|
|
|
|
genStdMsgs(m_rpt);
|
|
m_ntx=6;
|
|
ui->txrb6->setChecked(true);
|
|
if(m_mode!="JT9" and m_mode!="JT65" and m_mode!="JT9+JT65") m_mode="JT9";
|
|
on_actionWide_Waterfall_triggered(); //###
|
|
m_wideGraph->setRxFreq(m_rxFreq);
|
|
m_wideGraph->setTxFreq(m_txFreq);
|
|
m_wideGraph->setLockTxFreq(m_lockTxFreq);
|
|
m_wideGraph->setModeTx(m_mode);
|
|
m_wideGraph->setModeTx(m_modeTx);
|
|
dialFreqChanged2(m_dialFreq);
|
|
|
|
connect(m_wideGraph.data (), SIGNAL(setFreq3(int,int)),this,
|
|
SLOT(setFreq4(int,int)));
|
|
|
|
if(m_mode=="JT9") on_actionJT9_1_triggered();
|
|
if(m_mode=="JT65") on_actionJT65_triggered();
|
|
if(m_mode=="JT9+JT65") on_actionJT9_JT65_triggered();
|
|
|
|
future1 = new QFuture<void>;
|
|
watcher1 = new QFutureWatcher<void>;
|
|
connect(watcher1, SIGNAL(finished()),this,SLOT(diskDat()));
|
|
|
|
future2 = new QFuture<void>;
|
|
watcher2 = new QFutureWatcher<void>;
|
|
connect(watcher2, SIGNAL(finished()),this,SLOT(diskWriteFinished()));
|
|
|
|
Q_EMIT startDetector (m_audioInputChannel);
|
|
Q_EMIT startAudioInputStream (m_audioInputDevice, AudioDevice::Mono == m_audioInputChannel ? 1 : 2, m_framesAudioInputBuffered, &m_detector);
|
|
|
|
Q_EMIT transmitFrequency (m_txFreq - (m_bSplit || m_bXIT ? m_XIT : 0));
|
|
Q_EMIT muteAudioOutput (false);
|
|
m_monitoring=!m_monitorStartOFF; // Start with Monitoring ON/OFF
|
|
Q_EMIT detectorSetMonitoring (m_monitoring);
|
|
m_diskData=false;
|
|
|
|
// Create "m_worked", a dictionary of all calls in wsjtx.log
|
|
QFile f("wsjtx.log");
|
|
f.open(QIODevice::ReadOnly | QIODevice::Text);
|
|
QTextStream in(&f);
|
|
QString line,t,callsign;
|
|
for(int i=0; i<99999; i++) {
|
|
line=in.readLine();
|
|
if(line.length()<=0) break;
|
|
t=line.mid(18,12);
|
|
callsign=t.mid(0,t.indexOf(","));
|
|
}
|
|
f.close();
|
|
|
|
ui->decodedTextLabel->setFont(ui->decodedTextBrowser->font());
|
|
ui->decodedTextLabel2->setFont(ui->decodedTextBrowser2->font());
|
|
t="UTC dB DT Freq Message";
|
|
ui->decodedTextLabel->setText(t);
|
|
ui->decodedTextLabel2->setText(t);
|
|
|
|
psk_Reporter->setLocalStation(m_myCall,m_myGrid, m_antDescription[m_band], "WSJT-X r" + rev.mid(6,4) );
|
|
|
|
on_actionEnable_DXCC_entity_triggered(m_displayDXCCEntity); // sets text window proportions and (re)inits the logbook
|
|
|
|
ui->label_9->setStyleSheet("QLabel{background-color: #aabec8}");
|
|
ui->label_10->setStyleSheet("QLabel{background-color: #aabec8}");
|
|
ui->labUTC->setStyleSheet( \
|
|
"QLabel { background-color : black; color : yellow; }");
|
|
ui->labDialFreq->setStyleSheet( \
|
|
"QLabel { background-color : black; color : yellow; }");
|
|
|
|
QFile f2("ALL.TXT");
|
|
f2.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
|
|
QTextStream out(&f2);
|
|
out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm")
|
|
<< " " << m_dialFreq << " MHz " << m_mode << endl;
|
|
f2.close();
|
|
} // End of MainWindow constructor
|
|
|
|
//--------------------------------------------------- MainWindow destructor
|
|
MainWindow::~MainWindow()
|
|
{
|
|
if(!m_decoderBusy) {
|
|
QFile lockFile(m_appDir + "/.lock");
|
|
lockFile.remove();
|
|
}
|
|
delete ui;
|
|
}
|
|
|
|
//-------------------------------------------------------- writeSettings()
|
|
void MainWindow::writeSettings()
|
|
{
|
|
m_settings->beginGroup("MainWindow");
|
|
m_settings->setValue ("geometry", saveGeometry ());
|
|
m_settings->setValue ("state", saveState ());
|
|
m_settings->setValue("MRUdir", m_path);
|
|
m_settings->setValue("TxFirst",m_txFirst);
|
|
m_settings->setValue("DXcall",ui->dxCallEntry->text());
|
|
m_settings->setValue("DXgrid",ui->dxGridEntry->text());
|
|
m_settings->endGroup();
|
|
|
|
m_settings->beginGroup("Common");
|
|
m_settings->setValue("MyCall",m_myCall);
|
|
m_settings->setValue("MyGrid",m_myGrid);
|
|
m_settings->setValue("IDint",m_idInt);
|
|
m_settings->setValue("PTTmethod",m_pttMethodIndex);
|
|
m_settings->setValue("PTTport",m_pttPort);
|
|
m_settings->setValue("SaveDir",m_saveDir);
|
|
m_settings->setValue("SoundInName", m_audioInputDevice.deviceName ());
|
|
m_settings->setValue("SoundOutName", m_audioOutputDevice.deviceName ());
|
|
|
|
m_settings->setValue ("AudioInputChannel", AudioDevice::toString (m_audioInputChannel));
|
|
m_settings->setValue ("AudioOutputChannel", AudioDevice::toString (m_audioOutputChannel));
|
|
m_settings->setValue("Mode",m_mode);
|
|
m_settings->setValue("ModeTx",m_modeTx);
|
|
m_settings->setValue("SaveNone",ui->actionNone->isChecked());
|
|
m_settings->setValue("SaveDecoded",ui->actionSave_decoded->isChecked());
|
|
m_settings->setValue("SaveAll",ui->actionSave_all->isChecked());
|
|
m_settings->setValue("NDepth",m_ndepth);
|
|
m_settings->setValue("MonitorOFF",m_monitorStartOFF);
|
|
m_settings->setValue("DialFreq",m_dialFreq);
|
|
m_settings->setValue("RxFreq",m_rxFreq);
|
|
m_settings->setValue("TxFreq",m_txFreq);
|
|
m_settings->setValue("InGain",m_inGain);
|
|
m_settings->setValue("OutAttenuation", ui->outAttenuation->value ());
|
|
m_settings->setValue("PSKReporter",m_pskReporter);
|
|
m_settings->setValue("After73",m_After73);
|
|
m_settings->setValue("Macros",m_macro);
|
|
//Band Settings
|
|
m_settings->setValue("BandFrequencies",m_dFreq);
|
|
m_settings->setValue("BandDescriptions",m_bandDescription);
|
|
m_settings->setValue("AntennaDescriptions",m_antDescription);
|
|
m_settings->setValue("toRTTY",m_toRTTY);
|
|
m_settings->setValue("NoSuffix",m_noSuffix);
|
|
m_settings->setValue("dBtoComments",m_dBtoComments);
|
|
m_settings->setValue("catEnabled",m_catEnabled);
|
|
m_settings->setValue("Rig",m_rig);
|
|
m_settings->setValue("RigIndex",m_rigIndex);
|
|
m_settings->setValue("CATport",m_catPort);
|
|
m_settings->setValue("CATportIndex",m_catPortIndex);
|
|
m_settings->setValue("SerialRate",m_serialRate);
|
|
m_settings->setValue("SerialRateIndex",m_serialRateIndex);
|
|
m_settings->setValue("DataBits",m_dataBits);
|
|
m_settings->setValue("DataBitsIndex",m_dataBitsIndex);
|
|
m_settings->setValue("StopBits",m_stopBits);
|
|
m_settings->setValue("StopBitsIndex",m_stopBitsIndex);
|
|
m_settings->setValue("Handshake",m_handshake);
|
|
m_settings->setValue("HandshakeIndex",m_handshakeIndex);
|
|
m_settings->setValue("BandIndex",m_band);
|
|
m_settings->setValue("PromptToLog",m_promptToLog);
|
|
m_settings->setValue("InsertBlank",m_insertBlank);
|
|
m_settings->setValue("DXCCEntity",m_displayDXCCEntity);
|
|
m_settings->setValue("ClearCallGrid",m_clearCallGrid);
|
|
m_settings->setValue("Miles",m_bMiles);
|
|
m_settings->setValue("GUItab",ui->tabWidget->currentIndex());
|
|
m_settings->setValue("QuickCall",m_quickCall);
|
|
m_settings->setValue("73TxDisable",m_73TxDisable);
|
|
m_settings->setValue("Runaway",m_runaway);
|
|
m_settings->setValue("Tx2QSO",m_tx2QSO);
|
|
m_settings->setValue("MultipleOK",m_bMultipleOK);
|
|
m_settings->setValue("DTR",m_bDTR);
|
|
m_settings->setValue("RTS",m_bRTS); m_settings->setValue("pttData",m_pttData);
|
|
m_settings->setValue("Polling",m_poll);
|
|
m_settings->setValue("OutBufSize",outBufSize);
|
|
m_settings->setValue("LockTxFreq",m_lockTxFreq);
|
|
m_settings->setValue("TxSplit",m_bSplit);
|
|
m_settings->setValue("UseXIT",m_bXIT);
|
|
m_settings->setValue("XIT",m_XIT);
|
|
m_settings->setValue("Plus2kHz",m_plus2kHz);
|
|
m_settings->endGroup();
|
|
}
|
|
|
|
//---------------------------------------------------------- readSettings()
|
|
void MainWindow::readSettings()
|
|
{
|
|
m_settings->beginGroup("MainWindow");
|
|
restoreGeometry (m_settings->value ("geometry", saveGeometry ()).toByteArray ());
|
|
restoreState (m_settings->value ("state", saveState ()).toByteArray ());
|
|
ui->dxCallEntry->setText(m_settings->value("DXcall","").toString());
|
|
ui->dxGridEntry->setText(m_settings->value("DXgrid","").toString());
|
|
m_path = m_settings->value("MRUdir", m_appDir + "/save").toString();
|
|
m_txFirst = m_settings->value("TxFirst",false).toBool();
|
|
ui->txFirstCheckBox->setChecked(m_txFirst);
|
|
m_settings->endGroup();
|
|
|
|
m_settings->beginGroup("Common");
|
|
m_myCall=m_settings->value("MyCall","").toString();
|
|
morse_(m_myCall.toLatin1().data(),icw,&m_ncw,m_myCall.length());
|
|
m_myGrid=m_settings->value("MyGrid","").toString();
|
|
m_idInt=m_settings->value("IDint",0).toInt();
|
|
m_pttMethodIndex=m_settings->value("PTTmethod",1).toInt();
|
|
m_pttPort=m_settings->value("PTTport",0).toInt();
|
|
m_saveDir=m_settings->value("SaveDir",m_appDir + "/save").toString();
|
|
|
|
{
|
|
//
|
|
// retrieve audio input device
|
|
//
|
|
QString savedName = m_settings->value( "SoundInName").toString();
|
|
QList<QAudioDeviceInfo> audioInputDevices (QAudioDeviceInfo::availableDevices (QAudio::AudioInput)); // available audio input devices
|
|
for (QList<QAudioDeviceInfo>::const_iterator p = audioInputDevices.begin (); p != audioInputDevices.end (); ++p)
|
|
{
|
|
if (p->deviceName () == savedName)
|
|
{
|
|
m_audioInputDevice = *p;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
//
|
|
// retrieve audio output device
|
|
//
|
|
QString savedName = m_settings->value("SoundOutName").toString();
|
|
QList<QAudioDeviceInfo> audioOutputDevices (QAudioDeviceInfo::availableDevices (QAudio::AudioOutput)); // available audio output devices
|
|
for (QList<QAudioDeviceInfo>::const_iterator p = audioOutputDevices.begin (); p != audioOutputDevices.end (); ++p)
|
|
{
|
|
if (p->deviceName () == savedName) {
|
|
m_audioOutputDevice = *p;
|
|
}
|
|
}
|
|
}
|
|
|
|
// retrieve audio channel info
|
|
m_audioInputChannel = AudioDevice::fromString (m_settings->value ("AudioInputChannel", "Mono").toString ());
|
|
m_audioOutputChannel = AudioDevice::fromString (m_settings->value ("AudioOutputChannel", "Mono").toString ());
|
|
|
|
m_mode=m_settings->value("Mode","JT9").toString();
|
|
m_modeTx=m_settings->value("ModeTx","JT9").toString();
|
|
if(m_modeTx=="JT9") ui->pbTxMode->setText("Tx JT9 @");
|
|
if(m_modeTx=="JT65") ui->pbTxMode->setText("Tx JT65 #");
|
|
ui->actionNone->setChecked(m_settings->value("SaveNone",true).toBool());
|
|
ui->actionSave_decoded->setChecked(m_settings->value(
|
|
"SaveDecoded",false).toBool());
|
|
ui->actionSave_all->setChecked(m_settings->value("SaveAll",false).toBool());
|
|
m_dialFreq=m_settings->value("DialFreq",14.078).toDouble();
|
|
m_rxFreq=m_settings->value("RxFreq",1500).toInt();
|
|
ui->RxFreqSpinBox->setValue(m_rxFreq);
|
|
m_txFreq=m_settings->value("TxFreq",1500).toInt();
|
|
ui->TxFreqSpinBox->setValue(m_txFreq);
|
|
Q_EMIT transmitFrequency (m_txFreq - (m_bSplit || m_bXIT ? m_XIT : 0));
|
|
m_saveDecoded=ui->actionSave_decoded->isChecked();
|
|
m_saveAll=ui->actionSave_all->isChecked();
|
|
m_ndepth=m_settings->value("NDepth",3).toInt();
|
|
m_inGain=m_settings->value("InGain",0).toInt();
|
|
ui->inGain->setValue(m_inGain);
|
|
|
|
// setup initial value of tx attenuator
|
|
ui->outAttenuation->setValue (m_settings->value ("OutAttenuation", 0).toInt ());
|
|
on_outAttenuation_valueChanged (ui->outAttenuation->value ());
|
|
|
|
m_monitorStartOFF=m_settings->value("MonitorOFF",false).toBool();
|
|
ui->actionMonitor_OFF_at_startup->setChecked(m_monitorStartOFF);
|
|
m_pskReporter=m_settings->value("PSKReporter",false).toBool();
|
|
m_After73=m_settings->value("After73",false).toBool();
|
|
m_macro=m_settings->value("Macros","TNX 73 GL").toStringList();
|
|
//Band Settings
|
|
m_dFreq=m_settings->value("BandFrequencies","").toStringList();
|
|
m_bandDescription=m_settings->value("BandDescriptions","").toStringList();
|
|
m_antDescription=m_settings->value("AntennaDescriptions","").toStringList();
|
|
m_toRTTY=m_settings->value("toRTTY",false).toBool();
|
|
ui->actionConvert_JT9_x_to_RTTY->setChecked(m_toRTTY);
|
|
m_noSuffix=m_settings->value("NoSuffix",false).toBool();
|
|
m_dBtoComments=m_settings->value("dBtoComments",false).toBool();
|
|
ui->actionLog_dB_reports_to_Comments->setChecked(m_dBtoComments);
|
|
m_rig=m_settings->value("Rig",214).toInt();
|
|
m_rigIndex=m_settings->value("RigIndex",100).toInt();
|
|
m_catPort=m_settings->value("CATport","None").toString();
|
|
m_catPortIndex=m_settings->value("CATportIndex",0).toInt();
|
|
m_serialRate=m_settings->value("SerialRate",4800).toInt();
|
|
m_serialRateIndex=m_settings->value("SerialRateIndex",1).toInt();
|
|
m_dataBits=m_settings->value("DataBits",8).toInt();
|
|
m_dataBitsIndex=m_settings->value("DataBitsIndex",1).toInt();
|
|
m_stopBits=m_settings->value("StopBits",2).toInt();
|
|
m_stopBitsIndex=m_settings->value("StopBitsIndex",1).toInt();
|
|
m_handshake=m_settings->value("Handshake","None").toString();
|
|
m_handshakeIndex=m_settings->value("HandshakeIndex",0).toInt();
|
|
m_band=m_settings->value("BandIndex",7).toInt();
|
|
ui->bandComboBox->setCurrentIndex(m_band);
|
|
dialFreqChanged2(m_dialFreq);
|
|
m_catEnabled=m_settings->value("catEnabled",false).toBool();
|
|
m_promptToLog=m_settings->value("PromptToLog",false).toBool();
|
|
ui->actionPrompt_to_log_QSO->setChecked(m_promptToLog);
|
|
m_insertBlank=m_settings->value("InsertBlank",false).toBool();
|
|
ui->actionBlank_line_between_decoding_periods->setChecked(m_insertBlank);
|
|
m_displayDXCCEntity=m_settings->value("DXCCEntity",false).toBool();
|
|
ui->actionEnable_DXCC_entity->setChecked(m_displayDXCCEntity);
|
|
m_clearCallGrid=m_settings->value("ClearCallGrid",false).toBool();
|
|
ui->actionClear_DX_Call_and_Grid_after_logging->setChecked(m_clearCallGrid);
|
|
m_bMiles=m_settings->value("Miles",false).toBool();
|
|
ui->actionDisplay_distance_in_miles->setChecked(m_bMiles);
|
|
int n=m_settings->value("GUItab",0).toInt();
|
|
ui->tabWidget->setCurrentIndex(n);
|
|
m_quickCall=m_settings->value("QuickCall",false).toBool();
|
|
ui->actionDouble_click_on_call_sets_Tx_Enable->setChecked(m_quickCall);
|
|
m_73TxDisable=m_settings->value("73TxDisable",false).toBool();
|
|
ui->action_73TxDisable->setChecked(m_73TxDisable);
|
|
m_runaway=m_settings->value("Runaway",false).toBool();
|
|
ui->actionRunaway_Tx_watchdog->setChecked(m_runaway);
|
|
m_tx2QSO=m_settings->value("Tx2QSO",false).toBool();
|
|
ui->actionTx2QSO->setChecked(m_tx2QSO);
|
|
m_bMultipleOK=m_settings->value("MultipleOK",false).toBool();
|
|
ui->actionAllow_multiple_instances->setChecked(m_bMultipleOK);
|
|
m_bDTR=m_settings->value("DTR",false).toBool();
|
|
m_bRTS=m_settings->value("RTS",false).toBool(); m_pttData=m_settings->value("pttData",false).toBool();
|
|
m_poll=m_settings->value("Polling",0).toInt();
|
|
outBufSize=m_settings->value("OutBufSize",4096).toInt();
|
|
m_lockTxFreq=m_settings->value("LockTxFreq",false).toBool();
|
|
ui->cbTxLock->setChecked(m_lockTxFreq);
|
|
m_bSplit=m_settings->value("TxSplit",false).toBool();
|
|
m_bXIT=m_settings->value("UseXIT",false).toBool();
|
|
m_XIT=m_settings->value("XIT",0).toInt();
|
|
m_plus2kHz=m_settings->value("Plus2kHz",false).toBool();
|
|
ui->cbPlus2kHz->setChecked(m_plus2kHz);
|
|
m_settings->endGroup();
|
|
|
|
// use these initialisation settings to tune the audio o/p bufefr
|
|
// size and audio thread priority
|
|
m_settings->beginGroup ("Tune");
|
|
m_msAudioOutputBuffered = m_settings->value ("Audio/OutputBufferMs").toInt ();
|
|
m_framesAudioInputBuffered = m_settings->value ("Audio/InputBufferFrames", RX_SAMPLE_RATE / 10).toInt ();
|
|
m_audioThreadPriority = static_cast<QThread::Priority> (m_settings->value ("Audio/ThreadPriority", QThread::HighPriority).toInt () % 8);
|
|
m_settings->endGroup ();
|
|
|
|
if(m_ndepth==1) ui->actionQuickDecode->setChecked(true);
|
|
if(m_ndepth==2) ui->actionMediumDecode->setChecked(true);
|
|
if(m_ndepth==3) ui->actionDeepestDecode->setChecked(true);
|
|
|
|
statusChanged();
|
|
}
|
|
|
|
//-------------------------------------------------------------- dataSink()
|
|
void MainWindow::dataSink(qint64 frames)
|
|
{
|
|
static float s[NSMAX];
|
|
static int ihsym=0;
|
|
static int nzap=0;
|
|
static int trmin;
|
|
static int npts8;
|
|
static float px=0.0;
|
|
static float df3;
|
|
static float slope;
|
|
|
|
if(m_diskData) {
|
|
jt9com_.ndiskdat=1;
|
|
} else {
|
|
jt9com_.ndiskdat=0;
|
|
}
|
|
|
|
// Get power, spectrum, and ihsym
|
|
trmin=m_TRperiod/60;
|
|
slope=0.0;
|
|
slope=(float)m_wideGraph->getSlope();
|
|
int k (frames - 1);
|
|
symspec_(&k,&trmin,&m_nsps,&m_inGain,&slope,&px,s,&df3,&ihsym,&npts8);
|
|
if(ihsym <=0) return;
|
|
QString t;
|
|
m_pctZap=nzap*100.0/m_nsps;
|
|
t.sprintf(" Rx noise: %5.1f ",px);
|
|
signalMeter->setValue(px); // Update thermometer
|
|
if(m_monitoring || m_diskData) {
|
|
m_wideGraph->dataSink2(s,df3,ihsym,m_diskData);
|
|
}
|
|
|
|
if(ihsym == m_hsymStop) {
|
|
m_dataAvailable=true;
|
|
jt9com_.npts8=(ihsym*m_nsps)/16;
|
|
jt9com_.newdat=1;
|
|
jt9com_.nagain=0;
|
|
jt9com_.nzhsym=m_hsymStop;
|
|
QDateTime t = QDateTime::currentDateTimeUtc();
|
|
m_dateTime=t.toString("yyyy-MMM-dd hh:mm");
|
|
decode(); //Start decoder
|
|
if(!m_diskData) { //Always save; may delete later
|
|
int ihr=t.time().toString("hh").toInt();
|
|
int imin=t.time().toString("mm").toInt();
|
|
imin=imin - (imin%(m_TRperiod/60));
|
|
QString t2;
|
|
t2.sprintf("%2.2d%2.2d",ihr,imin);
|
|
m_fname=m_saveDir + "/" + t.date().toString("yyMMdd") + "_" +
|
|
t2 + ".wav";
|
|
*future2 = QtConcurrent::run(savewav, m_fname, m_TRperiod);
|
|
watcher2->setFuture(*future2);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::showSoundInError(const QString& errorMsg)
|
|
{QMessageBox::critical(this, tr("Error in SoundInput"), errorMsg);}
|
|
|
|
void MainWindow::showSoundOutError(const QString& errorMsg)
|
|
{QMessageBox::critical(this, tr("Error in SoundOutput"), errorMsg);}
|
|
|
|
void MainWindow::showStatusMessage(const QString& statusMsg)
|
|
{statusBar()->showMessage(statusMsg);}
|
|
|
|
void MainWindow::on_actionDeviceSetup_triggered() //Setup Dialog
|
|
{
|
|
DevSetup dlg(this);
|
|
dlg.m_myCall=m_myCall;
|
|
dlg.m_myGrid=m_myGrid;
|
|
dlg.m_idInt=m_idInt;
|
|
dlg.m_pttMethodIndex=m_pttMethodIndex;
|
|
dlg.m_pttPort=m_pttPort;
|
|
dlg.m_saveDir=m_saveDir;
|
|
dlg.m_audioInputDevice = m_audioInputDevice;
|
|
dlg.m_audioOutputDevice = m_audioOutputDevice;
|
|
dlg.m_audioInputChannel = m_audioInputChannel;
|
|
dlg.m_audioOutputChannel = m_audioOutputChannel;
|
|
dlg.m_pskReporter=m_pskReporter;
|
|
dlg.m_After73=m_After73;
|
|
dlg.m_macro=m_macro;
|
|
dlg.m_dFreq=m_dFreq;
|
|
dlg.m_antDescription=m_antDescription;
|
|
dlg.m_bandDescription=m_bandDescription;
|
|
dlg.m_catEnabled=m_catEnabled;
|
|
dlg.m_rig=m_rig;
|
|
dlg.m_rigIndex=m_rigIndex;
|
|
dlg.m_catPort=m_catPort;
|
|
dlg.m_catPortIndex=m_catPortIndex;
|
|
dlg.m_serialRate=m_serialRate;
|
|
dlg.m_serialRateIndex=m_serialRateIndex;
|
|
dlg.m_dataBits=m_dataBits;
|
|
dlg.m_dataBitsIndex=m_dataBitsIndex;
|
|
dlg.m_stopBits=m_stopBits;
|
|
dlg.m_stopBitsIndex=m_stopBitsIndex;
|
|
dlg.m_handshake=m_handshake;
|
|
dlg.m_handshakeIndex=m_handshakeIndex;
|
|
dlg.m_bDTR=m_bDTR;
|
|
dlg.m_bRTS=m_bRTS; dlg.m_pttData=m_pttData;
|
|
dlg.m_poll=m_poll;
|
|
dlg.m_bSplit=m_bSplit;
|
|
dlg.m_bXIT=m_bXIT;
|
|
|
|
if(m_bRigOpen) {
|
|
rig->close();
|
|
ui->readFreq->setStyleSheet("");
|
|
ui->readFreq->setEnabled(false);
|
|
if(m_rig<9900) delete rig;
|
|
m_bRigOpen=false;
|
|
m_catEnabled=false;
|
|
m_CATerror=false;
|
|
}
|
|
|
|
dlg.initDlg();
|
|
if(dlg.exec() == QDialog::Accepted) {
|
|
m_myCall=dlg.m_myCall;
|
|
m_myGrid=dlg.m_myGrid;
|
|
m_idInt=dlg.m_idInt;
|
|
m_pttMethodIndex=dlg.m_pttMethodIndex;
|
|
m_pttPort=dlg.m_pttPort;
|
|
m_saveDir=dlg.m_saveDir;
|
|
m_audioInputDevice = dlg.m_audioInputDevice;
|
|
m_audioOutputDevice = dlg.m_audioOutputDevice;
|
|
m_audioInputChannel = dlg.m_audioInputChannel;
|
|
m_audioOutputChannel = dlg.m_audioOutputChannel;
|
|
m_macro=dlg.m_macro;
|
|
m_dFreq=dlg.m_dFreq;
|
|
m_antDescription=dlg.m_antDescription;
|
|
m_bandDescription=dlg.m_bandDescription;
|
|
m_catEnabled=dlg.m_catEnabled;
|
|
m_rig=dlg.m_rig;
|
|
m_rigIndex=dlg.m_rigIndex;
|
|
m_catPort=dlg.m_catPort;
|
|
m_catPortIndex=dlg.m_catPortIndex;
|
|
m_serialRate=dlg.m_serialRate;
|
|
m_serialRateIndex=dlg.m_serialRateIndex;
|
|
m_dataBits=dlg.m_dataBits;
|
|
m_dataBitsIndex=dlg.m_dataBitsIndex;
|
|
m_stopBits=dlg.m_stopBits;
|
|
m_stopBitsIndex=dlg.m_stopBitsIndex;
|
|
m_handshake=dlg.m_handshake;
|
|
m_handshakeIndex=dlg.m_handshakeIndex;
|
|
m_bDTR=dlg.m_bDTR;
|
|
m_bRTS=dlg.m_bRTS;
|
|
m_pttData=dlg.m_pttData;
|
|
m_poll=dlg.m_poll;
|
|
|
|
//Band Settings
|
|
ui->bandComboBox->clear();
|
|
ui->bandComboBox->addItems(dlg.m_bandDescription);
|
|
ui->bandComboBox->setCurrentIndex(m_band);
|
|
m_pskReporter=dlg.m_pskReporter;
|
|
|
|
if(m_pskReporter) {
|
|
psk_Reporter->setLocalStation(m_myCall, m_myGrid, m_antDescription[m_band], "WSJT-X r" + rev.mid(6,4) );
|
|
}
|
|
|
|
m_After73=dlg.m_After73;
|
|
|
|
if(dlg.m_restartSoundIn) {
|
|
Q_EMIT stopAudioInputStream ();
|
|
Q_EMIT detectorClose ();
|
|
Q_EMIT startDetector (m_audioInputChannel);
|
|
Q_EMIT startAudioInputStream (m_audioInputDevice, AudioDevice::Mono == m_audioInputChannel ? 1 : 2, m_framesAudioInputBuffered, &m_detector);
|
|
}
|
|
|
|
if(dlg.m_restartSoundOut) {
|
|
Q_EMIT stopAudioOutputStream ();
|
|
Q_EMIT startAudioOutputStream (m_audioOutputDevice, AudioDevice::Mono == m_audioOutputChannel ? 1 : 2, m_msAudioOutputBuffered);
|
|
}
|
|
}
|
|
m_catEnabled=dlg.m_catEnabled;
|
|
|
|
if(m_catEnabled) {
|
|
rigOpen();
|
|
} else {
|
|
ui->readFreq->setStyleSheet("");
|
|
}
|
|
|
|
if(dlg.m_bSplit!=m_bSplit or dlg.m_bXIT!=m_bXIT) {
|
|
m_bSplit=dlg.m_bSplit;
|
|
if(m_bSplit) ui->readFreq->setText("S");
|
|
if(!m_bSplit) ui->readFreq->setText("");
|
|
m_bXIT=dlg.m_bXIT;
|
|
if(m_bSplit or m_bXIT) setXIT(m_txFreq);
|
|
if(m_bRigOpen and !m_bSplit) {
|
|
int ret=rig->setSplitFreq(MHz(m_dialFreq),RIG_VFO_B);
|
|
if(ret!=RIG_OK) {
|
|
QString rt;
|
|
rt.sprintf("Setting VFO_B failed: %d",ret);
|
|
msgBox(rt);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_monitorButton_clicked() //Monitor
|
|
{
|
|
m_monitoring=true;
|
|
Q_EMIT detectorSetMonitoring (true);
|
|
// Q_EMIT startAudioInputStream (m_audioInputDevice, AudioDevice::Mono == m_audioInputChannel ? 1 : 2, m_framesAudioInputBuffered, &m_detector);
|
|
m_diskData=false;
|
|
}
|
|
|
|
void MainWindow::on_actionAbout_triggered() //Display "About"
|
|
{
|
|
CAboutDlg dlg(this,Program_Title_Version);
|
|
dlg.exec();
|
|
}
|
|
|
|
void MainWindow::on_autoButton_clicked() //Auto
|
|
{
|
|
m_auto = !m_auto;
|
|
if(m_auto) {
|
|
ui->autoButton->setStyleSheet(m_pbAutoOn_style);
|
|
} else {
|
|
m_btxok=false;
|
|
Q_EMIT muteAudioOutput ();
|
|
ui->autoButton->setStyleSheet("");
|
|
on_monitorButton_clicked();
|
|
m_repeatMsg=0;
|
|
}
|
|
}
|
|
|
|
void MainWindow::keyPressEvent( QKeyEvent *e ) //keyPressEvent
|
|
{
|
|
int n;
|
|
switch(e->key())
|
|
{
|
|
case Qt::Key_1:
|
|
if(e->modifiers() & Qt::AltModifier) {
|
|
on_txb1_clicked();
|
|
break;
|
|
}
|
|
case Qt::Key_2:
|
|
if(e->modifiers() & Qt::AltModifier) {
|
|
on_txb2_clicked();
|
|
break;
|
|
}
|
|
case Qt::Key_3:
|
|
if(e->modifiers() & Qt::AltModifier) {
|
|
on_txb3_clicked();
|
|
break;
|
|
}
|
|
case Qt::Key_4:
|
|
if(e->modifiers() & Qt::AltModifier) {
|
|
on_txb4_clicked();
|
|
break;
|
|
}
|
|
case Qt::Key_5:
|
|
if(e->modifiers() & Qt::AltModifier) {
|
|
on_txb5_clicked();
|
|
break;
|
|
}
|
|
case Qt::Key_6:
|
|
if(e->modifiers() & Qt::AltModifier) {
|
|
on_txb6_clicked();
|
|
break;
|
|
}
|
|
case Qt::Key_D:
|
|
if(e->modifiers() & Qt::ShiftModifier) {
|
|
if(!m_decoderBusy) {
|
|
jt9com_.newdat=0;
|
|
jt9com_.nagain=0;
|
|
decode();
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case Qt::Key_F4:
|
|
ui->dxCallEntry->setText("");
|
|
ui->dxGridEntry->setText("");
|
|
genStdMsgs("");
|
|
m_ntx=6;
|
|
ui->txrb6->setChecked(true);
|
|
break;
|
|
case Qt::Key_F6:
|
|
if(e->modifiers() & Qt::ShiftModifier) {
|
|
on_actionDecode_remaining_files_in_directory_triggered();
|
|
}
|
|
break;
|
|
case Qt::Key_F11:
|
|
n=11;
|
|
if(e->modifiers() & Qt::ControlModifier) n+=100;
|
|
bumpFqso(n);
|
|
break;
|
|
case Qt::Key_F12:
|
|
n=12;
|
|
if(e->modifiers() & Qt::ControlModifier) n+=100;
|
|
bumpFqso(n);
|
|
break;
|
|
case Qt::Key_F:
|
|
if(e->modifiers() & Qt::ControlModifier) {
|
|
if(ui->tabWidget->currentIndex()==0) {
|
|
ui->tx5->clear();
|
|
ui->tx5->setFocus();
|
|
} else {
|
|
ui->freeTextMsg->clear();
|
|
ui->freeTextMsg->setFocus();
|
|
}
|
|
break;
|
|
}
|
|
case Qt::Key_G:
|
|
if(e->modifiers() & Qt::AltModifier) {
|
|
genStdMsgs(m_rpt);
|
|
break;
|
|
}
|
|
case Qt::Key_H:
|
|
if(e->modifiers() & Qt::AltModifier) {
|
|
on_stopTxButton_clicked();
|
|
break;
|
|
}
|
|
case Qt::Key_L:
|
|
if(e->modifiers() & Qt::ControlModifier) {
|
|
lookup();
|
|
genStdMsgs(m_rpt);
|
|
break;
|
|
}
|
|
case Qt::Key_V:
|
|
if(e->modifiers() & Qt::AltModifier) {
|
|
m_fileToSave=m_fname;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::bumpFqso(int n) //bumpFqso()
|
|
{
|
|
int i;
|
|
bool ctrl = (n>=100);
|
|
n=n%100;
|
|
i=m_wideGraph->rxFreq();
|
|
if(n==11) i--;
|
|
if(n==12) i++;
|
|
m_wideGraph->setRxFreq(i);
|
|
if(ctrl) {
|
|
ui->TxFreqSpinBox->setValue(i);
|
|
m_wideGraph->setTxFreq(i);
|
|
}
|
|
}
|
|
|
|
void MainWindow::dialFreqChanged2(double f)
|
|
{
|
|
m_dialFreq=f;
|
|
if(m_band<0 or m_band>15 or m_dFreq.length()<=1) return;
|
|
QString t;
|
|
t.sprintf("%.6f",m_dialFreq);
|
|
int n=t.length();
|
|
t=t.mid(0,n-3) + " " + t.mid(n-3,3);
|
|
double fBand=m_dFreq[m_band].toDouble();
|
|
if(qAbs(m_dialFreq-fBand)<0.01) {
|
|
ui->labDialFreq->setStyleSheet( \
|
|
"QLabel { background-color : black; color : yellow; }");
|
|
} else {
|
|
ui->labDialFreq->setStyleSheet( \
|
|
"QLabel { background-color : red; color : yellow; }");
|
|
ui->labDialFreq->setText(t);
|
|
}
|
|
ui->labDialFreq->setText(t);
|
|
statusChanged();
|
|
m_wideGraph->setDialFreq(m_dialFreq);
|
|
}
|
|
|
|
void MainWindow::statusChanged()
|
|
{
|
|
QFile f("wsjtx_status.txt");
|
|
if(f.open(QFile::WriteOnly | QIODevice::Text)) {
|
|
QTextStream out(&f);
|
|
out << m_dialFreq << ";" << m_mode << ";" << m_hisCall << ";"
|
|
<< ui->rptSpinBox->value() << ";" << m_modeTx << endl;
|
|
f.close();
|
|
} else {
|
|
msgBox("Cannot open file \"wsjtx_status.txt\".");
|
|
return;
|
|
}
|
|
}
|
|
|
|
bool MainWindow::eventFilter(QObject *object, QEvent *event) //eventFilter()
|
|
{
|
|
if (event->type() == QEvent::KeyPress) {
|
|
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
|
MainWindow::keyPressEvent(keyEvent);
|
|
return QObject::eventFilter(object, event);
|
|
}
|
|
return QObject::eventFilter(object, event);
|
|
}
|
|
|
|
void MainWindow::createStatusBar() //createStatusBar
|
|
{
|
|
lab1 = new QLabel("Receiving");
|
|
lab1->setAlignment(Qt::AlignHCenter);
|
|
lab1->setMinimumSize(QSize(80,18));
|
|
lab1->setStyleSheet("QLabel{background-color: #00ff00}");
|
|
lab1->setFrameStyle(QFrame::Panel | QFrame::Sunken);
|
|
statusBar()->addWidget(lab1);
|
|
|
|
|
|
lab2 = new QLabel("");
|
|
lab2->setAlignment(Qt::AlignHCenter);
|
|
lab2->setMinimumSize(QSize(80,18));
|
|
lab2->setFrameStyle(QFrame::Panel | QFrame::Sunken);
|
|
statusBar()->addWidget(lab2);
|
|
|
|
lab3 = new QLabel("");
|
|
lab3->setAlignment(Qt::AlignHCenter);
|
|
lab3->setMinimumSize(QSize(150,18));
|
|
lab3->setFrameStyle(QFrame::Panel | QFrame::Sunken);
|
|
statusBar()->addWidget(lab3);
|
|
}
|
|
|
|
void MainWindow::on_actionExit_triggered() //Exit()
|
|
{
|
|
OnExit();
|
|
}
|
|
|
|
void MainWindow::closeEvent(QCloseEvent * e)
|
|
{
|
|
writeSettings ();
|
|
OnExit();
|
|
QMainWindow::closeEvent (e);
|
|
}
|
|
|
|
void MainWindow::OnExit()
|
|
{
|
|
m_guiTimer.stop ();
|
|
if(m_fname != "") killFile();
|
|
m_killAll=true;
|
|
mem_jt9->detach();
|
|
QFile quitFile(m_appDir + "/.quit");
|
|
quitFile.open(QIODevice::ReadWrite);
|
|
QFile lockFile(m_appDir + "/.lock");
|
|
lockFile.remove(); // Allow jt9 to terminate
|
|
bool b=proc_jt9.waitForFinished(1000);
|
|
if(!b) proc_jt9.kill();
|
|
quitFile.remove();
|
|
|
|
Q_EMIT finished ();
|
|
m_audioThread.wait ();
|
|
}
|
|
|
|
void MainWindow::on_stopButton_clicked() //stopButton
|
|
{
|
|
m_monitoring=false;
|
|
Q_EMIT detectorSetMonitoring (m_monitoring);
|
|
m_loopall=false;
|
|
}
|
|
|
|
void MainWindow::msgBox(QString t) //msgBox
|
|
{
|
|
msgBox0.setText(t);
|
|
msgBox0.exec();
|
|
}
|
|
|
|
void MainWindow::on_actionOnline_Users_Guide_triggered() //Display manual
|
|
{
|
|
QDesktopServices::openUrl(QUrl(
|
|
"http://www.physics.princeton.edu/pulsar/K1JT/WSJT-X_Users_Guide_v1.2.pdf",
|
|
QUrl::TolerantMode));
|
|
}
|
|
|
|
void MainWindow::on_actionWide_Waterfall_triggered() //Display Waterfalls
|
|
{
|
|
m_wideGraph->show();
|
|
}
|
|
|
|
void MainWindow::on_actionOpen_triggered() //Open File
|
|
{
|
|
m_monitoring=false;
|
|
Q_EMIT detectorSetMonitoring (m_monitoring);
|
|
QString fname;
|
|
fname=QFileDialog::getOpenFileName(this, "Open File", m_path,
|
|
"WSJT Files (*.wav)");
|
|
if(fname != "") {
|
|
m_path=fname;
|
|
int i;
|
|
i=fname.indexOf(".wav") - 11;
|
|
if(i>=0) {
|
|
lab1->setStyleSheet("QLabel{background-color: #66ff66}");
|
|
lab1->setText(" " + fname.mid(i,15) + " ");
|
|
}
|
|
on_stopButton_clicked();
|
|
m_diskData=true;
|
|
*future1 = QtConcurrent::run(getfile, fname, m_TRperiod);
|
|
watcher1->setFuture(*future1); // call diskDat() when done
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_actionOpen_next_in_directory_triggered() //Open Next
|
|
{
|
|
int i,len;
|
|
QFileInfo fi(m_path);
|
|
QStringList list;
|
|
list= fi.dir().entryList().filter(".wav");
|
|
for (i = 0; i < list.size()-1; ++i) {
|
|
if(i==list.size()-2) m_loopall=false;
|
|
len=list.at(i).length();
|
|
if(list.at(i)==m_path.right(len)) {
|
|
int n=m_path.length();
|
|
QString fname=m_path.replace(n-len,len,list.at(i+1));
|
|
m_path=fname;
|
|
int i;
|
|
i=fname.indexOf(".wav") - 11;
|
|
if(i>=0) {
|
|
lab1->setStyleSheet("QLabel{background-color: #66ff66}");
|
|
lab1->setText(" " + fname.mid(i,len) + " ");
|
|
}
|
|
m_diskData=true;
|
|
*future1 = QtConcurrent::run(getfile, fname, m_TRperiod);
|
|
watcher1->setFuture(*future1);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
//Open all remaining files
|
|
void MainWindow::on_actionDecode_remaining_files_in_directory_triggered()
|
|
{
|
|
m_loopall=true;
|
|
on_actionOpen_next_in_directory_triggered();
|
|
}
|
|
|
|
void MainWindow::diskDat() //diskDat()
|
|
{
|
|
int k;
|
|
int kstep=m_nsps/2;
|
|
m_diskData=true;
|
|
for(int n=1; n<=m_hsymStop; n++) { // Do the half-symbol FFTs
|
|
k=(n+1)*kstep;
|
|
jt9com_.npts8=k/8;
|
|
dataSink(k * sizeof (jt9com_.d2[0]));
|
|
if(n%10 == 1 or n == m_hsymStop)
|
|
qApp->processEvents(); //Keep GUI responsive
|
|
}
|
|
}
|
|
|
|
void MainWindow::diskWriteFinished() //diskWriteFinished
|
|
{
|
|
}
|
|
|
|
//Delete ../save/*.wav
|
|
void MainWindow::on_actionDelete_all_wav_files_in_SaveDir_triggered()
|
|
{
|
|
int i;
|
|
QString fname;
|
|
int ret = QMessageBox::warning(this, "Confirm Delete",
|
|
"Are you sure you want to delete all *.wav files in\n" +
|
|
QDir::toNativeSeparators(m_saveDir) + " ?",
|
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
|
if(ret==QMessageBox::Yes) {
|
|
QDir dir(m_saveDir);
|
|
QStringList files=dir.entryList(QDir::Files);
|
|
QList<QString>::iterator f;
|
|
for(f=files.begin(); f!=files.end(); ++f) {
|
|
fname=*f;
|
|
i=(fname.indexOf(".wav"));
|
|
if(i>10) dir.remove(fname);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_actionNone_triggered() //Save None
|
|
{
|
|
m_saveDecoded=false;
|
|
m_saveAll=false;
|
|
ui->actionNone->setChecked(true);
|
|
}
|
|
|
|
void MainWindow::on_actionSave_decoded_triggered()
|
|
{
|
|
m_saveDecoded=true;
|
|
m_saveAll=false;
|
|
ui->actionSave_decoded->setChecked(true);
|
|
}
|
|
|
|
void MainWindow::on_actionSave_all_triggered() //Save All
|
|
{
|
|
m_saveDecoded=false;
|
|
m_saveAll=true;
|
|
ui->actionSave_all->setChecked(true);
|
|
}
|
|
|
|
void MainWindow::on_actionKeyboard_shortcuts_triggered()
|
|
{
|
|
pShortcuts = new QTextEdit(0);
|
|
pShortcuts->setReadOnly(true);
|
|
pShortcuts->setFontPointSize(10);
|
|
pShortcuts->setWindowTitle("Keyboard Shortcuts");
|
|
pShortcuts->setGeometry(QRect(45,50,430,460));
|
|
Qt::WindowFlags flags = Qt::WindowCloseButtonHint |
|
|
Qt::WindowMinimizeButtonHint;
|
|
pShortcuts->setWindowFlags(flags);
|
|
QString shortcuts = m_appDir + "/shortcuts.txt";
|
|
QFile f(shortcuts);
|
|
if(!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
msgBox("Cannot open " + shortcuts);
|
|
return;
|
|
}
|
|
QTextStream s(&f);
|
|
QString t;
|
|
for(int i=0; i<100; i++) {
|
|
t=s.readLine();
|
|
pShortcuts->append(t);
|
|
if(s.atEnd()) break;
|
|
}
|
|
pShortcuts->show();
|
|
}
|
|
|
|
void MainWindow::on_actionSpecial_mouse_commands_triggered()
|
|
{
|
|
QTextEdit* pMouseCmnds;
|
|
pMouseCmnds = new QTextEdit(0);
|
|
pMouseCmnds->setReadOnly(true);
|
|
pMouseCmnds->setFontPointSize(10);
|
|
pMouseCmnds->setWindowTitle("Special Mouse Commands");
|
|
pMouseCmnds->setGeometry(QRect(45,50,440,300));
|
|
Qt::WindowFlags flags = Qt::WindowCloseButtonHint |
|
|
Qt::WindowMinimizeButtonHint;
|
|
pMouseCmnds->setWindowFlags(flags);
|
|
QString mouseCmnds = m_appDir + "/mouse_commands.txt";
|
|
QFile f(mouseCmnds);
|
|
if(!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
msgBox("Cannot open " + mouseCmnds);
|
|
return;
|
|
}
|
|
QTextStream s(&f);
|
|
QString t;
|
|
for(int i=0; i<100; i++) {
|
|
t=s.readLine();
|
|
pMouseCmnds->append(t);
|
|
if(s.atEnd()) break;
|
|
}
|
|
pMouseCmnds->show();
|
|
}
|
|
|
|
void MainWindow::on_DecodeButton_clicked() //Decode request
|
|
{
|
|
if(!m_decoderBusy) {
|
|
jt9com_.newdat=0;
|
|
jt9com_.nagain=1;
|
|
m_blankLine=false; // don't insert the separator again
|
|
decode();
|
|
}
|
|
}
|
|
|
|
void MainWindow::freezeDecode(int n) //freezeDecode()
|
|
{
|
|
bool ctrl = (n>=100);
|
|
int i=m_wideGraph->rxFreq();
|
|
if(ctrl) {
|
|
ui->TxFreqSpinBox->setValue(i);
|
|
m_wideGraph->setTxFreq(i);
|
|
}
|
|
if((n%100)==2) on_DecodeButton_clicked();
|
|
}
|
|
|
|
void MainWindow::decode() //decode()
|
|
{
|
|
if(!m_dataAvailable) return;
|
|
ui->DecodeButton->setStyleSheet(m_pbdecoding_style1);
|
|
if(jt9com_.newdat==1 && (!m_diskData)) {
|
|
qint64 ms = QDateTime::currentMSecsSinceEpoch() % 86400000;
|
|
int imin=ms/60000;
|
|
int ihr=imin/60;
|
|
imin=imin % 60;
|
|
imin=imin - (imin % (m_TRperiod/60));
|
|
jt9com_.nutc=100*ihr + imin;
|
|
}
|
|
|
|
jt9com_.nfqso=m_wideGraph->rxFreq();
|
|
jt9com_.ndepth=m_ndepth;
|
|
jt9com_.ndiskdat=0;
|
|
if(m_diskData) jt9com_.ndiskdat=1;
|
|
jt9com_.nfa=m_wideGraph->nStartFreq();
|
|
jt9com_.nfSplit=m_wideGraph->getFmin();
|
|
jt9com_.nfb=m_wideGraph->getFmax();
|
|
jt9com_.ntol=20;
|
|
if(jt9com_.nutc < m_nutc0) m_RxLog |= 1; //Date and Time to all.txt
|
|
m_nutc0=jt9com_.nutc;
|
|
jt9com_.ntxmode=9;
|
|
if(m_modeTx=="JT65") jt9com_.ntxmode=65;
|
|
jt9com_.nmode=9;
|
|
if(m_mode=="JT65") jt9com_.nmode=65;
|
|
if(m_mode=="JT9+JT65") jt9com_.nmode=9+65;
|
|
jt9com_.ntrperiod=m_TRperiod;
|
|
m_nsave=0;
|
|
if(m_saveDecoded) m_nsave=2;
|
|
jt9com_.nsave=m_nsave;
|
|
strncpy(jt9com_.datetime, m_dateTime.toLatin1(), 20);
|
|
|
|
//newdat=1 ==> this is new data, must do the big FFT
|
|
//nagain=1 ==> decode only at fQSO +/- Tol
|
|
|
|
char *to = (char*)mem_jt9->data();
|
|
char *from = (char*) jt9com_.ss;
|
|
int size=sizeof(jt9com_);
|
|
if(jt9com_.newdat==0) {
|
|
int noffset = 4*184*NSMAX + 4*NSMAX + 2*NTMAX*12000;
|
|
to += noffset;
|
|
from += noffset;
|
|
size -= noffset;
|
|
}
|
|
memcpy(to, from, qMin(mem_jt9->size(), size));
|
|
|
|
QFile lockFile(m_appDir + "/.lock"); // Allow jt9 to start
|
|
lockFile.remove();
|
|
decodeBusy(true);
|
|
}
|
|
|
|
void MainWindow::jt9_error(QProcess::ProcessError e) //jt9_error
|
|
{
|
|
if(!m_killAll) {
|
|
msgBox("Error starting or running\n" + m_appDir + "/jt9 -s");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
void MainWindow::readFromStderr() //readFromStderr
|
|
{
|
|
QByteArray t=proc_jt9.readAllStandardError();
|
|
msgBox(t);
|
|
}
|
|
|
|
void MainWindow::readFromStdout() //readFromStdout
|
|
{
|
|
while(proc_jt9.canReadLine())
|
|
{
|
|
QByteArray t=proc_jt9.readLine();
|
|
if(t.indexOf("<DecodeFinished>") >= 0)
|
|
{
|
|
m_bdecoded = (t.mid(23,1).toInt()==1);
|
|
bool keepFile=m_saveAll or (m_saveDecoded and m_bdecoded);
|
|
if(!keepFile and !m_diskData) killFileTimer->start(45*1000); //Kill in 45 s
|
|
jt9com_.nagain=0;
|
|
jt9com_.ndiskdat=0;
|
|
QFile lockFile(m_appDir + "/.lock");
|
|
lockFile.open(QIODevice::ReadWrite);
|
|
ui->DecodeButton->setStyleSheet("");
|
|
decodeBusy(false);
|
|
m_RxLog=0;
|
|
m_startAnother=m_loopall;
|
|
m_blankLine=true;
|
|
return;
|
|
} else {
|
|
QFile f("ALL.TXT");
|
|
f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
|
|
QTextStream out(&f);
|
|
if(m_RxLog && 1) {
|
|
out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm")
|
|
<< " " << m_dialFreq << " MHz " << m_mode << endl;
|
|
m_RxLog=0;
|
|
}
|
|
int n=t.length();
|
|
out << t.mid(0,n-2) << endl;
|
|
f.close();
|
|
|
|
if(m_insertBlank and m_blankLine)
|
|
{
|
|
ui->decodedTextBrowser->insertLineSpacer();
|
|
m_blankLine=false;
|
|
}
|
|
|
|
DecodedText decodedtext;
|
|
decodedtext = t.replace("\n",""); //t.replace("\n","").mid(0,t.length()-4);
|
|
|
|
// the left band display
|
|
ui->decodedTextBrowser->displayDecodedText(decodedtext,m_myCall,m_displayDXCCEntity,m_logBook);
|
|
|
|
if (abs(decodedtext.frequencyOffset() - m_wideGraph->rxFreq()) <= 10) // this msg is within 10 hertz of our tuned frequency
|
|
{
|
|
// the right QSO window
|
|
ui->decodedTextBrowser2->displayDecodedText(decodedtext,m_myCall,false,m_logBook);
|
|
|
|
bool b65=decodedtext.isJT65();
|
|
if(b65 and m_modeTx!="JT65") on_pbTxMode_clicked();
|
|
if(!b65 and m_modeTx=="JT65") on_pbTxMode_clicked();
|
|
m_QSOText=decodedtext;
|
|
}
|
|
|
|
// find and extract any report for myCall
|
|
bool stdMsg = decodedtext.report(m_myCall,/*mod*/m_rptRcvd);
|
|
|
|
// extract details and send to PSKreporter
|
|
int nsec=QDateTime::currentMSecsSinceEpoch()/1000-m_secBandChanged;
|
|
bool okToPost=(nsec>50);
|
|
if(m_pskReporter and stdMsg and !m_diskData and okToPost)
|
|
{
|
|
QString msgmode="JT9";
|
|
if (decodedtext.isJT65())
|
|
msgmode="JT65";
|
|
|
|
QString deCall;
|
|
QString grid;
|
|
decodedtext.deCallAndGrid(/*out*/deCall,grid);
|
|
int audioFrequency = decodedtext.frequencyOffset();
|
|
int snr = decodedtext.snr();
|
|
uint frequency = 1000000.0*m_dialFreq + audioFrequency + 0.5;
|
|
|
|
psk_Reporter->setLocalStation(m_myCall, m_myGrid, m_antDescription[m_band], "WSJT-X r" + rev.mid(6,4) );
|
|
if(gridOK(grid))
|
|
psk_Reporter->addRemoteStation(deCall,grid,QString::number(frequency),msgmode,QString::number(snr),
|
|
QString::number(QDateTime::currentDateTime().toTime_t()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::killFile()
|
|
{
|
|
if(m_fname==m_fileToSave) {
|
|
} else {
|
|
QFile savedFile(m_fname);
|
|
savedFile.remove();
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_EraseButton_clicked() //Erase
|
|
{
|
|
qint64 ms=QDateTime::currentMSecsSinceEpoch();
|
|
ui->decodedTextBrowser2->clear();
|
|
m_QSOText.clear();
|
|
if((ms-m_msErase)<500) {
|
|
ui->decodedTextBrowser->clear();
|
|
QFile f(m_appDir + "/decoded.txt");
|
|
if(f.exists()) f.remove();
|
|
}
|
|
m_msErase=ms;
|
|
}
|
|
|
|
void MainWindow::decodeBusy(bool b) //decodeBusy()
|
|
{
|
|
m_decoderBusy=b;
|
|
ui->DecodeButton->setEnabled(!b);
|
|
ui->actionOpen->setEnabled(!b);
|
|
ui->actionOpen_next_in_directory->setEnabled(!b);
|
|
ui->actionDecode_remaining_files_in_directory->setEnabled(!b);
|
|
}
|
|
|
|
//------------------------------------------------------------- //guiUpdate()
|
|
void MainWindow::guiUpdate()
|
|
{
|
|
static int iptt0=0;
|
|
static bool btxok0=false;
|
|
static char message[29];
|
|
static char msgsent[29];
|
|
static int nsendingsh=0;
|
|
static int giptt00=-1;
|
|
static int gcomport00=-1;
|
|
static double onAirFreq0=0.0;
|
|
int ret=0;
|
|
QString rt;
|
|
|
|
double tx1=0.0;
|
|
double tx2=1.0 + 85.0*m_nsps/12000.0 + icw[0]*2560.0/48000.0;
|
|
if(m_modeTx=="JT65") tx2=1.0 + 126*4096/11025.0 + icw[0]*2560.0/48000.0;
|
|
|
|
if(!m_txFirst) {
|
|
tx1 += m_TRperiod;
|
|
tx2 += m_TRperiod;
|
|
}
|
|
qint64 ms = QDateTime::currentMSecsSinceEpoch() % 86400000;
|
|
int nsec=ms/1000;
|
|
double tsec=0.001*ms;
|
|
double t2p=fmod(tsec,2*m_TRperiod);
|
|
bool bTxTime = ((t2p >= tx1) and (t2p < tx2)) or m_tune;
|
|
|
|
if(m_auto or m_tune) {
|
|
QFile f("txboth");
|
|
if(f.exists() and fmod(tsec,m_TRperiod) < (1.0 + 85.0*m_nsps/12000.0)) {
|
|
bTxTime=true;
|
|
}
|
|
|
|
double onAirFreq=m_dialFreq+1.e-6*m_txFreq;
|
|
if(onAirFreq>10.139900 and onAirFreq<10.140320) {
|
|
bTxTime=false;
|
|
if(m_tune) on_tuneButton_clicked();
|
|
if(onAirFreq!=onAirFreq0) {
|
|
onAirFreq0=onAirFreq;
|
|
on_autoButton_clicked();
|
|
QString t="Please choose another Tx frequency.\n";
|
|
t+="WSJT-X will not knowingly transmit\n";
|
|
t+="in the WSPR sub-band on 30 m.";
|
|
msgBox0.setText(t);
|
|
msgBox0.show();
|
|
}
|
|
}
|
|
|
|
float fTR=float((nsec%m_TRperiod))/m_TRperiod;
|
|
if(g_iptt==0 and ((bTxTime and !m_btxMute and fTR<0.4) or m_tune )) {
|
|
icw[0]=m_ncw;
|
|
|
|
//Raise PTT
|
|
if(m_catEnabled and m_bRigOpen and m_pttMethodIndex==0) {
|
|
g_iptt=1;
|
|
if(m_pttData) ret=rig->setPTT(RIG_PTT_ON_DATA, RIG_VFO_CURR);
|
|
if(!m_pttData) ret=rig->setPTT(RIG_PTT_ON_MIC, RIG_VFO_CURR);
|
|
if(ret!=RIG_OK) {
|
|
rt.sprintf("CAT control PTT failed: %d",ret);
|
|
msgBox(rt);
|
|
}
|
|
|
|
}
|
|
|
|
if(m_pttMethodIndex==1 or m_pttMethodIndex==2) { //DTR or RTS
|
|
ptt(m_pttPort,1,&g_iptt,&g_COMportOpen);
|
|
}
|
|
if(m_pttMethodIndex==3) { //VOX
|
|
g_iptt=1;
|
|
}
|
|
ptt1Timer->start(200); //Sequencer delay
|
|
}
|
|
if(!bTxTime || m_btxMute) {
|
|
m_btxok=false;
|
|
Q_EMIT muteAudioOutput ();
|
|
}
|
|
}
|
|
|
|
// Calculate Tx tones when needed
|
|
if((g_iptt==1 && iptt0==0) || m_restart) {
|
|
QByteArray ba;
|
|
if(m_ntx == 1) ba=ui->tx1->text().toLocal8Bit();
|
|
if(m_ntx == 2) ba=ui->tx2->text().toLocal8Bit();
|
|
if(m_ntx == 3) ba=ui->tx3->text().toLocal8Bit();
|
|
if(m_ntx == 4) ba=ui->tx4->text().toLocal8Bit();
|
|
if(m_ntx == 5) ba=ui->tx5->text().toLocal8Bit();
|
|
if(m_ntx == 6) ba=ui->tx6->text().toLocal8Bit();
|
|
if(m_ntx == 7) ba=ui->genMsg->text().toLocal8Bit();
|
|
if(m_ntx == 8) ba=ui->freeTextMsg->text().toLocal8Bit();
|
|
|
|
ba2msg(ba,message);
|
|
// ba2msg(ba,msgsent);
|
|
int len1=22;
|
|
int ichk=0,itext=0;
|
|
if(m_modeTx=="JT9") genjt9_(message,&ichk,msgsent,itone,&itext,len1,len1);
|
|
if(m_modeTx=="JT65") gen65_(message,&ichk,msgsent,itone,&itext,len1,len1);
|
|
msgsent[22]=0;
|
|
QString t=QString::fromLatin1(msgsent);
|
|
if(m_tune) t="TUNE";
|
|
lab3->setText("Last Tx: " + t);
|
|
if(m_restart) {
|
|
QFile f("ALL.TXT");
|
|
f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
|
|
QTextStream out(&f);
|
|
out << QDateTime::currentDateTimeUtc().toString("hhmm")
|
|
<< " Transmitting " << m_dialFreq << " MHz " << m_modeTx
|
|
<< ": " << t << endl;
|
|
f.close();
|
|
if(m_tx2QSO)
|
|
ui->decodedTextBrowser2->displayTransmittedText(t,m_modeTx,m_txFreq);
|
|
}
|
|
|
|
QStringList w=t.split(" ",QString::SkipEmptyParts);
|
|
t="";
|
|
if(w.length()==3) t=w[2];
|
|
icw[0]=0;
|
|
m_sent73=(t=="73" or itext!=0);
|
|
if(m_sent73) {
|
|
if(m_After73) icw[0]=m_ncw;
|
|
if(m_promptToLog and !m_tune) logQSOTimer->start(200);
|
|
}
|
|
|
|
if(m_idInt>0) {
|
|
int nmin=(m_sec0-m_secID)/60;
|
|
if(nmin >= m_idInt) {
|
|
icw[0]=m_ncw;
|
|
m_secID=m_sec0;
|
|
}
|
|
}
|
|
|
|
QString t2=QDateTime::currentDateTimeUtc().toString("hhmm");
|
|
if(itext==0 and w.length()>=3 and w[1]==m_myCall) {
|
|
int i1;
|
|
bool ok;
|
|
i1=t.toInt(&ok);
|
|
if(ok and i1>=-50 and i1<50) {
|
|
m_rptSent=t;
|
|
m_qsoStart=t2;
|
|
} else {
|
|
if(t.mid(0,1)=="R") {
|
|
i1=t.mid(1).toInt(&ok);
|
|
if(ok and i1>=-50 and i1<50) {
|
|
m_rptSent=t.mid(1);
|
|
m_qsoStart=t2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(itext==1 or (w.length()==3 and w[2]=="73")) m_qsoStop=t2;
|
|
m_restart=false;
|
|
}
|
|
|
|
|
|
// If PTT was just raised, start a countdown for raising TxOK:
|
|
// NB: could be better implemented with a timer
|
|
if(g_iptt == 1 && iptt0 == 0) {
|
|
nc1=-9; // TxDelay = 0.8 s
|
|
}
|
|
if(nc1 <= 0) {
|
|
nc1++;
|
|
}
|
|
if(nc1 == 0) {
|
|
QString t=QString::fromLatin1(msgsent);
|
|
if(t==m_msgSent0) {
|
|
m_repeatMsg++;
|
|
} else {
|
|
m_repeatMsg=0;
|
|
m_msgSent0=t;
|
|
}
|
|
|
|
signalMeter->setValue(0);
|
|
m_monitoring=false;
|
|
Q_EMIT detectorSetMonitoring (false);
|
|
m_btxok=true;
|
|
Q_EMIT muteAudioOutput (false);
|
|
m_transmitting=true;
|
|
ui->pbTxMode->setEnabled(false);
|
|
if(!m_tune) {
|
|
QFile f("ALL.TXT");
|
|
f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
|
|
QTextStream out(&f);
|
|
out << QDateTime::currentDateTimeUtc().toString("hhmm")
|
|
<< " Transmitting " << m_dialFreq << " MHz " << m_modeTx
|
|
<< ": " << t << endl;
|
|
f.close();
|
|
}
|
|
if(m_tx2QSO and !m_tune)
|
|
ui->decodedTextBrowser2->displayTransmittedText(t,m_modeTx,m_txFreq);
|
|
}
|
|
|
|
if(!m_btxok && btxok0 && g_iptt==1) stopTx();
|
|
|
|
/*
|
|
// If m_btxok was just lowered, start a countdown for lowering PTT
|
|
if(!m_btxok && btxok0 && g_iptt==1) nc0=-11; //RxDelay = 1.0 s
|
|
if(nc0 <= 0) {
|
|
nc0++;
|
|
}
|
|
*/
|
|
|
|
if(m_monitoring) {
|
|
ui->monitorButton->setStyleSheet(m_pbmonitor_style);
|
|
} else {
|
|
ui->monitorButton->setStyleSheet("");
|
|
}
|
|
|
|
if(m_startAnother) {
|
|
m_startAnother=false;
|
|
on_actionOpen_next_in_directory_triggered();
|
|
}
|
|
|
|
if(m_catEnabled and !m_bRigOpen) {
|
|
rigOpen();
|
|
if(m_bSplit or m_bXIT) setXIT(m_txFreq);
|
|
if(m_bRigOpen and !m_bSplit) {
|
|
int ret=rig->setSplitFreq(MHz(m_dialFreq),RIG_VFO_B);
|
|
if(ret!=RIG_OK) {
|
|
QString rt;
|
|
rt.sprintf("Setting VFO_B failed: %d",ret);
|
|
msgBox(rt);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(nsec != m_sec0) { //Once per second
|
|
QDateTime t = QDateTime::currentDateTimeUtc();
|
|
if(m_transmitting) {
|
|
if(nsendingsh==1) {
|
|
lab1->setStyleSheet("QLabel{background-color: #66ffff}");
|
|
} else if(nsendingsh==-1) {
|
|
lab1->setStyleSheet("QLabel{background-color: #ffccff}");
|
|
} else {
|
|
lab1->setStyleSheet("QLabel{background-color: #ffff33}");
|
|
}
|
|
if(m_tune) {
|
|
lab1->setText("Tx: TUNE");
|
|
} else {
|
|
char s[37];
|
|
sprintf(s,"Tx: %s",msgsent);
|
|
lab1->setText(s);
|
|
}
|
|
} else if(m_monitoring) {
|
|
lab1->setStyleSheet("QLabel{background-color: #00ff00}");
|
|
lab1->setText("Receiving ");
|
|
} else if (!m_diskData) {
|
|
lab1->setStyleSheet("");
|
|
lab1->setText("");
|
|
}
|
|
|
|
m_setftx=0;
|
|
QString utc = t.date().toString("yyyy MMM dd") + "\n " +
|
|
t.time().toString() + " ";
|
|
ui->labUTC->setText(utc);
|
|
if(!m_monitoring and !m_diskData) {
|
|
signalMeter->setValue(0);
|
|
}
|
|
|
|
if(m_catEnabled and m_poll>0 and (nsec%m_poll)==0 and
|
|
!m_decoderBusy) pollRigFreq();
|
|
m_sec0=nsec;
|
|
}
|
|
|
|
if(g_iptt!=giptt00 or g_COMportOpen!=gcomport00) {
|
|
giptt00=g_iptt;
|
|
gcomport00=g_COMportOpen;
|
|
}
|
|
|
|
iptt0=g_iptt;
|
|
btxok0=m_btxok;
|
|
} //End of GUIupdate
|
|
|
|
|
|
void MainWindow::startTx2()
|
|
{
|
|
if (!m_modulator.isActive ()) {
|
|
QString t=ui->tx6->text();
|
|
double snr=t.mid(1,5).toDouble();
|
|
if(snr>0.0 or snr < -50.0) snr=99.0;
|
|
transmit (snr);
|
|
signalMeter->setValue(0);
|
|
m_monitoring=false;
|
|
Q_EMIT detectorSetMonitoring (false);
|
|
m_btxok=true;
|
|
Q_EMIT muteAudioOutput (false);
|
|
m_transmitting=true;
|
|
ui->pbTxMode->setEnabled(false);
|
|
}
|
|
}
|
|
|
|
void MainWindow::stopTx()
|
|
{
|
|
Q_EMIT endTransmitMessage ();
|
|
Q_EMIT stopAudioOutputStream ();
|
|
m_transmitting=false;
|
|
ui->pbTxMode->setEnabled(true);
|
|
g_iptt=0;
|
|
lab1->setStyleSheet("");
|
|
lab1->setText("");
|
|
ptt0Timer->start(200); //Sequencer delay
|
|
m_monitoring=true;
|
|
Q_EMIT detectorSetMonitoring (true);
|
|
}
|
|
|
|
void MainWindow::stopTx2()
|
|
{
|
|
int ret=0;
|
|
QString rt;
|
|
|
|
//Lower PTT
|
|
if(m_catEnabled and m_bRigOpen and m_pttMethodIndex==0) {
|
|
ret=rig->setPTT(RIG_PTT_OFF, RIG_VFO_CURR); //CAT control for PTT=0
|
|
if(ret!=RIG_OK) {
|
|
rt.sprintf("CAT control PTT failed: %d",ret);
|
|
msgBox(rt);
|
|
}
|
|
}
|
|
if(m_pttMethodIndex==1 or m_pttMethodIndex==2) {
|
|
ptt(m_pttPort,0,&g_iptt,&g_COMportOpen);
|
|
}
|
|
if(m_73TxDisable and m_sent73) on_stopTxButton_clicked();
|
|
|
|
if(m_runaway and m_repeatMsg>m_watchdogLimit) {
|
|
on_stopTxButton_clicked();
|
|
msgBox0.setText("Runaway Tx watchdog");
|
|
msgBox0.show();
|
|
m_repeatMsg=0;
|
|
}
|
|
}
|
|
|
|
void MainWindow::ba2msg(QByteArray ba, char message[]) //ba2msg()
|
|
{
|
|
int iz=ba.length();
|
|
for(int i=0;i<22; i++) {
|
|
if(i<iz) {
|
|
message[i]=ba[i];
|
|
} else {
|
|
message[i]=32;
|
|
}
|
|
}
|
|
message[22]=0;
|
|
}
|
|
|
|
void MainWindow::on_txFirstCheckBox_stateChanged(int nstate) //TxFirst
|
|
{
|
|
m_txFirst = (nstate==2);
|
|
}
|
|
|
|
void MainWindow::set_ntx(int n) //set_ntx()
|
|
{
|
|
m_ntx=n;
|
|
}
|
|
|
|
void MainWindow::on_txb1_clicked() //txb1
|
|
{
|
|
m_ntx=1;
|
|
ui->txrb1->setChecked(true);
|
|
m_restart=true;
|
|
}
|
|
|
|
void MainWindow::on_txb2_clicked() //txb2
|
|
{
|
|
m_ntx=2;
|
|
ui->txrb2->setChecked(true);
|
|
m_restart=true;
|
|
}
|
|
|
|
void MainWindow::on_txb3_clicked() //txb3
|
|
{
|
|
m_ntx=3;
|
|
ui->txrb3->setChecked(true);
|
|
m_restart=true;
|
|
}
|
|
|
|
void MainWindow::on_txb4_clicked() //txb4
|
|
{
|
|
m_ntx=4;
|
|
ui->txrb4->setChecked(true);
|
|
m_restart=true;
|
|
}
|
|
|
|
void MainWindow::on_txb5_clicked() //txb5
|
|
{
|
|
m_ntx=5;
|
|
ui->txrb5->setChecked(true);
|
|
m_restart=true;
|
|
}
|
|
|
|
void MainWindow::on_txb6_clicked() //txb6
|
|
{
|
|
m_ntx=6;
|
|
ui->txrb6->setChecked(true);
|
|
m_restart=true;
|
|
}
|
|
|
|
void MainWindow::doubleClickOnCall2(bool shift, bool ctrl)
|
|
{
|
|
m_decodedText2=true;
|
|
doubleClickOnCall(shift,ctrl);
|
|
m_decodedText2=false;
|
|
}
|
|
|
|
void MainWindow::doubleClickOnCall(bool shift, bool ctrl)
|
|
{
|
|
QTextCursor cursor;
|
|
if(!m_decodedText2) cursor=ui->decodedTextBrowser2->textCursor();
|
|
if(m_decodedText2) cursor=ui->decodedTextBrowser->textCursor();
|
|
cursor.select(QTextCursor::LineUnderCursor);
|
|
int i2=cursor.position();
|
|
if(shift and i2==-9999) return; //Silence compiler warning
|
|
|
|
QString t;
|
|
if(!m_decodedText2) t= ui->decodedTextBrowser2->toPlainText(); //Full contents
|
|
if(m_decodedText2) t= ui->decodedTextBrowser->toPlainText();
|
|
|
|
QString t1 = t.mid(0,i2); //contents up to \n on selected line
|
|
int i1=t1.lastIndexOf("\n") + 1; //points to first char of line
|
|
DecodedText decodedtext;
|
|
decodedtext = t1.mid(i1,i2-i1); //selected line
|
|
|
|
if (decodedtext.indexOf(" CQ ") > 0)
|
|
{
|
|
// TODO this magic 36 characters is also referenced in DisplayText::_appendDXCCWorkedB4()
|
|
int s3 = decodedtext.indexOf(" ",35);
|
|
if (s3 < 35)
|
|
s3 = 35; // we always want at least the characters to position 35
|
|
s3 += 1; // convert the index into a character count
|
|
decodedtext = decodedtext.left(s3); // remove DXCC entity and worked B4 status. TODO need a better way to do this
|
|
}
|
|
|
|
|
|
// if(decodedtext.indexOf("Tx")==6) return; //Ignore Tx line
|
|
int i4=t.mid(i1).length();
|
|
if(i4>55) i4=55;
|
|
QString t3=t.mid(i1,i4);
|
|
int i5=t3.indexOf(" CQ DX ");
|
|
if(i5>0) t3=t3.mid(0,i5+3) + "_" + t3.mid(i5+4); //Make it "CQ_DX" (one word)
|
|
QStringList t4=t3.split(" ",QString::SkipEmptyParts);
|
|
if(t4.length() <5) return; //Skip the rest if no decoded text
|
|
|
|
int i9=m_QSOText.indexOf(decodedtext.string());
|
|
if (i9<0 and !decodedtext.isTX())
|
|
{
|
|
ui->decodedTextBrowser2->displayDecodedText(decodedtext,m_myCall,false,m_logBook);
|
|
m_QSOText=decodedtext;
|
|
}
|
|
|
|
|
|
int frequency = decodedtext.frequencyOffset();
|
|
m_wideGraph->setRxFreq(frequency); //Set Rx freq
|
|
if (decodedtext.isTX())
|
|
{
|
|
if (ctrl)
|
|
ui->TxFreqSpinBox->setValue(frequency); //Set Tx freq
|
|
return;
|
|
}
|
|
|
|
QString firstcall = decodedtext.call();
|
|
// Don't change Tx freq if a station is calling me, unless m_lockTxFreq
|
|
// is true or CTRL is held down
|
|
if ((firstcall!=m_myCall) or m_lockTxFreq or ctrl)
|
|
ui->TxFreqSpinBox->setValue(frequency);
|
|
|
|
if (decodedtext.isJT9())
|
|
{
|
|
m_modeTx="JT9";
|
|
ui->pbTxMode->setText("Tx JT9 @");
|
|
m_wideGraph->setModeTx(m_modeTx);
|
|
}
|
|
else
|
|
if (decodedtext.isJT65())
|
|
{
|
|
m_modeTx="JT65";
|
|
ui->pbTxMode->setText("Tx JT65 #");
|
|
m_wideGraph->setModeTx(m_modeTx);
|
|
}
|
|
|
|
QString hiscall;
|
|
QString hisgrid;
|
|
decodedtext.deCallAndGrid(/*out*/hiscall,hisgrid);
|
|
if (hiscall != ui->dxCallEntry->text())
|
|
ui->dxGridEntry->setText("");
|
|
ui->dxCallEntry->setText(hiscall);
|
|
if (gridOK(hisgrid))
|
|
ui->dxGridEntry->setText(hisgrid);
|
|
if (ui->dxGridEntry->text()=="")
|
|
lookup();
|
|
m_hisGrid = ui->dxGridEntry->text();
|
|
|
|
int n = decodedtext.timeInSeconds();
|
|
int nmod=n%(m_TRperiod/30);
|
|
m_txFirst=(nmod!=0);
|
|
ui->txFirstCheckBox->setChecked(m_txFirst);
|
|
|
|
QString rpt = decodedtext.report();
|
|
ui->rptSpinBox->setValue(rpt.toInt());
|
|
genStdMsgs(rpt);
|
|
|
|
// determine the appropriate response to the received msg
|
|
if(decodedtext.indexOf(m_myCall)>=0)
|
|
{
|
|
if (t4.length()>=7 // enough fields for a normal msg
|
|
and !gridOK(t4.at(7))) // but no grid on end of msg
|
|
{
|
|
QString r=t4.at(7);
|
|
if(r.mid(0,3)=="RRR") {
|
|
m_ntx=5;
|
|
ui->txrb5->setChecked(true);
|
|
if(ui->tabWidget->currentIndex()==1) {
|
|
ui->genMsg->setText(ui->tx5->text());
|
|
m_ntx=7;
|
|
ui->rbGenMsg->setChecked(true);
|
|
}
|
|
} else if(r.mid(0,1)=="R") {
|
|
m_ntx=4;
|
|
ui->txrb4->setChecked(true);
|
|
if(ui->tabWidget->currentIndex()==1) {
|
|
ui->genMsg->setText(ui->tx4->text());
|
|
m_ntx=7;
|
|
ui->rbGenMsg->setChecked(true);
|
|
}
|
|
} else if(r.toInt()>=-50 and r.toInt()<=49) {
|
|
m_ntx=3;
|
|
ui->txrb3->setChecked(true);
|
|
if(ui->tabWidget->currentIndex()==1) {
|
|
ui->genMsg->setText(ui->tx3->text());
|
|
m_ntx=7;
|
|
ui->rbGenMsg->setChecked(true);
|
|
}
|
|
} else if(r.toInt()==73) {
|
|
m_ntx=5;
|
|
ui->txrb5->setChecked(true);
|
|
if(ui->tabWidget->currentIndex()==1) {
|
|
ui->genMsg->setText(ui->tx5->text());
|
|
m_ntx=7;
|
|
ui->rbGenMsg->setChecked(true);
|
|
}
|
|
}
|
|
} else {
|
|
m_ntx=2;
|
|
ui->txrb2->setChecked(true);
|
|
if(ui->tabWidget->currentIndex()==1) {
|
|
ui->genMsg->setText(ui->tx2->text());
|
|
m_ntx=7;
|
|
ui->rbGenMsg->setChecked(true);
|
|
}
|
|
}
|
|
|
|
}
|
|
else // myCall not in msg
|
|
{
|
|
m_ntx=1;
|
|
ui->txrb1->setChecked(true);
|
|
if(ui->tabWidget->currentIndex()==1) {
|
|
ui->genMsg->setText(ui->tx1->text());
|
|
m_ntx=7;
|
|
ui->rbGenMsg->setChecked(true);
|
|
}
|
|
}
|
|
if(m_quickCall) {
|
|
m_auto=true;
|
|
ui->autoButton->setStyleSheet(m_pbAutoOn_style);
|
|
}
|
|
}
|
|
|
|
void MainWindow::genStdMsgs(QString rpt) //genStdMsgs()
|
|
{
|
|
QString t;
|
|
QString hisCall=ui->dxCallEntry->text().toUpper().trimmed();
|
|
ui->dxCallEntry->setText(hisCall);
|
|
if(hisCall=="") {
|
|
ui->labAz->setText("");
|
|
ui->labDist->setText("");
|
|
ui->tx1->setText("");
|
|
ui->tx2->setText("");
|
|
ui->tx3->setText("");
|
|
ui->tx4->setText("");
|
|
ui->tx5->setText("");
|
|
ui->tx6->setText("");
|
|
if(m_myCall!="" and m_myGrid!="") {
|
|
t="CQ " + m_myCall + " " + m_myGrid.mid(0,4);
|
|
msgtype(t, ui->tx6);
|
|
}
|
|
ui->genMsg->setText("");
|
|
ui->freeTextMsg->setText("");
|
|
return;
|
|
}
|
|
QString hisBase=baseCall(hisCall);
|
|
QString myBase=baseCall(m_myCall);
|
|
QString t0=hisBase + " " + myBase + " ";
|
|
t=t0 + m_myGrid.mid(0,4);
|
|
if(myBase!=m_myCall) t="DE " + m_myCall + " " + m_myGrid.mid(0,4);
|
|
msgtype(t, ui->tx1);
|
|
if(rpt == "") {
|
|
t=t+" OOO";
|
|
msgtype(t, ui->tx2);
|
|
msgtype("RO", ui->tx3);
|
|
msgtype("RRR", ui->tx4);
|
|
msgtype("73", ui->tx5);
|
|
} else {
|
|
t=t0 + rpt;
|
|
msgtype(t, ui->tx2);
|
|
t=t0 + "R" + rpt;
|
|
msgtype(t, ui->tx3);
|
|
t=t0 + "RRR";
|
|
msgtype(t, ui->tx4);
|
|
t=t0 + "73";
|
|
if(myBase!=m_myCall) t="DE " + m_myCall + " 73";
|
|
msgtype(t, ui->tx5);
|
|
}
|
|
|
|
t="CQ " + m_myCall + " " + m_myGrid.mid(0,4);
|
|
msgtype(t, ui->tx6);
|
|
m_ntx=1;
|
|
ui->txrb1->setChecked(true);
|
|
m_rpt=rpt;
|
|
}
|
|
|
|
QString MainWindow::baseCall(QString t)
|
|
{
|
|
int n1=t.indexOf("/");
|
|
if(n1<0) return t;
|
|
int n2=t.length()-n1-1;
|
|
if(n2>=n1) return t.mid(n1+1);
|
|
return t.mid(0,n1);
|
|
}
|
|
|
|
void MainWindow::lookup() //lookup()
|
|
{
|
|
QString hisCall=ui->dxCallEntry->text().toUpper().trimmed();
|
|
ui->dxCallEntry->setText(hisCall);
|
|
QString call3File = m_appDir + "/CALL3.TXT";
|
|
QFile f(call3File);
|
|
if(!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
msgBox("Cannot open " + call3File);
|
|
return;
|
|
}
|
|
char c[132];
|
|
qint64 n=0;
|
|
for(int i=0; i<999999; i++) {
|
|
n=f.readLine(c,sizeof(c));
|
|
if(n <= 0) {
|
|
ui->dxGridEntry->setText("");
|
|
break;
|
|
}
|
|
QString t=QString(c);
|
|
if(t.indexOf(hisCall)==0) {
|
|
int i1=t.indexOf(",");
|
|
QString hisgrid=t.mid(i1+1,6);
|
|
i1=hisgrid.indexOf(",");
|
|
if(i1>0) {
|
|
hisgrid=hisgrid.mid(0,4);
|
|
} else {
|
|
hisgrid=hisgrid.mid(0,4) + hisgrid.mid(4,2).toLower();
|
|
}
|
|
ui->dxGridEntry->setText(hisgrid);
|
|
break;
|
|
}
|
|
}
|
|
f.close();
|
|
}
|
|
|
|
void MainWindow::on_lookupButton_clicked() //Lookup button
|
|
{
|
|
lookup();
|
|
}
|
|
|
|
void MainWindow::on_addButton_clicked() //Add button
|
|
{
|
|
if(ui->dxGridEntry->text()=="") {
|
|
msgBox("Please enter a valid grid locator.");
|
|
return;
|
|
}
|
|
m_call3Modified=false;
|
|
QString hisCall=ui->dxCallEntry->text().toUpper().trimmed();
|
|
QString hisgrid=ui->dxGridEntry->text().trimmed();
|
|
QString newEntry=hisCall + "," + hisgrid;
|
|
|
|
// int ret = QMessageBox::warning(this, "Add",
|
|
// newEntry + "\n" + "Is this station known to be active on EME?",
|
|
// QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
|
// if(ret==QMessageBox::Yes) {
|
|
// newEntry += ",EME,,";
|
|
// } else {
|
|
newEntry += ",,,";
|
|
// }
|
|
|
|
QString call3File = m_appDir + "/CALL3.TXT";
|
|
QFile f1(call3File);
|
|
if(!f1.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
msgBox("Cannot open " + call3File);
|
|
return;
|
|
}
|
|
if(f1.size()==0) {
|
|
f1.close();
|
|
f1.open(QIODevice::WriteOnly | QIODevice::Text);
|
|
QTextStream out(&f1);
|
|
out << "ZZZZZZ" << endl;
|
|
f1.close();
|
|
f1.open(QIODevice::ReadOnly | QIODevice::Text);
|
|
}
|
|
QString tmpFile = m_appDir + "/CALL3.TMP";
|
|
QFile f2(tmpFile);
|
|
if(!f2.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
msgBox("Cannot open " + tmpFile);
|
|
return;
|
|
}
|
|
QTextStream in(&f1);
|
|
QTextStream out(&f2);
|
|
QString hc=hisCall;
|
|
QString hc1="";
|
|
QString hc2="AAAAAA";
|
|
QString s;
|
|
do {
|
|
s=in.readLine();
|
|
hc1=hc2;
|
|
if(s.mid(0,2)=="//") {
|
|
out << s + "\n";
|
|
} else {
|
|
int i1=s.indexOf(",");
|
|
hc2=s.mid(0,i1);
|
|
if(hc>hc1 && hc<hc2) {
|
|
out << newEntry + "\n";
|
|
if(s.mid(0,6)=="ZZZZZZ") {
|
|
out << s + "\n";
|
|
// exit; //Statement has no effect!
|
|
}
|
|
m_call3Modified=true;
|
|
} else if(hc==hc2) {
|
|
QString t=s + "\n\n is already in CALL3.TXT\n" +
|
|
"Do you wish to replace it?";
|
|
int ret = QMessageBox::warning(this, "Add",t,
|
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
|
if(ret==QMessageBox::Yes) {
|
|
out << newEntry + "\n";
|
|
m_call3Modified=true;
|
|
}
|
|
} else {
|
|
if(s!="") out << s + "\n";
|
|
}
|
|
}
|
|
} while(!s.isNull());
|
|
|
|
f1.close();
|
|
if(hc>hc1 && !m_call3Modified) {
|
|
out << newEntry + "\n";
|
|
}
|
|
if(m_call3Modified) {
|
|
QFile f0(m_appDir + "/CALL3.OLD");
|
|
if(f0.exists()) f0.remove();
|
|
QFile f1(m_appDir + "/CALL3.TXT");
|
|
f1.rename(m_appDir + "/CALL3.OLD");
|
|
f2.rename(m_appDir + "/CALL3.TXT");
|
|
f2.close();
|
|
}
|
|
}
|
|
|
|
void MainWindow::msgtype(QString t, QLineEdit* tx) //msgtype()
|
|
{
|
|
char message[23];
|
|
char msgsent[23];
|
|
int len1=22;
|
|
|
|
t=t.toUpper();
|
|
QByteArray s=t.toUpper().toLocal8Bit();
|
|
ba2msg(s,message);
|
|
int ichk=1,itext=0;
|
|
genjt9_(message,&ichk,msgsent,itone,&itext,len1,len1);
|
|
msgsent[22]=0;
|
|
bool text=false;
|
|
if(itext!=0) text=true;
|
|
QString t1;
|
|
t1.fromLatin1(msgsent);
|
|
if(text) t1=t1.mid(0,13);
|
|
QPalette p(tx->palette());
|
|
if(text) {
|
|
p.setColor(QPalette::Base,"#ffccff");
|
|
} else {
|
|
p.setColor(QPalette::Base,Qt::white);
|
|
}
|
|
tx->setPalette(p);
|
|
int len=t.length();
|
|
if(text) {
|
|
len=qMin(len,13);
|
|
tx->setText(t.mid(0,len).toUpper());
|
|
} else {
|
|
tx->setText(t);
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_tx1_editingFinished() //tx1 edited
|
|
{
|
|
QString t=ui->tx1->text();
|
|
msgtype(t, ui->tx1);
|
|
}
|
|
|
|
void MainWindow::on_tx2_editingFinished() //tx2 edited
|
|
{
|
|
QString t=ui->tx2->text();
|
|
msgtype(t, ui->tx2);
|
|
}
|
|
|
|
void MainWindow::on_tx3_editingFinished() //tx3 edited
|
|
{
|
|
QString t=ui->tx3->text();
|
|
msgtype(t, ui->tx3);
|
|
}
|
|
|
|
void MainWindow::on_tx4_editingFinished() //tx4 edited
|
|
{
|
|
QString t=ui->tx4->text();
|
|
msgtype(t, ui->tx4);
|
|
}
|
|
|
|
void MainWindow::on_tx5_editingFinished() //tx5 edited
|
|
{
|
|
QString t=ui->tx5->text();
|
|
msgtype(t, ui->tx5);
|
|
}
|
|
|
|
void MainWindow::on_tx6_editingFinished() //tx6 edited
|
|
{
|
|
QString t=ui->tx6->text();
|
|
msgtype(t, ui->tx6);
|
|
|
|
// G4WJS: disabled setting of snr from msg 6 on live edit, will
|
|
// still generate noise on next full tx period
|
|
|
|
// double snr=t.mid(1,5).toDouble();
|
|
// if(snr>0.0 or snr < -50.0) snr=99.0;
|
|
// m_modulator.setTxSNR(snr);
|
|
}
|
|
|
|
void MainWindow::on_dxCallEntry_textChanged(const QString &t) //dxCall changed
|
|
{
|
|
m_hisCall=t.toUpper().trimmed();
|
|
ui->dxCallEntry->setText(m_hisCall);
|
|
statusChanged();
|
|
}
|
|
|
|
void MainWindow::on_dxGridEntry_textChanged(const QString &t) //dxGrid changed
|
|
{
|
|
int n=t.length();
|
|
if(n!=4 and n!=6) {
|
|
ui->labAz->setText("");
|
|
ui->labDist->setText("");
|
|
return;
|
|
}
|
|
if(!t[0].isLetter() or !t[1].isLetter()) return;
|
|
if(!t[2].isDigit() or !t[3].isDigit()) return;
|
|
if(n==4) m_hisGrid=t.mid(0,2).toUpper() + t.mid(2,2);
|
|
if(n==6) m_hisGrid=t.mid(0,2).toUpper() + t.mid(2,2) +
|
|
t.mid(4,2).toLower();
|
|
ui->dxGridEntry->setText(m_hisGrid);
|
|
if(gridOK(m_hisGrid)) {
|
|
qint64 nsec = QDateTime::currentMSecsSinceEpoch() % 86400;
|
|
double utch=nsec/3600.0;
|
|
int nAz,nEl,nDmiles,nDkm,nHotAz,nHotABetter;
|
|
|
|
azdist_(m_myGrid.toLatin1().data(),m_hisGrid.toLatin1().data(),&utch,
|
|
&nAz,&nEl,&nDmiles,&nDkm,&nHotAz,&nHotABetter,6,6);
|
|
QString t;
|
|
t.sprintf("Az: %d",nAz);
|
|
ui->labAz->setText(t);
|
|
if(m_bMiles) t.sprintf("%d mi",int(0.621371*nDkm));
|
|
if(!m_bMiles) t.sprintf("%d km",nDkm);
|
|
ui->labDist->setText(t);
|
|
} else {
|
|
ui->labAz->setText("");
|
|
ui->labDist->setText("");
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_genStdMsgsPushButton_clicked() //genStdMsgs button
|
|
{
|
|
genStdMsgs(m_rpt);
|
|
}
|
|
|
|
void MainWindow::on_logQSOButton_clicked() //Log QSO button
|
|
{
|
|
if(m_hisCall=="") return;
|
|
m_dateTimeQSO=QDateTime::currentDateTimeUtc();
|
|
|
|
m_logDlg->initLogQSO(m_hisCall,m_hisGrid,m_modeTx,m_rptSent,m_rptRcvd,
|
|
m_dateTimeQSO,m_dialFreq+m_txFreq/1.0e6,
|
|
m_myCall,m_myGrid,m_noSuffix,m_toRTTY,m_dBtoComments);
|
|
}
|
|
|
|
void MainWindow::acceptQSO2(bool accepted)
|
|
{
|
|
if(accepted)
|
|
{
|
|
QString band = ADIF::bandFromFrequency(m_dialFreq+m_txFreq/1.0e6);
|
|
QString date = m_dateTimeQSO.toString("yyyy-MM-dd");
|
|
date=date.mid(0,4) + date.mid(5,2) + date.mid(8,2);
|
|
m_logBook.addAsWorked(m_hisCall,band,m_modeTx,date);
|
|
|
|
if (m_clearCallGrid)
|
|
{
|
|
m_hisCall="";
|
|
ui->dxCallEntry->setText("");
|
|
m_hisGrid="";
|
|
ui->dxGridEntry->setText("");
|
|
m_rptSent="";
|
|
m_rptRcvd="";
|
|
m_qsoStart="";
|
|
m_qsoStop="";
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_actionJT9_1_triggered()
|
|
{
|
|
m_mode="JT9";
|
|
if(m_modeTx!="JT9") on_pbTxMode_clicked();
|
|
statusChanged();
|
|
m_TRperiod=60;
|
|
m_nsps=6912;
|
|
m_hsymStop=173;
|
|
lab2->setStyleSheet("QLabel{background-color: #ff6ec7}");
|
|
lab2->setText(m_mode);
|
|
ui->actionJT9_1->setChecked(true);
|
|
m_wideGraph->setPeriod(m_TRperiod,m_nsps);
|
|
m_wideGraph->setMode(m_mode);
|
|
m_wideGraph->setModeTx(m_modeTx);
|
|
ui->pbTxMode->setEnabled(false);
|
|
}
|
|
|
|
void MainWindow::on_actionJT65_triggered()
|
|
{
|
|
m_mode="JT65";
|
|
if(m_modeTx!="JT65") on_pbTxMode_clicked();
|
|
statusChanged();
|
|
m_TRperiod=60;
|
|
m_nsps=6912; //For symspec only
|
|
m_hsymStop=173;
|
|
lab2->setStyleSheet("QLabel{background-color: #ffff00}");
|
|
lab2->setText(m_mode);
|
|
ui->actionJT65->setChecked(true);
|
|
m_wideGraph->setPeriod(m_TRperiod,m_nsps);
|
|
m_wideGraph->setMode(m_mode);
|
|
m_wideGraph->setModeTx(m_modeTx);
|
|
ui->pbTxMode->setEnabled(false);
|
|
}
|
|
|
|
void MainWindow::on_actionJT9_JT65_triggered()
|
|
{
|
|
m_mode="JT9+JT65";
|
|
// if(m_modeTx!="JT9") on_pbTxMode_clicked();
|
|
statusChanged();
|
|
m_TRperiod=60;
|
|
m_nsps=6912;
|
|
m_hsymStop=173;
|
|
lab2->setStyleSheet("QLabel{background-color: #ffa500}");
|
|
lab2->setText(m_mode);
|
|
ui->actionJT9_JT65->setChecked(true);
|
|
m_wideGraph->setPeriod(m_TRperiod,m_nsps);
|
|
m_wideGraph->setMode(m_mode);
|
|
m_wideGraph->setModeTx(m_modeTx);
|
|
ui->pbTxMode->setEnabled(true);
|
|
}
|
|
|
|
void MainWindow::on_TxFreqSpinBox_valueChanged(int n)
|
|
{
|
|
m_txFreq=n;
|
|
m_wideGraph->setTxFreq(n);
|
|
if(m_lockTxFreq) ui->RxFreqSpinBox->setValue(n);
|
|
Q_EMIT transmitFrequency (m_txFreq - (m_bSplit || m_bXIT ? m_XIT : 0));
|
|
}
|
|
|
|
void MainWindow::on_RxFreqSpinBox_valueChanged(int n)
|
|
{
|
|
m_rxFreq=n;
|
|
m_wideGraph->setRxFreq(n);
|
|
if(m_lockTxFreq) ui->TxFreqSpinBox->setValue(n);
|
|
}
|
|
|
|
void MainWindow::on_actionQuickDecode_triggered()
|
|
{
|
|
m_ndepth=1;
|
|
ui->actionQuickDecode->setChecked(true);
|
|
}
|
|
|
|
void MainWindow::on_actionMediumDecode_triggered()
|
|
{
|
|
m_ndepth=2;
|
|
ui->actionMediumDecode->setChecked(true);
|
|
}
|
|
|
|
void MainWindow::on_actionDeepestDecode_triggered()
|
|
{
|
|
m_ndepth=3;
|
|
ui->actionDeepestDecode->setChecked(true);
|
|
}
|
|
|
|
void MainWindow::on_inGain_valueChanged(int n)
|
|
{
|
|
m_inGain=n;
|
|
}
|
|
|
|
void MainWindow::on_actionMonitor_OFF_at_startup_triggered()
|
|
{
|
|
m_monitorStartOFF=!m_monitorStartOFF;
|
|
}
|
|
|
|
void MainWindow::on_actionErase_ALL_TXT_triggered() //Erase ALL.TXT
|
|
{
|
|
int ret = QMessageBox::warning(this, "Confirm Erase",
|
|
"Are you sure you want to erase file ALL.TXT ?",
|
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
|
if(ret==QMessageBox::Yes) {
|
|
QFile f("ALL.TXT");
|
|
f.remove();
|
|
m_RxLog=1;
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_actionErase_wsjtx_log_adi_triggered()
|
|
{
|
|
int ret = QMessageBox::warning(this, "Confirm Erase",
|
|
"Are you sure you want to erase file wsjtx_log.adi ?",
|
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
|
if(ret==QMessageBox::Yes) {
|
|
QFile f("wsjtx_log.adi");
|
|
f.remove();
|
|
}
|
|
}
|
|
|
|
void MainWindow::showMacros(const QPoint &pos)
|
|
{
|
|
if(m_macro.length()<10) return;
|
|
QPoint globalPos = ui->tx5->mapToGlobal(pos);
|
|
QMenu popupMenu;
|
|
QAction* popup1 = new QAction(m_macro[0],ui->tx5);
|
|
QAction* popup2 = new QAction(m_macro[1],ui->tx5);
|
|
QAction* popup3 = new QAction(m_macro[2],ui->tx5);
|
|
QAction* popup4 = new QAction(m_macro[3],ui->tx5);
|
|
QAction* popup5 = new QAction(m_macro[4],ui->tx5);
|
|
QAction* popup6 = new QAction(m_macro[5],ui->tx5);
|
|
QAction* popup7 = new QAction(m_macro[6],ui->tx5);
|
|
QAction* popup8 = new QAction(m_macro[7],ui->tx5);
|
|
QAction* popup9 = new QAction(m_macro[8],ui->tx5);
|
|
QAction* popup10 = new QAction(m_macro[9],ui->tx5);
|
|
|
|
if(m_macro[0]!="") popupMenu.addAction(popup1);
|
|
if(m_macro[1]!="") popupMenu.addAction(popup2);
|
|
if(m_macro[2]!="") popupMenu.addAction(popup3);
|
|
if(m_macro[3]!="") popupMenu.addAction(popup4);
|
|
if(m_macro[4]!="") popupMenu.addAction(popup5);
|
|
if(m_macro[5]!="") popupMenu.addAction(popup6);
|
|
if(m_macro[6]!="") popupMenu.addAction(popup7);
|
|
if(m_macro[7]!="") popupMenu.addAction(popup8);
|
|
if(m_macro[8]!="") popupMenu.addAction(popup9);
|
|
if(m_macro[9]!="") popupMenu.addAction(popup10);
|
|
|
|
connect(popup1,SIGNAL(triggered()), this, SLOT(onPopup1()));
|
|
connect(popup2,SIGNAL(triggered()), this, SLOT(onPopup2()));
|
|
connect(popup3,SIGNAL(triggered()), this, SLOT(onPopup3()));
|
|
connect(popup4,SIGNAL(triggered()), this, SLOT(onPopup4()));
|
|
connect(popup5,SIGNAL(triggered()), this, SLOT(onPopup5()));
|
|
connect(popup6,SIGNAL(triggered()), this, SLOT(onPopup6()));
|
|
connect(popup7,SIGNAL(triggered()), this, SLOT(onPopup7()));
|
|
connect(popup8,SIGNAL(triggered()), this, SLOT(onPopup8()));
|
|
connect(popup9,SIGNAL(triggered()), this, SLOT(onPopup9()));
|
|
connect(popup10,SIGNAL(triggered()), this, SLOT(onPopup10()));
|
|
popupMenu.exec(globalPos);
|
|
}
|
|
|
|
void MainWindow::onPopup1() { ui->tx5->setText(m_macro[0]); freeText(); }
|
|
void MainWindow::onPopup2() { ui->tx5->setText(m_macro[1]); freeText(); }
|
|
void MainWindow::onPopup3() { ui->tx5->setText(m_macro[2]); freeText(); }
|
|
void MainWindow::onPopup4() { ui->tx5->setText(m_macro[3]); freeText(); }
|
|
void MainWindow::onPopup5() { ui->tx5->setText(m_macro[4]); freeText(); }
|
|
void MainWindow::onPopup6() { ui->tx5->setText(m_macro[5]); freeText(); }
|
|
void MainWindow::onPopup7() { ui->tx5->setText(m_macro[6]); freeText(); }
|
|
void MainWindow::onPopup8() { ui->tx5->setText(m_macro[7]); freeText(); }
|
|
void MainWindow::onPopup9() { ui->tx5->setText(m_macro[8]); freeText(); }
|
|
void MainWindow::onPopup10() { ui->tx5->setText(m_macro[9]); freeText(); }
|
|
|
|
void MainWindow::freeText() { ui->freeTextMsg->setText(ui->tx5->text()); }
|
|
|
|
bool MainWindow::gridOK(QString g)
|
|
{
|
|
bool b=g.mid(0,1).compare("A")>=0 and
|
|
g.mid(0,1).compare("R")<=0 and
|
|
g.mid(1,1).compare("A")>=0 and
|
|
g.mid(1,1).compare("R")<=0 and
|
|
g.mid(2,1).compare("0")>=0 and
|
|
g.mid(2,1).compare("9")<=0 and
|
|
g.mid(3,1).compare("0")>=0 and
|
|
g.mid(3,1).compare("9")<=0;
|
|
return b;
|
|
}
|
|
|
|
void MainWindow::on_actionConvert_JT9_x_to_RTTY_triggered(bool checked)
|
|
{
|
|
m_toRTTY=checked;
|
|
}
|
|
|
|
void MainWindow::on_actionLog_dB_reports_to_Comments_triggered(bool checked)
|
|
{
|
|
m_dBtoComments=checked;
|
|
}
|
|
|
|
void MainWindow::on_bandComboBox_activated(int index)
|
|
{
|
|
int ret=0;
|
|
QString rt;
|
|
|
|
m_band=index;
|
|
QString t=m_dFreq[index];
|
|
m_dialFreq=t.toDouble();
|
|
if(m_plus2kHz) m_dialFreq+=0.002;
|
|
dialFreqChanged2(m_dialFreq);
|
|
m_repeatMsg=0;
|
|
m_secBandChanged=QDateTime::currentMSecsSinceEpoch()/1000;
|
|
if(m_catEnabled) {
|
|
if(!m_bRigOpen) {
|
|
rigOpen();
|
|
}
|
|
if(m_bRigOpen) {
|
|
m_dontReadFreq=true;
|
|
ret=rig->setFreq(MHz(m_dialFreq));
|
|
if(m_bSplit or m_bXIT) setXIT(m_txFreq);
|
|
|
|
bumpFqso(11);
|
|
bumpFqso(12);
|
|
|
|
if(ret!=RIG_OK) {
|
|
rt.sprintf("Set rig frequency failed: %d",ret);
|
|
msgBox(rt);
|
|
}
|
|
}
|
|
}
|
|
QFile f2("ALL.TXT");
|
|
f2.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
|
|
QTextStream out(&f2);
|
|
out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm")
|
|
<< " " << m_dialFreq << " MHz " << m_mode << endl;
|
|
f2.close();
|
|
psk_Reporter->setLocalStation(m_myCall, m_myGrid, m_antDescription[m_band], "WSJT-X r" + rev.mid(6,4) );
|
|
}
|
|
|
|
void MainWindow::on_actionPrompt_to_log_QSO_triggered(bool checked)
|
|
{
|
|
m_promptToLog=checked;
|
|
}
|
|
|
|
void MainWindow::on_actionBlank_line_between_decoding_periods_triggered(bool checked)
|
|
{
|
|
m_insertBlank=checked;
|
|
}
|
|
|
|
void MainWindow::on_actionEnable_DXCC_entity_triggered(bool checked)
|
|
{
|
|
m_displayDXCCEntity=checked;
|
|
if (checked)
|
|
m_logBook.init(); // re-read the log and cty.dat files
|
|
|
|
if (checked) // adjust the proportions between the two text displays
|
|
{
|
|
ui->gridLayout->setColumnStretch(0,55);
|
|
ui->gridLayout->setColumnStretch(1,45);
|
|
}
|
|
else
|
|
{
|
|
ui->gridLayout->setColumnStretch(0,0);
|
|
ui->gridLayout->setColumnStretch(1,0);
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_actionClear_DX_Call_and_Grid_after_logging_triggered(bool checked)
|
|
{
|
|
m_clearCallGrid=checked;
|
|
}
|
|
|
|
void MainWindow::on_actionDisplay_distance_in_miles_triggered(bool checked)
|
|
{
|
|
m_bMiles=checked;
|
|
on_dxGridEntry_textChanged(m_hisGrid);
|
|
}
|
|
|
|
void MainWindow::on_pbCallCQ_clicked()
|
|
{
|
|
genStdMsgs(m_rpt);
|
|
ui->genMsg->setText(ui->tx6->text());
|
|
m_ntx=7;
|
|
ui->rbGenMsg->setChecked(true);
|
|
if(m_transmitting) m_restart=true;
|
|
}
|
|
|
|
void MainWindow::on_pbAnswerCaller_clicked()
|
|
{
|
|
genStdMsgs(m_rpt);
|
|
ui->genMsg->setText(ui->tx2->text());
|
|
m_ntx=7;
|
|
ui->rbGenMsg->setChecked(true);
|
|
if(m_transmitting) m_restart=true;
|
|
}
|
|
|
|
void MainWindow::on_pbSendRRR_clicked()
|
|
{
|
|
genStdMsgs(m_rpt);
|
|
ui->genMsg->setText(ui->tx4->text());
|
|
m_ntx=7;
|
|
ui->rbGenMsg->setChecked(true);
|
|
if(m_transmitting) m_restart=true;
|
|
}
|
|
|
|
void MainWindow::on_pbAnswerCQ_clicked()
|
|
{
|
|
genStdMsgs(m_rpt);
|
|
ui->genMsg->setText(ui->tx1->text());
|
|
m_ntx=7;
|
|
ui->rbGenMsg->setChecked(true);
|
|
if(m_transmitting) m_restart=true;
|
|
}
|
|
|
|
void MainWindow::on_pbSendReport_clicked()
|
|
{
|
|
genStdMsgs(m_rpt);
|
|
ui->genMsg->setText(ui->tx3->text());
|
|
m_ntx=7;
|
|
ui->rbGenMsg->setChecked(true);
|
|
if(m_transmitting) m_restart=true;
|
|
}
|
|
|
|
void MainWindow::on_pbSend73_clicked()
|
|
{
|
|
genStdMsgs(m_rpt);
|
|
ui->genMsg->setText(ui->tx5->text());
|
|
m_ntx=7;
|
|
ui->rbGenMsg->setChecked(true);
|
|
if(m_transmitting) m_restart=true;
|
|
}
|
|
|
|
void MainWindow::on_rbGenMsg_toggled(bool checked)
|
|
{
|
|
m_freeText=!checked;
|
|
if(!m_freeText) {
|
|
m_ntx=7;
|
|
if(m_transmitting) m_restart=true;
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_rbFreeText_toggled(bool checked)
|
|
{
|
|
m_freeText=checked;
|
|
if(m_freeText) {
|
|
m_ntx=8;
|
|
if (m_transmitting) m_restart=true;
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_freeTextMsg_editingFinished()
|
|
{
|
|
QString t=ui->freeTextMsg->text();
|
|
msgtype(t, ui->freeTextMsg);
|
|
}
|
|
|
|
void MainWindow::on_actionDouble_click_on_call_sets_Tx_Enable_triggered(bool checked)
|
|
{
|
|
m_quickCall=checked;
|
|
}
|
|
|
|
void MainWindow::on_rptSpinBox_valueChanged(int n)
|
|
{
|
|
m_rpt=QString::number(n);
|
|
int ntx0=m_ntx;
|
|
QString t=ui->tx5->text();
|
|
genStdMsgs(m_rpt);
|
|
ui->tx5->setText(t);
|
|
m_ntx=ntx0;
|
|
if(m_ntx==1) ui->txrb1->setChecked(true);
|
|
if(m_ntx==2) ui->txrb2->setChecked(true);
|
|
if(m_ntx==3) ui->txrb3->setChecked(true);
|
|
if(m_ntx==4) ui->txrb4->setChecked(true);
|
|
if(m_ntx==5) ui->txrb5->setChecked(true);
|
|
if(m_ntx==6) ui->txrb6->setChecked(true);
|
|
statusChanged();
|
|
}
|
|
|
|
void MainWindow::on_action_73TxDisable_triggered(bool checked)
|
|
{
|
|
m_73TxDisable=checked;
|
|
}
|
|
|
|
void MainWindow::on_actionRunaway_Tx_watchdog_triggered(bool checked)
|
|
{
|
|
m_runaway=checked;
|
|
}
|
|
|
|
void MainWindow::on_tuneButton_clicked()
|
|
{
|
|
if(m_tune) {
|
|
nc1=1; //disable the countdown timer
|
|
tuneButtonTimer->start(250);
|
|
} else {
|
|
m_tune=true;
|
|
m_sent73=false;
|
|
Q_EMIT tune ();
|
|
m_repeatMsg=0;
|
|
ui->tuneButton->setStyleSheet(m_pbTune_style);
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_stopTxButton_clicked() //Stop Tx
|
|
{
|
|
if(m_tune) {
|
|
m_tune=false;
|
|
Q_EMIT tune (m_tune);
|
|
}
|
|
if(m_auto) on_autoButton_clicked();
|
|
m_btxok=false;
|
|
Q_EMIT muteAudioOutput ();
|
|
m_repeatMsg=0;
|
|
ui->tuneButton->setStyleSheet("");
|
|
}
|
|
|
|
void MainWindow::rigOpen()
|
|
{
|
|
QString t;
|
|
int ret;
|
|
rig = new Rig();
|
|
|
|
if(m_rig<9900) {
|
|
if (!rig->init(m_rig)) {
|
|
msgBox("Rig init failure");
|
|
return;
|
|
}
|
|
QString sCATport=m_catPort;
|
|
#ifdef WIN32
|
|
sCATport="\\\\.\\" + m_catPort; //Allow COM ports above 9
|
|
#endif
|
|
rig->setConf("rig_pathname", sCATport.toLatin1().data());
|
|
char buf[80];
|
|
sprintf(buf,"%d",m_serialRate);
|
|
rig->setConf("serial_speed",buf);
|
|
sprintf(buf,"%d",m_dataBits);
|
|
rig->setConf("data_bits",buf);
|
|
sprintf(buf,"%d",m_stopBits);
|
|
rig->setConf("stop_bits",buf);
|
|
rig->setConf("serial_handshake",m_handshake.toLatin1().data());
|
|
if(m_handshakeIndex != 2) {
|
|
rig->setConf("rts_state",m_bRTS ? "ON" : "OFF");
|
|
rig->setConf("dtr_state",m_bDTR ? "ON" : "OFF");
|
|
}
|
|
}
|
|
|
|
ret=rig->open(m_rig);
|
|
if(ret==RIG_OK) {
|
|
m_bRigOpen=true;
|
|
m_bad=0;
|
|
if(m_poll==0) ui->readFreq->setEnabled(true);
|
|
m_CATerror=false;
|
|
} else {
|
|
t="Open rig failed";
|
|
msgBox(t);
|
|
m_catEnabled=false;
|
|
m_bRigOpen=false;
|
|
m_CATerror=true;
|
|
}
|
|
|
|
if(m_bRigOpen) {
|
|
if(m_poll>0) {
|
|
ui->readFreq->setStyleSheet("QPushButton{background-color: #00ff00; \
|
|
border-width: 0px; border-radius: 5px;}");
|
|
} else {
|
|
ui->readFreq->setStyleSheet("QPushButton{background-color: orange; \
|
|
border-width: 0px; border-radius: 5px;}");
|
|
}
|
|
|
|
if(m_bSplit) ui->readFreq->setText("S");
|
|
if(!m_bSplit) ui->readFreq->setText("");
|
|
} else {
|
|
if(m_CATerror) ui->readFreq->setStyleSheet("QPushButton{background-color: red; \
|
|
border-width: 0px; border-radius: 5px;}");
|
|
if(!m_CATerror) ui->readFreq->setStyleSheet("");
|
|
ui->readFreq->setText("");
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_actionAllow_multiple_instances_triggered(bool checked)
|
|
{
|
|
m_bMultipleOK=checked;
|
|
}
|
|
|
|
void MainWindow::on_pbR2T_clicked()
|
|
{
|
|
int n=m_wideGraph->rxFreq();
|
|
ui->TxFreqSpinBox->setValue(n);
|
|
}
|
|
|
|
void MainWindow::on_pbT2R_clicked()
|
|
{
|
|
m_wideGraph->setRxFreq(m_txFreq);
|
|
}
|
|
|
|
|
|
void MainWindow::on_readFreq_clicked()
|
|
{
|
|
if(m_transmitting) return;
|
|
m_dontReadFreq=false;
|
|
double fMHz=rig->getFreq(RIG_VFO_CURR)/1000000.0;
|
|
if(fMHz<0.0) {
|
|
QString rt;
|
|
rt.sprintf("Rig control error %d\nFailed to read frequency.",
|
|
int(1000000.0*fMHz));
|
|
msgBox(rt);
|
|
m_catEnabled=false;
|
|
}
|
|
if(fMHz<0.01 or fMHz>1300.0) fMHz=0;
|
|
int ndiff=1000000.0*(fMHz-m_dialFreq);
|
|
if(ndiff!=0) dialFreqChanged2(fMHz);
|
|
}
|
|
|
|
void MainWindow::on_pbTxMode_clicked()
|
|
{
|
|
if(m_modeTx=="JT9") {
|
|
m_modeTx="JT65";
|
|
ui->pbTxMode->setText("Tx JT65 #");
|
|
} else {
|
|
m_modeTx="JT9";
|
|
ui->pbTxMode->setText("Tx JT9 @");
|
|
}
|
|
m_wideGraph->setModeTx(m_modeTx);
|
|
statusChanged();
|
|
}
|
|
|
|
void MainWindow::setXIT(int n)
|
|
{
|
|
int ret;
|
|
m_XIT = 0;
|
|
if(m_bRigOpen) {
|
|
m_XIT=(n/500)*500 - 1500;
|
|
if(m_bXIT) {
|
|
ret=rig->setXit((shortfreq_t)m_XIT,RIG_VFO_TX);
|
|
if(ret!=RIG_OK) {
|
|
QString rt;
|
|
rt.sprintf("Setting RIG_VFO_TX failed: %d",ret);
|
|
msgBox(rt);
|
|
}
|
|
}
|
|
if(m_bSplit) {
|
|
ret=rig->setSplitFreq(MHz(m_dialFreq)+m_XIT,RIG_VFO_B);
|
|
}
|
|
}
|
|
Q_EMIT transmitFrequency (m_txFreq - (m_bSplit || m_bXIT ? m_XIT : 0));
|
|
}
|
|
|
|
void MainWindow::setFreq4(int rxFreq, int txFreq)
|
|
{
|
|
m_rxFreq=rxFreq;
|
|
m_txFreq=txFreq;
|
|
ui->RxFreqSpinBox->setValue(m_rxFreq);
|
|
ui->TxFreqSpinBox->setValue(m_txFreq);
|
|
}
|
|
|
|
void MainWindow::on_cbTxLock_clicked(bool checked)
|
|
{
|
|
m_lockTxFreq=checked;
|
|
m_wideGraph->setLockTxFreq(m_lockTxFreq);
|
|
if(m_lockTxFreq) on_pbR2T_clicked();
|
|
}
|
|
|
|
void MainWindow::on_actionTx2QSO_triggered(bool checked)
|
|
{
|
|
m_tx2QSO=checked;
|
|
}
|
|
|
|
void MainWindow::on_cbPlus2kHz_toggled(bool checked)
|
|
{
|
|
m_plus2kHz=checked;
|
|
on_bandComboBox_activated(m_band);
|
|
}
|
|
|
|
void MainWindow::pollRigFreq()
|
|
{
|
|
double fMHz;
|
|
if(m_dontReadFreq) {
|
|
m_dontReadFreq=false;
|
|
} else if(!m_transmitting) {
|
|
fMHz=rig->getFreq(RIG_VFO_CURR)/1000000.0;
|
|
if(fMHz<0.0) {
|
|
m_bad++;
|
|
if(m_bad>=20) {
|
|
QString rt;
|
|
rt.sprintf("Rig control error %d\nFailed to read frequency.",
|
|
int(1000000.0*fMHz));
|
|
msgBox(rt);
|
|
m_catEnabled=false;
|
|
ui->readFreq->setStyleSheet("QPushButton{background-color: red; \
|
|
border-width: 0px; border-radius: 5px;}");
|
|
}
|
|
} else {
|
|
int ndiff=1000000.0*(fMHz-m_dialFreq);
|
|
if(ndiff!=0) dialFreqChanged2(fMHz);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::transmit (double snr)
|
|
{
|
|
if (m_modeTx == "JT65")
|
|
{
|
|
Q_EMIT sendMessage (NUM_JT65_SYMBOLS, 4096.0 * 12000.0 / 11025.0, m_txFreq - (m_bSplit || m_bXIT ? m_XIT : 0), m_audioOutputChannel, true, snr);
|
|
}
|
|
else
|
|
{
|
|
Q_EMIT sendMessage (NUM_JT9_SYMBOLS, m_nsps, m_txFreq - (m_bSplit || m_bXIT ? m_XIT : 0), m_audioOutputChannel, true, snr);
|
|
}
|
|
Q_EMIT startAudioOutputStream (m_audioOutputDevice, AudioDevice::Mono == m_audioOutputChannel ? 1 : 2, m_msAudioOutputBuffered);
|
|
}
|
|
|
|
void MainWindow::on_outAttenuation_valueChanged (int a)
|
|
{
|
|
qreal dBAttn (a / 10.); // slider interpreted as hundredths of a dB
|
|
ui->outAttenuation->setToolTip (tr ("Transmit digital gain ") + (a ? QString::number (-dBAttn, 'f', 1) : "0") + "dB");
|
|
Q_EMIT outAttenuationChanged (dBAttn);
|
|
}
|