diff --git a/sdrgui/CMakeLists.txt b/sdrgui/CMakeLists.txt index c91149014..5b62544bb 100644 --- a/sdrgui/CMakeLists.txt +++ b/sdrgui/CMakeLists.txt @@ -74,6 +74,7 @@ set(sdrgui_SOURCES gui/mdiutils.cpp gui/mypositiondialog.cpp gui/nanosecondsdelegate.cpp + gui/perioddial.cpp gui/pluginsdialog.cpp gui/pluginpresetsdialog.cpp gui/presetitem.cpp @@ -201,6 +202,7 @@ set(sdrgui_HEADERS gui/mdiutils.h gui/mypositiondialog.h gui/nanosecondsdelegate.h + gui/perioddial.h gui/physicalunit.h gui/pluginsdialog.h gui/pluginpresetsdialog.h diff --git a/sdrgui/gui/perioddial.cpp b/sdrgui/gui/perioddial.cpp new file mode 100644 index 000000000..207300796 --- /dev/null +++ b/sdrgui/gui/perioddial.cpp @@ -0,0 +1,123 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include "perioddial.h" +#include "wrappingdial.h" +#include "wrappingspinbox.h" + +#include +#include + +PeriodDial::PeriodDial(QWidget *parent) : + QWidget(parent) +{ + m_layout = new QHBoxLayout(this); + m_layout->setContentsMargins(0, 0, 0, 0); + + m_dial = new WrappingDial(); + m_dial->setMinimum(1); + m_dial->setMaximum(999); + m_dial->setMaximumSize(24, 24); + + m_spinBox = new WrappingSpinBox(); + m_spinBox->setMinimum(1); + m_spinBox->setMaximum(999); + m_spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons); + + m_units = new QComboBox(); + m_units->addItem(QString("%1s").arg(QChar(0x3bc))); + m_units->addItem("ms"); + m_units->addItem("s"); + + m_layout->addWidget(m_dial); + m_layout->addWidget(m_spinBox); + m_layout->addWidget(m_units); + + connect(m_dial, &WrappingDial::valueChanged, this, &PeriodDial::on_dial_valueChanged); + connect(m_dial, &WrappingDial::wrapUp, this, &PeriodDial::on_wrapUp); + connect(m_dial, &WrappingDial::wrapDown, this, &PeriodDial::on_wrapDown); + connect(m_spinBox, QOverload::of(&WrappingSpinBox::valueChanged), this, &PeriodDial::on_spinBox_valueChanged); + connect(m_spinBox, &WrappingSpinBox::wrapUp, this, &PeriodDial::on_wrapUp); + connect(m_spinBox, &WrappingSpinBox::wrapDown, this, &PeriodDial::on_wrapDown); + connect(m_units, QOverload::of(&QComboBox::currentIndexChanged), this, &PeriodDial::on_units_currentIndexChanged); +} + +void PeriodDial::on_dial_valueChanged(int dialValue) +{ + m_spinBox->setValue(dialValue); + emit valueChanged(value()); +} + +void PeriodDial::on_spinBox_valueChanged(int boxValue) +{ + m_dial->setValue(boxValue); +} + +void PeriodDial::on_units_currentIndexChanged(int index) +{ + emit valueChanged(value()); +} + +void PeriodDial::on_wrapUp() +{ + int index = m_units->currentIndex(); + if (index < m_units->count() - 1) { + m_units->setCurrentIndex(index + 1); + } +} + +void PeriodDial::on_wrapDown() +{ + int index = m_units->currentIndex(); + if (index > 0) { + m_units->setCurrentIndex(index - 1); + } +} + +void PeriodDial::setValue(double newValue) +{ + double oldValue = value(); + int index; + if (newValue < 1e-3) { + index = 0; + } else if (newValue < 1.0) { + index = 1; + } else { + index = 2; + } + double scale = std::pow(10.0, 3 * (2 - index)); + int mantissa = std::round(newValue * scale); + + bool blocked = blockSignals(true); + m_dial->setValue(mantissa); + m_units->setCurrentIndex(index); + blockSignals(blocked); + + if (newValue != oldValue) { + emit valueChanged(value()); + } +} + +double PeriodDial::value() +{ + int index = -3 * (2 - m_units->currentIndex()); // 0=s -3=ms -6=us + double scale = std::pow(10.0, index); + int mantissa = m_dial->value(); + return mantissa * scale; +} diff --git a/sdrgui/gui/perioddial.h b/sdrgui/gui/perioddial.h new file mode 100644 index 000000000..18cf9e6ae --- /dev/null +++ b/sdrgui/gui/perioddial.h @@ -0,0 +1,60 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRGUI_GUI_PERIODDIAL_H +#define SDRGUI_GUI_PERIODDIAL_H + +#include + +#include "export.h" + +class QHBoxLayout; +class WrappingDial; +class WrappingSpinBox; +class QComboBox; + +// Combines QDial, QSpinBox and QComboBox to allow user to enter time period in s, ms or us +class SDRGUI_API PeriodDial : public QWidget { + Q_OBJECT + +public: + explicit PeriodDial(QWidget *parent = nullptr); + + void setValue(double value); + double value(); + +private: + + QHBoxLayout *m_layout; + WrappingDial *m_dial; + WrappingSpinBox *m_spinBox; + QComboBox *m_units; + +private slots: + + void on_dial_valueChanged(int value); + void on_spinBox_valueChanged(int value); + void on_units_currentIndexChanged(int index); + void on_wrapUp(); + void on_wrapDown(); + +signals: + void valueChanged(double value); + +}; + +#endif // SDRGUI_GUI_PERIODDIAL_H