#include "wfmain.h" #include "ui_wfmain.h" #include "commhandler.h" #include "rigidentities.h" #include "logcategories.h" // This code is copyright 2017-2022 Elliott H. Liggett // All rights reserved // Log support: //static void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg); QScopedPointer m_logFile; QMutex logMutex; QMutex logTextMutex; QVector logStringBuffer; #ifdef QT_DEBUG bool debugModeLogging = true; #else bool debugModeLogging = false; #endif wfmain::wfmain(const QString settingsFile, const QString logFile, bool debugMode, QWidget *parent ) : QMainWindow(parent), ui(new Ui::wfmain), logFilename(logFile) { QGuiApplication::setApplicationDisplayName("wfview"); QGuiApplication::setApplicationName(QString("wfview")); setWindowIcon(QIcon( QString(":resources/wfview.png"))); this->debugMode = debugMode; debugModeLogging = debugMode; version = QString("wfview version: %1 (Git:%2 on %3 at %4 by %5@%6). Operating System: %7 (%8). Build Qt Version %9. Current Qt Version: %10") .arg(QString(WFVIEW_VERSION)) .arg(GITSHORT).arg(__DATE__).arg(__TIME__).arg(UNAME).arg(HOST) .arg(QSysInfo::prettyProductName()).arg(QSysInfo::buildCpuArchitecture()) .arg(QT_VERSION_STR).arg(qVersion()); ui->setupUi(this); setWindowTitle(QString("wfview")); logWindow = new loggingWindow(logFile); initLogging(); logWindow->setInitialDebugState(debugMode); qInfo(logSystem()) << version; cal = new calibrationWindow(); rpt = new repeaterSetup(); sat = new satelliteSetup(); trxadj = new transceiverAdjustments(); cw = new cwSender(); abtBox = new aboutbox(); selRad = new selectRadio(); qRegisterMetaType(); // Needs to be registered early. qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType (); qRegisterMetaType (); qRegisterMetaType (); qRegisterMetaType (); qRegisterMetaType(); qRegisterMetaType>(); qRegisterMetaType*>(); qRegisterMetaType*>(); qRegisterMetaType*>(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType>(); qRegisterMetaType>(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); haveRigCaps = false; setupKeyShortcuts(); setupMainUI(); prepareSettingsWindow(); setSerialDevicesUI(); setDefPrefs(); getSettingsFilePath(settingsFile); setupPlots(); setDefaultColorPresets(); loadSettings(); // Look for saved preferences audioDev = new audioDevices(prefs.audioSystem, QFontMetrics(ui->audioInputCombo->font())); connect(audioDev, SIGNAL(updated()), this, SLOT(setAudioDevicesUI())); audioDev->enumerate(); //setAudioDevicesUI(); // no need to call this as it will be called by the updated() signal setTuningSteps(); // TODO: Combine into preferences qDebug(logSystem()) << "Running setUIToPrefs()"; setUIToPrefs(); qDebug(logSystem()) << "Running setInititalTiming()"; setInitialTiming(); qDebug(logSystem()) << "Running openRig()"; openRig(); qDebug(logSystem()) << "Running rigConnections()"; rigConnections(); cluster = new dxClusterClient(); clusterThread = new QThread(this); clusterThread->setObjectName("dxcluster()"); cluster->moveToThread(clusterThread); connect(this, SIGNAL(setClusterEnableUdp(bool)), cluster, SLOT(enableUdp(bool))); connect(this, SIGNAL(setClusterEnableTcp(bool)), cluster, SLOT(enableTcp(bool))); connect(this, SIGNAL(setClusterUdpPort(int)), cluster, SLOT(setUdpPort(int))); connect(this, SIGNAL(setClusterServerName(QString)), cluster, SLOT(setTcpServerName(QString))); connect(this, SIGNAL(setClusterTcpPort(int)), cluster, SLOT(setTcpPort(int))); connect(this, SIGNAL(setClusterUserName(QString)), cluster, SLOT(setTcpUserName(QString))); connect(this, SIGNAL(setClusterPassword(QString)), cluster, SLOT(setTcpPassword(QString))); connect(this, SIGNAL(setClusterTimeout(int)), cluster, SLOT(setTcpTimeout(int))); connect(this, SIGNAL(setFrequencyRange(double, double)), cluster, SLOT(freqRange(double, double))); connect(this, SIGNAL(setClusterSkimmerSpots(bool)), cluster, SLOT(enableSkimmerSpots(bool))); connect(cluster, SIGNAL(sendSpots(QList)), this, SLOT(receiveSpots(QList))); connect(cluster, SIGNAL(sendOutput(QString)), this, SLOT(receiveClusterOutput(QString))); connect(clusterThread, SIGNAL(finished()), cluster, SLOT(deleteLater())); clusterThread->start(); emit setClusterUdpPort(prefs.clusterUdpPort); emit setClusterEnableUdp(prefs.clusterUdpEnable); for (int f = 0; f < clusters.size(); f++) { if (clusters[f].isdefault) { emit setClusterServerName(clusters[f].server); emit setClusterTcpPort(clusters[f].port); emit setClusterUserName(clusters[f].userName); emit setClusterPassword(clusters[f].password); emit setClusterTimeout(clusters[f].timeout); } } emit setClusterEnableTcp(prefs.clusterTcpEnable); setServerToPrefs(); amTransmitting = false; connect(ui->txPowerSlider, &QSlider::sliderMoved, [&](int value) { QToolTip::showText(QCursor::pos(), QString("%1").arg(value*100/255), nullptr); }); #if !defined(USB_CONTROLLER) ui->enableUsbChk->setVisible(false); ui->usbControllerBtn->setVisible(false); ui->usbControllersResetBtn->setVisible(false); ui->usbResetLbl->setVisible(false); #else #if defined(USB_HOTPLUG) && defined(Q_OS_LINUX) uDev = udev_new(); if (!uDev) { qInfo(logUsbControl()) << "Cannot register udev, hotplug of USB devices is not available"; return; } uDevMonitor = udev_monitor_new_from_netlink(uDev, "udev"); if (!uDevMonitor) { qInfo(logUsbControl()) << "Cannot register udev_monitor, hotplug of USB devices is not available"; return; } int fd = udev_monitor_get_fd(uDevMonitor); uDevNotifier = new QSocketNotifier(fd, QSocketNotifier::Read,this); connect(uDevNotifier, SIGNAL(activated(int)), this, SLOT(uDevEvent())); udev_monitor_enable_receiving(uDevMonitor); #endif #endif } wfmain::~wfmain() { rigThread->quit(); rigThread->wait(); if (serverThread != Q_NULLPTR) { serverThread->quit(); serverThread->wait(); } if (clusterThread != Q_NULLPTR) { clusterThread->quit(); clusterThread->wait(); } if (rigCtl != Q_NULLPTR) { delete rigCtl; } if (audioDev != Q_NULLPTR) { delete audioDev; } if (prefs.audioSystem == portAudio) { Pa_Terminate(); } delete rpt; delete ui; delete settings; #if defined(USB_CONTROLLER) if (usbControllerThread != Q_NULLPTR) { usbControllerThread->quit(); usbControllerThread->wait(); } #if defined(Q_OS_LINUX) if (uDevMonitor) { udev_monitor_unref(uDevMonitor); udev_unref(uDev); delete uDevNotifier; } #endif #endif } void wfmain::closeEvent(QCloseEvent *event) { // Are you sure? if (!prefs.confirmExit) { QApplication::exit(); } QCheckBox *cb = new QCheckBox("Don't ask me again"); cb->setToolTip("Don't ask me to confirm exit again"); QMessageBox msgbox; msgbox.setText("Are you sure you wish to exit?\n"); msgbox.setIcon(QMessageBox::Icon::Question); QAbstractButton *yesButton = msgbox.addButton(QMessageBox::Yes); msgbox.addButton(QMessageBox::No); msgbox.setDefaultButton(QMessageBox::Yes); msgbox.setCheckBox(cb); QObject::connect(cb, &QCheckBox::stateChanged, [this](int state){ if (static_cast(state) == Qt::CheckState::Checked) { prefs.confirmExit=false; } else { prefs.confirmExit=true; } settings->beginGroup("Interface"); settings->setValue("ConfirmExit", this->prefs.confirmExit); settings->endGroup(); settings->sync(); }); msgbox.exec(); if (msgbox.clickedButton() == yesButton) { QApplication::exit(); } else { event->ignore(); } delete cb; } void wfmain::openRig() { // This function is intended to handle opening a connection to the rig. // the connection can be either serial or network, // and this function is also responsible for initiating the search for a rig model and capabilities. // Any errors, such as unable to open connection or unable to open port, are to be reported to the user. //TODO: if(hasRunPreviously) //TODO: if(useNetwork){... // } else { // if (prefs.fileWasNotFound) { // showRigSettings(); // rig setting dialog box for network/serial, CIV, hostname, port, baud rate, serial device, etc // TODO: How do we know if the setting was loaded? ui->audioSystemServerCombo->setEnabled(false); ui->audioSystemCombo->setEnabled(false); ui->connectBtn->setText("Cancel connection"); // We are attempting to connect makeRig(); if (prefs.enableLAN) { ui->lanEnableBtn->setChecked(true); usingLAN = true; // We need to setup the tx/rx audio: udpPrefs.waterfallFormat = prefs.waterfallFormat; emit sendCommSetup(prefs.radioCIVAddr, udpPrefs, rxSetup, txSetup, prefs.virtualSerialPort, prefs.tcpPort); } else { ui->serialEnableBtn->setChecked(true); if( (prefs.serialPortRadio.toLower() == QString("auto"))) { findSerialPort(); } else { serialPortRig = prefs.serialPortRadio; } usingLAN = false; emit sendCommSetup(prefs.radioCIVAddr, serialPortRig, prefs.serialPortBaud,prefs.virtualSerialPort, prefs.tcpPort,prefs.waterfallFormat); ui->statusBar->showMessage(QString("Connecting to rig using serial port ").append(serialPortRig), 1000); } } void wfmain::createSettingsListItems() { // Add items to the settings tab list widget ui->settingsList->addItem("Radio Access"); // 0 ui->settingsList->addItem("User Interface"); // 1 ui->settingsList->addItem("Radio Settings"); // 2 ui->settingsList->addItem("Radio Server"); // 3 ui->settingsList->addItem("External Control"); // 4 ui->settingsList->addItem("DX Cluster"); // 5 ui->settingsList->addItem("Experimental"); // 6 //ui->settingsList->addItem("Audio Processing"); // 7 ui->settingsStack->setCurrentIndex(0); } void wfmain::on_settingsList_currentRowChanged(int currentRow) { ui->settingsStack->setCurrentIndex(currentRow); } void wfmain::connectSettingsList() { } void wfmain::rigConnections() { connect(this, SIGNAL(setCIVAddr(unsigned char)), rig, SLOT(setCIVAddr(unsigned char))); connect(this, SIGNAL(sendPowerOn()), rig, SLOT(powerOn())); connect(this, SIGNAL(sendPowerOff()), rig, SLOT(powerOff())); connect(rig, SIGNAL(haveFrequency(freqt)), this, SLOT(receiveFreq(freqt))); connect(this, SIGNAL(getFrequency()), rig, SLOT(getFrequency())); connect(this, SIGNAL(getFrequency(unsigned char)), rig, SLOT(getFrequency(unsigned char))); connect(this, SIGNAL(getMode()), rig, SLOT(getMode())); connect(this, SIGNAL(getDataMode()), rig, SLOT(getDataMode())); connect(this, SIGNAL(setDataMode(bool, unsigned char)), rig, SLOT(setDataMode(bool, unsigned char))); connect(this, SIGNAL(getBandStackReg(char,char)), rig, SLOT(getBandStackReg(char,char))); connect(rig, SIGNAL(havePTTStatus(bool)), this, SLOT(receivePTTstatus(bool))); connect(this, SIGNAL(setPTT(bool)), rig, SLOT(setPTT(bool))); connect(this, SIGNAL(getPTT()), rig, SLOT(getPTT())); connect(this, SIGNAL(getVox()), rig, SLOT(getVox())); connect(this, SIGNAL(getMonitor()), rig, SLOT(getMonitor())); connect(this, SIGNAL(getCompressor()), rig, SLOT(getCompressor())); connect(this, SIGNAL(getNB()), rig, SLOT(getNB())); connect(this, SIGNAL(getNR()), rig, SLOT(getNR())); connect(this, SIGNAL(selectVFO(vfo_t)), rig, SLOT(selectVFO(vfo_t))); connect(this, SIGNAL(sendVFOSwap()), rig, SLOT(exchangeVFOs())); connect(this, SIGNAL(sendVFOEqualAB()), rig, SLOT(equalizeVFOsAB())); connect(this, SIGNAL(sendVFOEqualMS()), rig, SLOT(equalizeVFOsMS())); connect(this, SIGNAL(sendCW(QString)), rig, SLOT(sendCW(QString))); connect(this, SIGNAL(stopCW()), rig, SLOT(sendStopCW())); connect(this, SIGNAL(setKeySpeed(unsigned char)), rig, SLOT(setKeySpeed(unsigned char))); connect(this, SIGNAL(getKeySpeed()), rig, SLOT(getKeySpeed())); connect(this, SIGNAL(setCwPitch(unsigned char)), rig, SLOT(setCwPitch(unsigned char))); connect(this, SIGNAL(setDashRatio(unsigned char)), rig, SLOT(setDashRatio(unsigned char))); connect(this, SIGNAL(setCWBreakMode(unsigned char)), rig, SLOT(setBreakIn(unsigned char))); connect(this, SIGNAL(getCWBreakMode()), rig, SLOT(getBreakIn())); connect(this->rig, &rigCommander::haveKeySpeed, [=](const unsigned char& wpm) { cw->handleKeySpeed(wpm); }); connect(this->rig, &rigCommander::haveDashRatio, [=](const unsigned char& ratio) { cw->handleDashRatio(ratio); }); connect(this->rig, &rigCommander::haveCwPitch, [=](const unsigned char& speed) { cw->handlePitch(speed); }); connect(this->rig, &rigCommander::haveCWBreakMode, [=](const unsigned char &bm) { cw->handleBreakInMode(bm);}); connect(rig, SIGNAL(haveBandStackReg(freqt,char,char,bool)), this, SLOT(receiveBandStackReg(freqt,char,char,bool))); connect(this, SIGNAL(setRitEnable(bool)), rig, SLOT(setRitEnable(bool))); connect(this, SIGNAL(setRitValue(int)), rig, SLOT(setRitValue(int))); connect(rig, SIGNAL(haveRitEnabled(bool)), this, SLOT(receiveRITStatus(bool))); connect(rig, SIGNAL(haveRitFrequency(int)), this, SLOT(receiveRITValue(int))); connect(this, SIGNAL(getRitEnabled()), rig, SLOT(getRitEnabled())); connect(this, SIGNAL(getRitValue()), rig, SLOT(getRitValue())); connect(this, SIGNAL(getDebug()), rig, SLOT(getDebug())); connect(this, SIGNAL(spectOutputDisable()), rig, SLOT(disableSpectOutput())); connect(this, SIGNAL(spectOutputEnable()), rig, SLOT(enableSpectOutput())); connect(this, SIGNAL(scopeDisplayDisable()), rig, SLOT(disableSpectrumDisplay())); connect(this, SIGNAL(scopeDisplayEnable()), rig, SLOT(enableSpectrumDisplay())); connect(rig, SIGNAL(haveMode(unsigned char, unsigned char)), this, SLOT(receiveMode(unsigned char, unsigned char))); connect(rig, SIGNAL(haveDataMode(bool)), this, SLOT(receiveDataModeStatus(bool))); connect(rig, SIGNAL(havePassband(quint16)), this, SLOT(receivePassband(quint16))); connect(rig, SIGNAL(haveCwPitch(unsigned char)), this, SLOT(receiveCwPitch(unsigned char))); connect(rig, SIGNAL(haveMonitorGain(unsigned char)), this, SLOT(receiveMonitorGain(unsigned char))); connect(rig, SIGNAL(haveVoxGain(unsigned char)), this, SLOT(receiveVoxGain(unsigned char))); connect(rig, SIGNAL(haveAntiVoxGain(unsigned char)), this, SLOT(receiveAntiVoxGain(unsigned char))); connect(rig, SIGNAL(haveNBLevel(unsigned char)), this, SLOT(receiveNBLevel(unsigned char))); connect(rig, SIGNAL(haveNRLevel(unsigned char)), this, SLOT(receiveNRLevel(unsigned char))); connect(rig, SIGNAL(haveNB(bool)), this, SLOT(receiveNB(bool))); connect(rig, SIGNAL(haveNR(bool)), this, SLOT(receiveNR(bool))); connect(rig, SIGNAL(haveComp(bool)), this, SLOT(receiveComp(bool))); connect(rig, SIGNAL(haveVox(bool)), this, SLOT(receiveVox(bool))); connect(rig, SIGNAL(haveMonitor(bool)), this, SLOT(receiveMonitor(bool))); // Repeater, duplex, and split: connect(rpt, SIGNAL(getDuplexMode()), rig, SLOT(getDuplexMode())); connect(rpt, SIGNAL(setDuplexMode(duplexMode)), rig, SLOT(setDuplexMode(duplexMode))); connect(rig, SIGNAL(haveDuplexMode(duplexMode)), rpt, SLOT(receiveDuplexMode(duplexMode))); connect(this, SIGNAL(getRptDuplexOffset()), rig, SLOT(getRptDuplexOffset())); connect(rig, SIGNAL(haveRptOffsetFrequency(freqt)), rpt, SLOT(handleRptOffsetFrequency(freqt))); // These are the current tone frequency or DCS code selected: connect(rpt, SIGNAL(getTone()), rig, SLOT(getTone())); connect(rpt, SIGNAL(getTSQL()), rig, SLOT(getTSQL())); connect(rpt, SIGNAL(getDTCS()), rig, SLOT(getDTCS())); connect(this->rpt, &repeaterSetup::setTone, [=](const rptrTone_t &t) { issueCmd(cmdSetTone, t);}); connect(this->rpt, &repeaterSetup::setTSQL, [=](const rptrTone_t &t) { issueCmd(cmdSetTSQL, t);}); // TODO: struct with the DCS components and command queue entry connect(rpt, SIGNAL(setDTCS(quint16,bool,bool)), rig, SLOT(setDTCS(quint16,bool,bool))); //connect(rpt, SIGNAL(getRptAccessMode()), rig, SLOT(getRptAccessMode())); connect(this->rpt, &repeaterSetup::getRptAccessMode, [=]() { if(rigCaps.hasAdvancedRptrToneCmds) { issueDelayedCommand(cmdGetRptAccessMode); } else { issueDelayedCommand(cmdGetToneEnabled); issueDelayedCommand(cmdGetTSQLEnabled); } }); connect(this->rpt, &repeaterSetup::setQuickSplit, [=](const bool &qsEnabled) { issueCmd(cmdSetQuickSplit, qsEnabled); }); connect(this, SIGNAL(setQuickSplit(bool)), rig, SLOT(setQuickSplit(bool))); connect(this->rpt, &repeaterSetup::setRptAccessMode, [=](const rptrAccessData_t &rd) { issueCmd(cmdSetRptAccessMode, rd); }); connect(this, SIGNAL(setRepeaterAccessMode(rptrAccessData_t)), rig, SLOT(setRptAccessMode(rptrAccessData_t))); connect(this, SIGNAL(setTone(rptrTone_t)), rig, SLOT(setTone(rptrTone_t))); connect(rig, SIGNAL(haveTone(quint16)), rpt, SLOT(handleTone(quint16))); connect(rig, SIGNAL(haveTSQL(quint16)), rpt, SLOT(handleTSQL(quint16))); connect(rig, SIGNAL(haveDTCS(quint16,bool,bool)), rpt, SLOT(handleDTCS(quint16,bool,bool))); connect(rig, SIGNAL(haveRptAccessMode(rptAccessTxRx)), rpt, SLOT(handleRptAccessMode(rptAccessTxRx))); connect(this->rig, &rigCommander::haveDuplexMode, [=](const duplexMode &dm) { if(dm==dmSplitOn) this->splitModeEnabled = true; else this->splitModeEnabled = false; }); connect(this, SIGNAL(getToneEnabled()), rig, SLOT(getToneEnabled())); connect(this, SIGNAL(getTSQLEnabled()), rig, SLOT(getToneSqlEnabled())); connect(this->rpt, &repeaterSetup::setTransmitFrequency, [=](const freqt &transmitFreq) { issueCmdUniquePriority(cmdSetFreq, transmitFreq);}); connect(this->rpt, &repeaterSetup::setTransmitMode, [=](const mode_info &transmitMode) { issueCmd(cmdSetMode, transmitMode);}); connect(this->rpt, &repeaterSetup::selectVFO, [=](const vfo_t &v) { issueCmd(cmdSelVFO, v);}); connect(this->rpt, &repeaterSetup::equalizeVFOsAB, [=]() { issueDelayedCommand(cmdVFOEqualAB);}); connect(this->rpt, &repeaterSetup::equalizeVFOsMS, [=]() { issueDelayedCommand(cmdVFOEqualMS);}); connect(this->rpt, &repeaterSetup::swapVFOs, [=]() { issueDelayedCommand(cmdVFOSwap);}); connect(this->rpt, &repeaterSetup::setRptDuplexOffset, [=](const freqt &fOffset) { issueCmd(cmdSetRptDuplexOffset, fOffset);}); connect(this->rpt, &repeaterSetup::getRptDuplexOffset, [=]() { issueDelayedCommand(cmdGetRptDuplexOffset);}); connect(this, SIGNAL(setRptDuplexOffset(freqt)), rig, SLOT(setRptDuplexOffset(freqt))); connect(this, SIGNAL(getDuplexMode()), rig, SLOT(getDuplexMode())); connect(this, SIGNAL(getModInput(bool)), rig, SLOT(getModInput(bool))); connect(rig, SIGNAL(haveModInput(rigInput,bool)), this, SLOT(receiveModInput(rigInput, bool))); connect(this, SIGNAL(setModInput(rigInput, bool)), rig, SLOT(setModInput(rigInput,bool))); connect(rig, SIGNAL(haveSpectrumData(QByteArray, double, double)), this, SLOT(receiveSpectrumData(QByteArray, double, double))); connect(rig, SIGNAL(haveSpectrumMode(spectrumMode)), this, SLOT(receiveSpectrumMode(spectrumMode))); connect(rig, SIGNAL(haveScopeOutOfRange(bool)), this, SLOT(handleScopeOutOfRange(bool))); connect(this, SIGNAL(setScopeMode(spectrumMode)), rig, SLOT(setSpectrumMode(spectrumMode))); connect(this, SIGNAL(getScopeMode()), rig, SLOT(getScopeMode())); connect(this, SIGNAL(setFrequency(unsigned char, freqt)), rig, SLOT(setFrequency(unsigned char, freqt))); connect(this, SIGNAL(setScopeEdge(char)), rig, SLOT(setScopeEdge(char))); connect(this, SIGNAL(setScopeSpan(char)), rig, SLOT(setScopeSpan(char))); //connect(this, SIGNAL(getScopeMode()), rig, SLOT(getScopeMode())); connect(this, SIGNAL(getScopeEdge()), rig, SLOT(getScopeEdge())); connect(this, SIGNAL(getScopeSpan()), rig, SLOT(getScopeSpan())); connect(rig, SIGNAL(haveScopeSpan(freqt,bool)), this, SLOT(receiveSpectrumSpan(freqt,bool))); connect(this, SIGNAL(setScopeFixedEdge(double,double,unsigned char)), rig, SLOT(setSpectrumBounds(double,double,unsigned char))); connect(this, SIGNAL(setMode(unsigned char, unsigned char)), rig, SLOT(setMode(unsigned char, unsigned char))); connect(this, SIGNAL(setMode(mode_info)), rig, SLOT(setMode(mode_info))); connect(this, SIGNAL(setVox(bool)), rig, SLOT(setVox(bool))); connect(this, SIGNAL(setMonitor(bool)), rig, SLOT(setMonitor(bool))); connect(this, SIGNAL(setCompressor(bool)), rig, SLOT(setCompressor(bool))); connect(this, SIGNAL(setNB(bool)), rig, SLOT(setNB(bool))); connect(this, SIGNAL(setNR(bool)), rig, SLOT(setNR(bool))); connect(this, SIGNAL(setPassband(quint16)), rig, SLOT(setPassband(quint16))); // Levels (read and write) // Levels: Query: connect(this, SIGNAL(getLevels()), rig, SLOT(getLevels())); connect(this, SIGNAL(getRfGain()), rig, SLOT(getRfGain())); connect(this, SIGNAL(getAfGain()), rig, SLOT(getAfGain())); connect(this, SIGNAL(getSql()), rig, SLOT(getSql())); connect(this, SIGNAL(getIfShift()), rig, SLOT(getIFShift())); connect(this, SIGNAL(getTPBFInner()), rig, SLOT(getTPBFInner())); connect(this, SIGNAL(getTPBFOuter()), rig, SLOT(getTPBFOuter())); connect(this, SIGNAL(getTxPower()), rig, SLOT(getTxLevel())); connect(this, SIGNAL(getMicGain()), rig, SLOT(getMicGain())); connect(this, SIGNAL(getSpectrumRefLevel()), rig, SLOT(getSpectrumRefLevel())); connect(this, SIGNAL(getModInputLevel(rigInput)), rig, SLOT(getModInputLevel(rigInput))); connect(this, SIGNAL(getPassband()), rig, SLOT(getPassband())); connect(this, SIGNAL(getMonitorGain()), rig, SLOT(getMonitorGain())); connect(this, SIGNAL(getVoxGain()), rig, SLOT(getVoxGain())); connect(this, SIGNAL(getAntiVoxGain()), rig, SLOT(getAntiVoxGain())); connect(this, SIGNAL(getNBLevel()), rig, SLOT(getNBLevel())); connect(this, SIGNAL(getNRLevel()), rig, SLOT(getNRLevel())); connect(this, SIGNAL(getCompLevel()), rig, SLOT(getCompLevel())); connect(this, SIGNAL(getCwPitch()), rig, SLOT(getCwPitch())); connect(this, SIGNAL(getDashRatio()), rig, SLOT(getDashRatio())); connect(this, SIGNAL(getPskTone()), rig, SLOT(getPskTone())); connect(this, SIGNAL(getRttyMark()), rig, SLOT(getRttyMark())); connect(this, SIGNAL(getTone()), rig, SLOT(getTone())); connect(this, SIGNAL(getTSQL()), rig, SLOT(getTSQL())); connect(this, SIGNAL(getRptAccessMode()), rig, SLOT(getRptAccessMode())); // Levels: Set: connect(this, SIGNAL(setRfGain(unsigned char)), rig, SLOT(setRfGain(unsigned char))); connect(this, SIGNAL(setAfGain(unsigned char)), rig, SLOT(setAfGain(unsigned char))); connect(this, SIGNAL(setSql(unsigned char)), rig, SLOT(setSquelch(unsigned char))); connect(this, SIGNAL(setIFShift(unsigned char)), rig, SLOT(setIFShift(unsigned char))); connect(this, SIGNAL(setTPBFInner(unsigned char)), rig, SLOT(setTPBFInner(unsigned char))); connect(this, SIGNAL(setTPBFOuter(unsigned char)), rig, SLOT(setTPBFOuter(unsigned char))); connect(this, SIGNAL(setTxPower(unsigned char)), rig, SLOT(setTxPower(unsigned char))); connect(this, SIGNAL(setMicGain(unsigned char)), rig, SLOT(setMicGain(unsigned char))); connect(this, SIGNAL(setMonitorGain(unsigned char)), rig, SLOT(setMonitorGain(unsigned char))); connect(this, SIGNAL(setVoxGain(unsigned char)), rig, SLOT(setVoxGain(unsigned char))); connect(this, SIGNAL(setAntiVoxGain(unsigned char)), rig, SLOT(setAntiVoxGain(unsigned char))); connect(this, SIGNAL(setSpectrumRefLevel(int)), rig, SLOT(setSpectrumRefLevel(int))); connect(this, SIGNAL(setModLevel(rigInput, unsigned char)), rig, SLOT(setModInputLevel(rigInput, unsigned char))); connect(this, SIGNAL(setNBLevel(unsigned char)), rig, SLOT(setNBLevel(unsigned char))); connect(this, SIGNAL(setNBLevel(unsigned char)), rig, SLOT(setNBLevel(unsigned char))); // Levels: handle return on query: connect(rig, SIGNAL(haveRfGain(unsigned char)), this, SLOT(receiveRfGain(unsigned char))); connect(rig, SIGNAL(haveAfGain(unsigned char)), this, SLOT(receiveAfGain(unsigned char))); connect(rig, SIGNAL(haveSql(unsigned char)), this, SLOT(receiveSql(unsigned char))); connect(rig, SIGNAL(haveIFShift(unsigned char)), trxadj, SLOT(updateIFShift(unsigned char))); connect(rig, SIGNAL(haveTPBFInner(unsigned char)), trxadj, SLOT(updateTPBFInner(unsigned char))); connect(rig, SIGNAL(haveTPBFOuter(unsigned char)), trxadj, SLOT(updateTPBFOuter(unsigned char))); connect(rig, SIGNAL(haveTPBFInner(unsigned char)), this, SLOT(receiveTPBFInner(unsigned char))); connect(rig, SIGNAL(haveTPBFOuter(unsigned char)), this, SLOT(receiveTPBFOuter(unsigned char))); connect(rig, SIGNAL(haveTxPower(unsigned char)), this, SLOT(receiveTxPower(unsigned char))); connect(rig, SIGNAL(haveMicGain(unsigned char)), this, SLOT(receiveMicGain(unsigned char))); connect(rig, SIGNAL(haveSpectrumRefLevel(int)), this, SLOT(receiveSpectrumRefLevel(int))); connect(rig, SIGNAL(haveACCGain(unsigned char,unsigned char)), this, SLOT(receiveACCGain(unsigned char,unsigned char))); connect(rig, SIGNAL(haveUSBGain(unsigned char)), this, SLOT(receiveUSBGain(unsigned char))); connect(rig, SIGNAL(haveLANGain(unsigned char)), this, SLOT(receiveLANGain(unsigned char))); //Metering: connect(this, SIGNAL(getMeters(meterKind)), rig, SLOT(getMeters(meterKind))); connect(rig, SIGNAL(haveMeter(meterKind,unsigned char)), this, SLOT(receiveMeter(meterKind,unsigned char))); // Rig and ATU info: connect(this, SIGNAL(startATU()), rig, SLOT(startATU())); connect(this, SIGNAL(setATU(bool)), rig, SLOT(setATU(bool))); connect(this, SIGNAL(getATUStatus()), rig, SLOT(getATUStatus())); connect(this, SIGNAL(getRigID()), rig, SLOT(getRigID())); connect(rig, SIGNAL(haveATUStatus(unsigned char)), this, SLOT(receiveATUStatus(unsigned char))); connect(rig, SIGNAL(haveRigID(rigCapabilities)), this, SLOT(receiveRigID(rigCapabilities))); connect(this, SIGNAL(setAttenuator(unsigned char)), rig, SLOT(setAttenuator(unsigned char))); connect(this, SIGNAL(setPreamp(unsigned char)), rig, SLOT(setPreamp(unsigned char))); connect(this, SIGNAL(setAntenna(unsigned char, bool)), rig, SLOT(setAntenna(unsigned char, bool))); connect(this, SIGNAL(getPreamp()), rig, SLOT(getPreamp())); connect(rig, SIGNAL(havePreamp(unsigned char)), this, SLOT(receivePreamp(unsigned char))); connect(this, SIGNAL(getAttenuator()), rig, SLOT(getAttenuator())); connect(rig, SIGNAL(haveAttenuator(unsigned char)), this, SLOT(receiveAttenuator(unsigned char))); connect(this, SIGNAL(getAntenna()), rig, SLOT(getAntenna())); connect(rig, SIGNAL(haveAntenna(unsigned char,bool)), this, SLOT(receiveAntennaSel(unsigned char,bool))); // Speech (emitted from rig speaker) connect(this, SIGNAL(sayAll()), rig, SLOT(sayAll())); connect(this, SIGNAL(sayFrequency()), rig, SLOT(sayFrequency())); connect(this, SIGNAL(sayMode()), rig, SLOT(sayMode())); // calibration window: connect(cal, SIGNAL(requestRefAdjustCourse()), rig, SLOT(getRefAdjustCourse())); connect(cal, SIGNAL(requestRefAdjustFine()), rig, SLOT(getRefAdjustFine())); connect(rig, SIGNAL(haveRefAdjustCourse(unsigned char)), cal, SLOT(handleRefAdjustCourse(unsigned char))); connect(rig, SIGNAL(haveRefAdjustFine(unsigned char)), cal, SLOT(handleRefAdjustFine(unsigned char))); connect(cal, SIGNAL(setRefAdjustCourse(unsigned char)), rig, SLOT(setRefAdjustCourse(unsigned char))); connect(cal, SIGNAL(setRefAdjustFine(unsigned char)), rig, SLOT(setRefAdjustFine(unsigned char))); // Date and Time: connect(this, SIGNAL(setTime(timekind)), rig, SLOT(setTime(timekind))); connect(this, SIGNAL(setDate(datekind)), rig, SLOT(setDate(datekind))); connect(this, SIGNAL(setUTCOffset(timekind)), rig, SLOT(setUTCOffset(timekind))); } //void wfmain::removeRigConnections() //{ //} void wfmain::makeRig() { if (rigThread == Q_NULLPTR) { rig = new rigCommander(); rigThread = new QThread(this); rigThread->setObjectName("rigCommander()"); // Thread: rig->moveToThread(rigThread); connect(rigThread, SIGNAL(started()), rig, SLOT(process())); connect(rigThread, SIGNAL(finished()), rig, SLOT(deleteLater())); rigThread->start(); // Rig status and Errors: connect(rig, SIGNAL(havePortError(errorType)), this, SLOT(receivePortError(errorType))); connect(rig, SIGNAL(haveStatusUpdate(networkStatus)), this, SLOT(receiveStatusUpdate(networkStatus))); connect(rig, SIGNAL(haveNetworkAudioLevels(networkAudioLevels)), this, SLOT(receiveNetworkAudioLevels(networkAudioLevels))); connect(rig, SIGNAL(requestRadioSelection(QList)), this, SLOT(radioSelection(QList))); connect(rig, SIGNAL(setRadioUsage(quint8, quint8, QString, QString)), selRad, SLOT(setInUse(quint8, quint8, QString, QString))); connect(selRad, SIGNAL(selectedRadio(quint8)), rig, SLOT(setCurrentRadio(quint8))); // Rig comm setup: connect(this, SIGNAL(sendCommSetup(unsigned char, udpPreferences, audioSetup, audioSetup, QString, quint16)), rig, SLOT(commSetup(unsigned char, udpPreferences, audioSetup, audioSetup, QString, quint16))); connect(this, SIGNAL(sendCommSetup(unsigned char, QString, quint32,QString, quint16,quint8)), rig, SLOT(commSetup(unsigned char, QString, quint32,QString, quint16,quint8))); connect(this, SIGNAL(setRTSforPTT(bool)), rig, SLOT(setRTSforPTT(bool))); connect(rig, SIGNAL(haveBaudRate(quint32)), this, SLOT(receiveBaudRate(quint32))); connect(this, SIGNAL(sendCloseComm()), rig, SLOT(closeComm())); connect(this, SIGNAL(sendChangeLatency(quint16)), rig, SLOT(changeLatency(quint16))); connect(this, SIGNAL(getRigCIV()), rig, SLOT(findRigs())); connect(this, SIGNAL(setRigID(unsigned char)), rig, SLOT(setRigID(unsigned char))); connect(rig, SIGNAL(discoveredRigID(rigCapabilities)), this, SLOT(receiveFoundRigID(rigCapabilities))); connect(rig, SIGNAL(commReady()), this, SLOT(receiveCommReady())); connect(this, SIGNAL(requestRigState()), rig, SLOT(sendState())); connect(this, SIGNAL(stateUpdated()), rig, SLOT(stateUpdated())); connect(rig, SIGNAL(stateInfo(rigstate*)), this, SLOT(receiveStateInfo(rigstate*))); if (rigCtl != Q_NULLPTR) { connect(rig, SIGNAL(stateInfo(rigstate*)), rigCtl, SLOT(receiveStateInfo(rigstate*))); connect(rigCtl, SIGNAL(stateUpdated()), rig, SLOT(stateUpdated())); } // Create link for server so it can have easy access to rig. if (serverConfig.rigs.first() != Q_NULLPTR) { serverConfig.rigs.first()->rig = rig; serverConfig.rigs.first()->rigThread = rigThread; } } } void wfmain::removeRig() { if (rigThread != Q_NULLPTR) { if (rigCtl != Q_NULLPTR) { rigCtl->disconnect(); } rigThread->disconnect(); rig->disconnect(); delete rigThread; delete rig; rig = Q_NULLPTR; } } void wfmain::findSerialPort() { // Find the ICOM radio connected, or, if none, fall back to OS default. // qInfo(logSystem()) << "Searching for serial port..."; bool found = false; // First try to find first Icom port: foreach(const QSerialPortInfo & serialPortInfo, QSerialPortInfo::availablePorts()) { if (serialPortInfo.serialNumber().left(3) == "IC-") { qInfo(logSystem()) << "Serial Port found: " << serialPortInfo.portName() << "Manufacturer:" << serialPortInfo.manufacturer() << "Product ID" << serialPortInfo.description() << "S/N" << serialPortInfo.serialNumber(); #if defined(Q_OS_LINUX) || defined(Q_OS_MAC) serialPortRig = (QString("/dev/") + serialPortInfo.portName()); #else serialPortRig = serialPortInfo.portName(); #endif found = true; break; } } if (!found) { QDirIterator it73("/dev/serial/by-id", QStringList() << "*IC-7300*", QDir::Files, QDirIterator::Subdirectories); QDirIterator it97("/dev/serial", QStringList() << "*IC-9700*A*", QDir::Files, QDirIterator::Subdirectories); QDirIterator it785x("/dev/serial", QStringList() << "*IC-785*A*", QDir::Files, QDirIterator::Subdirectories); QDirIterator it705("/dev/serial", QStringList() << "*IC-705*A", QDir::Files, QDirIterator::Subdirectories); QDirIterator it7610("/dev/serial", QStringList() << "*IC-7610*A", QDir::Files, QDirIterator::Subdirectories); QDirIterator itR8600("/dev/serial", QStringList() << "*IC-R8600*A", QDir::Files, QDirIterator::Subdirectories); if(!it73.filePath().isEmpty()) { // IC-7300 serialPortRig = it73.filePath(); // first } else if(!it97.filePath().isEmpty()) { // IC-9700 serialPortRig = it97.filePath(); } else if(!it785x.filePath().isEmpty()) { // IC-785x serialPortRig = it785x.filePath(); } else if(!it705.filePath().isEmpty()) { // IC-705 serialPortRig = it705.filePath(); } else if(!it7610.filePath().isEmpty()) { // IC-7610 serialPortRig = it7610.filePath(); } else if(!itR8600.filePath().isEmpty()) { // IC-R8600 serialPortRig = itR8600.filePath(); } else { //fall back: qInfo(logSystem()) << "Could not find Icom serial port. Falling back to OS default. Use --port to specify, or modify preferences."; #ifdef Q_OS_MAC serialPortRig = QString("/dev/tty.SLAB_USBtoUART"); #endif #ifdef Q_OS_LINUX serialPortRig = QString("/dev/ttyUSB0"); #endif #ifdef Q_OS_WIN serialPortRig = QString("COM1"); #endif } } } void wfmain::receiveCommReady() { qInfo(logSystem()) << "Received CommReady!! "; if(!usingLAN) { // usingLAN gets set when we emit the sendCommSetup signal. // If we're not using the LAN, then we're on serial, and // we already know the baud rate and can calculate the timing parameters. calculateTimingParameters(); } if(prefs.radioCIVAddr == 0) { // tell rigCommander to broadcast a request for all rig IDs. // qInfo(logSystem()) << "Beginning search from wfview for rigCIV (auto-detection broadcast)"; ui->statusBar->showMessage(QString("Searching CI-V bus for connected radios."), 1000); emit getRigCIV(); issueDelayedCommand(cmdGetRigCIV); delayedCommand->start(); } else { // don't bother, they told us the CIV they want, stick with it. // We still query the rigID to find the model, but at least we know the CIV. qInfo(logSystem()) << "Skipping automatic CIV, using user-supplied value of " << prefs.radioCIVAddr; showStatusBarText(QString("Using user-supplied radio CI-V address of 0x%1").arg(prefs.radioCIVAddr, 2, 16)); if(prefs.CIVisRadioModel) { qInfo(logSystem()) << "Skipping Rig ID query, using user-supplied model from CI-V address: " << prefs.radioCIVAddr; emit setCIVAddr(prefs.radioCIVAddr); emit setRigID(prefs.radioCIVAddr); } else { emit setCIVAddr(prefs.radioCIVAddr); emit getRigID(); issueDelayedCommand(cmdGetRigID); delayedCommand->start(); } } } void wfmain::receiveFoundRigID(rigCapabilities rigCaps) { // Entry point for unknown rig being identified at the start of the program. //now we know what the rig ID is: //qInfo(logSystem()) << "In wfview, we now have a reply to our request for rig identity sent to CIV BROADCAST."; if(rig->usingLAN()) { usingLAN = true; } else { usingLAN = false; } receiveRigID(rigCaps); getInitialRigState(); return; } void wfmain::receivePortError(errorType err) { if (err.alert) { connectionHandler(false); // Force disconnect QMessageBox::critical(this, err.device, err.message, QMessageBox::Ok); } else { qInfo(logSystem()) << "wfmain: received error for device: " << err.device << " with message: " << err.message; ui->statusBar->showMessage(QString("ERROR: using device ").append(err.device).append(": ").append(err.message), 10000); } // TODO: Dialog box, exit, etc } void wfmain::receiveStatusUpdate(networkStatus status) { this->rigStatus->setText(status.message); selRad->audioOutputLevel(status.rxAudioLevel); selRad->audioInputLevel(status.txAudioLevel); //qInfo(logSystem()) << "Got Status Update" << status.rxAudioLevel; } void wfmain::receiveNetworkAudioLevels(networkAudioLevels l) { /* meterKind m2mtr = ui->meter2Widget->getMeterType(); if(m2mtr == meterAudio) { if(amTransmitting) { if(l.haveTxLevels) ui->meter2Widget->setLevels(l.txAudioRMS, l.txAudioPeak); } else { if(l.haveRxLevels) ui->meter2Widget->setLevels(l.rxAudioRMS, l.rxAudioPeak); } } else if (m2mtr == meterTxMod) { if(l.haveTxLevels) ui->meter2Widget->setLevels(l.txAudioRMS, l.txAudioPeak); } else if (m2mtr == meterRxAudio) { if(l.haveRxLevels) ui->meter2Widget->setLevels(l.rxAudioRMS, l.rxAudioPeak); } */ meterKind m = meterNone; if(l.haveRxLevels) { m = meterRxAudio; receiveMeter(m, l.rxAudioPeak); } if(l.haveTxLevels) { m = meterTxMod; receiveMeter(m, l.txAudioPeak); } } void wfmain::setupPlots() { spectrumDrawLock = true; plot = ui->plot; wf = ui->waterfall; passbandIndicator = new QCPItemRect(plot); passbandIndicator->setAntialiased(true); passbandIndicator->setPen(QPen(Qt::red)); passbandIndicator->setBrush(QBrush(Qt::red)); passbandIndicator->setSelectable(true); pbtIndicator = new QCPItemRect(plot); pbtIndicator->setAntialiased(true); pbtIndicator->setPen(QPen(Qt::red)); pbtIndicator->setBrush(QBrush(Qt::red)); pbtIndicator->setSelectable(true); pbtIndicator->setVisible(false); freqIndicatorLine = new QCPItemLine(plot); freqIndicatorLine->setAntialiased(true); freqIndicatorLine->setPen(QPen(Qt::blue)); /* text = new QCPItemText(plot); text->setAntialiased(true); text->setColor(QColor(Qt::red)); text->setText("TEST"); text->position->setCoords(14.195, rigCaps.spectAmpMax); text->setFont(QFont(font().family(), 12)); */ ui->plot->addGraph(); // primary ui->plot->addGraph(0, 0); // secondary, peaks, same axis as first. ui->plot->addLayer( "Top Layer", ui->plot->layer("main")); ui->plot->graph(0)->setLayer("Top Layer"); ui->waterfall->addGraph(); colorMap = new QCPColorMap(wf->xAxis, wf->yAxis); colorMapData = NULL; #if QCUSTOMPLOT_VERSION < 0x020001 wf->addPlottable(colorMap); #endif colorScale = new QCPColorScale(wf); ui->tabWidget->setCurrentIndex(0); QColor color(20+200/4.0*1,70*(1.6-1/4.0), 150, 150); plot->graph(1)->setLineStyle(QCPGraph::lsLine); plot->graph(1)->setPen(QPen(color.lighter(200))); plot->graph(1)->setBrush(QBrush(color)); freqIndicatorLine->start->setCoords(0.5, 0); freqIndicatorLine->end->setCoords(0.5, 160); passbandIndicator->topLeft->setCoords(0.5, 0); passbandIndicator->bottomRight->setCoords(0.5, 160); pbtIndicator->topLeft->setCoords(0.5, 0); pbtIndicator->bottomRight->setCoords(0.5, 160); // Plot user interaction connect(plot, SIGNAL(mouseDoubleClick(QMouseEvent*)), this, SLOT(handlePlotDoubleClick(QMouseEvent*))); connect(wf, SIGNAL(mouseDoubleClick(QMouseEvent*)), this, SLOT(handleWFDoubleClick(QMouseEvent*))); connect(plot, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(handlePlotClick(QMouseEvent*))); connect(wf, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(handleWFClick(QMouseEvent*))); connect(plot, SIGNAL(mouseRelease(QMouseEvent*)), this, SLOT(handlePlotMouseRelease(QMouseEvent*))); connect(plot, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(handlePlotMouseMove(QMouseEvent *))); connect(wf, SIGNAL(mouseWheel(QWheelEvent*)), this, SLOT(handleWFScroll(QWheelEvent*))); connect(plot, SIGNAL(mouseWheel(QWheelEvent*)), this, SLOT(handlePlotScroll(QWheelEvent*))); spectrumDrawLock = false; } void wfmain::setupMainUI() { createSettingsListItems(); ui->bandStkLastUsedBtn->setVisible(false); ui->bandStkVoiceBtn->setVisible(false); ui->bandStkDataBtn->setVisible(false); ui->bandStkCWBtn->setVisible(false); ui->baudRateCombo->insertItem(0, QString("115200"), 115200); ui->baudRateCombo->insertItem(1, QString("57600"), 57600); ui->baudRateCombo->insertItem(2, QString("38400"), 38400); ui->baudRateCombo->insertItem(3, QString("28800"), 28800); ui->baudRateCombo->insertItem(4, QString("19200"), 19200); ui->baudRateCombo->insertItem(5, QString("9600"), 9600); ui->baudRateCombo->insertItem(6, QString("4800"), 4800); ui->baudRateCombo->insertItem(7, QString("2400"), 2400); ui->baudRateCombo->insertItem(8, QString("1200"), 1200); ui->baudRateCombo->insertItem(9, QString("300"), 300); ui->spectrumModeCombo->addItem("Center", (spectrumMode)spectModeCenter); ui->spectrumModeCombo->addItem("Fixed", (spectrumMode)spectModeFixed); ui->spectrumModeCombo->addItem("Scroll-C", (spectrumMode)spectModeScrollC); ui->spectrumModeCombo->addItem("Scroll-F", (spectrumMode)spectModeScrollF); ui->modeSelectCombo->addItem("LSB", 0x00); ui->modeSelectCombo->addItem("USB", 0x01); ui->modeSelectCombo->addItem("FM", 0x05); ui->modeSelectCombo->addItem("AM", 0x02); ui->modeSelectCombo->addItem("CW", 0x03); ui->modeSelectCombo->addItem("CW-R", 0x07); ui->modeSelectCombo->addItem("RTTY", 0x04); ui->modeSelectCombo->addItem("RTTY-R", 0x08); ui->modeFilterCombo->addItem("1", 1); ui->modeFilterCombo->addItem("2", 2); ui->modeFilterCombo->addItem("3", 3); ui->modeFilterCombo->addItem("Setup...", 99); ui->tuningStepCombo->blockSignals(true); ui->tuningStepCombo->addItem("1 Hz", (unsigned int) 1); ui->tuningStepCombo->addItem("10 Hz", (unsigned int) 10); ui->tuningStepCombo->addItem("100 Hz", (unsigned int) 100); ui->tuningStepCombo->addItem("500 Hz", (unsigned int) 500); ui->tuningStepCombo->addItem("1 kHz", (unsigned int) 1000); ui->tuningStepCombo->addItem("2.5 kHz", (unsigned int) 2500); ui->tuningStepCombo->addItem("5 kHz", (unsigned int) 5000); ui->tuningStepCombo->addItem("6.25 kHz", (unsigned int) 6250); // PMR ui->tuningStepCombo->addItem("8.333 kHz", (unsigned int) 8333); // airband stepsize ui->tuningStepCombo->addItem("9 kHz", (unsigned int) 9000); // European medium wave stepsize ui->tuningStepCombo->addItem("10 kHz", (unsigned int) 10000); ui->tuningStepCombo->addItem("12.5 kHz", (unsigned int) 12500); ui->tuningStepCombo->addItem("25 kHz", (unsigned int) 25000); ui->tuningStepCombo->addItem("100 kHz", (unsigned int) 100000); ui->tuningStepCombo->addItem("250 kHz", (unsigned int) 250000); ui->tuningStepCombo->addItem("1 MHz", (unsigned int) 1000000); //for 23 cm and HF ui->tuningStepCombo->setCurrentIndex(2); ui->tuningStepCombo->blockSignals(false); ui->wfthemeCombo->addItem("Jet", QCPColorGradient::gpJet); ui->wfthemeCombo->addItem("Cold", QCPColorGradient::gpCold); ui->wfthemeCombo->addItem("Hot", QCPColorGradient::gpHot); ui->wfthemeCombo->addItem("Thermal", QCPColorGradient::gpThermal); ui->wfthemeCombo->addItem("Night", QCPColorGradient::gpNight); ui->wfthemeCombo->addItem("Ion", QCPColorGradient::gpIon); ui->wfthemeCombo->addItem("Gray", QCPColorGradient::gpGrayscale); ui->wfthemeCombo->addItem("Geography", QCPColorGradient::gpGeography); ui->wfthemeCombo->addItem("Hues", QCPColorGradient::gpHues); ui->wfthemeCombo->addItem("Polar", QCPColorGradient::gpPolar); ui->wfthemeCombo->addItem("Spectrum", QCPColorGradient::gpSpectrum); ui->wfthemeCombo->addItem("Candy", QCPColorGradient::gpCandy); ui->meter2selectionCombo->addItem("None", meterNone); ui->meter2selectionCombo->addItem("SWR", meterSWR); ui->meter2selectionCombo->addItem("ALC", meterALC); ui->meter2selectionCombo->addItem("Compression", meterComp); ui->meter2selectionCombo->addItem("Voltage", meterVoltage); ui->meter2selectionCombo->addItem("Current", meterCurrent); ui->meter2selectionCombo->addItem("Center", meterCenter); ui->meter2selectionCombo->addItem("TxRxAudio", meterAudio); ui->meter2selectionCombo->addItem("RxAudio", meterRxAudio); ui->meter2selectionCombo->addItem("TxAudio", meterTxMod); ui->meter2Widget->hide(); ui->meter2selectionCombo->show(); ui->meter2selectionCombo->setCurrentIndex((int)prefs.meter2Type); ui->secondaryMeterSelectionLabel->show(); // Future ideas: //ui->meter2selectionCombo->addItem("Transmit Audio", meterTxMod); //ui->meter2selectionCombo->addItem("Receive Audio", meterRxAudio); //ui->meter2selectionCombo->addItem("Latency", meterLatency); spans << "2.5k" << "5.0k" << "10k" << "25k"; spans << "50k" << "100k" << "250k" << "500k"; ui->scopeBWCombo->insertItems(0, spans); edges << "1" << "2" << "3" << "4"; ui->scopeEdgeCombo->insertItems(0, edges); ui->splitter->setHandleWidth(5); // Set scroll wheel response (tick interval) // and set arrow key response (single step) ui->rfGainSlider->setTickInterval(100); ui->rfGainSlider->setSingleStep(10); ui->afGainSlider->setTickInterval(100); ui->afGainSlider->setSingleStep(10); ui->sqlSlider->setTickInterval(100); ui->sqlSlider->setSingleStep(10); ui->txPowerSlider->setTickInterval(100); ui->txPowerSlider->setSingleStep(10); ui->micGainSlider->setTickInterval(100); ui->micGainSlider->setSingleStep(10); ui->scopeRefLevelSlider->setTickInterval(50); ui->scopeRefLevelSlider->setSingleStep(20); ui->freqMhzLineEdit->setValidator( new QDoubleValidator(0, 100, 6, this)); ui->controlPortTxt->setValidator(new QIntValidator(this)); qDebug(logSystem()) << "Running with debugging options enabled."; #ifdef QT_DEBUG ui->debugBtn->setVisible(true); ui->satOpsBtn->setVisible(true); #else ui->debugBtn->setVisible(false); ui->satOpsBtn->setVisible(false); #endif rigStatus = new QLabel(this); ui->statusBar->addPermanentWidget(rigStatus); ui->statusBar->showMessage("Connecting to rig...", 1000); pttLed = new QLedLabel(this); ui->statusBar->addPermanentWidget(pttLed); pttLed->setState(QLedLabel::State::StateOk); pttLed->setToolTip("Receiving"); connectedLed = new QLedLabel(this); ui->statusBar->addPermanentWidget(connectedLed); rigName = new QLabel(this); rigName->setAlignment(Qt::AlignRight); ui->statusBar->addPermanentWidget(rigName); rigName->setText("NONE"); rigName->setFixedWidth(60); freq.MHzDouble = 0.0; freq.Hz = 0; oldFreqDialVal = ui->freqDial->value(); ui->tuneLockChk->setChecked(false); freqLock = false; connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(updateSizes(int))); connect( ui->txPowerSlider, &QSlider::valueChanged, [=](const int &newValue) { statusFromSliderPercent("Tx Power", newValue);} ); connect( ui->rfGainSlider, &QSlider::valueChanged, [=](const int &newValue) { statusFromSliderPercent("RF Gain", newValue);} ); connect( ui->afGainSlider, &QSlider::valueChanged, [=](const int &newValue) { statusFromSliderPercent("AF Gain", newValue);} ); connect( ui->micGainSlider, &QSlider::valueChanged, [=](const int &newValue) { statusFromSliderPercent("TX Audio Gain", newValue);} ); connect( ui->sqlSlider, &QSlider::valueChanged, [=](const int &newValue) { statusFromSliderPercent("Squelch", newValue);} ); // -200 0 +200.. take log? connect( ui->scopeRefLevelSlider, &QSlider::valueChanged, [=](const int &newValue) { statusFromSliderRaw("Scope Ref Level", newValue);} ); connect( ui->wfLengthSlider, &QSlider::valueChanged, [=](const int &newValue) { statusFromSliderRaw("Waterfall Length", newValue);} ); connect(this->trxadj, &transceiverAdjustments::setIFShift, [=](const unsigned char &newValue) { issueCmdUniquePriority(cmdSetIFShift, newValue);} ); connect(this->trxadj, &transceiverAdjustments::setTPBFInner, [=](const unsigned char &newValue) { issueCmdUniquePriority(cmdSetTPBFInner, newValue);} ); connect(this->trxadj, &transceiverAdjustments::setTPBFOuter, [=](const unsigned char &newValue) { issueCmdUniquePriority(cmdSetTPBFOuter, newValue);} ); connect(this->trxadj, &transceiverAdjustments::setPassband, [=](const quint16 &passbandHz) { issueCmdUniquePriority(cmdSetPassband, passbandHz);} ); connect(this->cw, &cwSender::sendCW, [=](const QString &cwMessage) { issueCmd(cmdSendCW, cwMessage);}); connect(this->cw, &cwSender::stopCW, [=]() { issueDelayedCommand(cmdStopCW);}); connect(this->cw, &cwSender::setBreakInMode, [=](const unsigned char &bmode) { issueCmd(cmdSetBreakMode, bmode);}); connect(this->cw, &cwSender::setKeySpeed, [=](const unsigned char& wpm) { issueCmd(cmdSetKeySpeed, wpm); }); connect(this->cw, &cwSender::setDashRatio, [=](const unsigned char& ratio) { issueCmd(cmdSetDashRatio, ratio); }); connect(this->cw, &cwSender::setPitch, [=](const unsigned char& pitch) { issueCmd(cmdSetCwPitch, pitch); }); connect(this->cw, &cwSender::getCWSettings, [=]() { issueDelayedCommand(cmdGetKeySpeed); issueDelayedCommand(cmdGetBreakMode); issueDelayedCommand(cmdGetCwPitch); issueDelayedCommand(cmdGetDashRatio); }); } void wfmain::prepareSettingsWindow() { settingsTabisAttached = true; settingsWidgetWindow = new QWidget; settingsWidgetLayout = new QGridLayout; settingsWidgetTab = new QTabWidget; settingsWidgetWindow->setLayout(settingsWidgetLayout); settingsWidgetLayout->addWidget(settingsWidgetTab); settingsWidgetWindow->setWindowFlag(Qt::WindowCloseButtonHint, false); //settingsWidgetWindow->setWindowFlag(Qt::WindowMinimizeButtonHint, false); //settingsWidgetWindow->setWindowFlag(Qt::WindowMaximizeButtonHint, false); // TODO: Capture an event when the window closes and handle accordingly. } void wfmain::updateSizes(int tabIndex) { // This function does nothing unless you are using a rig without spectrum. // This is a hack. It is not great, but it seems to work ok. if(!rigCaps.hasSpectrum) { // Set "ignore" size policy for non-selected tabs: for(int i=1;itabWidget->count();i++) if((i!=tabIndex)) ui->tabWidget->widget(i)->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); // allows size to be any size that fits the tab bar if(tabIndex==0) { ui->tabWidget->widget(0)->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); ui->tabWidget->widget(0)->setMaximumSize(ui->tabWidget->widget(0)->minimumSizeHint()); ui->tabWidget->widget(0)->adjustSize(); // tab this->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); this->setMaximumSize(QSize(940,350)); this->setMinimumSize(QSize(940,350)); resize(minimumSize()); adjustSize(); // main window } else { // At some other tab, with or without spectrum: ui->tabWidget->widget(tabIndex)->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); this->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); this->setMinimumSize(QSize(1024, 600)); // not large enough for settings tab this->setMaximumSize(QSize(65535,65535)); resize(minimumSize()); adjustSize(); } } else { ui->tabWidget->widget(tabIndex)->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); ui->tabWidget->widget(tabIndex)->setMaximumSize(65535,65535); //ui->tabWidget->widget(0)->setMinimumSize(); } } void wfmain::getSettingsFilePath(QString settingsFile) { if (settingsFile.isNull()) { settings = new QSettings(); } else { QString file = settingsFile; QFile info(settingsFile); QString path=""; if (!QFileInfo(info).isAbsolute()) { path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); if (path.isEmpty()) { path = QDir::homePath(); } path = path + "/"; file = info.fileName(); } settings = new QSettings(path + file, QSettings::Format::IniFormat); } } void wfmain::setInitialTiming() { loopTickCounter = 0; delayedCmdIntervalLAN_ms = 70; // interval for regular delayed commands, including initial rig/UI state queries delayedCmdIntervalSerial_ms = 100; // interval for regular delayed commands, including initial rig/UI state queries delayedCmdStartupInterval_ms = 250; // interval for rigID polling delayedCommand = new QTimer(this); delayedCommand->setInterval(delayedCmdStartupInterval_ms); // 250ms until we find rig civ and id, then 100ms. delayedCommand->setSingleShot(false); connect(delayedCommand, SIGNAL(timeout()), this, SLOT(sendRadioCommandLoop())); pttTimer = new QTimer(this); pttTimer->setInterval(180*1000); // 3 minute max transmit time in ms pttTimer->setSingleShot(true); connect(pttTimer, SIGNAL(timeout()), this, SLOT(handlePttLimit())); timeSync = new QTimer(this); connect(timeSync, SIGNAL(timeout()), this, SLOT(setRadioTimeDateSend())); waitingToSetTimeDate = false; lastFreqCmdTime_ms = QDateTime::currentMSecsSinceEpoch() - 5000; // 5 seconds ago } void wfmain::setServerToPrefs() { // Start server if enabled in config ui->serverSetupGroup->setEnabled(serverConfig.enabled); if (serverThread != Q_NULLPTR) { serverThread->quit(); serverThread->wait(); serverThread = Q_NULLPTR; udp = Q_NULLPTR; ui->statusBar->showMessage(QString("Server disabled"), 1000); } if (serverConfig.enabled) { serverConfig.lan = prefs.enableLAN; udp = new udpServer(&serverConfig); serverThread = new QThread(this); udp->moveToThread(serverThread); connect(this, SIGNAL(initServer()), udp, SLOT(init())); connect(serverThread, SIGNAL(finished()), udp, SLOT(deleteLater())); if (rig != Q_NULLPTR) { connect(rig, SIGNAL(haveAudioData(audioPacket)), udp, SLOT(receiveAudioData(audioPacket))); // Need to add a signal/slot for audio from the client to rig. //connect(udp, SIGNAL(haveAudioData(audioPacket)), rig, SLOT(receiveAudioData(audioPacket))); connect(rig, SIGNAL(haveDataForServer(QByteArray)), udp, SLOT(dataForServer(QByteArray))); connect(udp, SIGNAL(haveDataFromServer(QByteArray)), rig, SLOT(dataFromServer(QByteArray))); } if (serverConfig.lan) { connect(udp, SIGNAL(haveNetworkStatus(networkStatus)), this, SLOT(receiveStatusUpdate(networkStatus))); } else { qInfo(logAudio()) << "Audio Input device " << serverConfig.rigs.first()->rxAudioSetup.name; qInfo(logAudio()) << "Audio Output device " << serverConfig.rigs.first()->txAudioSetup.name; } serverThread->start(); emit initServer(); connect(this, SIGNAL(sendRigCaps(rigCapabilities)), udp, SLOT(receiveRigCaps(rigCapabilities))); ui->statusBar->showMessage(QString("Server enabled"), 1000); } } void wfmain::setUIToPrefs() { ui->fullScreenChk->setChecked(prefs.useFullScreen); on_fullScreenChk_clicked(prefs.useFullScreen); ui->useSystemThemeChk->setChecked(prefs.useSystemTheme); on_useSystemThemeChk_clicked(prefs.useSystemTheme); underlayMode = prefs.underlayMode; switch(underlayMode) { case underlayNone: ui->underlayNone->setChecked(true); break; case underlayPeakHold: ui->underlayPeakHold->setChecked(true); break; case underlayPeakBuffer: ui->underlayPeakBuffer->setChecked(true); break; case underlayAverageBuffer: ui->underlayAverageBuffer->setChecked(true); break; default: break; } ui->underlayBufferSlider->setValue(prefs.underlayBufferSize); on_underlayBufferSlider_valueChanged(prefs.underlayBufferSize); ui->wfAntiAliasChk->setChecked(prefs.wfAntiAlias); on_wfAntiAliasChk_clicked(prefs.wfAntiAlias); ui->wfInterpolateChk->setChecked(prefs.wfInterpolate); on_wfInterpolateChk_clicked(prefs.wfInterpolate); ui->wfLengthSlider->setValue(prefs.wflength); prepareWf(prefs.wflength); preparePlasma(); ui->topLevelSlider->setValue(prefs.plotCeiling); ui->botLevelSlider->setValue(prefs.plotFloor); plot->yAxis->setRange(QCPRange(prefs.plotFloor, prefs.plotCeiling)); colorMap->setDataRange(QCPRange(prefs.plotFloor, prefs.plotCeiling)); colorPrefsType p; for(int pn=0; pn < numColorPresetsTotal; pn++) { p = colorPreset[pn]; if(p.presetName != Q_NULLPTR) ui->colorPresetCombo->setItemText(pn, *p.presetName); } ui->colorPresetCombo->setCurrentIndex(prefs.currentColorPresetNumber); loadColorPresetToUIandPlots(prefs.currentColorPresetNumber); ui->wfthemeCombo->setCurrentIndex(ui->wfthemeCombo->findData(prefs.wftheme)); colorMap->setGradient(static_cast(prefs.wftheme)); ui->tuningFloorZerosChk->blockSignals(true); ui->tuningFloorZerosChk->setChecked(prefs.niceTS); ui->tuningFloorZerosChk->blockSignals(false); ui->autoSSBchk->blockSignals(true); ui->autoSSBchk->setChecked(prefs.automaticSidebandSwitching); ui->autoSSBchk->blockSignals(false); ui->useCIVasRigIDChk->blockSignals(true); ui->useCIVasRigIDChk->setChecked(prefs.CIVisRadioModel); ui->useCIVasRigIDChk->blockSignals(false); } void wfmain::setSerialDevicesUI() { ui->serialDeviceListCombo->blockSignals(true); ui->serialDeviceListCombo->addItem("Auto", 0); int i = 0; foreach(const QSerialPortInfo & serialPortInfo, QSerialPortInfo::availablePorts()) { portList.append(serialPortInfo.portName()); #if defined(Q_OS_LINUX) || defined(Q_OS_MAC) ui->serialDeviceListCombo->addItem(QString("/dev/") + serialPortInfo.portName(), i++); #else ui->serialDeviceListCombo->addItem(serialPortInfo.portName(), i++); //qInfo(logSystem()) << "Serial Port found: " << serialPortInfo.portName() << "Manufacturer:" << serialPortInfo.manufacturer() << "Product ID" << serialPortInfo.description() << "S/N" << serialPortInfo.serialNumber(); #endif } #if defined(Q_OS_LINUX) || defined(Q_OS_MAC) ui->serialDeviceListCombo->addItem("Manual...", 256); #endif ui->serialDeviceListCombo->blockSignals(false); ui->vspCombo->blockSignals(true); #ifdef Q_OS_WIN ui->vspCombo->addItem(QString("None"), i++); foreach(const QSerialPortInfo & serialPortInfo, QSerialPortInfo::availablePorts()) { ui->vspCombo->addItem(serialPortInfo.portName()); } #else // Provide reasonable names for the symbolic link to the pty device #ifdef Q_OS_MAC QString vspName = QStandardPaths::standardLocations(QStandardPaths::DownloadLocation)[0] + "/rig-pty"; #else QString vspName = QDir::homePath() + "/rig-pty"; #endif for (i = 1; i < 8; i++) { ui->vspCombo->addItem(vspName + QString::number(i)); if (QFile::exists(vspName + QString::number(i))) { auto* model = qobject_cast(ui->vspCombo->model()); auto* item = model->item(ui->vspCombo->count() - 1); item->setEnabled(false); } } ui->vspCombo->addItem(vspName + QString::number(i)); ui->vspCombo->addItem(QString("None"), i++); #endif ui->vspCombo->setEditable(true); ui->vspCombo->blockSignals(false); } void wfmain::setupKeyShortcuts() { keyF1 = new QShortcut(this); keyF1->setKey(Qt::Key_F1); connect(keyF1, SIGNAL(activated()), this, SLOT(shortcutF1())); keyF2 = new QShortcut(this); keyF2->setKey(Qt::Key_F2); connect(keyF2, SIGNAL(activated()), this, SLOT(shortcutF2())); keyF3 = new QShortcut(this); keyF3->setKey(Qt::Key_F3); connect(keyF3, SIGNAL(activated()), this, SLOT(shortcutF3())); keyF4 = new QShortcut(this); keyF4->setKey(Qt::Key_F4); connect(keyF4, SIGNAL(activated()), this, SLOT(shortcutF4())); keyF5 = new QShortcut(this); keyF5->setKey(Qt::Key_F5); connect(keyF5, SIGNAL(activated()), this, SLOT(shortcutF5())); keyF6 = new QShortcut(this); keyF6->setKey(Qt::Key_F6); connect(keyF6, SIGNAL(activated()), this, SLOT(shortcutF6())); keyF7 = new QShortcut(this); keyF7->setKey(Qt::Key_F7); connect(keyF7, SIGNAL(activated()), this, SLOT(shortcutF7())); keyF8 = new QShortcut(this); keyF8->setKey(Qt::Key_F8); connect(keyF8, SIGNAL(activated()), this, SLOT(shortcutF8())); keyF9 = new QShortcut(this); keyF9->setKey(Qt::Key_F9); connect(keyF9, SIGNAL(activated()), this, SLOT(shortcutF9())); keyF10 = new QShortcut(this); keyF10->setKey(Qt::Key_F10); connect(keyF10, SIGNAL(activated()), this, SLOT(shortcutF10())); keyF11 = new QShortcut(this); keyF11->setKey(Qt::Key_F11); connect(keyF11, SIGNAL(activated()), this, SLOT(shortcutF11())); keyF12 = new QShortcut(this); keyF12->setKey(Qt::Key_F12); connect(keyF12, SIGNAL(activated()), this, SLOT(shortcutF12())); keyControlT = new QShortcut(this); keyControlT->setKey(Qt::CTRL | Qt::Key_T); connect(keyControlT, SIGNAL(activated()), this, SLOT(shortcutControlT())); keyControlR = new QShortcut(this); keyControlR->setKey(Qt::CTRL | Qt::Key_R); connect(keyControlR, SIGNAL(activated()), this, SLOT(shortcutControlR())); keyControlI = new QShortcut(this); keyControlI->setKey(Qt::CTRL | Qt::Key_I); connect(keyControlI, SIGNAL(activated()), this, SLOT(shortcutControlI())); keyControlU = new QShortcut(this); keyControlU->setKey(Qt::CTRL | Qt::Key_U); connect(keyControlU, SIGNAL(activated()), this, SLOT(shortcutControlU())); keyStar = new QShortcut(this); keyStar->setKey(Qt::Key_Asterisk); connect(keyStar, SIGNAL(activated()), this, SLOT(shortcutStar())); keySlash = new QShortcut(this); keySlash->setKey(Qt::Key_Slash); connect(keySlash, SIGNAL(activated()), this, SLOT(shortcutSlash())); keyMinus = new QShortcut(this); keyMinus->setKey(Qt::Key_Minus); connect(keyMinus, SIGNAL(activated()), this, SLOT(shortcutMinus())); keyPlus = new QShortcut(this); keyPlus->setKey(Qt::Key_Plus); connect(keyPlus, SIGNAL(activated()), this, SLOT(shortcutPlus())); keyShiftMinus = new QShortcut(this); keyShiftMinus->setKey(Qt::SHIFT | Qt::Key_Minus); connect(keyShiftMinus, SIGNAL(activated()), this, SLOT(shortcutShiftMinus())); keyShiftPlus = new QShortcut(this); keyShiftPlus->setKey(Qt::SHIFT | Qt::Key_Plus); connect(keyShiftPlus, SIGNAL(activated()), this, SLOT(shortcutShiftPlus())); keyControlMinus = new QShortcut(this); keyControlMinus->setKey(Qt::CTRL | Qt::Key_Minus); connect(keyControlMinus, SIGNAL(activated()), this, SLOT(shortcutControlMinus())); keyControlPlus = new QShortcut(this); keyControlPlus->setKey(Qt::CTRL | Qt::Key_Plus); connect(keyControlPlus, SIGNAL(activated()), this, SLOT(shortcutControlPlus())); keyQuit = new QShortcut(this); keyQuit->setKey(Qt::CTRL | Qt::Key_Q); connect(keyQuit, SIGNAL(activated()), this, SLOT(on_exitBtn_clicked())); keyPageUp = new QShortcut(this); keyPageUp->setKey(Qt::Key_PageUp); connect(keyPageUp, SIGNAL(activated()), this, SLOT(shortcutPageUp())); keyPageDown = new QShortcut(this); keyPageDown->setKey(Qt::Key_PageDown); connect(keyPageDown, SIGNAL(activated()), this, SLOT(shortcutPageDown())); keyF = new QShortcut(this); keyF->setKey(Qt::Key_F); connect(keyF, SIGNAL(activated()), this, SLOT(shortcutF())); keyM = new QShortcut(this); keyM->setKey(Qt::Key_M); connect(keyM, SIGNAL(activated()), this, SLOT(shortcutM())); // Alternate for plus: keyK = new QShortcut(this); keyK->setKey(Qt::Key_K); connect(keyK, &QShortcut::activated, [=]() { if (freqLock) return; this->shortcutPlus(); }); // Alternate for minus: keyJ = new QShortcut(this); keyJ->setKey(Qt::Key_J); connect(keyJ, &QShortcut::activated, [=]() { if (freqLock) return; this->shortcutMinus(); }); keyShiftK = new QShortcut(this); keyShiftK->setKey(Qt::SHIFT | Qt::Key_K); connect(keyShiftK, &QShortcut::activated, [=]() { if (freqLock) return; this->shortcutShiftPlus(); }); keyShiftJ = new QShortcut(this); keyShiftJ->setKey(Qt::SHIFT | Qt::Key_J); connect(keyShiftJ, &QShortcut::activated, [=]() { if (freqLock) return; this->shortcutShiftMinus(); }); keyControlK = new QShortcut(this); keyControlK->setKey(Qt::CTRL | Qt::Key_K); connect(keyControlK, &QShortcut::activated, [=]() { if (freqLock) return; this->shortcutControlPlus(); }); keyControlJ = new QShortcut(this); keyControlJ->setKey(Qt::CTRL | Qt::Key_J); connect(keyControlJ, &QShortcut::activated, [=]() { if (freqLock) return; this->shortcutControlMinus(); }); // Move the tuning knob by the tuning step selected: // H = Down keyH = new QShortcut(this); keyH->setKey(Qt::Key_H); connect(keyH, &QShortcut::activated, [=]() { if (freqLock) return; freqt f; f.Hz = roundFrequencyWithStep(freq.Hz, -1, tsKnobHz); f.MHzDouble = f.Hz / (double)1E6; freq.Hz = f.Hz; freq.MHzDouble = f.MHzDouble; setUIFreq(); issueCmd(cmdSetFreq, f); }); // L = Up keyL = new QShortcut(this); keyL->setKey(Qt::Key_L); connect(keyL, &QShortcut::activated, [=]() { if (freqLock) return; freqt f; f.Hz = roundFrequencyWithStep(freq.Hz, 1, tsKnobHz); f.MHzDouble = f.Hz / (double)1E6; ui->freqLabel->setText(QString("%1").arg(f.MHzDouble, 0, 'f')); freq.Hz = f.Hz; freq.MHzDouble = f.MHzDouble; setUIFreq(); issueCmd(cmdSetFreq, f); }); keyDebug = new QShortcut(this); #if (QT_VERSION < QT_VERSION_CHECK(6,0,0)) keyDebug->setKey(Qt::CTRL | Qt::SHIFT | Qt::Key_D); #else keyDebug->setKey(Qt::CTRL | Qt::Key_D); #endif connect(keyDebug, SIGNAL(activated()), this, SLOT(on_debugBtn_clicked())); } void wfmain::setupUsbControllerDevice() { #if defined (USB_CONTROLLER) if (usbWindow == Q_NULLPTR) { usbWindow = new controllerSetup(); } usbControllerDev = new usbController(); usbControllerThread = new QThread(this); usbControllerThread->setObjectName("usb()"); usbControllerDev->moveToThread(usbControllerThread); connect(usbControllerThread, SIGNAL(started()), usbControllerDev, SLOT(run())); connect(usbControllerThread, SIGNAL(finished()), usbControllerDev, SLOT(deleteLater())); connect(usbControllerThread, SIGNAL(finished()), usbWindow, SLOT(deleteLater())); // Delete window when controller is deleted connect(usbControllerDev, SIGNAL(sendJog(int)), this, SLOT(changeFrequency(int))); connect(usbControllerDev, SIGNAL(doShuttle(bool,unsigned char)), this, SLOT(doShuttle(bool,unsigned char))); connect(usbControllerDev, SIGNAL(button(const COMMAND*)), this, SLOT(buttonControl(const COMMAND*))); connect(usbControllerDev, SIGNAL(setBand(int)), this, SLOT(setBand(int))); connect(usbControllerDev, SIGNAL(removeDevice(USBDEVICE*)), usbWindow, SLOT(removeDevice(USBDEVICE*))); connect(usbControllerDev, SIGNAL(initUI(usbDevMap*, QVector