diff --git a/companion/src/simulation/radiooutputswidget.cpp b/companion/src/simulation/radiooutputswidget.cpp index 646f16b32..18cdbec81 100644 --- a/companion/src/simulation/radiooutputswidget.cpp +++ b/companion/src/simulation/radiooutputswidget.cpp @@ -27,9 +27,11 @@ #include "radiodata.h" #include "simulator.h" +#include + extern AppData g; // ensure what "g" means -const quint16 RadioOutputsWidget::m_savedViewStateVersion = 1; +const quint16 RadioOutputsWidget::m_savedViewStateVersion = 2; RadioOutputsWidget::RadioOutputsWidget(SimulatorInterface * simulator, Firmware * firmware, QWidget *parent) : QWidget(parent), @@ -42,7 +44,12 @@ RadioOutputsWidget::RadioOutputsWidget(SimulatorInterface * simulator, Firmware restoreState(); + // link the channels and mixes display horizontal scroll + connect(ui->channelsScroll->horizontalScrollBar(), &QScrollBar::sliderMoved, ui->mixersScroll->horizontalScrollBar(), &QScrollBar::setValue); + connect(ui->mixersScroll->horizontalScrollBar(), &QScrollBar::sliderMoved, ui->channelsScroll->horizontalScrollBar(), &QScrollBar::setValue); + connect(m_simulator, &SimulatorInterface::channelOutValueChange, this, &RadioOutputsWidget::onChannelOutValueChange); + connect(m_simulator, &SimulatorInterface::channelMixValueChange, this, &RadioOutputsWidget::onChannelMixValueChange); connect(m_simulator, &SimulatorInterface::virtualSwValueChange, this, &RadioOutputsWidget::onVirtSwValueChange); connect(m_simulator, &SimulatorInterface::gVarValueChange, this, &RadioOutputsWidget::onGVarValueChange); connect(m_simulator, &SimulatorInterface::phaseChanged, this, &RadioOutputsWidget::onPhaseChanged); @@ -69,7 +76,8 @@ void RadioOutputsWidget::changeEvent(QEvent *e) void RadioOutputsWidget::start() { - setupChannelsDisplay(); + setupChannelsDisplay(false); + setupChannelsDisplay(true); setupGVarsDisplay(); setupLsDisplay(); } @@ -91,6 +99,8 @@ void RadioOutputsWidget::saveState() stream << m_savedViewStateVersion << ui->btnLogiSw->isChecked() << ui->btnGlobalVars->isChecked() << ui->btnChannels->isChecked() << ui->splitter->saveState(); + // view state version 2 + stream << ui->btnMixes->isChecked(); SimulatorOptions opts = g.profile[m_radioProfileId].simulatorOptions(); opts.radioOutputsState = state; @@ -101,29 +111,39 @@ void RadioOutputsWidget::restoreState() { quint16 ver = 0; QByteArray splitterState; - bool ls = true, gv = true, ch = true; + bool ls = true, gv = true, ch = true, mx = false; QByteArray state = g.profile[m_radioProfileId].simulatorOptions().radioOutputsState; QDataStream stream(state); stream >> ver; - if (ver && ver <= m_savedViewStateVersion) + if (ver && ver <= m_savedViewStateVersion) { stream >> ls >> gv >> ch >> splitterState; + if (ver >= 2) + stream >> mx; + } ui->btnLogiSw->setChecked(ls); ui->btnGlobalVars->setChecked(gv); ui->btnChannels->setChecked(ch); + ui->btnMixes->setChecked(mx); if (!splitterState.isEmpty()) ui->splitter->restoreState(splitterState); } -void RadioOutputsWidget::setupChannelsDisplay() +void RadioOutputsWidget::setupChannelsDisplay(bool mixes) { int outputs = std::min(32, m_firmware->getCapability(Capability(Outputs))); // delete old widgets if already exist - m_channelsMap.clear(); - - QWidget * oldChanW = ui->channelsScroll->takeWidget(); + QWidget * oldChanW = nullptr; + if (mixes) { + m_mixesMap.clear(); + oldChanW = ui->mixersScroll->takeWidget(); + } + else { + m_channelsMap.clear(); + oldChanW = ui->channelsScroll->takeWidget(); + } if (oldChanW) oldChanW->deleteLater(); @@ -136,7 +156,10 @@ void RadioOutputsWidget::setupChannelsDisplay() channelsLayout->setVerticalSpacing(3); channelsLayout->setContentsMargins(5, 5, 5, 5); - ui->channelsScroll->setWidget(channelsWidget); + if (mixes) + ui->mixersScroll->setWidget(channelsWidget); + else + ui->channelsScroll->setWidget(channelsWidget); // populate outputs int column = 0; @@ -168,7 +191,10 @@ void RadioOutputsWidget::setupChannelsDisplay() ++column; - m_channelsMap.insert(i, QPair(value, slider)); + if (mixes) + m_mixesMap.insert(i, QPair(value, slider)); + else + m_channelsMap.insert(i, QPair(value, slider)); } } @@ -273,14 +299,30 @@ QWidget * RadioOutputsWidget::createLogicalSwitch(QWidget * parent, int switchNo return swtch; } -void RadioOutputsWidget::onChannelOutValueChange(quint8 index, qint32 value) +void RadioOutputsWidget::onChannelOutValueChange(quint8 index, qint32 value, qint32 limit) { if (m_channelsMap.contains(index)) { QPair ch = m_channelsMap.value(index); + if (ch.second->maximum() != limit) { + ch.second->setMaximum(limit); + ch.second->setMinimum(-limit); + } ch.first->setText(QString("%1%").arg(calcRESXto100(value))); - ch.second->setValue(qMin(1024, qMax(-1024, value))); + ch.second->setValue(qMin(limit, qMax(-limit, value))); + } +} + +void RadioOutputsWidget::onChannelMixValueChange(quint8 index, qint32 value, qint32 limit) +{ + if (m_mixesMap.contains(index)) { + QPair ch = m_mixesMap.value(index); + if (ch.second->maximum() != limit) { + ch.second->setMaximum(limit); + ch.second->setMinimum(-limit); + } + ch.first->setText(QString("%1%").arg(calcRESXto100(value))); + ch.second->setValue(qMin(limit, qMax(-limit, value))); } - //qDebug() << index << value; } void RadioOutputsWidget::onVirtSwValueChange(quint8 index, qint32 value) diff --git a/companion/src/simulation/radiooutputswidget.h b/companion/src/simulation/radiooutputswidget.h index 1f699e99d..216a83393 100644 --- a/companion/src/simulation/radiooutputswidget.h +++ b/companion/src/simulation/radiooutputswidget.h @@ -56,14 +56,15 @@ class RadioOutputsWidget : public QWidget protected slots: void saveState(); void restoreState(); - void onChannelOutValueChange(quint8 index, qint32 value); + void onChannelOutValueChange(quint8 index, qint32 value, qint32 limit); + void onChannelMixValueChange(quint8 index, qint32 value, qint32 limit); void onVirtSwValueChange(quint8 index, qint32 value); void onGVarValueChange(quint8 index, qint32 value); void onPhaseChanged(qint32 phase, const QString &); protected: void changeEvent(QEvent *e); - void setupChannelsDisplay(); + void setupChannelsDisplay(bool mixes = false); void setupLsDisplay(); void setupGVarsDisplay(); QWidget * createLogicalSwitch(QWidget * parent, int switchNo); @@ -72,6 +73,7 @@ class RadioOutputsWidget : public QWidget Firmware * m_firmware; QHash > m_channelsMap; // m_channelsMap[chanIndex] = {QLabel*, QSlider*} + QHash > m_mixesMap; // m_mixesMap[chanIndex] = {QLabel*, QSlider*} QHash m_logicSwitchMap; // m_logicSwitchMap[lsIndex] = QLabel* QHash > m_globalVarsMap; // m_globalVarsMap[gvarIndex][fmodeIndex] = QLabel* diff --git a/companion/src/simulation/radiooutputswidget.ui b/companion/src/simulation/radiooutputswidget.ui index 94888173c..056f46ce0 100644 --- a/companion/src/simulation/radiooutputswidget.ui +++ b/companion/src/simulation/radiooutputswidget.ui @@ -7,7 +7,7 @@ 0 0 762 - 436 + 452 @@ -126,6 +126,25 @@ + + + + Mix Outputs + + + true + + + true + + + Qt::ToolButtonTextBesideIcon + + + true + + + @@ -219,7 +238,7 @@ c 0 0 740 - 85 + 68 @@ -297,7 +316,7 @@ l 0 0 739 - 101 + 78 @@ -374,7 +393,81 @@ s 0 0 739 - 194 + 128 + + + + + + + + + + + 0 + 3 + + + + + 0 + + + 1 + + + 1 + + + 1 + + + 1 + + + + + + 0 + 0 + + + + 3 + + + M +i +x +e +s + + + Qt::AlignCenter + + + true + + + true + + + + + + + QFrame::NoFrame + + + true + + + + + 0 + 0 + 738 + 118 @@ -436,5 +529,21 @@ s + + btnMixes + toggled(bool) + mixersWidget + setVisible(bool) + + + 370 + 17 + + + 380 + 384 + + + diff --git a/companion/src/simulation/simulatorinterface.h b/companion/src/simulation/simulatorinterface.h index 396316bb9..47c5c2289 100644 --- a/companion/src/simulation/simulatorinterface.h +++ b/companion/src/simulation/simulatorinterface.h @@ -158,8 +158,8 @@ class SimulatorInterface : public QObject void runtimeError(const QString & error); void lcdChange(bool backlightEnable); void phaseChanged(qint8 phase, const QString & name); - void channelOutValueChange(quint8 index, qint32 value); - void channelMixValueChange(quint8 index, qint32 value); + void channelOutValueChange(quint8 index, qint32 value, qint32 limit); + void channelMixValueChange(quint8 index, qint32 value, qint32 limit); void virtualSwValueChange(quint8 index, qint32 value); void trimValueChange(quint8 index, qint32 value); void trimRangeChange(quint8 index, qint32 min, qint16 max); diff --git a/companion/src/themes/default/style.css b/companion/src/themes/default/style.css index 5b018a1d0..9f8470df5 100644 --- a/companion/src/themes/default/style.css +++ b/companion/src/themes/default/style.css @@ -80,35 +80,52 @@ RadioOutputsWidget QLabel[heading=true] { font-size: 8pt; } -/* Channel output indicator sliders */ +/* Output indicator sliders common styles */ -RadioOutputsWidget #channelsWidget QSlider::groove:vertical { +RadioOutputsWidget QSlider::groove:vertical { width: 18px; background-color: transparent; border-image: url(:/images/simulator/icons/svg/line_horiz.svg) 0 0 0 0 stretch round; } -RadioOutputsWidget #channelsWidget QSlider::add-page:vertical, -RadioOutputsWidget #channelsWidget QSlider::sub-page:vertical { +RadioOutputsWidget QSlider::add-page:vertical, +RadioOutputsWidget QSlider::sub-page:vertical { border: 1px solid #777; margin: 0 5px; } -RadioOutputsWidget #channelsWidget QSlider::sub-page:vertical { - background: qlineargradient(x1: .4, y1: 0, x2: 1, y2: 1, stop: 0 #bbb, stop:1 #fff); - border-top-left-radius: 4px; - border-top-right-radius: 4px; -} - -RadioOutputsWidget #channelsWidget QSlider::add-page:vertical { - background: qlineargradient(x1: .6, y1: 1, x2: 0, y2: 0, stop:0 #55f, stop: 1 #eef); - border-bottom-left-radius: 4px; - border-bottom-right-radius: 4px; -} - -RadioOutputsWidget #channelsWidget QSlider::handle:vertical:disabled { +RadioOutputsWidget QSlider::handle:vertical:disabled { background-color: darkgreen; border: 1px solid #ccc; border-radius: 1px; height: 3px; } + +RadioOutputsWidget QSlider::sub-page:vertical { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +RadioOutputsWidget QSlider::add-page:vertical { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; +} + +/* Channel output indicator sliders */ +RadioOutputsWidget #channelsWidget QSlider::sub-page:vertical { + background: qlineargradient(x1: .4, y1: 0, x2: 1, y2: 1, stop: 0 #bbb, stop:1 #fff); +} + +RadioOutputsWidget #channelsWidget QSlider::add-page:vertical { + background: qlineargradient(x1: .6, y1: 1, x2: 0, y2: 0, stop:0 #55f, stop: 1 #eef); +} + +/* Mixes output indicator sliders */ +RadioOutputsWidget #mixersWidget QSlider::sub-page:vertical { + background: qlineargradient(x1: .4, y1: 0, x2: 1, y2: 1, stop: 0 #bbb, stop:1 #686868); +} + +RadioOutputsWidget #mixersWidget QSlider::add-page:vertical { + background: qlineargradient(x1: .6, y1: 1, x2: 0, y2: 0, stop:0 #9E38FF, stop: 1 #F1DDFF); +} + diff --git a/radio/src/targets/simu/opentxsimulator.cpp b/radio/src/targets/simu/opentxsimulator.cpp index 141c38d67..87819232b 100644 --- a/radio/src/targets/simu/opentxsimulator.cpp +++ b/radio/src/targets/simu/opentxsimulator.cpp @@ -473,15 +473,16 @@ void OpenTxSimulator::checkOutputsChanged() { static TxOutputs lastOutputs; static size_t chansDim = DIM(channelOutputs); + const static int16_t limit = 512 * 2; qint32 tmpVal; uint8_t i, idx; - uint8_t phase = getFlightMode(); // opentx.cpp - uint8_t mode = getStickMode(); + const uint8_t phase = getFlightMode(); // opentx.cpp + const uint8_t mode = getStickMode(); for (i=0; i < chansDim; i++) { if (lastOutputs.chans[i] != channelOutputs[i] || m_resetOutputsData) { - emit channelOutValueChange(i, channelOutputs[i]); - emit channelMixValueChange(i, ex_chans[i]); + emit channelOutValueChange(i, channelOutputs[i], (g_model.extendedLimits ? limit * LIMIT_EXT_PERCENT / 100 : limit)); + emit channelMixValueChange(i, ex_chans[i], limit * 2); emit outputValueChange(OUTPUT_SRC_CHAN_OUT, i, channelOutputs[i]); emit outputValueChange(OUTPUT_SRC_CHAN_MIX, i, ex_chans[i]); lastOutputs.chans[i] = channelOutputs[i];