2 ******************************************************************************
4 * @file outputchannelform.cpp
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2011.
6 * @addtogroup GCSPlugins GCS Plugins
8 * @addtogroup ConfigPlugin Config Plugin
10 * @brief Servo output configuration form for the config output gadget
11 *****************************************************************************/
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "outputchannelform.h"
30 #include "ui_outputchannelform.h"
32 #define MAXOUTPUT_VALUE 2500
33 #define MINOUTPUT_VALUE 500
35 OutputChannelForm::OutputChannelForm(const int index
, QWidget
*parent
) :
36 ChannelForm(index
, parent
), ui(new Ui::outputChannelForm
), m_inChannelTest(false)
40 // The convention for OP is Channel 1 to Channel 10.
41 ui
->actuatorNumber
->setText(QString("%1").arg(index
+ 1));
43 // Register for ActuatorSettings changes:
44 connect(ui
->actuatorMin
, SIGNAL(editingFinished()), this, SLOT(setChannelRange()));
45 connect(ui
->actuatorMax
, SIGNAL(editingFinished()), this, SLOT(setChannelRange()));
46 connect(ui
->actuatorRev
, SIGNAL(toggled(bool)), this, SLOT(reverseChannel(bool)));
47 // Now connect the channel out sliders to our signal to send updates in test mode
48 connect(ui
->actuatorNeutral
, SIGNAL(valueChanged(int)), this, SLOT(sendChannelTest(int)));
50 ui
->actuatorLink
->setChecked(false);
51 connect(ui
->actuatorLink
, SIGNAL(toggled(bool)), this, SLOT(linkToggled(bool)));
54 ui
->actuatorMin
->setMaximum(MAXOUTPUT_VALUE
);
55 ui
->actuatorMax
->setMaximum(MAXOUTPUT_VALUE
);
56 ui
->actuatorValue
->setMaximum(MAXOUTPUT_VALUE
);
57 ui
->actuatorMin
->setMinimum(MINOUTPUT_VALUE
);
58 ui
->actuatorMax
->setMinimum(MINOUTPUT_VALUE
);
59 ui
->actuatorValue
->setMinimum(MINOUTPUT_VALUE
);
63 disableMouseWheelEvents();
66 OutputChannelForm::~OutputChannelForm()
71 QString
OutputChannelForm::name()
73 return ui
->actuatorName
->text();
76 QString
OutputChannelForm::bank()
78 return ui
->actuatorBankNumber
->text();
82 * Set the channel assignment label.
84 void OutputChannelForm::setName(const QString
&name
)
86 ui
->actuatorName
->setText(name
);
89 void OutputChannelForm::setColor(const QColor
&color
)
91 QString stylesheet
= ui
->actuatorNumberFrame
->styleSheet();
93 stylesheet
= stylesheet
.split("background-color").first();
95 QString("background-color: rgb(%1, %2, %3)")
96 .arg(color
.red()).arg(color
.green()).arg(color
.blue()));
97 ui
->actuatorNumberFrame
->setStyleSheet(stylesheet
);
101 * Set the channel bank label.
103 void OutputChannelForm::setBank(const QString
&bank
)
105 ui
->actuatorBankNumber
->setText(bank
);
109 * Restrict UI to protect users from accidental misuse.
111 void OutputChannelForm::enableChannelTest(bool state
)
113 if (m_inChannelTest
== state
) {
116 m_inChannelTest
= state
;
118 if (m_inChannelTest
) {
119 // Prevent stupid users from touching the minimum & maximum ranges while
120 // moving the sliders. Thanks Ivan for the tip :)
121 ui
->actuatorMin
->setEnabled(false);
122 ui
->actuatorMax
->setEnabled(false);
123 ui
->actuatorRev
->setEnabled(false);
124 } else if (m_mixerType
!= "Disabled") {
125 ui
->actuatorMin
->setEnabled(true);
126 ui
->actuatorMax
->setEnabled(true);
127 if (m_mixerType
!= "Motor") {
128 ui
->actuatorRev
->setEnabled(true);
134 * Toggles the channel linked state for use in testing mode
136 void OutputChannelForm::linkToggled(bool state
)
140 if (!m_inChannelTest
) {
141 return; // we are not in Test Output mode
143 // find the minimum slider value for the linked ones
147 int min
= MAXOUTPUT_VALUE
;
148 int linked_count
= 0;
149 QList
<OutputChannelForm
*> outputChannelForms
= parent()->findChildren
<OutputChannelForm
*>();
150 // set the linked channels of the parent widget to the same value
151 foreach(OutputChannelForm
* outputChannelForm
, outputChannelForms
) {
152 if (!outputChannelForm
->ui
->actuatorLink
->checkState()) {
155 if (this == outputChannelForm
) {
158 int value
= outputChannelForm
->ui
->actuatorNeutral
->value();
165 if (linked_count
<= 0) {
166 return; // no linked channels
168 // set the linked channels to the same value
169 foreach(OutputChannelForm
* outputChannelForm
, outputChannelForms
) {
170 if (!outputChannelForm
->ui
->actuatorLink
->checkState()) {
173 outputChannelForm
->ui
->actuatorNeutral
->setValue(min
);
177 int OutputChannelForm::max() const
179 return ui
->actuatorMax
->value();
183 * Set maximal channel value.
185 void OutputChannelForm::setMax(int maximum
)
187 setRange(ui
->actuatorMax
->value(), maximum
);
190 int OutputChannelForm::min() const
192 return ui
->actuatorMin
->value();
196 * Set minimal channel value.
198 void OutputChannelForm::setMin(int minimum
)
200 setRange(minimum
, ui
->actuatorMin
->value());
203 int OutputChannelForm::neutral() const
205 return ui
->actuatorNeutral
->value();
209 * Set neutral of channel.
211 void OutputChannelForm::setNeutral(int value
)
213 ui
->actuatorNeutral
->setValue(value
);
217 * Set minimal and maximal channel value.
219 void OutputChannelForm::setRange(int minimum
, int maximum
)
221 ui
->actuatorMin
->setValue(minimum
);
222 ui
->actuatorMax
->setValue(maximum
);
227 * Sets the minimum/maximum value of the channel output sliders.
228 * Have to do it here because setMinimum is not a slot.
230 * One added trick: if the slider is at its min when the value
231 * is changed, then keep it on the min.
233 void OutputChannelForm::setChannelRange()
235 int minValue
= ui
->actuatorMin
->value();
236 int maxValue
= ui
->actuatorMax
->value();
238 int oldMini
= ui
->actuatorNeutral
->minimum();
239 int oldMaxi
= ui
->actuatorNeutral
->maximum();
241 m_mixerType
= outputMixerType();
243 // Red handle for Motors
244 if ((m_mixerType
== "Motor") || (m_mixerType
== "ReversableMotor")) {
245 ui
->actuatorNeutral
->setStyleSheet("QSlider::handle:horizontal { background: rgb(255, 100, 100); width: 18px; height: 28px;"
246 "margin: -3px 0; border-radius: 3px; border: 1px solid #777; }");
248 ui
->actuatorNeutral
->setStyleSheet("QSlider::handle:horizontal { background: rgb(196, 196, 196); width: 18px; height: 28px;"
249 "margin: -3px 0; border-radius: 3px; border: 1px solid #777; }");
252 // Normal motor will be *** never *** reversed : without arming a "Min" value (like 1900) can be applied !
253 if (m_mixerType
== "Motor") {
254 if (minValue
>= maxValue
) {
256 ui
->actuatorMin
->setValue(oldMini
);
257 ui
->actuatorMax
->setValue(oldMaxi
);
259 ui
->actuatorRev
->setChecked(false);
260 ui
->actuatorRev
->setEnabled(false);
261 ui
->actuatorNeutral
->setInvertedAppearance(false);
262 ui
->actuatorNeutral
->setRange(ui
->actuatorMin
->value(), ui
->actuatorMax
->value());
264 // Others output (!Motor)
265 // Auto check reverse checkbox SpinBox Min/Max changes
266 ui
->actuatorRev
->setEnabled(true);
267 if (minValue
<= maxValue
) {
268 ui
->actuatorRev
->setChecked(false);
269 ui
->actuatorNeutral
->setInvertedAppearance(false);
270 ui
->actuatorNeutral
->setRange(minValue
, maxValue
);
272 ui
->actuatorRev
->setChecked(true);
273 ui
->actuatorNeutral
->setInvertedAppearance(true);
274 ui
->actuatorNeutral
->setRange(maxValue
, minValue
);
277 // If old neutral was Min, stay Min
278 if (ui
->actuatorNeutral
->value() == oldMini
) {
279 ui
->actuatorNeutral
->setValue(ui
->actuatorNeutral
->minimum());
282 // Enable only outputs already set in mixer
283 if (m_mixerType
!= "Disabled") {
284 ui
->actuatorMin
->setEnabled(true);
285 ui
->actuatorMax
->setEnabled(true);
286 ui
->actuatorNeutral
->setEnabled(true);
287 ui
->actuatorValue
->setEnabled(true);
288 ui
->actuatorLink
->setEnabled(true);
290 ui
->actuatorMin
->setEnabled(false);
291 ui
->actuatorMax
->setEnabled(false);
292 ui
->actuatorRev
->setEnabled(false);
293 ui
->actuatorLink
->setEnabled(false);
294 ui
->actuatorMin
->setValue(1000);
295 ui
->actuatorMax
->setValue(1000);
296 ui
->actuatorNeutral
->setRange(minValue
, maxValue
);
297 ui
->actuatorNeutral
->setValue(minValue
);
298 ui
->actuatorValue
->setEnabled(false);
303 * Reverses the channel when the checkbox is clicked
305 void OutputChannelForm::reverseChannel(bool state
)
307 // if 'state' (reverse channel requested) apply only if not already reversed
308 if ((state
&& (ui
->actuatorMax
->value() > ui
->actuatorMin
->value()))
309 || (!state
&& (ui
->actuatorMax
->value() < ui
->actuatorMin
->value()))) {
310 // Now, swap the min & max values (spin boxes)
311 int temp
= ui
->actuatorMax
->value();
312 ui
->actuatorMax
->setValue(ui
->actuatorMin
->value());
313 ui
->actuatorMin
->setValue(temp
);
314 ui
->actuatorNeutral
->setInvertedAppearance(state
);
322 * Emits the channel value which will be send to the UAV to move the servo.
323 * Returns immediately if we are not in testing mode.
325 void OutputChannelForm::sendChannelTest(int value
)
327 int in_value
= value
;
329 QSlider
*ob
= (QSlider
*)QObject::sender();
336 ui
->actuatorValue
->setValue(value
);
338 if (ui
->actuatorLink
->checkState() && parent()) {
339 // the channel is linked to other channels
340 QList
<OutputChannelForm
*> outputChannelForms
= parent()->findChildren
<OutputChannelForm
*>();
341 // set the linked channels of the parent widget to the same value
342 foreach(OutputChannelForm
* outputChannelForm
, outputChannelForms
) {
343 if (this == outputChannelForm
) {
346 if (!outputChannelForm
->ui
->actuatorLink
->checkState()) {
351 if (val
< outputChannelForm
->ui
->actuatorNeutral
->minimum()) {
352 val
= outputChannelForm
->ui
->actuatorNeutral
->minimum();
354 if (val
> outputChannelForm
->ui
->actuatorNeutral
->maximum()) {
355 val
= outputChannelForm
->ui
->actuatorNeutral
->maximum();
358 if (outputChannelForm
->ui
->actuatorNeutral
->value() == val
) {
362 outputChannelForm
->ui
->actuatorNeutral
->setValue(val
);
363 outputChannelForm
->ui
->actuatorValue
->setValue(val
);
367 if (!m_inChannelTest
) {
368 // we are not in Test Output mode
371 emit
channelChanged(index(), value
);
378 QString
OutputChannelForm::outputMixerType()
380 UAVDataObject
*mixer
= dynamic_cast<UAVDataObject
*>(getObjectManager()->getObject(QString("MixerSettings")));
384 QString mixerNumType
= QString("Mixer%1Type").arg(index() + 1);
385 UAVObjectField
*field
= mixer
->getField(mixerNumType
);
387 QString mixerType
= field
->getValue().toString();