fix(sim): Fix for 2POS switch logic affected by 6POS switch change (#2860)
* Fix 2POS switch logic in simulator. Recent change for 6POS switch broke the 2POS switches. * Rework switch and pot controls in the simulator ensure consistent values, avoid extraneous events in Qt and, hopefully, simplify the code. Co-authored-by: Phil Mitchell <phil.a.mitchell@gmail.com>
This commit is contained in:
@@ -39,124 +39,122 @@ class RadioKnobWidget : public RadioWidget
|
||||
public:
|
||||
|
||||
explicit RadioKnobWidget(Board::PotType type = Board::POT_WITH_DETENT, QWidget * parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
|
||||
RadioWidget(parent, f),
|
||||
m_potType(type)
|
||||
RadioWidget(parent, f)
|
||||
{
|
||||
init();
|
||||
}
|
||||
explicit RadioKnobWidget(Board::PotType type, const QString & labelText, int value = 0, QWidget * parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
|
||||
RadioWidget(labelText, value, parent, f),
|
||||
m_potType(type)
|
||||
{
|
||||
init();
|
||||
init(type);
|
||||
}
|
||||
|
||||
void init()
|
||||
explicit RadioKnobWidget(Board::PotType type, const QString & labelText, int value = 0, QWidget * parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
|
||||
RadioWidget(labelText, value, parent, f)
|
||||
{
|
||||
init(type);
|
||||
}
|
||||
|
||||
void init(Board::PotType potType)
|
||||
{
|
||||
m_type = RADIO_WIDGET_KNOB;
|
||||
|
||||
KnobWidget * pot = new KnobWidget(m_potType, this);
|
||||
pot->setValue(m_value);
|
||||
m_stepSize = (potType == Board::POT_MULTIPOS_SWITCH) ? 2048 / 5 : 1;
|
||||
|
||||
connect(pot, &KnobWidget::valueChanged, this, &RadioWidget::setValue);
|
||||
connect(this, &RadioWidget::valueChanged, pot, &KnobWidget::setValue);
|
||||
m_toolTip = tr("<p>Value (input): <b>%1</b></p>");
|
||||
if (m_stepSize == 1)
|
||||
m_toolTip.append(tr("Right-double-click to reset to center."));
|
||||
|
||||
setWidget(pot);
|
||||
m_dial = new QDial(this);
|
||||
|
||||
#ifdef __APPLE__
|
||||
// Set style for dial to show dot instead of arrow pointer for selected position
|
||||
m_dial->setStyle(QStyleFactory::create("fusion"));
|
||||
#endif
|
||||
|
||||
m_dial->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
m_dial->setFixedSize(QSize(42, 42));
|
||||
m_dial->setNotchesVisible(true);
|
||||
|
||||
if (m_stepSize > 1) {
|
||||
m_dial->setMinimum(0);
|
||||
m_dial->setMaximum(2048);
|
||||
// this is a bit of a hack to get the notch markers to display correctly
|
||||
// the actual notches/value are constrained in setValue()
|
||||
m_dial->setSingleStep(m_stepSize / 10);
|
||||
m_dial->setPageStep(m_stepSize);
|
||||
m_dial->setNotchTarget(5.7);
|
||||
}
|
||||
else {
|
||||
m_dial->setMinimum(-1024);
|
||||
m_dial->setMaximum(1024);
|
||||
m_dial->setPageStep(128);
|
||||
m_dial->setNotchTarget(64);
|
||||
}
|
||||
|
||||
m_dial->setValue(m_value);
|
||||
|
||||
connect(m_dial, &QDial::valueChanged, this, &RadioKnobWidget::setValueFromDial);
|
||||
connect(this, &RadioWidget::valueChanged, m_dial, &QDial::setValue);
|
||||
|
||||
setWidget(m_dial);
|
||||
}
|
||||
|
||||
void setValueFromDial(const int & value)
|
||||
{
|
||||
int v = value;
|
||||
if (m_stepSize > 1) {
|
||||
v = ((v + m_stepSize / 2) / m_stepSize) * m_stepSize;
|
||||
// Fix values to account for lack of precision from using integer step size
|
||||
// This makes the values more symmetrical around the center point
|
||||
// Note: this is specific to the 6 position switch which is currently the only use case here
|
||||
if (v > 1024) v += 3;
|
||||
if (v != value) {
|
||||
// If the desired value is different then update the slider position
|
||||
// Note: this will trigger another value changed event call back into this function, at which time setValue will be called below
|
||||
m_dial->setValue(v);
|
||||
return;
|
||||
}
|
||||
}
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
void mousePressEvent(QMouseEvent * event)
|
||||
{
|
||||
if (m_stepSize == 1 && event->button() == Qt::RightButton && event->type() == QEvent::MouseButtonDblClick) {
|
||||
m_dial->setValue(0);
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
RadioWidget::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void wheelEvent(QWheelEvent * event)
|
||||
{
|
||||
if (event->angleDelta().isNull())
|
||||
return;
|
||||
|
||||
if (m_stepSize > 1) {
|
||||
int numSteps = event->angleDelta().y() / 8 / 15 * m_stepSize; // one step per 15deg
|
||||
m_dial->setValue(m_dial->value() + numSteps);
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
RadioWidget::wheelEvent(event);
|
||||
}
|
||||
|
||||
bool event(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::ToolTip) {
|
||||
QHelpEvent * helpEvent = static_cast<QHelpEvent *>(event);
|
||||
if (helpEvent) {
|
||||
QToolTip::showText(helpEvent->globalPos(), m_toolTip.arg(m_dial->value()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return RadioWidget::event(event);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Board::PotType m_potType;
|
||||
|
||||
class KnobWidget : public QDial
|
||||
{
|
||||
public:
|
||||
|
||||
explicit KnobWidget(Board::PotType type, QWidget * parent = 0):
|
||||
QDial(parent)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
// Set style for dial to show dot instead of arrow pointer for selected position
|
||||
setStyle(QStyleFactory::create("fusion"));
|
||||
#endif
|
||||
|
||||
m_toolTip = tr("<p>Value (input): <b>%1</b></p>");
|
||||
|
||||
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
setFixedSize(QSize(42, 42));
|
||||
setNotchesVisible(true);
|
||||
if (type == Board::POT_MULTIPOS_SWITCH) {
|
||||
m_stepSize = 2048 / 5;
|
||||
setMinimum(0);
|
||||
setMaximum(2048);
|
||||
// this is a bit of a hack to get the notch markers to display correctly
|
||||
// the actual notches/value are constrained in setValue()
|
||||
setSingleStep(m_stepSize / 10);
|
||||
setPageStep(m_stepSize);
|
||||
setNotchTarget(5.7);
|
||||
}
|
||||
else {
|
||||
m_stepSize = 1;
|
||||
m_toolTip.append(tr("Right-double-click to reset to center."));
|
||||
setMinimum(-1024);
|
||||
setMaximum(1024);
|
||||
setPageStep(128);
|
||||
setNotchTarget(64);
|
||||
}
|
||||
}
|
||||
|
||||
void setValue(int value)
|
||||
{
|
||||
if (m_stepSize > 1) {
|
||||
value = ((value + m_stepSize / 2) / m_stepSize) * m_stepSize;
|
||||
// Fix values to account for lack of precision from using integer step size
|
||||
// This makes the values more symmetrical around the center point
|
||||
// Note: this is specific to the TX16 6 position switch which is currently the only use case here
|
||||
if (value > 1024) value += 3;
|
||||
}
|
||||
QDial::setValue(value);
|
||||
}
|
||||
|
||||
|
||||
bool event(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::ToolTip) {
|
||||
QHelpEvent * helpEvent = static_cast<QHelpEvent *>(event);
|
||||
if (helpEvent) {
|
||||
QToolTip::showText(helpEvent->globalPos(), m_toolTip.arg(this->value()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return QWidget::event(event);
|
||||
}
|
||||
|
||||
void mousePressEvent(QMouseEvent * event)
|
||||
{
|
||||
if (m_stepSize == 1 && event->button() == Qt::RightButton && event->type() == QEvent::MouseButtonDblClick) {
|
||||
setValue(0);
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
QDial::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void wheelEvent(QWheelEvent * event)
|
||||
{
|
||||
if (event->angleDelta().isNull())
|
||||
return;
|
||||
|
||||
if (m_stepSize > 1) {
|
||||
int numSteps = event->angleDelta().y() / 8 / 15 * m_stepSize; // one step per 15deg
|
||||
setValue(value() + numSteps);
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
QDial::wheelEvent(event);
|
||||
}
|
||||
|
||||
quint16 m_stepSize;
|
||||
QString m_toolTip;
|
||||
};
|
||||
QDial * m_dial;
|
||||
quint16 m_stepSize;
|
||||
QString m_toolTip;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -36,34 +36,34 @@ class RadioSwitchWidget : public RadioWidget
|
||||
public:
|
||||
|
||||
explicit RadioSwitchWidget(Board::SwitchType type = Board::SWITCH_3POS, QWidget * parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
|
||||
RadioWidget(parent, f),
|
||||
swType(type)
|
||||
RadioWidget(parent, f)
|
||||
{
|
||||
init();
|
||||
init(type);
|
||||
}
|
||||
|
||||
explicit RadioSwitchWidget(Board::SwitchType type, const QString & labelText, int value = -1, QWidget * parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
|
||||
RadioWidget(labelText, value, parent, f),
|
||||
swType(type)
|
||||
RadioWidget(labelText, value, parent, f)
|
||||
{
|
||||
init();
|
||||
init(type);
|
||||
}
|
||||
|
||||
void init()
|
||||
void init(Board::SwitchType swType)
|
||||
{
|
||||
m_type = RADIO_WIDGET_SWITCH;
|
||||
|
||||
m_stepSize = (swType == Board::SWITCH_3POS ? 1 : 2);
|
||||
|
||||
m_slider = new QSlider();
|
||||
m_slider->setOrientation(Qt::Vertical);
|
||||
m_slider->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
||||
m_slider->setInvertedAppearance(true);
|
||||
m_slider->setInvertedControls(true);
|
||||
m_slider->setTickPosition(QSlider::TicksBothSides);
|
||||
m_slider->setPageStep(1);
|
||||
m_slider->setMinimum((swType == Board::SWITCH_3POS ? -1 : 0));
|
||||
m_slider->setMinimum(-1);
|
||||
m_slider->setMaximum(1);
|
||||
m_slider->setTickInterval(1);
|
||||
m_slider->setSingleStep(1);
|
||||
m_slider->setTickInterval(m_stepSize);
|
||||
m_slider->setSingleStep(m_stepSize);
|
||||
m_slider->setPageStep(m_stepSize);
|
||||
m_slider->setValue(m_value);
|
||||
|
||||
if (swType == Board::SWITCH_TOGGLE) {
|
||||
@@ -101,20 +101,15 @@ class RadioSwitchWidget : public RadioWidget
|
||||
connect(this, &RadioWidget::valueChanged, m_slider, &QSlider::setValue);
|
||||
}
|
||||
|
||||
int getValue() const override
|
||||
{
|
||||
if (swType == Board::SWITCH_3POS)
|
||||
return m_slider->value();
|
||||
else
|
||||
return m_slider->value() > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
void setValueFromSlider(const int & value)
|
||||
{
|
||||
if (swType == Board::SWITCH_3POS)
|
||||
RadioWidget::setValue(value);
|
||||
else
|
||||
RadioWidget::setValue(value ? 1 : -1);
|
||||
// 2POS and TOGGLE switches do not have a center point - force slider value to 1 if dragged to center
|
||||
if ((m_stepSize > 1) && (value == 0)) {
|
||||
// Note: this will trigger another value changed event call back into this function, at which time setValue will be called below
|
||||
m_slider->setValue(1);
|
||||
return;
|
||||
}
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
void setToggleLocked(bool lock)
|
||||
@@ -145,8 +140,10 @@ class RadioSwitchWidget : public RadioWidget
|
||||
}
|
||||
|
||||
private:
|
||||
Board::SwitchType swType;
|
||||
|
||||
QSlider * m_slider;
|
||||
quint16 m_stepSize;
|
||||
|
||||
};
|
||||
|
||||
#endif // _RADIOSWITCHWIDGET_H_
|
||||
|
||||
@@ -66,13 +66,8 @@ void RadioWidget::setValue(const int & value)
|
||||
if (value != m_value || m_valueReset) {
|
||||
m_value = value;
|
||||
m_valueReset = false;
|
||||
// This 'emit valueChanged()' call can trigger another call into this function if the value is altered.
|
||||
// This can happen with the TX16 6 Position switch control.
|
||||
emit valueChanged(value);
|
||||
// If actual value was changed by the 'emit valueChanged()' call above, then
|
||||
// skip the 'valueChange' signal that would send the original value. We have already sent the signal with the updated value.
|
||||
if (value == getValue())
|
||||
emit valueChange(m_type, m_index, value);
|
||||
emit valueChange(m_type, m_index, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user