feat(cpn): add support for surface radios inc Radiomaster MT12 (#5381)

This commit is contained in:
Neil Horne
2024-09-26 20:39:51 +10:00
committed by GitHub
parent 2bd62c95c8
commit 149e1a2df0
90 changed files with 3746 additions and 2387 deletions
+68 -34
View File
@@ -27,11 +27,12 @@
#include "namevalidator.h"
FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseIdx, GeneralSettings & generalSettings, Firmware * firmware,
FilteredItemModel * rawSwitchFilteredModel):
FilteredItemModel * rawSwitchFilteredModel, QString radioType):
ModelPanel(parent, model, generalSettings, firmware),
ui(new Ui::FlightMode),
phaseIdx(phaseIdx),
phase(model.flightModeData[phaseIdx])
phase(model.flightModeData[phaseIdx]),
radioType(radioType)
{
ui->setupUi(this);
connectItemModelEvents(rawSwitchFilteredModel);
@@ -40,7 +41,7 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI
ui->labelName->setToolTip(tr("Popup menu available"));
connect(ui->labelName, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onCustomContextMenuRequested(const QPoint &)));
board = getCurrentBoard();
board = firmware->getBoard();
fmCount = firmware->getCapability(FlightModes);
gvCount = firmware->getCapability(Gvars);
reCount = firmware->getCapability(RotaryEncoders);
@@ -85,13 +86,14 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI
// The trims
QString labels[CPN_MAX_TRIMS];
for(int i = 0; i < CPN_MAX_STICKS; i++) {
for (int i = 0; i < Boards::getCapability(board, Board::Sticks); i++) {
labels[i] = Boards::getInputName(i);
}
labels[4] = "T5"; // TODO firmware function
labels[5] = "T6"; // TODO firmware function
labels[6] = "T7"; // TODO firmware function
labels[7] = "T8"; // TODO firmware function
for (int i = Boards::getCapability(board, Board::Sticks); i < CPN_MAX_TRIMS; i++) {
labels[i] = QString("T%1").arg(i + 1);
}
trimsLabel << ui->trim1Label << ui->trim2Label << ui->trim3Label << ui->trim4Label << ui->trim5Label << ui->trim6Label << ui->trim7Label << ui->trim8Label;
trimsUse << ui->trim1Use << ui->trim2Use << ui->trim3Use << ui->trim4Use << ui->trim5Use << ui->trim6Use << ui->trim7Use << ui->trim8Use;
@@ -106,7 +108,7 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI
}
for (int i = 0; i < trimCount; i++) {
trimsLabel[i]->setText(labels[CONVERT_MODE(i + 1) - 1]);
trimsLabel[i]->setText(labels[Boards::isAir(board) ? CONVERT_AIRMODE(i + 1) - 1 : CONVERT_SURFACEMODE(i + 1) - 1]);
QComboBox * cb = trimsUse[i];
cb->setProperty("index", i);
if (IS_HORUS_OR_TARANIS(board)) {
@@ -118,9 +120,9 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI
cb->addItem(tr("Own Trim"), m * 2);
}
else if (phaseIdx > 0) {
cb->addItem(tr("Use Trim from Flight mode %1").arg(m), m * 2);
cb->addItem(tr("Use Trim from %1 Mode %2").arg(radioType).arg(m), m * 2);
if (IS_HORUS_OR_TARANIS(board)) {
cb->addItem(tr("Use Trim from Flight mode %1 + Own Trim as an offset").arg(m), m * 2 + 1);
cb->addItem(tr("Use Trim from %1 Mode %2 + Own Trim as an offset").arg(radioType).arg(m), m * 2 + 1);
}
}
}
@@ -137,8 +139,9 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI
trimsSlider[i]->setProperty("index", i);
trimsSlider[i]->setRange(-trimsMax, +trimsMax);
int chn = CONVERT_MODE(i + 1) - 1;
if (chn == 2/*TODO constant*/ && model.throttleReversed)
int chn = Boards::isAir(board) ? CONVERT_AIRMODE(i + 1) - 1 : CONVERT_SURFACEMODE(i + 1) - 1;
if (model.throttleReversed && ((Boards::isAir(board) && chn == 2/*TODO constant*/) ||
(Boards::isSurface(board) && chn == 1/*TODO constant*/)))
trimsSlider[i]->setInvertedAppearance(true);
connect(trimsSlider[i], SIGNAL(valueChanged(int)), this, SLOT(phaseTrimSlider_valueChanged()));
}
@@ -155,7 +158,7 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI
// RE link to another RE
reUse[i] = new QComboBox(ui->reGB);
reUse[i]->setProperty("index", i);
Helpers::populateGvarUseCB(reUse[i], phaseIdx);
populateGvarUseCB(reUse[i], phaseIdx);
connect(reUse[i], SIGNAL(currentIndexChanged(int)), this, SLOT(phaseREUse_currentIndexChanged(int)));
reLayout->addWidget(reUse[i], i, 1, 1, 1);
}
@@ -221,7 +224,7 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI
int col = 0;
// GVar label
QLabel *label = new QLabel(ui->gvGB);
label->setText(tr("GVAR%1").arg(i + 1));
label->setText(tr("GV%1").arg(i + 1));
label->setProperty("index", i);
label->setContextMenuPolicy(Qt::CustomContextMenu);
label->setToolTip(tr("Popup menu available"));
@@ -241,7 +244,7 @@ FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseI
// GVar link to another GVar
gvUse[i] = new QComboBox(ui->gvGB);
gvUse[i]->setProperty("index", i);
Helpers::populateGvarUseCB(gvUse[i], phaseIdx);
populateGvarUseCB(gvUse[i], phaseIdx);
connect(gvUse[i], SIGNAL(currentIndexChanged(int)), this, SLOT(phaseGVUse_currentIndexChanged(int)));
gvLayout->addWidget(gvUse[i], i + 1, col++, 1, 1);
}
@@ -348,6 +351,16 @@ void FlightModePanel::updateGVar(int index)
lock = false;
}
void FlightModePanel::populateGvarUseCB(QComboBox * b, unsigned int phase)
{
b->addItem(tr("Own value"));
for (int i = 0; i < getCurrentFirmware()->getCapability(FlightModes); i++) {
if (i != (int)phase) {
b->addItem(tr("%1 Mode %2 value").arg(radioType).arg(i));
}
}
}
void FlightModePanel::setGVSB(QDoubleSpinBox * sb, int min, int max, int val)
{
int idx = sb->property("index").toInt();
@@ -430,7 +443,7 @@ void FlightModePanel::phaseFadeOut_editingFinished()
void FlightModePanel::trimUpdate(unsigned int trim)
{
lock = true;
int chn = CONVERT_MODE(trim + 1) - 1;
int chn = Boards::isAir(board) ? CONVERT_AIRMODE(trim + 1) - 1 : CONVERT_SURFACEMODE(trim + 1) - 1;
int value = model->getTrimValue(phaseIdx, chn);
trimsSlider[trim]->setValue(value);
trimsValue[trim]->setValue(value);
@@ -496,7 +509,7 @@ void FlightModePanel::phaseGVUse_currentIndexChanged(int index)
phase.gvars[gvar] = GVAR_MAX_VALUE + index;
}
if (model->isGVarLinkedCircular(phaseIdx, gvar))
QMessageBox::warning(this, "Companion", tr("Warning: Global variable links back to itself. Flight Mode 0 value used."));
QMessageBox::warning(this, "Companion", tr("Warning: Global variable links back to itself. %1 Mode 0 value used.").arg(radioType));
updateGVar(gvar);
emit modified();
lock = false;
@@ -605,7 +618,7 @@ void FlightModePanel::phaseREUse_currentIndexChanged(int index)
}
update();
if (model->isREncLinkedCircular(phaseIdx, re))
QMessageBox::warning(this, "Companion", tr("Warning: Rotary encoder links back to itself. Flight Mode 0 value used."));
QMessageBox::warning(this, "Companion", tr("Warning: Rotary encoder links back to itself. %1 Mode 0 value used.").arg(radioType));
emit modified();
lock = false;
}
@@ -616,7 +629,7 @@ void FlightModePanel::phaseTrimUse_currentIndexChanged(int index)
if (!lock) {
QComboBox *comboBox = qobject_cast<QComboBox*>(sender());
int trim = comboBox->property("index").toInt();
int chn = CONVERT_MODE(trim + 1) - 1;
int chn = Boards::isAir(board) ? CONVERT_AIRMODE(trim + 1) - 1 : CONVERT_SURFACEMODE(trim + 1) - 1;
int data = comboBox->itemData(index).toInt();
if (data < 0) {
phase.trimMode[chn] = -1;
@@ -648,7 +661,7 @@ void FlightModePanel::phaseTrim_valueChanged()
if (!lock) {
QSpinBox *spinBox = qobject_cast<QSpinBox*>(sender());
int trim = spinBox->property("index").toInt();
int chn = CONVERT_MODE(trim + 1) - 1;
int chn = Boards::isAir(board) ? CONVERT_AIRMODE(trim + 1) - 1 : CONVERT_SURFACEMODE(trim + 1) - 1;
int value = spinBox->value();
model->setTrimValue(phaseIdx, chn, value);
lock = true;
@@ -663,7 +676,7 @@ void FlightModePanel::phaseTrimSlider_valueChanged()
if (!lock) {
QSlider *slider = qobject_cast<QSlider*>(sender());
int trim = slider->property("index").toInt();
int chn = CONVERT_MODE(trim + 1) - 1;
int chn = Boards::isAir(board) ? CONVERT_AIRMODE(trim + 1) - 1 : CONVERT_SURFACEMODE(trim + 1) - 1;
int value = slider->value();
model->setTrimValue(phaseIdx, chn, value);
lock = true;
@@ -724,7 +737,7 @@ bool FlightModePanel::moveUpAllowed() const
void FlightModePanel::cmClear(bool prompt)
{
if (prompt) {
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Flight Mode. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear %1 Mode. Are you sure?").arg(radioType), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
}
@@ -761,7 +774,7 @@ void FlightModePanel::cmClear(bool prompt)
void FlightModePanel::cmClearAll()
{
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Flight Modes. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all %1 Modes. Are you sure?").arg(radioType), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
for (int j = 0; j < fmCount; j++) {
@@ -796,7 +809,7 @@ void FlightModePanel::cmCopy()
void FlightModePanel::cmCut()
{
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Flight Mode. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut %1 Mode. Are you sure?").arg(radioType), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
cmCopy();
cmClear(false);
@@ -804,7 +817,7 @@ void FlightModePanel::cmCut()
void FlightModePanel::cmDelete()
{
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Flight Mode. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete %1 Mode. Are you sure?").arg(radioType), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
const int maxidx = fmCount - 1;
@@ -1160,7 +1173,7 @@ void FlightModePanel::gvCmClear(bool prompt)
{
if (phaseIdx == 0) {
if (prompt) {
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Global Variable across all Flight Modes. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Global Variable across all %1 Modes. Are you sure?").arg(radioType), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
}
model->gvarData[gvIdx].clear();
@@ -1184,7 +1197,7 @@ void FlightModePanel::gvCmClear(bool prompt)
void FlightModePanel::gvCmClearAll()
{
if (phaseIdx == 0) {
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Global Variables for all Flight Modes. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Global Variables for all %1 Modes. Are you sure?").arg(radioType), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
for (int i = 0; i < gvCount; i++) {
model->gvarData[i].clear();
@@ -1195,7 +1208,7 @@ void FlightModePanel::gvCmClearAll()
}
}
else {
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Global Variables for this Flight Mode. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Global Variables for this %1 Mode. Are you sure?").arg(radioType), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
for (int i = 0; i < gvCount; i++) {
phase.gvars[i] = phase.linkedGVarFlightModeZero(phaseIdx);
@@ -1247,7 +1260,7 @@ void FlightModePanel::gvCmCopy()
void FlightModePanel::gvCmCut()
{
if (phaseIdx == 0) {
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Global Variable across all Flight Modes. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Global Variable across all %1 Modes. Are you sure?").arg(radioType), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
}
else {
@@ -1325,7 +1338,7 @@ void FlightModePanel::gvCmPaste()
{
QByteArray data;
if (phaseIdx == 0) {
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Paste to selected Global Variable across all Flight Modes. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Paste to selected Global Variable across all %1 Modes. Are you sure?").arg(radioType), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
if (gvHasDefnClipboardData(&data)) {
memcpy(&model->gvarData[gvIdx], data.constData(), sizeof(GVarData));
@@ -1391,6 +1404,18 @@ void FlightModePanel::onItemModelUpdateComplete()
lock = false;
}
void FlightModePanel::onThrottleReverseChanged()
{
for (int i = 0; i < CPN_MAX_TRIMS; i++) {
int chn = Boards::isAir(board) ? CONVERT_AIRMODE(i + 1) - 1 : CONVERT_SURFACEMODE(i + 1) - 1;
if (model->throttleReversed && ((Boards::isAir(board) && chn == 2/*TODO constant*/) ||
(Boards::isSurface(board) && chn == 1/*TODO constant*/)))
trimsSlider[i]->setInvertedAppearance(true);
else
trimsSlider[i]->setInvertedAppearance(false);
}
}
/**********************************************************/
FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware,
@@ -1402,11 +1427,13 @@ FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralS
connectItemModelEvents(rawSwitchFilteredModel);
modesCount = firmware->getCapability(FlightModes);
radioType = Boards::getRadioTypeString(firmware->getBoard());
QGridLayout * gridLayout = new QGridLayout(this);
tabWidget = new QTabWidget(this);
for (int i = 0; i < modesCount; i++) {
FlightModePanel * tab = new FlightModePanel(tabWidget, model, i, generalSettings, firmware, rawSwitchFilteredModel);
FlightModePanel * tab = new FlightModePanel(tabWidget, model, i, generalSettings, firmware, rawSwitchFilteredModel, radioType);
tab->setProperty("index", i);
connect(tab, &FlightModePanel::modified, this, &FlightModesPanel::modified);
connect(tab, &FlightModePanel::phaseDataChanged, this, &FlightModesPanel::onPhaseNameChanged);
@@ -1414,10 +1441,12 @@ FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralS
connect(tab, &FlightModePanel::phaseSwitchChanged, this, &FlightModesPanel::updateItemModels);
connect(tab, &FlightModePanel::gvNameChanged, this, &FlightModesPanel::updateItemModels);
connect(this, &FlightModesPanel::updated, tab, &FlightModePanel::update);
connect(this, &FlightModesPanel::updated, tab, &FlightModePanel::update);
connect(this, &FlightModesPanel::refreshThrottleTrim, tab, &FlightModePanel::onThrottleReverseChanged);
tabWidget->addTab(tab, getTabName(i));
panels << tab;
}
connect(tabWidget, &QTabWidget::currentChanged, this, &FlightModesPanel::onTabIndexChanged);
gridLayout->addWidget(tabWidget, 0, 0, 1, 1);
onTabIndexChanged(0);
@@ -1430,7 +1459,7 @@ FlightModesPanel::~FlightModesPanel()
QString FlightModesPanel::getTabName(int index)
{
QString result = tr("Flight Mode %1").arg(index);
QString result = tr("%1 Mode %2").arg(radioType).arg(index);
const char *name = model->flightModeData[index].name;
if (firmware->getCapability(FlightModesName) && strlen(name) > 0) {
result += tr(" (%1)").arg(name);
@@ -1479,3 +1508,8 @@ void FlightModesPanel::onTabIndexChanged(int index)
if (index < panels.size())
panels.at(index)->update();
}
void FlightModesPanel::onThrottleReverseChanged()
{
emit refreshThrottleTrim();
}