1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-10-01 01:06:35 -04:00
sdrangel/plugins/channelrx/demodnfm/nfmdemodgui.cpp
Jon Beniston c966f1cb5a dd maximize button to MainSpectrum and expandible Channels and Features.
Add sizeToContents in ChannelGUI and FeatureGUI, called when widget is
rolled, so we can remove resizing code from all of the individual
channels and features.

In RollupContents, use minimumSizeHint for calculated size, so that
minimumWidth can come from .ui file.

In DeviceGUI::sizeToContents(), call adjustSize(), so Device GUIs start
out at minimum needed size (which should restore appearance prior to
last patch).

In stackSubWindows, use available space for channels if no
spectrum/features present.
In stackSubWindows, fix spectrum from being sized too big, resulting in
scroll bars appearing.
Reset user-defined channel width in stackSubWindows, when channels are
removed.
Don't stack maximized windows.

There's one hack in Channel/FeatureGUI::maximizeWindow(). It seems that
when maximimzing a window, QOpenGLWidgets aren't always paint properly
immediately afterwards, so the code forces an additional update. I can't
see why the first call to paintGL doesn't work.
2022-11-11 12:24:27 +00:00

651 lines
21 KiB
C++

#include "device/deviceuiset.h"
#include <QDockWidget>
#include <QMainWindow>
#include <QDebug>
#include "ui_nfmdemodgui.h"
#include "plugin/pluginapi.h"
#include "util/simpleserializer.h"
#include "util/db.h"
#include "gui/basicchannelsettingsdialog.h"
#include "gui/devicestreamselectiondialog.h"
#include "gui/crightclickenabler.h"
#include "gui/audioselectdialog.h"
#include "dsp/dspengine.h"
#include "dsp/dcscodes.h"
#include "dsp/dspcommands.h"
#include "maincore.h"
#include "nfmdemodreport.h"
#include "nfmdemod.h"
#include "nfmdemodgui.h"
NFMDemodGUI* NFMDemodGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel)
{
NFMDemodGUI* gui = new NFMDemodGUI(pluginAPI, deviceUISet, rxChannel);
return gui;
}
void NFMDemodGUI::destroy()
{
delete this;
}
void NFMDemodGUI::resetToDefaults()
{
m_settings.resetToDefaults();
displaySettings();
applySettings();
}
QByteArray NFMDemodGUI::serialize() const
{
return m_settings.serialize();
}
bool NFMDemodGUI::deserialize(const QByteArray& data)
{
if(m_settings.deserialize(data)) {
displaySettings();
applySettings(true);
return true;
} else {
resetToDefaults();
return false;
}
}
bool NFMDemodGUI::handleMessage(const Message& message)
{
if (NFMDemodReport::MsgReportCTCSSFreq::match(message))
{
NFMDemodReport::MsgReportCTCSSFreq& report = (NFMDemodReport::MsgReportCTCSSFreq&) message;
setCtcssFreq(report.getFrequency());
return true;
}
else if (NFMDemodReport::MsgReportDCSCode::match(message))
{
NFMDemodReport::MsgReportDCSCode& report = (NFMDemodReport::MsgReportDCSCode&) message;
m_reportedDcsCode = report.getCode();
setDcsCode(report.getCode());
return true;
}
else if (NFMDemod::MsgConfigureNFMDemod::match(message))
{
qDebug("NFMDemodGUI::handleMessage: NFMDemod::MsgConfigureNFMDemod");
const NFMDemod::MsgConfigureNFMDemod& cfg = (NFMDemod::MsgConfigureNFMDemod&) message;
m_settings = cfg.getSettings();
blockApplySettings(true);
m_channelMarker.updateSettings(static_cast<const ChannelMarker*>(m_settings.m_channelMarker));
displaySettings();
blockApplySettings(false);
return true;
}
else if (DSPSignalNotification::match(message))
{
DSPSignalNotification& notif = (DSPSignalNotification&) message;
m_deviceCenterFrequency = notif.getCenterFrequency();
m_basebandSampleRate = notif.getSampleRate();
ui->deltaFrequency->setValueRange(false, 7, -m_basebandSampleRate/2, m_basebandSampleRate/2);
ui->deltaFrequencyLabel->setToolTip(tr("Range %1 %L2 Hz").arg(QChar(0xB1)).arg(m_basebandSampleRate/2));
updateAbsoluteCenterFrequency();
return true;
}
return false;
}
void NFMDemodGUI::handleInputMessages()
{
Message* message;
while ((message = getInputMessageQueue()->pop()) != 0)
{
if (handleMessage(*message))
{
delete message;
}
}
}
void NFMDemodGUI::channelMarkerChangedByCursor()
{
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
applySettings();
}
void NFMDemodGUI::channelMarkerHighlightedByCursor()
{
setHighlighted(m_channelMarker.getHighlighted());
}
void NFMDemodGUI::on_deltaFrequency_changed(qint64 value)
{
m_channelMarker.setCenterFrequency(value);
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
updateAbsoluteCenterFrequency();
applySettings();
}
void NFMDemodGUI::on_channelSpacingApply_clicked()
{
int index = ui->channelSpacing->currentIndex();
qDebug("NFMDemodGUI::on_channelSpacing_currentIndexChanged: %d", index);
m_settings.m_rfBandwidth = NFMDemodSettings::getRFBW(index);
m_settings.m_afBandwidth = NFMDemodSettings::getAFBW(index);
m_settings.m_fmDeviation = 2.0 * NFMDemodSettings::getFMDev(index);
m_channelMarker.setBandwidth(m_settings.m_rfBandwidth);
ui->rfBW->blockSignals(true);
ui->afBW->blockSignals(true);
ui->fmDev->blockSignals(true);
ui->rfBWText->setText(QString("%1k").arg(m_settings.m_rfBandwidth / 1000.0, 0, 'f', 1));
ui->rfBW->setValue(m_settings.m_rfBandwidth / 100.0);
ui->afBWText->setText(QString("%1k").arg(m_settings.m_afBandwidth / 1000.0, 0, 'f', 1));
ui->afBW->setValue(m_settings.m_afBandwidth / 100.0);
ui->fmDevText->setText(QString("%1%2k").arg(QChar(0xB1, 0x00)).arg(m_settings.m_fmDeviation / 2000.0, 0, 'f', 1));
ui->fmDev->setValue(m_settings.m_fmDeviation / 200.0);
ui->rfBW->blockSignals(false);
ui->afBW->blockSignals(false);
ui->fmDev->blockSignals(false);
applySettings();
}
void NFMDemodGUI::on_rfBW_valueChanged(int value)
{
ui->rfBWText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1));
m_settings.m_rfBandwidth = value * 100.0;
m_channelMarker.setBandwidth(m_settings.m_rfBandwidth);
ui->channelSpacing->blockSignals(true);
ui->channelSpacing->setCurrentIndex(NFMDemodSettings::getChannelSpacingIndex(m_settings.m_rfBandwidth));
ui->channelSpacing->update();
ui->channelSpacing->blockSignals(false);
applySettings();
}
void NFMDemodGUI::on_afBW_valueChanged(int value)
{
ui->afBWText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1));
m_settings.m_afBandwidth = value * 100.0;
applySettings();
}
void NFMDemodGUI::on_fmDev_valueChanged(int value)
{
ui->fmDevText->setText(QString("%1%2k").arg(QChar(0xB1, 0x00)).arg(value / 10.0, 0, 'f', 1));
m_settings.m_fmDeviation = value * 200.0;
applySettings();
}
void NFMDemodGUI::on_volume_valueChanged(int value)
{
ui->volumeText->setText(QString("%1").arg(value));
m_settings.m_volume = value / 100.0;
applySettings();
}
void NFMDemodGUI::on_squelchGate_valueChanged(int value)
{
ui->squelchGateText->setText(QString("%1").arg(value * 10.0f, 0, 'f', 0));
m_settings.m_squelchGate = value;
applySettings();
}
void NFMDemodGUI::on_deltaSquelch_toggled(bool checked)
{
if (checked)
{
ui->squelchText->setText(QString("%1").arg((-ui->squelch->value()) / 1.0, 0, 'f', 0));
ui->squelchText->setToolTip(tr("Squelch AF balance threshold (%)"));
ui->squelch->setToolTip(tr("Squelch AF balance threshold (%)"));
}
else
{
ui->squelchText->setText(QString("%1").arg(ui->squelch->value() / 1.0, 0, 'f', 0));
ui->squelchText->setToolTip(tr("Squelch power threshold (dB)"));
ui->squelch->setToolTip(tr("Squelch power threshold (dB)"));
}
m_settings.m_deltaSquelch = checked;
applySettings();
}
void NFMDemodGUI::on_squelch_valueChanged(int value)
{
if (ui->deltaSquelch->isChecked())
{
ui->squelchText->setText(QString("%1").arg(-value / 1.0, 0, 'f', 0));
ui->squelchText->setToolTip(tr("Squelch AF balance threshold (%)"));
ui->squelch->setToolTip(tr("Squelch AF balance threshold (%)"));
}
else
{
ui->squelchText->setText(QString("%1").arg(value / 1.0, 0, 'f', 0));
ui->squelchText->setToolTip(tr("Squelch power threshold (dB)"));
ui->squelch->setToolTip(tr("Squelch power threshold (dB)"));
}
m_settings.m_squelch = value * 1.0;
applySettings();
}
void NFMDemodGUI::on_ctcssOn_toggled(bool checked)
{
m_settings.m_ctcssOn = checked;
applySettings();
}
void NFMDemodGUI::on_dcsOn_toggled(bool checked)
{
m_settings.m_dcsOn = checked;
applySettings();
}
void NFMDemodGUI::on_dcsCode_currentIndexChanged(int index)
{
if (index == 0)
{
m_settings.m_dcsCode = 0;
applySettings();
}
else
{
QString dcsText = ui->dcsCode->currentText();
bool positive = (dcsText[3] == 'P');
dcsText.chop(1);
bool ok;
int dcsCode = dcsText.toInt(&ok, 8);
if (ok)
{
m_settings.m_dcsCode = dcsCode;
m_settings.m_dcsPositive = positive;
applySettings();
}
}
}
void NFMDemodGUI::on_highPassFilter_toggled(bool checked)
{
m_settings.m_highPass = checked;
applySettings();
}
void NFMDemodGUI::on_audioMute_toggled(bool checked)
{
m_settings.m_audioMute = checked;
applySettings();
}
void NFMDemodGUI::on_ctcss_currentIndexChanged(int index)
{
m_settings.m_ctcssIndex = index;
applySettings();
}
void NFMDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown)
{
(void) widget;
(void) rollDown;
/*
if((widget == ui->spectrumContainer) && (m_nfmDemod != NULL))
m_nfmDemod->setSpectrum(m_threadedSampleSink->getMessageQueue(), rollDown);
*/
getRollupContents()->saveState(m_rollupState);
applySettings();
}
void NFMDemodGUI::onMenuDialogCalled(const QPoint &p)
{
if (m_contextMenuType == ContextMenuChannelSettings)
{
BasicChannelSettingsDialog dialog(&m_channelMarker, this);
dialog.setUseReverseAPI(m_settings.m_useReverseAPI);
dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress);
dialog.setReverseAPIPort(m_settings.m_reverseAPIPort);
dialog.setReverseAPIDeviceIndex(m_settings.m_reverseAPIDeviceIndex);
dialog.setReverseAPIChannelIndex(m_settings.m_reverseAPIChannelIndex);
dialog.setDefaultTitle(m_displayedName);
if (m_deviceUISet->m_deviceMIMOEngine)
{
dialog.setNumberOfStreams(m_nfmDemod->getNumberOfDeviceStreams());
dialog.setStreamIndex(m_settings.m_streamIndex);
}
dialog.move(p);
dialog.exec();
m_settings.m_rgbColor = m_channelMarker.getColor().rgb();
m_settings.m_title = m_channelMarker.getTitle();
m_settings.m_useReverseAPI = dialog.useReverseAPI();
m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress();
m_settings.m_reverseAPIPort = dialog.getReverseAPIPort();
m_settings.m_reverseAPIDeviceIndex = dialog.getReverseAPIDeviceIndex();
m_settings.m_reverseAPIChannelIndex = dialog.getReverseAPIChannelIndex();
setWindowTitle(m_settings.m_title);
setTitle(m_channelMarker.getTitle());
setTitleColor(m_settings.m_rgbColor);
if (m_deviceUISet->m_deviceMIMOEngine)
{
m_settings.m_streamIndex = dialog.getSelectedStreamIndex();
m_channelMarker.clearStreamIndexes();
m_channelMarker.addStreamIndex(m_settings.m_streamIndex);
updateIndexLabel();
}
applySettings();
}
resetContextMenuType();
}
NFMDemodGUI::NFMDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent) :
ChannelGUI(parent),
ui(new Ui::NFMDemodGUI),
m_pluginAPI(pluginAPI),
m_deviceUISet(deviceUISet),
m_channelMarker(this),
m_deviceCenterFrequency(0),
m_basebandSampleRate(1),
m_basicSettingsShown(false),
m_doApplySettings(true),
m_squelchOpen(false),
m_audioSampleRate(-1),
m_reportedDcsCode(0),
m_dcsShowPositive(false),
m_tickCount(0)
{
setAttribute(Qt::WA_DeleteOnClose, true);
m_helpURL = "plugins/channelrx/demodnfm/readme.md";
RollupContents *rollupContents = getRollupContents();
ui->setupUi(rollupContents);
setSizePolicy(rollupContents->sizePolicy());
rollupContents->arrangeRollups();
connect(rollupContents, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
m_nfmDemod = reinterpret_cast<NFMDemod*>(rxChannel);
m_nfmDemod->setMessageQueueToGUI(getInputMessageQueue());
connect(&MainCore::instance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
CRightClickEnabler *audioMuteRightClickEnabler = new CRightClickEnabler(ui->audioMute);
connect(audioMuteRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioSelect()));
blockApplySettings(true);
ui->channelSpacing->clear();
for (int i = 0; i < NFMDemodSettings::m_nbChannelSpacings; i++) {
ui->channelSpacing->addItem(QString("%1").arg(NFMDemodSettings::getChannelSpacing(i) / 1000.0, 0, 'f', 2));
}
ui->channelSpacing->setCurrentIndex(NFMDemodSettings::getChannelSpacingIndex(12500));
int ctcss_nbTones;
const Real *ctcss_tones = m_nfmDemod->getCtcssToneSet(ctcss_nbTones);
ui->ctcss->addItem("--");
for (int i=0; i<ctcss_nbTones; i++) {
ui->ctcss->addItem(QString("%1").arg(ctcss_tones[i]));
}
ui->dcsOn->setChecked(m_settings.m_dcsOn);
QList<unsigned int> dcsCodes;
DCSCodes::getCanonicalCodes(dcsCodes);
ui->dcsCode->addItem("--");
for (auto dcsCode : dcsCodes)
{
ui->dcsCode->addItem(QString("%1P").arg(dcsCode, 3, 8, QLatin1Char('0')));
ui->dcsCode->addItem(QString("%1N").arg(dcsCode, 3, 8, QLatin1Char('0')));
}
blockApplySettings(false);
ui->audioMute->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); // squelch closed
ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
ui->channelPowerMeter->setColorTheme(LevelMeterSignalDB::ColorGreenAndBlue);
m_channelMarker.blockSignals(true);
m_channelMarker.setColor(Qt::red);
m_channelMarker.setBandwidth(5000);
m_channelMarker.setCenterFrequency(0);
m_channelMarker.setTitle("NFM Demodulator");
m_channelMarker.blockSignals(false);
m_channelMarker.setVisible(true); // activate signal on the last setting only
m_settings.setChannelMarker(&m_channelMarker);
m_settings.setRollupState(&m_rollupState);
m_deviceUISet->addChannelMarker(&m_channelMarker);
connect(&m_channelMarker, SIGNAL(changedByCursor()), this, SLOT(channelMarkerChangedByCursor()));
connect(&m_channelMarker, SIGNAL(highlightedByCursor()), this, SLOT(channelMarkerHighlightedByCursor()));
QChar delta = QChar(0x94, 0x03);
ui->deltaSquelch->setText(delta);
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
displaySettings();
makeUIConnections();
applySettings(true);
}
NFMDemodGUI::~NFMDemodGUI()
{
delete ui;
}
void NFMDemodGUI::applySettings(bool force)
{
if (m_doApplySettings)
{
qDebug() << "NFMDemodGUI::applySettings";
NFMDemod::MsgConfigureNFMDemod* message = NFMDemod::MsgConfigureNFMDemod::create( m_settings, force);
m_nfmDemod->getInputMessageQueue()->push(message);
}
}
void NFMDemodGUI::displaySettings()
{
m_channelMarker.blockSignals(true);
m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset);
m_channelMarker.setBandwidth(m_settings.m_rfBandwidth);
m_channelMarker.setTitle(m_settings.m_title);
m_channelMarker.blockSignals(false);
m_channelMarker.setColor(m_settings.m_rgbColor);
setTitleColor(m_settings.m_rgbColor);
setWindowTitle(m_channelMarker.getTitle());
setTitle(m_channelMarker.getTitle());
blockApplySettings(true);
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
ui->rfBWText->setText(QString("%1k").arg(m_settings.m_rfBandwidth / 1000.0, 0, 'f', 1));
ui->rfBW->setValue(m_settings.m_rfBandwidth / 100.0);
ui->afBWText->setText(QString("%1k").arg(m_settings.m_afBandwidth / 1000.0, 0, 'f', 1));
ui->afBW->setValue(m_settings.m_afBandwidth / 100.0);
ui->fmDevText->setText(QString("%1%2k").arg(QChar(0xB1, 0x00)).arg(m_settings.m_fmDeviation / 2000.0, 0, 'f', 1));
ui->fmDev->setValue(m_settings.m_fmDeviation / 200.0);
ui->channelSpacing->blockSignals(true);
ui->channelSpacing->setCurrentIndex(NFMDemodSettings::getChannelSpacingIndex(m_settings.m_rfBandwidth));
ui->channelSpacing->blockSignals(false);
ui->volumeText->setText(QString("%1").arg(m_settings.m_volume*100.0, 0, 'f', 0));
ui->volume->setValue(m_settings.m_volume * 100.0);
ui->squelchGateText->setText(QString("%1").arg(m_settings.m_squelchGate * 10.0f, 0, 'f', 0));
ui->squelchGate->setValue(m_settings.m_squelchGate);
ui->deltaSquelch->setChecked(m_settings.m_deltaSquelch);
ui->squelch->setValue(m_settings.m_squelch * 1.0);
if (m_settings.m_deltaSquelch)
{
ui->squelchText->setText(QString("%1").arg((-m_settings.m_squelch) / 1.0, 0, 'f', 0));
ui->squelchText->setToolTip(tr("Squelch AF balance threshold (%)"));
ui->squelch->setToolTip(tr("Squelch AF balance threshold (%)"));
}
else
{
ui->squelchText->setText(QString("%1").arg(m_settings.m_squelch / 1.0, 0, 'f', 0));
ui->squelchText->setToolTip(tr("Squelch power threshold (dB)"));
ui->squelch->setToolTip(tr("Squelch power threshold (dB)"));
}
ui->ctcssOn->setChecked(m_settings.m_ctcssOn);
ui->highPassFilter->setChecked(m_settings.m_highPass);
ui->audioMute->setChecked(m_settings.m_audioMute);
ui->ctcss->setCurrentIndex(m_settings.m_ctcssIndex);
ui->dcsOn->setChecked(m_settings.m_dcsOn);
if (m_settings.m_dcsCode == 0) {
ui->dcsCode->setCurrentText(tr("--"));
} else {
ui->dcsCode->setCurrentText(tr("%1%2")
.arg(m_settings.m_dcsCode, 3, 8, QLatin1Char('0'))
.arg(m_settings.m_dcsPositive ? "P" : "N")
);
}
setDcsCode(m_reportedDcsCode);
updateIndexLabel();
getRollupContents()->restoreState(m_rollupState);
updateAbsoluteCenterFrequency();
blockApplySettings(false);
}
void NFMDemodGUI::leaveEvent(QEvent* event)
{
m_channelMarker.setHighlighted(false);
ChannelGUI::leaveEvent(event);
}
void NFMDemodGUI::enterEvent(QEvent* event)
{
m_channelMarker.setHighlighted(true);
ChannelGUI::enterEvent(event);
}
void NFMDemodGUI::setCtcssFreq(Real ctcssFreq)
{
if (ctcssFreq == 0) {
ui->ctcssText->setText("--");
} else {
ui->ctcssText->setText(QString("%1").arg(ctcssFreq));
}
}
void NFMDemodGUI::setDcsCode(unsigned int dcsCode)
{
if (dcsCode == 0)
{
ui->dcsText->setText("--");
}
else
{
unsigned int normalizedCode;
bool showPositive = ui->dcsPositive->isChecked();
normalizedCode = DCSCodes::m_toCanonicalCode[dcsCode];
normalizedCode = showPositive ? normalizedCode : DCSCodes::m_signFlip[normalizedCode];
ui->dcsText->setText(tr("%1").arg(normalizedCode, 3, 8, QLatin1Char('0')));
}
}
void NFMDemodGUI::blockApplySettings(bool block)
{
m_doApplySettings = !block;
}
void NFMDemodGUI::audioSelect()
{
qDebug("NFMDemodGUI::audioSelect");
AudioSelectDialog audioSelect(DSPEngine::instance()->getAudioDeviceManager(), m_settings.m_audioDeviceName);
audioSelect.exec();
if (audioSelect.m_selected)
{
m_settings.m_audioDeviceName = audioSelect.m_audioDeviceName;
applySettings();
}
}
void NFMDemodGUI::tick()
{
double magsqAvg, magsqPeak;
int nbMagsqSamples;
m_nfmDemod->getMagSqLevels(magsqAvg, magsqPeak, nbMagsqSamples);
double powDbAvg = CalcDb::dbPower(magsqAvg);
double powDbPeak = CalcDb::dbPower(magsqPeak);
ui->channelPowerMeter->levelChanged(
(100.0f + powDbAvg) / 100.0f,
(100.0f + powDbPeak) / 100.0f,
nbMagsqSamples);
if (m_tickCount % 4 == 0) {
ui->channelPower->setText(tr("%1 dB").arg(powDbAvg, 0, 'f', 1));
}
int audioSampleRate = m_nfmDemod->getAudioSampleRate();
bool squelchOpen = m_nfmDemod->getSquelchOpen();
if ((audioSampleRate != m_audioSampleRate) || (squelchOpen != m_squelchOpen))
{
if (audioSampleRate < 0) {
ui->audioMute->setStyleSheet("QToolButton { background-color : red; }");
} else if (squelchOpen) {
ui->audioMute->setStyleSheet("QToolButton { background-color : green; }");
} else {
ui->audioMute->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
}
m_audioSampleRate = audioSampleRate;
m_squelchOpen = squelchOpen;
}
m_tickCount++;
}
void NFMDemodGUI::makeUIConnections()
{
QObject::connect(ui->deltaFrequency, &ValueDialZ::changed, this, &NFMDemodGUI::on_deltaFrequency_changed);
QObject::connect(ui->channelSpacingApply, &QPushButton::clicked, this, &NFMDemodGUI::on_channelSpacingApply_clicked);
QObject::connect(ui->rfBW, &QSlider::valueChanged, this, &NFMDemodGUI::on_rfBW_valueChanged);
QObject::connect(ui->afBW, &QSlider::valueChanged, this, &NFMDemodGUI::on_afBW_valueChanged);
QObject::connect(ui->fmDev, &QSlider::valueChanged, this, &NFMDemodGUI::on_fmDev_valueChanged);
QObject::connect(ui->volume, &QDial::valueChanged, this, &NFMDemodGUI::on_volume_valueChanged);
QObject::connect(ui->squelchGate, &QDial::valueChanged, this, &NFMDemodGUI::on_squelchGate_valueChanged);
QObject::connect(ui->deltaSquelch, &ButtonSwitch::toggled, this, &NFMDemodGUI::on_deltaSquelch_toggled);
QObject::connect(ui->squelch, &QDial::valueChanged, this, &NFMDemodGUI::on_squelch_valueChanged);
QObject::connect(ui->ctcss, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &NFMDemodGUI::on_ctcss_currentIndexChanged);
QObject::connect(ui->ctcssOn, &QCheckBox::toggled, this, &NFMDemodGUI::on_ctcssOn_toggled);
QObject::connect(ui->dcsOn, &QCheckBox::toggled, this, &NFMDemodGUI::on_dcsOn_toggled);
QObject::connect(ui->dcsCode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &NFMDemodGUI::on_dcsCode_currentIndexChanged);
QObject::connect(ui->highPassFilter, &ButtonSwitch::toggled, this, &NFMDemodGUI::on_highPassFilter_toggled);
QObject::connect(ui->audioMute, &QToolButton::toggled, this, &NFMDemodGUI::on_audioMute_toggled);
}
void NFMDemodGUI::updateAbsoluteCenterFrequency()
{
setStatusFrequency(m_deviceCenterFrequency + m_settings.m_inputFrequencyOffset);
}