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"
29 #include "simulatorinterface.h"
31 extern AppData g
; // ensure what "g" means
33 const int RadioOutputsWidget::m_dataUpdateFreqDefault
= 10; // ms
34 const quint16
RadioOutputsWidget::m_savedViewStateVersion
= 1;
36 RadioOutputsWidget::RadioOutputsWidget(SimulatorInterface
* simulator
, Firmware
* firmware
, QWidget
*parent
) :
38 m_simulator(simulator
),
40 m_tmrUpdateData(new QTimer
),
41 m_radioProfileId(g
.sessionId()),
43 ui(new Ui::RadioOutputsWidget
)
49 m_dataUpdateFreq
= m_dataUpdateFreqDefault
;
50 m_tmrUpdateData
->setInterval(m_dataUpdateFreq
);
52 connect(m_tmrUpdateData
, &QTimer::timeout
, this, &RadioOutputsWidget::setValues
);
55 RadioOutputsWidget::~RadioOutputsWidget()
60 delete m_tmrUpdateData
;
64 void RadioOutputsWidget::changeEvent(QEvent
*e
)
66 QWidget::changeEvent(e
);
68 case QEvent::LanguageChange
:
69 ui
->retranslateUi(this);
76 void RadioOutputsWidget::showEvent(QShowEvent
* event
)
79 m_tmrUpdateData
->start();
82 void RadioOutputsWidget::hideEvent(QHideEvent
* event
)
84 m_tmrUpdateData
->stop();
87 void RadioOutputsWidget::start()
89 setupChannelsDisplay();
92 m_tmrUpdateData
->start();
96 void RadioOutputsWidget::stop()
98 m_tmrUpdateData
->stop();
102 void RadioOutputsWidget::restart()
108 void RadioOutputsWidget::saveState()
111 QDataStream
stream(&state
, QIODevice::WriteOnly
);
112 stream
<< m_savedViewStateVersion
113 << ui
->btnLogiSw
->isChecked() << ui
->btnGlobalVars
->isChecked() << ui
->btnChannels
->isChecked()
114 << ui
->splitter
->saveState();
116 SimulatorOptions opts
= g
.profile
[m_radioProfileId
].simulatorOptions();
117 opts
.radioOutputsState
= state
;
118 g
.profile
[m_radioProfileId
].simulatorOptions(opts
);
121 void RadioOutputsWidget::restoreState()
124 QByteArray splitterState
;
125 bool ls
= true, gv
= true, ch
= true;
126 QByteArray state
= g
.profile
[m_radioProfileId
].simulatorOptions().radioOutputsState
;
127 QDataStream
stream(state
);
130 if (ver
&& ver
<= m_savedViewStateVersion
)
131 stream
>> ls
>> gv
>> ch
>> splitterState
;
133 ui
->btnLogiSw
->setChecked(ls
);
134 ui
->btnGlobalVars
->setChecked(gv
);
135 ui
->btnChannels
->setChecked(ch
);
136 if (!splitterState
.isEmpty())
137 ui
->splitter
->restoreState(splitterState
);
141 void RadioOutputsWidget::setupChannelsDisplay()
143 int outputs
= std::min(32, m_firmware
->getCapability(Capability(Outputs
)));
145 // delete old widgets if already exist
146 m_channelsMap
.clear();
148 QWidget
* oldChanW
= ui
->channelsScroll
->takeWidget();
150 oldChanW
->deleteLater();
155 QWidget
* channelsWidget
= new QWidget();
156 QGridLayout
* channelsLayout
= new QGridLayout(channelsWidget
);
157 channelsLayout
->setHorizontalSpacing(4);
158 channelsLayout
->setVerticalSpacing(3);
159 channelsLayout
->setContentsMargins(5, 5, 5, 5);
161 ui
->channelsScroll
->setWidget(channelsWidget
);
165 for (int i
=0; i
< outputs
; i
++) {
166 QLabel
* label
= new QLabel(channelsWidget
);
167 label
->setText(" " + RawSource(SOURCE_TYPE_CH
, i
).toString() + " ");
168 label
->setAlignment(Qt::AlignCenter
);
169 label
->setSizePolicy(QSizePolicy::Preferred
, QSizePolicy::Fixed
);
170 channelsLayout
->addWidget(label
, 0, column
, 1, 1);
172 QSlider
* slider
= new QSlider(channelsWidget
);
173 slider
->setEnabled(false);
174 slider
->setMinimum(-1024);
175 slider
->setMaximum(1024);
176 slider
->setPageStep(128);
177 slider
->setTracking(false);
178 slider
->setOrientation(Qt::Vertical
);
179 slider
->setInvertedAppearance(false);
180 slider
->setTickPosition(QSlider::TicksRight
);
181 slider
->setSizePolicy(QSizePolicy::Fixed
, QSizePolicy::Preferred
);
182 channelsLayout
->addWidget(slider
, 2, column
, 1, 1);
183 channelsLayout
->setAlignment(slider
, Qt::AlignHCenter
);
185 QLabel
* value
= new QLabel(channelsWidget
);
186 value
->setMinimumSize(QSize(value
->fontMetrics().size(Qt::TextSingleLine
, "-100.0").width(), 0));
187 value
->setAlignment(Qt::AlignCenter
);
188 value
->setSizePolicy(QSizePolicy::Preferred
, QSizePolicy::Fixed
);
189 channelsLayout
->addWidget(value
, 1, column
, 1, 1);
193 m_channelsMap
.insert(i
, QPair
<QLabel
*, QSlider
*>(value
, slider
));
197 void RadioOutputsWidget::setupGVarsDisplay()
199 int gvars
= m_firmware
->getCapability(Capability(Gvars
));
200 int fmodes
= m_firmware
->getCapability(Capability(FlightModes
));
202 // delete old widgets if already exist
203 m_globalVarsMap
.clear();
205 QWidget
* oldGv
= ui
->globalVarsScroll
->takeWidget();
207 oldGv
->deleteLater();
212 QWidget
* gvarsWidget
= new QWidget();
213 QGridLayout
* gvarsLayout
= new QGridLayout(gvarsWidget
);
214 gvarsLayout
->setContentsMargins(5, 5, 5, 5);
215 gvarsLayout
->setHorizontalSpacing(6);
216 gvarsLayout
->setVerticalSpacing(3);
217 ui
->globalVarsScroll
->setWidget(gvarsWidget
);
219 QPalette::ColorRole bgrole
= QPalette::AlternateBase
;
220 for (int fm
=0; fm
< fmodes
; fm
++) {
221 QLabel
* label
= new QLabel(gvarsWidget
);
222 label
->setText(QString("FM%1").arg(fm
));
223 label
->setAlignment(Qt::AlignCenter
);
224 label
->setBackgroundRole(bgrole
);
225 gvarsLayout
->addWidget(label
, 0, fm
+1);
227 QHash
<int, QLabel
*> fmMap
;
228 for (int gv
=0; gv
< gvars
; gv
++) {
229 bgrole
= ((gv
% 2) ? QPalette::Background
: QPalette::AlternateBase
);
230 QLabel
* label
= new QLabel(gvarsWidget
);
231 label
->setText(QString("GV%1").arg(gv
+1));
232 label
->setAutoFillBackground(true);
233 label
->setBackgroundRole(bgrole
);
234 gvarsLayout
->addWidget(label
, gv
+1, 0);
235 for (int fm
=0; fm
< fmodes
; fm
++) {
236 QLabel
* value
= new QLabel(gvarsWidget
);
237 value
->setAlignment(Qt::AlignRight
| Qt::AlignVCenter
);
238 value
->setAutoFillBackground(true);
239 value
->setBackgroundRole(bgrole
);
241 value
->setStyleSheet("padding-right: .06em;");
242 gvarsLayout
->addWidget(value
, gv
+1, fm
+1);
244 fmMap
.insert(fm
, value
);
246 m_globalVarsMap
.insert(gv
, fmMap
);
250 void RadioOutputsWidget::setupLsDisplay()
252 int switches
= m_firmware
->getCapability(LogicalSwitches
);
254 // delete old widgets if already exist
255 m_logicSwitchMap
.clear();
257 QWidget
* oldLsW
= ui
->logicalSwitchesScroll
->takeWidget();
259 oldLsW
->deleteLater();
264 QWidget
* logicalSwitches
= new QWidget();
265 logicalSwitches
->setSizePolicy(QSizePolicy::Preferred
, QSizePolicy::Maximum
);
266 QGridLayout
* logicalSwitchesLayout
= new QGridLayout(logicalSwitches
);
267 logicalSwitchesLayout
->setHorizontalSpacing(3);
268 logicalSwitchesLayout
->setVerticalSpacing(2);
269 logicalSwitchesLayout
->setContentsMargins(5, 5, 5, 5);
270 ui
->logicalSwitchesScroll
->setWidget(logicalSwitches
);
272 // populate logical switches
273 int rows
= switches
/ (switches
> 16 ? 4 : 2);
274 for (int i
=0; i
< switches
; i
++) {
275 logicalSwitchesLayout
->addWidget(createLogicalSwitch(logicalSwitches
, i
), i
/ rows
, i
% rows
, 1, 1);
279 QWidget
* RadioOutputsWidget::createLogicalSwitch(QWidget
* parent
, int switchNo
)
281 QLabel
* swtch
= new QLabel(parent
);
282 swtch
->setAutoFillBackground(true);
283 swtch
->setFrameStyle(QFrame::Panel
| QFrame::Raised
);
284 swtch
->setLineWidth(2);
285 swtch
->setSizePolicy(QSizePolicy::Preferred
, QSizePolicy::Fixed
);
286 QFont font
= swtch
->font();
288 swtch
->setFont(font
);
289 swtch
->setMinimumWidth(swtch
->fontMetrics().width("99") + 10);
291 swtch
->setFont(font
);
292 swtch
->setText(QString("%1").arg(RawSwitch(SWITCH_TYPE_VIRTUAL
, switchNo
+1).toString().remove("L"), 2, QLatin1Char('0')));
293 swtch
->setAlignment(Qt::AlignCenter
);
294 m_logicSwitchMap
.insert(switchNo
, swtch
);
298 // Read various values from firmware simulator and populate values in this UI
299 void RadioOutputsWidget::setValues()
301 static int lastPhase
= -1;
302 static TxOutputs prevOutputs
= TxOutputs();
303 static bool firstGvarsRun
= true;
308 m_simulator
->getValues(outputs
);
309 currentPhase
= m_simulator
->getPhase();
311 if (ui
->channelsWidget
->isVisible()) {
312 QHash
<int, QPair
<QLabel
*, QSlider
*> >::const_iterator ch
;
313 for (ch
= m_channelsMap
.constBegin(); ch
!= m_channelsMap
.constEnd(); ++ch
) {
314 if (ch
.key() >= CPN_MAX_CHNOUT
)
316 ch
.value().first
->setText(QString("%1%").arg(outputs
.chans
[ch
.key()] * 100 / 1024));
317 ch
.value().second
->setValue(qMin(1024, qMax(-1024, outputs
.chans
[ch
.key()])));
321 if (ui
->logicalSwitchesWidget
->isVisible()) {
322 QHash
<int, QLabel
* >::const_iterator ls
;
323 for (ls
= m_logicSwitchMap
.constBegin(); ls
!= m_logicSwitchMap
.constEnd(); ++ls
) {
324 if (ls
.key() >= CPN_MAX_CSW
|| prevOutputs
.vsw
[ls
.key()] == outputs
.vsw
[ls
.key()])
326 ls
.value()->setBackgroundRole(outputs
.vsw
[ls
.key()] ? QPalette::Dark
: QPalette::Background
);
327 ls
.value()->setForegroundRole(outputs
.vsw
[ls
.key()] ? QPalette::BrightText
: QPalette::WindowText
);
328 ls
.value()->setFrameShadow(outputs
.vsw
[ls
.key()] ? QFrame::Sunken
: QFrame::Raised
);
329 font
= ls
.value()->font();
330 font
.setBold(outputs
.vsw
[ls
.key()]);
331 ls
.value()->setFont(font
);
332 prevOutputs
.vsw
[ls
.key()] = outputs
.vsw
[ls
.key()];
336 if (ui
->globalVarsWidget
->isVisible()) {
337 QPalette::ColorRole bgrole
;
338 QHash
<int, QHash
<int, QLabel
*> >::const_iterator gv
;
339 QHash
<int, QLabel
*>::const_iterator fm
;
340 for (gv
= m_globalVarsMap
.constBegin(); gv
!= m_globalVarsMap
.constEnd(); ++gv
) {
341 if (gv
.key() >= CPN_MAX_GVARS
)
343 for (fm
= gv
.value().constBegin(); fm
!= gv
.value().constEnd(); ++fm
) {
344 if (fm
.key() >= CPN_MAX_FLIGHT_MODES
)
346 if (currentPhase
!= lastPhase
|| prevOutputs
.gvars
[fm
.key()][gv
.key()] != outputs
.gvars
[fm
.key()][gv
.key()] || firstGvarsRun
) {
347 if (fm
.key() == currentPhase
)
348 bgrole
= QPalette::Dark
;
350 bgrole
= ((gv
.key() % 2) ? QPalette::Background
: QPalette::AlternateBase
);
351 fm
.value()->setBackgroundRole(bgrole
);
352 fm
.value()->setForegroundRole(fm
.key() == currentPhase
? QPalette::BrightText
: QPalette::WindowText
);
353 font
= fm
.value()->font();
354 font
.setBold(fm
.key() == currentPhase
);
355 fm
.value()->setFont(font
);
356 fm
.value()->setText(QString::number(outputs
.gvars
[fm
.key()][gv
.key()]));
357 prevOutputs
.gvars
[fm
.key()][gv
.key()] = outputs
.gvars
[fm
.key()][gv
.key()];
358 firstGvarsRun
= false;
364 lastPhase
= currentPhase
;