5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
21 #include "radiooutputswidget.h"
22 #include "ui_radiooutputswidget.h"
25 #include "constants.h"
26 #include "eeprominterface.h"
27 #include "radiodata.h"
28 #include "simulator.h"
30 extern AppData g
; // ensure what "g" means
32 const quint16
RadioOutputsWidget::m_savedViewStateVersion
= 1;
34 RadioOutputsWidget::RadioOutputsWidget(SimulatorInterface
* simulator
, Firmware
* firmware
, QWidget
*parent
) :
36 m_simulator(simulator
),
38 m_radioProfileId(g
.sessionId()),
39 ui(new Ui::RadioOutputsWidget
)
45 connect(m_simulator
, &SimulatorInterface::channelOutValueChange
, this, &RadioOutputsWidget::onChannelOutValueChange
);
46 connect(m_simulator
, &SimulatorInterface::virtualSwValueChange
, this, &RadioOutputsWidget::onVirtSwValueChange
);
47 connect(m_simulator
, &SimulatorInterface::gVarValueChange
, this, &RadioOutputsWidget::onGVarValueChange
);
48 connect(m_simulator
, &SimulatorInterface::phaseChanged
, this, &RadioOutputsWidget::onPhaseChanged
);
51 RadioOutputsWidget::~RadioOutputsWidget()
58 void RadioOutputsWidget::changeEvent(QEvent
*e
)
60 QWidget::changeEvent(e
);
62 case QEvent::LanguageChange
:
63 ui
->retranslateUi(this);
70 void RadioOutputsWidget::start()
72 setupChannelsDisplay();
77 //void RadioOutputsWidget::stop()
81 void RadioOutputsWidget::restart()
87 void RadioOutputsWidget::saveState()
90 QDataStream
stream(&state
, QIODevice::WriteOnly
);
91 stream
<< m_savedViewStateVersion
92 << ui
->btnLogiSw
->isChecked() << ui
->btnGlobalVars
->isChecked() << ui
->btnChannels
->isChecked()
93 << ui
->splitter
->saveState();
95 SimulatorOptions opts
= g
.profile
[m_radioProfileId
].simulatorOptions();
96 opts
.radioOutputsState
= state
;
97 g
.profile
[m_radioProfileId
].simulatorOptions(opts
);
100 void RadioOutputsWidget::restoreState()
103 QByteArray splitterState
;
104 bool ls
= true, gv
= true, ch
= true;
105 QByteArray state
= g
.profile
[m_radioProfileId
].simulatorOptions().radioOutputsState
;
106 QDataStream
stream(state
);
109 if (ver
&& ver
<= m_savedViewStateVersion
)
110 stream
>> ls
>> gv
>> ch
>> splitterState
;
112 ui
->btnLogiSw
->setChecked(ls
);
113 ui
->btnGlobalVars
->setChecked(gv
);
114 ui
->btnChannels
->setChecked(ch
);
115 if (!splitterState
.isEmpty())
116 ui
->splitter
->restoreState(splitterState
);
119 void RadioOutputsWidget::setupChannelsDisplay()
121 int outputs
= std::min(32, m_firmware
->getCapability(Capability(Outputs
)));
123 // delete old widgets if already exist
124 m_channelsMap
.clear();
126 QWidget
* oldChanW
= ui
->channelsScroll
->takeWidget();
128 oldChanW
->deleteLater();
133 QWidget
* channelsWidget
= new QWidget();
134 QGridLayout
* channelsLayout
= new QGridLayout(channelsWidget
);
135 channelsLayout
->setHorizontalSpacing(4);
136 channelsLayout
->setVerticalSpacing(3);
137 channelsLayout
->setContentsMargins(5, 5, 5, 5);
139 ui
->channelsScroll
->setWidget(channelsWidget
);
143 for (int i
=0; i
< outputs
; i
++) {
144 QLabel
* label
= new QLabel(channelsWidget
);
145 label
->setText(" " + RawSource(SOURCE_TYPE_CH
, i
).toString() + " ");
146 label
->setAlignment(Qt::AlignCenter
);
147 label
->setSizePolicy(QSizePolicy::Preferred
, QSizePolicy::Fixed
);
148 channelsLayout
->addWidget(label
, 0, column
, 1, 1);
150 QSlider
* slider
= new QSlider(channelsWidget
);
151 slider
->setEnabled(false);
152 slider
->setMinimum(-1024);
153 slider
->setMaximum(1024);
154 slider
->setPageStep(128);
155 slider
->setTracking(false);
156 slider
->setOrientation(Qt::Vertical
);
157 slider
->setInvertedAppearance(false);
158 slider
->setTickPosition(QSlider::TicksRight
);
159 slider
->setSizePolicy(QSizePolicy::Fixed
, QSizePolicy::Preferred
);
160 channelsLayout
->addWidget(slider
, 2, column
, 1, 1);
161 channelsLayout
->setAlignment(slider
, Qt::AlignHCenter
);
163 QLabel
* value
= new QLabel(channelsWidget
);
164 value
->setMinimumSize(QSize(value
->fontMetrics().size(Qt::TextSingleLine
, "-100.0").width(), 0));
165 value
->setAlignment(Qt::AlignCenter
);
166 value
->setSizePolicy(QSizePolicy::Preferred
, QSizePolicy::Fixed
);
167 channelsLayout
->addWidget(value
, 1, column
, 1, 1);
171 m_channelsMap
.insert(i
, QPair
<QLabel
*, QSlider
*>(value
, slider
));
175 void RadioOutputsWidget::setupGVarsDisplay()
177 int gvars
= m_firmware
->getCapability(Capability(Gvars
));
178 int fmodes
= m_firmware
->getCapability(Capability(FlightModes
));
180 // delete old widgets if already exist
181 m_globalVarsMap
.clear();
183 QWidget
* oldGv
= ui
->globalVarsScroll
->takeWidget();
185 oldGv
->deleteLater();
190 QWidget
* gvarsWidget
= new QWidget();
191 QGridLayout
* gvarsLayout
= new QGridLayout(gvarsWidget
);
192 gvarsLayout
->setContentsMargins(5, 5, 5, 5);
193 gvarsLayout
->setHorizontalSpacing(6);
194 gvarsLayout
->setVerticalSpacing(3);
195 ui
->globalVarsScroll
->setWidget(gvarsWidget
);
197 QPalette::ColorRole bgrole
= QPalette::AlternateBase
;
198 for (int fm
=0; fm
< fmodes
; fm
++) {
199 QLabel
* label
= new QLabel(gvarsWidget
);
200 label
->setText(QString("FM%1").arg(fm
));
201 label
->setAlignment(Qt::AlignCenter
);
202 label
->setBackgroundRole(bgrole
);
203 gvarsLayout
->addWidget(label
, 0, fm
+1);
205 QHash
<int, QLabel
*> fmMap
;
206 for (int gv
=0; gv
< gvars
; gv
++) {
207 bgrole
= ((gv
% 2) ? QPalette::Background
: QPalette::AlternateBase
);
208 QLabel
* label
= new QLabel(gvarsWidget
);
209 label
->setText(QString("GV%1").arg(gv
+1));
210 label
->setAutoFillBackground(true);
211 label
->setBackgroundRole(bgrole
);
212 gvarsLayout
->addWidget(label
, gv
+1, 0);
213 for (int fm
=0; fm
< fmodes
; fm
++) {
214 QLabel
* value
= new QLabel(gvarsWidget
);
215 value
->setAlignment(Qt::AlignRight
| Qt::AlignVCenter
);
216 value
->setAutoFillBackground(true);
217 value
->setBackgroundRole(bgrole
);
219 value
->setStyleSheet("padding-right: .06em;");
220 gvarsLayout
->addWidget(value
, gv
+1, fm
+1);
222 fmMap
.insert(fm
, value
);
224 m_globalVarsMap
.insert(gv
, fmMap
);
228 void RadioOutputsWidget::setupLsDisplay()
230 int switches
= m_firmware
->getCapability(LogicalSwitches
);
232 // delete old widgets if already exist
233 m_logicSwitchMap
.clear();
235 QWidget
* oldLsW
= ui
->logicalSwitchesScroll
->takeWidget();
237 oldLsW
->deleteLater();
242 QWidget
* logicalSwitches
= new QWidget();
243 logicalSwitches
->setSizePolicy(QSizePolicy::Preferred
, QSizePolicy::Maximum
);
244 QGridLayout
* logicalSwitchesLayout
= new QGridLayout(logicalSwitches
);
245 logicalSwitchesLayout
->setHorizontalSpacing(3);
246 logicalSwitchesLayout
->setVerticalSpacing(2);
247 logicalSwitchesLayout
->setContentsMargins(5, 5, 5, 5);
248 ui
->logicalSwitchesScroll
->setWidget(logicalSwitches
);
250 // populate logical switches
251 int rows
= switches
/ (switches
> 16 ? 4 : 2);
252 for (int i
=0; i
< switches
; i
++) {
253 logicalSwitchesLayout
->addWidget(createLogicalSwitch(logicalSwitches
, i
), i
/ rows
, i
% rows
, 1, 1);
257 QWidget
* RadioOutputsWidget::createLogicalSwitch(QWidget
* parent
, int switchNo
)
259 QLabel
* swtch
= new QLabel(parent
);
260 swtch
->setAutoFillBackground(true);
261 swtch
->setFrameStyle(QFrame::Panel
| QFrame::Raised
);
262 swtch
->setLineWidth(2);
263 swtch
->setSizePolicy(QSizePolicy::Preferred
, QSizePolicy::Fixed
);
264 QFont font
= swtch
->font();
266 swtch
->setFont(font
);
267 swtch
->setMinimumWidth(swtch
->fontMetrics().width("99") + 10);
269 swtch
->setFont(font
);
270 swtch
->setText(QString("%1").arg(switchNo
+1, 2, 10, QChar('0')));
271 swtch
->setAlignment(Qt::AlignCenter
);
272 m_logicSwitchMap
.insert(switchNo
, swtch
);
276 void RadioOutputsWidget::onChannelOutValueChange(quint8 index
, qint32 value
)
278 if (m_channelsMap
.contains(index
)) {
279 QPair
<QLabel
*, QSlider
*> ch
= m_channelsMap
.value(index
);
280 ch
.first
->setText(QString("%1%").arg(calcRESXto100(value
)));
281 ch
.second
->setValue(qMin(1024, qMax(-1024, value
)));
283 //qDebug() << index << value;
286 void RadioOutputsWidget::onVirtSwValueChange(quint8 index
, qint32 value
)
288 if (!m_logicSwitchMap
.contains(index
))
291 QLabel
* ls
= m_logicSwitchMap
.value(index
);
292 ls
->setBackgroundRole(value
? QPalette::Dark
: QPalette::Background
);
293 ls
->setForegroundRole(value
? QPalette::BrightText
: QPalette::WindowText
);
294 ls
->setFrameShadow(value
? QFrame::Sunken
: QFrame::Raised
);
295 QFont font
= ls
->font();
296 font
.setBold((bool)value
);
298 //qDebug() << index << value;
301 void RadioOutputsWidget::onGVarValueChange(quint8 index
, qint32 value
)
303 if (!m_globalVarsMap
.contains(index
))
306 QHash
<int, QLabel
*> fmMap
= m_globalVarsMap
.value(index
);
307 SimulatorInterface::gVarMode_t
gv(value
);
310 if (fmMap
.contains(gv
.mode
) && (lbl
= fmMap
.value(gv
.mode
))) {
314 lbl
->setText(QString::number(gv
.value
* gvar
.multiplierGet(), 'f', gv
.prec
) + gvar
.unitToString());
316 //qDebug() << index << value << gv.mode << gv.value << gv.prec << gv.unit;
319 void RadioOutputsWidget::onPhaseChanged(qint32 phase
, const QString
&)
321 QPalette::ColorRole fgrole
, bgrole
;
324 QHash
<int, QHash
<int, QLabel
*> >::const_iterator gv
;
325 QHash
<int, QLabel
*>::const_iterator fm
;
327 for (gv
= m_globalVarsMap
.constBegin(); gv
!= m_globalVarsMap
.constEnd(); ++gv
) {
328 for (fm
= gv
.value().constBegin(); fm
!= gv
.value().constEnd(); ++fm
) {
331 if (fm
.key() == phase
) {
332 fgrole
= QPalette::BrightText
;
333 bgrole
= QPalette::Dark
;
337 fgrole
= QPalette::WindowText
;
338 bgrole
= ((gv
.key() % 2) ? QPalette::Background
: QPalette::AlternateBase
);
341 lbl
->setForegroundRole(fgrole
);
342 lbl
->setBackgroundRole(bgrole
);