1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-25 01:05:10 +03:00

[Simulator] Add mixes display to Radio Outputs widget (#5811)

* [Simulator] Add mixes output display to RadioOutputsWidget (closes #2655).

* Add proper limits reporting & representation for channel and mix values in RadioOutputsWidget.
This commit is contained in:
Max Paperno 2018-04-12 14:02:27 -04:00 committed by Andre Bernet
parent 7b12c99a0b
commit 9e4a0680ab
6 changed files with 213 additions and 42 deletions

View file

@ -27,9 +27,11 @@
#include "radiodata.h"
#include "simulator.h"
#include <QScrollBar>
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<QLabel *, QSlider *>(value, slider));
if (mixes)
m_mixesMap.insert(i, QPair<QLabel *, QSlider *>(value, slider));
else
m_channelsMap.insert(i, QPair<QLabel *, QSlider *>(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<QLabel *, QSlider *> 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<QLabel *, QSlider *> 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)

View file

@ -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<int, QPair<QLabel *, QSlider *> > m_channelsMap; // m_channelsMap[chanIndex] = {QLabel*, QSlider*}
QHash<int, QPair<QLabel *, QSlider *> > m_mixesMap; // m_mixesMap[chanIndex] = {QLabel*, QSlider*}
QHash<int, QLabel *> m_logicSwitchMap; // m_logicSwitchMap[lsIndex] = QLabel*
QHash<int, QHash<int, QLabel *> > m_globalVarsMap; // m_globalVarsMap[gvarIndex][fmodeIndex] = QLabel*

View file

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>762</width>
<height>436</height>
<height>452</height>
</rect>
</property>
<property name="windowTitle">
@ -126,6 +126,25 @@
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnMixes">
<property name="text">
<string>Mix Outputs</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextBesideIcon</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
@ -219,7 +238,7 @@ c</string>
<x>0</x>
<y>0</y>
<width>740</width>
<height>85</height>
<height>68</height>
</rect>
</property>
</widget>
@ -297,7 +316,7 @@ l</string>
<x>0</x>
<y>0</y>
<width>739</width>
<height>101</height>
<height>78</height>
</rect>
</property>
</widget>
@ -374,7 +393,81 @@ s</string>
<x>0</x>
<y>0</y>
<width>739</width>
<height>194</height>
<height>128</height>
</rect>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="mixersWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>3</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>1</number>
</property>
<property name="topMargin">
<number>1</number>
</property>
<property name="rightMargin">
<number>1</number>
</property>
<property name="bottomMargin">
<number>1</number>
</property>
<item>
<widget class="QLabel" name="label_11">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="midLineWidth">
<number>3</number>
</property>
<property name="text">
<string>M
i
x
e
s</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="heading" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QScrollArea" name="mixersScroll">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_12">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>738</width>
<height>118</height>
</rect>
</property>
</widget>
@ -436,5 +529,21 @@ s</string>
</hint>
</hints>
</connection>
<connection>
<sender>btnMixes</sender>
<signal>toggled(bool)</signal>
<receiver>mixersWidget</receiver>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>370</x>
<y>17</y>
</hint>
<hint type="destinationlabel">
<x>380</x>
<y>384</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -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);

View file

@ -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);
}

View file

@ -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];