Files
edgetx-gx12/companion/src/modeledit/flightmodes.cpp
T
2021-01-08 20:24:46 +11:00

1469 lines
48 KiB
C++

/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "flightmodes.h"
#include "ui_flightmode.h"
#include "filtereditemmodels.h"
#include "helpers.h"
#include "customdebug.h"
FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseIdx, GeneralSettings & generalSettings, Firmware * firmware,
FilteredItemModel * rawSwitchFilteredModel):
ModelPanel(parent, model, generalSettings, firmware),
ui(new Ui::FlightMode),
phaseIdx(phaseIdx),
phase(model.flightModeData[phaseIdx])
{
ui->setupUi(this);
connectItemModelEvents(rawSwitchFilteredModel);
ui->labelName->setContextMenuPolicy(Qt::CustomContextMenu);
ui->labelName->setToolTip(tr("Popup menu available"));
connect(ui->labelName, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onCustomContextMenuRequested(const QPoint &)));
board = getCurrentBoard();
fmCount = firmware->getCapability(FlightModes);
gvCount = firmware->getCapability(Gvars);
reCount = firmware->getCapability(RotaryEncoders);
trimCount = Boards::getCapability(board, Board::NumTrims);
// Flight mode name
QRegExp rx(CHAR_FOR_NAMES_REGEX);
if (fmCount) {
ui->name->setValidator(new QRegExpValidator(rx, this));
ui->name->setMaxLength(firmware->getCapability(FlightModesName));
connect(ui->name, SIGNAL(editingFinished()), this, SLOT(phaseName_editingFinished()));
}
else {
ui->name->setDisabled(true);
}
// Flight mode switch
if (phaseIdx > 0) {
ui->swtch->setModel(rawSwitchFilteredModel);
connect(ui->swtch, SIGNAL(currentIndexChanged(int)), this, SLOT(phaseSwitch_currentIndexChanged(int)));
}
else {
ui->swtch->hide();
}
// FadeIn / FadeOut
if (firmware->getCapability(FlightModesHaveFades)) {
int scale = firmware->getCapability(SlowScale);
int range = firmware->getCapability(SlowRange);
ui->fadeIn->setMaximum(float(range) / scale);
ui->fadeIn->setSingleStep(1.0 / scale);
ui->fadeIn->setDecimals((scale == 1 ? 0 :1) );
connect(ui->fadeIn, SIGNAL(editingFinished()), this, SLOT(phaseFadeIn_editingFinished()));
ui->fadeOut->setMaximum(float(range) / scale);
ui->fadeOut->setSingleStep(1.0 / scale);
ui->fadeOut->setDecimals((scale == 1 ? 0 :1));
connect(ui->fadeOut, SIGNAL(editingFinished()), this, SLOT(phaseFadeOut_editingFinished()));
}
else {
ui->fadeIn->setDisabled(true);
ui->fadeOut->setDisabled(true);
}
// The trims
QString labels[CPN_MAX_TRIMS];
for(int i = 0; i < CPN_MAX_STICKS; i++) {
labels[i] = firmware->getAnalogInputName(i);
}
labels[4] = "T5"; // TODO firmware function
labels[5] = "T6"; // TODO firmware function
trimsLabel << ui->trim1Label << ui->trim2Label << ui->trim3Label << ui->trim4Label << ui->trim5Label << ui->trim6Label;
trimsUse << ui->trim1Use << ui->trim2Use << ui->trim3Use << ui->trim4Use << ui->trim5Use << ui->trim6Use;
trimsValue << ui->trim1Value << ui->trim2Value << ui->trim3Value << ui->trim4Value << ui->trim5Value << ui->trim6Value;
trimsSlider << ui->trim1Slider << ui->trim2Slider << ui->trim3Slider << ui->trim4Slider << ui->trim5Slider << ui->trim6Slider;
for (int i = trimCount; i < CPN_MAX_TRIMS; i++) {
trimsLabel[i]->hide();
trimsUse[i]->hide();
trimsValue[i]->hide();
trimsSlider[i]->hide();
}
for (int i = 0; i < trimCount; i++) {
trimsLabel[i]->setText(labels[CONVERT_MODE(i + 1) - 1]);
QComboBox * cb = trimsUse[i];
cb->setProperty("index", i);
if (IS_HORUS_OR_TARANIS(board)) {
cb->addItem(tr("Trim disabled"), -1);
}
for (int m = 0; m < fmCount; m++) {
if (m == phaseIdx) {
cb->addItem(tr("Own Trim"), m * 2);
}
else if (phaseIdx > 0) {
cb->addItem(tr("Use Trim from Flight mode %1").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);
}
}
}
connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(phaseTrimUse_currentIndexChanged(int)));
int trimsMax = firmware->getCapability(ExtendedTrimsRange);
if (trimsMax == 0 || !model.extendedTrims) {
trimsMax = firmware->getCapability(TrimsRange);
}
trimsValue[i]->setProperty("index", i);
trimsValue[i]->setRange(-trimsMax, +trimsMax);
connect(trimsValue[i], SIGNAL(valueChanged(int)), this, SLOT(phaseTrim_valueChanged()));
trimsSlider[i]->setProperty("index", i);
trimsSlider[i]->setRange(-trimsMax, +trimsMax);
int chn = CONVERT_MODE(i + 1) - 1;
if (chn == 2/*TODO constant*/ && model.throttleReversed)
trimsSlider[i]->setInvertedAppearance(true);
connect(trimsSlider[i], SIGNAL(valueChanged(int)), this, SLOT(phaseTrimSlider_valueChanged()));
}
// Rotary encoders
if (reCount > 0) {
QGridLayout *reLayout = new QGridLayout(ui->reGB);
for (int i = 0; i < reCount; i++) {
// RE label
QLabel *label = new QLabel(ui->reGB);
label->setText(tr("Rotary Encoder %1").arg(i + 1));
reLayout->addWidget(label, i, 0, 1, 1);
if (phaseIdx > 0) {
// RE link to another RE
reUse[i] = new QComboBox(ui->reGB);
reUse[i]->setProperty("index", i);
Helpers::populateGvarUseCB(reUse[i], phaseIdx);
connect(reUse[i], SIGNAL(currentIndexChanged(int)), this, SLOT(phaseREUse_currentIndexChanged(int)));
reLayout->addWidget(reUse[i], i, 1, 1, 1);
}
// RE value
reValues[i] = new QSpinBox(ui->reGB);
reValues[i]->setProperty("index", i);
reValues[i]->setMinimum(RENC_MIN_VALUE);
reValues[i]->setMaximum(RENC_MAX_VALUE);
connect(reValues[i], SIGNAL(editingFinished()), this, SLOT(phaseREValue_editingFinished()));
reLayout->addWidget(reValues[i], i, 2, 1, 1);
}
}
else {
ui->reGB->hide();
}
// GVars
if (gvCount > 0 && (firmware->getCapability(GvarsFlightModes) || phaseIdx == 0) ) {
QGridLayout *gvLayout = new QGridLayout(ui->gvGB);
// Column headers
int headerCol = 1;
if (firmware->getCapability(GvarsName)) {
QLabel *nameLabel = new QLabel(ui->gvGB);
nameLabel->setText(tr("Name"));
gvLayout->addWidget(nameLabel, 0, headerCol++, 1, 1);
}
if (phaseIdx > 0) {
QLabel *sourceLabel = new QLabel(ui->gvGB);
sourceLabel->setText(tr("Value source"));
gvLayout->addWidget(sourceLabel, 0, headerCol++, 1, 1);
}
QLabel *valueLabel = new QLabel(ui->gvGB);
valueLabel->setText(tr("Value"));
gvLayout->addWidget(valueLabel, 0, headerCol++, 1, 1);
if (IS_HORUS_OR_TARANIS(board) && phaseIdx == 0) {
QLabel *unitLabel = new QLabel(ui->gvGB);
unitLabel->setText(tr("Unit"));
gvLayout->addWidget(unitLabel, 0, headerCol++, 1, 1);
QLabel *precLabel = new QLabel(ui->gvGB);
precLabel->setText(tr("Prec"));
gvLayout->addWidget(precLabel, 0, headerCol++, 1, 1);
QLabel *minLabel = new QLabel(ui->gvGB);
minLabel->setText(tr("Min"));
gvLayout->addWidget(minLabel, 0, headerCol++, 1, 1);
QLabel *maxLabel = new QLabel(ui->gvGB);
maxLabel->setText(tr("Max"));
gvLayout->addWidget(maxLabel, 0, headerCol++, 1, 1);
QLabel *popupLabel = new QLabel(ui->gvGB);
popupLabel->setText(tr("Popup enabled"));
gvLayout->addWidget(popupLabel, 0, headerCol++, 1, 1);
}
for (int i = 0; i < gvCount; i++) {
int col = 0;
// GVar label
QLabel *label = new QLabel(ui->gvGB);
label->setText(tr("GVAR%1").arg(i + 1));
label->setProperty("index", i);
label->setContextMenuPolicy(Qt::CustomContextMenu);
label->setToolTip(tr("Popup menu available"));
connect(label, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(gvOnCustomContextMenuRequested(const QPoint &)));
gvLayout->addWidget(label, i + 1, col++, 1, 1);
// GVar name
int nameLen = firmware->getCapability(GvarsName);
if (nameLen > 0) {
gvNames[i] = new QLineEdit(ui->gvGB);
gvNames[i]->setProperty("index", i);
gvNames[i]->setMaxLength(nameLen);
connect(gvNames[i], SIGNAL(editingFinished()), this, SLOT(GVName_editingFinished()));
gvLayout->addWidget(gvNames[i], i + 1, col++, 1, 1);
}
if (phaseIdx > 0) {
// GVar link to another GVar
gvUse[i] = new QComboBox(ui->gvGB);
gvUse[i]->setProperty("index", i);
Helpers::populateGvarUseCB(gvUse[i], phaseIdx);
connect(gvUse[i], SIGNAL(currentIndexChanged(int)), this, SLOT(phaseGVUse_currentIndexChanged(int)));
gvLayout->addWidget(gvUse[i], i + 1, col++, 1, 1);
}
// GVar value
gvValues[i] = new QDoubleSpinBox(ui->gvGB);
gvValues[i]->setProperty("index", i);
connect(gvValues[i], SIGNAL(editingFinished()), this, SLOT(phaseGVValue_editingFinished()));
gvLayout->addWidget(gvValues[i], i + 1, col++, 1, 1);
if (IS_HORUS_OR_TARANIS(board) && phaseIdx == 0) {
// GVar unit
gvUnit[i] = new QComboBox(ui->gvGB);
gvUnit[i]->setProperty("index", i);
populateGvarUnitCB(gvUnit[i]);
connect(gvUnit[i], SIGNAL(currentIndexChanged(int)), this, SLOT(phaseGVUnit_currentIndexChanged(int)));
gvLayout->addWidget(gvUnit[i], i + 1, col++, 1, 1);
// GVar precision
gvPrec[i] = new QComboBox(ui->gvGB);
gvPrec[i]->setProperty("index", i);
populateGvarPrecCB(gvPrec[i]);
connect(gvPrec[i], SIGNAL(currentIndexChanged(int)), this, SLOT(phaseGVPrec_currentIndexChanged(int)));
gvLayout->addWidget(gvPrec[i], i + 1, col++, 1, 1);
// GVar min
gvMin[i] = new QDoubleSpinBox(ui->gvGB);
gvMin[i]->setProperty("index", i);
connect(gvMin[i], SIGNAL(editingFinished()), this, SLOT(phaseGVMin_editingFinished()));
gvLayout->addWidget(gvMin[i], i + 1, col++, 1, 1);
// GVar max
gvMax[i] = new QDoubleSpinBox(ui->gvGB);
gvMax[i]->setProperty("index", i);
connect(gvMax[i], SIGNAL(editingFinished()), this, SLOT(phaseGVMax_editingFinished()));
gvLayout->addWidget(gvMax[i], i + 1, col++, 1, 1);
// Popups
gvPopups[i] = new QCheckBox(ui->gvGB);
gvPopups[i]->setProperty("index", i);
//gvPopups[i]->setText(tr("Popup enabled"));
connect(gvPopups[i], SIGNAL(toggled(bool)), this, SLOT(phaseGVPopupToggled(bool)));
gvLayout->addWidget(gvPopups[i], i + 1, col++, 1, 1);
}
}
}
else {
ui->gvGB->hide();
gvCount = 0;
}
disableMouseScrolling();
update();
}
FlightModePanel::~FlightModePanel()
{
delete ui;
}
void FlightModePanel::update()
{
ui->name->setText(phase.name);
ui->swtch->setCurrentIndex(ui->swtch->findData(phase.swtch.toValue()));
int scale = firmware->getCapability(SlowScale);
ui->fadeIn->setValue(float(phase.fadeIn)/scale);
ui->fadeOut->setValue(float(phase.fadeOut)/scale);
for (int i = 0; i < getBoardCapability(firmware->getBoard(), Board::NumTrims); i++) {
trimUpdate(i);
}
for (int i = 0; i < gvCount; i++) {
updateGVar(i);
}
for (int i = 0; i < reCount; i++) {
updateRotaryEncoder(i);
}
}
void FlightModePanel::updateGVar(int index)
{
lock = true;
if (firmware->getCapability(GvarsName) > 0) {
gvNames[index]->setText(model->gvarData[index].name);
}
if (phaseIdx > 0) {
if (model->isGVarLinked(phaseIdx, index))
gvUse[index]->setCurrentIndex(phase.gvars[index] - GVAR_MAX_VALUE);
else
gvUse[index]->setCurrentIndex(0);
}
gvValues[index]->setDisabled(model->isGVarLinked(phaseIdx, index));
setGVSB(gvValues[index], model->gvarData[index].getMin(), model->gvarData[index].getMax(), model->getGVarValue(phaseIdx, index));
if (IS_HORUS_OR_TARANIS(board) && phaseIdx == 0) {
gvUnit[index]->setCurrentIndex(model->gvarData[index].unit);
gvPrec[index]->setCurrentIndex(model->gvarData[index].prec);
setGVSB(gvMin[index], GVAR_MIN_VALUE, model->gvarData[index].getMax(), model->gvarData[index].getMin());
setGVSB(gvMax[index], model->gvarData[index].getMin(), GVAR_MAX_VALUE, model->gvarData[index].getMax());
gvPopups[index]->setChecked(model->gvarData[index].popup);
}
lock = false;
}
void FlightModePanel::setGVSB(QDoubleSpinBox * sb, int min, int max, int val)
{
int idx = sb->property("index").toInt();
float mul = model->gvarData[idx].multiplierGet();
sb->setDecimals(model->gvarData[idx].prec);
sb->setSingleStep(mul);
sb->setSuffix(model->gvarData[idx].unitToString());
sb->setMinimum(min * mul);
sb->setMaximum(max * mul);
sb->setValue(val * mul);
}
void FlightModePanel::updateRotaryEncoder(int index)
{
lock = true;
if (phaseIdx > 0) {
if (model->isREncLinked(phaseIdx, index))
reUse[index]->setCurrentIndex(phase.rotaryEncoders[index] - RENC_MAX_VALUE);
else
reUse[index]->setCurrentIndex(0);
}
reValues[index]->setDisabled(model->isREncLinked(phaseIdx, index));
reValues[index]->setValue(model->getREncValue(phaseIdx, index));
lock = false;
}
// TODO: pull units from GVarData
void FlightModePanel::populateGvarUnitCB(QComboBox * cb)
{
cb->clear();
cb->addItem("");
cb->addItem("%");
}
// TODO: pull precision string from GVarData
void FlightModePanel::populateGvarPrecCB(QComboBox * cb)
{
cb->clear();
cb->addItem(tr("0._"));
cb->addItem(tr("0.0"));
}
void FlightModePanel::phaseName_editingFinished()
{
QLineEdit *lineEdit = qobject_cast<QLineEdit*>(sender());
strcpy(phase.name, lineEdit->text().toLatin1());
emit phaseNameChanged();
emit modified();
}
void FlightModePanel::phaseSwitch_currentIndexChanged(int index)
{
if (!lock) {
bool ok;
const RawSwitch rs(ui->swtch->itemData(index).toInt(&ok));
if (ok && phase.swtch.toValue() != rs.toValue()) {
phase.swtch = rs;
emit phaseSwitchChanged();
emit modified();
}
}
}
void FlightModePanel::phaseFadeIn_editingFinished()
{
QDoubleSpinBox *spinBox = qobject_cast<QDoubleSpinBox*>(sender());
int scale = firmware->getCapability(SlowScale);
phase.fadeIn = round(spinBox->value()*scale);
emit modified();
}
void FlightModePanel::phaseFadeOut_editingFinished()
{
QDoubleSpinBox *spinBox = qobject_cast<QDoubleSpinBox*>(sender());
int scale = firmware->getCapability(SlowScale);
phase.fadeOut = round(spinBox->value()*scale);
emit modified();
}
void FlightModePanel::trimUpdate(unsigned int trim)
{
lock = true;
int chn = CONVERT_MODE(trim + 1) - 1;
int value = model->getTrimValue(phaseIdx, chn);
trimsSlider[trim]->setValue(value);
trimsValue[trim]->setValue(value);
if (phase.trimMode[chn] < 0) {
trimsUse[trim]->setCurrentIndex(0);
trimsValue[trim]->setEnabled(false);
trimsSlider[trim]->setEnabled(false);
}
else {
if (IS_HORUS_OR_TARANIS(board))
trimsUse[trim]->setCurrentIndex(1 + 2 * phase.trimRef[chn] + phase.trimMode[chn] - (phase.trimRef[chn] > phaseIdx ? 1 : 0));
else
trimsUse[trim]->setCurrentIndex(phase.trimRef[chn]);
if (phaseIdx == 0 || phase.trimRef[chn] == phaseIdx || (IS_HORUS_OR_TARANIS(board) && phase.trimMode[chn] != 0)) {
trimsValue[trim]->setEnabled(true);
trimsSlider[trim]->setEnabled(true);
}
else {
trimsValue[trim]->setEnabled(false);
trimsSlider[trim]->setEnabled(false);
}
}
lock = false;
}
void FlightModePanel::phaseGVValue_editingFinished()
{
if (!lock) {
QDoubleSpinBox *spinBox = qobject_cast<QDoubleSpinBox*>(sender());
int gvar = spinBox->property("index").toInt();
phase.gvars[gvar] = spinBox->value() * model->gvarData[gvar].multiplierSet();
updateGVar(gvar);
emit modified();
}
}
void FlightModePanel::GVName_editingFinished()
{
if (!lock) {
QLineEdit *lineedit = qobject_cast<QLineEdit*>(sender());
int gvar = lineedit->property("index").toInt();
memset(&model->gvarData[gvar].name, 0, sizeof(model->gvarData[gvar].name));
strcpy(model->gvarData[gvar].name, lineedit->text().toLatin1());
emit gvNameChanged();
emit modified();
}
}
void FlightModePanel::phaseGVUse_currentIndexChanged(int index)
{
if (!lock) {
lock = true;
QComboBox *comboBox = qobject_cast<QComboBox*>(sender());
int gvar = comboBox->property("index").toInt();
if (index == 0) {
phase.gvars[gvar] = 0;
}
else {
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."));
updateGVar(gvar);
emit modified();
lock = false;
}
}
void FlightModePanel::phaseGVUnit_currentIndexChanged(int index)
{
if (!lock) {
QComboBox *comboBox = qobject_cast<QComboBox*>(sender());
int gvar = comboBox->property("index").toInt();
model->gvarData[gvar].unit = index;
updateGVar(gvar);
emit modified();
}
}
void FlightModePanel::phaseGVPrec_currentIndexChanged(int index)
{
if (!lock) {
QComboBox *comboBox = qobject_cast<QComboBox*>(sender());
int gvar = comboBox->property("index").toInt();
model->gvarData[gvar].prec = index;
updateGVar(gvar);
emit modified();
}
}
void FlightModePanel::phaseGVMin_editingFinished()
{
if (!lock) {
QDoubleSpinBox *spinBox = qobject_cast<QDoubleSpinBox*>(sender());
int gvar = spinBox->property("index").toInt();
model->gvarData[gvar].setMin(spinBox->value());
if (!model->isGVarLinked(phaseIdx, gvar)) {
if (model->getGVarValuePrec(phaseIdx, gvar) < spinBox->value()) {
phase.gvars[gvar] = model->gvarData[gvar].getMin();
}
}
for (int x = 1; x < fmCount; x++) {
if (!model->isGVarLinked(x, gvar)) {
if (model->flightModeData[x].gvars[gvar] < model->gvarData[gvar].getMin()) {
model->flightModeData[x].gvars[gvar] = model->gvarData[gvar].getMin();
}
}
}
updateGVar(gvar);
emit modified();
}
}
void FlightModePanel::phaseGVMax_editingFinished()
{
if (!lock) {
QDoubleSpinBox *spinBox = qobject_cast<QDoubleSpinBox*>(sender());
int gvar = spinBox->property("index").toInt();
model->gvarData[gvar].setMax(spinBox->value());
if (!model->isGVarLinked(phaseIdx, gvar)) {
if (model->getGVarValuePrec(phaseIdx, gvar) > spinBox->value()) {
phase.gvars[gvar] = model->gvarData[gvar].getMax();
}
}
for (int x = 1; x < fmCount; x++) {
if (!model->isGVarLinked(x, gvar)) {
if (model->flightModeData[x].gvars[gvar] > model->gvarData[gvar].getMax()) {
model->flightModeData[x].gvars[gvar] = model->gvarData[gvar].getMax();
}
}
}
updateGVar(gvar);
emit modified();
}
}
void FlightModePanel::phaseGVPopupToggled(bool checked)
{
if (!lock) {
QCheckBox *cb = qobject_cast<QCheckBox*>(sender());
int gvar = cb->property("index").toInt();
model->gvarData[gvar].popup = checked;
emit modified();
}
}
void FlightModePanel::phaseREValue_editingFinished()
{
if (!lock) {
QSpinBox *spinBox = qobject_cast<QSpinBox*>(sender());
int re = spinBox->property("index").toInt();
phase.rotaryEncoders[re] = spinBox->value();
emit modified();
}
}
void FlightModePanel::phaseREUse_currentIndexChanged(int index)
{
if (!lock) {
lock = true;
QComboBox *comboBox = qobject_cast<QComboBox*>(sender());
int re = comboBox->property("index").toInt();
if (index == 0) {
phase.rotaryEncoders[re] = 0;
}
else {
phase.rotaryEncoders[re] = RENC_MAX_VALUE + index; ;
}
update();
if (model->isREncLinkedCircular(phaseIdx, re))
QMessageBox::warning(this, "Companion", tr("Warning: Rotary encoder links back to itself. Flight Mode 0 value used."));
emit modified();
lock = false;
}
}
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 data = comboBox->itemData(index).toInt();
if (data < 0) {
phase.trimMode[chn] = -1;
phase.trimRef[chn] = 0;
phase.trim[chn] = 0;
}
else {
if (IS_HORUS_OR_TARANIS(board)) {
phase.trimMode[chn] = data % 2;
phase.trimRef[chn] = data / 2;
}
else {
phase.trimMode[chn] = 0;
phase.trimRef[chn] = data / 2;
}
phase.trim[chn] = 0;
}
trimUpdate(trim);
emit modified();
}
}
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 value = spinBox->value();
model->setTrimValue(phaseIdx, chn, value);
lock = true;
trimsSlider[trim]->setValue(value);
lock = false;
emit modified();
}
}
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 value = slider->value();
model->setTrimValue(phaseIdx, chn, value);
lock = true;
trimsValue[trim]->setValue(value);
lock = false;
emit modified();
}
}
void FlightModePanel::onCustomContextMenuRequested(QPoint pos)
{
QLabel *label = (QLabel *)sender();
QPoint globalPos = label->mapToGlobal(pos);
QMenu contextMenu;
contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"), this, SLOT(cmCopy()));
contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"), this, SLOT(cmCut()));
contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"), this, SLOT(cmPaste()))->setEnabled(hasClipboardData());
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"), this, SLOT(cmClear()));
contextMenu.addSeparator();
contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"), this, SLOT(cmInsert()))->setEnabled(insertAllowed());
contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"), this, SLOT(cmDelete()));
contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"), this, SLOT(cmMoveUp()))->setEnabled(moveUpAllowed());
contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"), this, SLOT(cmMoveDown()))->setEnabled(moveDownAllowed());
contextMenu.addSeparator();
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"), this, SLOT(cmClearAll()))->setEnabled(phaseIdx == 0);
contextMenu.exec(globalPos);
}
bool FlightModePanel::hasClipboardData(QByteArray * data) const
{
const QClipboard * clipboard = QApplication::clipboard();
const QMimeData * mimeData = clipboard->mimeData();
if (mimeData->hasFormat(MIMETYPE_FLIGHTMODE)) {
if (data)
data->append(mimeData->data(MIMETYPE_FLIGHTMODE));
return true;
}
return false;
}
bool FlightModePanel::insertAllowed() const
{
return ((phaseIdx < fmCount - 1) && (model->flightModeData[fmCount - 1].isEmpty(fmCount - 1)));
}
bool FlightModePanel::moveDownAllowed() const
{
return phaseIdx < fmCount - 1;
}
bool FlightModePanel::moveUpAllowed() const
{
return phaseIdx > 0;
}
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)
return;
}
phase.clear(phaseIdx);
if (phaseIdx == 0) {
for (int i = 0; i < gvCount; i++) {
model->gvarData[i].clear();
for (int j = 0; j < fmCount; j++) {
FlightModeData *fm = &model->flightModeData[j];
fm->gvars[i] = fm->linkedGVarFlightModeZero(j);
}
model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, i);
}
}
else {
QComboBox * pswtch = ui->swtch;
RawSwitch item = RawSwitch(SWITCH_TYPE_NONE);
pswtch->setCurrentIndex(pswtch->findText(item.toString()));
for (int i = 0; i < gvCount; i++) {
phase.gvars[i] = phase.linkedGVarFlightModeZero(phaseIdx);
}
for (int i = 0; i < reCount; i++) {
phase.rotaryEncoders[i] = phase.linkedREncFlightModeZero(phaseIdx);
}
}
model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_CLEAR, phaseIdx);
update();
emit phaseDataChanged();
emit modified();
}
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)
return;
for (int j = 0; j < fmCount; j++) {
FlightModeData *fm = &model->flightModeData[j];
fm->clear(j);
for (int i = 0; i < gvCount; i++) {
fm->gvars[i] = fm->linkedGVarFlightModeZero(j);
}
for (int i = 0; i < reCount; i++) {
fm->rotaryEncoders[i] = fm->linkedREncFlightModeZero(j);
}
model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_CLEAR, j);
}
for (int i = 0; i < gvCount; i++) {
model->gvarData[i].clear();
model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, i);
}
emit phaseDataChanged();
emit modified();
}
void FlightModePanel::cmCopy()
{
QByteArray data;
data.append((char*)&model->flightModeData[phaseIdx], sizeof(FlightModeData));
QMimeData *mimeData = new QMimeData;
mimeData->setData(MIMETYPE_FLIGHTMODE, data);
QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
}
void FlightModePanel::cmCut()
{
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Flight Mode. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
cmCopy();
cmClear(false);
}
void FlightModePanel::cmDelete()
{
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Flight Mode. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
const int maxidx = fmCount - 1;
memmove(&model->flightModeData[phaseIdx], &model->flightModeData[phaseIdx + 1], (CPN_MAX_FLIGHT_MODES - (phaseIdx + 1)) * sizeof(FlightModeData));
model->flightModeData[maxidx].clear(maxidx);
for (int j = 0; j < maxidx; j++) {
FlightModeData *fm = &model->flightModeData[j];
if (phaseIdx == 0 && j == 0)
fm->swtch = RawSwitch(0);
for (int i = 0; i < trimCount; i++) {
if (phaseIdx == 0 && j == 0) {
fm->trimMode[i] = 0;
fm->trimRef[i] = 0;
}
else if (fm->trimRef[i] > phaseIdx && fm->trimMode[i] > -1) {
fm->trimRef[i]--;
}
else if (fm->trimRef[i] == phaseIdx) {
fm->trimMode[i] = 0;
fm->trimRef[i] = 0;
fm->trim[i] = 0;
}
}
for (int i = 0; i < gvCount; i++) {
if (model->isGVarLinked(j, i)) {
int idx = model->getGVarFlightModeIndex(j, i);
if (phaseIdx == 0 && j == 0)
model->setGVarFlightModeIndexToValue(j, i, j);
else if (idx > phaseIdx)
model->setGVarFlightModeIndexToValue(j, i, idx - 1);
else if (idx == phaseIdx)
model->setGVarFlightModeIndexToValue(j, i, 0);
}
}
for (int i = 0; i < reCount; i++) {
if (model->isREncLinked(j, i)) {
int idx = model->getREncFlightModeIndex(j, i);
if (phaseIdx == 0 && j == 0)
model->setREncFlightModeIndexToValue(j, i, j);
else if (idx > phaseIdx)
model->setREncFlightModeIndexToValue(j, i, idx - 1);
else if (idx == phaseIdx)
model->setREncFlightModeIndexToValue(j, i, 0);
}
}
}
model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_SHIFT, phaseIdx, 0, -1);
emit phaseDataChanged();
emit modified();
}
void FlightModePanel::cmInsert()
{
const int maxidx = fmCount - 1;
memmove(&model->flightModeData[phaseIdx + 1], &model->flightModeData[phaseIdx], (CPN_MAX_FLIGHT_MODES - (phaseIdx + 1)) * sizeof(FlightModeData));
model->flightModeData[phaseIdx].clear(phaseIdx);
for (int j = maxidx; j > 0; j--) {
FlightModeData *fm = &model->flightModeData[j];
for (int i = 0; i < trimCount; i++) {
if (phaseIdx == 0 && j == 1)
fm->trimRef[i] = j;
else if (fm->trimRef[i] >= phaseIdx) {
if (fm->trimRef[i] < maxidx)
fm->trimRef[i]++;
else {
fm->trimMode[i] = 0;
fm->trimRef[i] = 0;
fm->trim[i] = 0;
}
}
}
for (int i = 0; i < gvCount; i++) {
if (model->isGVarLinked(j, i)) {
int idx = model->getGVarFlightModeIndex(j, i);
if (phaseIdx == 0 && j == 1)
model->setGVarFlightModeIndexToValue(j, i, j);
else if (idx >= phaseIdx)
model->setGVarFlightModeIndexToValue(j, i, idx + 1);
}
}
for (int i = 0; i < reCount; i++) {
if (model->isREncLinked(j, i)) {
int idx = model->getREncFlightModeIndex(j, i);
if (phaseIdx == 0 && j == 1)
model->setREncFlightModeIndexToValue(j, i, j);
else if (idx >= phaseIdx)
model->setREncFlightModeIndexToValue(j, i, idx + 1);
}
}
}
model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_SHIFT, phaseIdx, 0, 1);
emit phaseDataChanged();
emit modified();
}
void FlightModePanel::cmMoveDown()
{
swapData(phaseIdx, phaseIdx + 1);
}
void FlightModePanel::cmMoveUp()
{
swapData(phaseIdx, phaseIdx - 1);
}
void FlightModePanel::cmPaste()
{
QByteArray data;
if (hasClipboardData(&data)) {
FlightModeData *fm = &model->flightModeData[phaseIdx];
memcpy(fm, data.constData(), sizeof(FlightModeData));
if (phaseIdx == 0)
fm->swtch = RawSwitch(0);
for (int i = 0; i < trimCount; i++) {
if (phaseIdx == 0) {
fm->trimMode[i] = 0;
fm->trimRef[i] = 0;
}
}
// TODO fix up linked GVs but need to know source FM index to make adjustments
for (int i = 0; i < gvCount; i++) {
if (model->isGVarLinked(phaseIdx, i)) {
int linkedidx = model->getGVarFlightModeIndex(phaseIdx, i);
if (phaseIdx == 0 || linkedidx == phaseIdx)
model->setGVarFlightModeIndexToValue(phaseIdx, i, phaseIdx);
}
}
// TODO fix up linked REs but need to know source FM index to make adjustments
for (int i = 0; i < reCount; i++) {
if (model->isREncLinked(phaseIdx, i)) {
int linkedidx = model->getREncFlightModeIndex(phaseIdx, i);
if (phaseIdx == 0 || linkedidx == phaseIdx)
model->setREncFlightModeIndexToValue(phaseIdx, i, phaseIdx);
}
}
emit phaseDataChanged();
emit modified();
}
}
void FlightModePanel::swapData(int idx1, int idx2)
{
if (idx1 == idx2)
return;
const int shift = idx2 - idx1;
FlightModeData fmdtmp = model->flightModeData[idx2];
FlightModeData *fmd1 = &model->flightModeData[idx1];
FlightModeData *fmd2 = &model->flightModeData[idx2];
memcpy(fmd2, fmd1, sizeof(FlightModeData));
memcpy(fmd1, &fmdtmp, sizeof(FlightModeData));
if (idx1 == 0)
fmd1->swtch = RawSwitch(0);
else if (idx2 == 0)
fmd2->swtch = RawSwitch(0);
for (int i = 0; i < trimCount; i++) {
if (fmd1->trimRef[i] == idx1)
fmd1->trimRef[i] = idx2;
else if (fmd1->trimRef[i] == idx2)
fmd1->trimRef[i] = idx1;
if (fmd2->trimRef[i] == idx1)
fmd2->trimRef[i] = idx2;
else if (fmd2->trimRef[i] == idx2)
fmd2->trimRef[i] = idx1;
if (idx1 == 0) {
fmd1->trimMode[i] = 0;
fmd1->trimRef[i] = 0;
}
else if (idx2 == 0) {
fmd2->trimMode[i] = 0;
fmd2->trimRef[i] = 0;
}
}
for (int i = 0; i < gvCount; i++) {
if (model->isGVarLinked(idx1, i)) {
int linkedidx = model->getGVarFlightModeIndex(idx1, i);
if (linkedidx == idx1)
model->setGVarFlightModeIndexToValue(idx1, i, idx2 - shift);
else if (linkedidx == idx2)
model->setGVarFlightModeIndexToValue(idx1, i, idx1 + shift);
else
model->setGVarFlightModeIndexToValue(idx1, i, linkedidx);
}
if (model->isGVarLinked(idx2, i)) {
int linkedidx = model->getGVarFlightModeIndex(idx2, i);
if (linkedidx == idx1)
model->setGVarFlightModeIndexToValue(idx2, i, idx2 - shift);
else if (linkedidx == idx2)
model->setGVarFlightModeIndexToValue(idx2, i, idx1 + shift);
else
model->setGVarFlightModeIndexToValue(idx2, i, linkedidx);
}
}
for (int i = 0; i < reCount; i++) {
if (model->isREncLinked(idx1, i)) {
int linkedidx = model->getREncFlightModeIndex(idx1, i);
if (linkedidx == idx1)
model->setREncFlightModeIndexToValue(idx1, i, idx2 - shift);
else if (linkedidx == idx2)
model->setREncFlightModeIndexToValue(idx1, i, idx1 + shift);
else
model->setREncFlightModeIndexToValue(idx1, i, linkedidx);
}
if (model->isREncLinked(idx2, i)) {
int linkedidx = model->getREncFlightModeIndex(idx2, i);
if (linkedidx == idx1)
model->setREncFlightModeIndexToValue(idx2, i, idx2 - shift);
else if (linkedidx == idx2)
model->setREncFlightModeIndexToValue(idx2, i, idx1 + shift);
else
model->setREncFlightModeIndexToValue(idx2, i, linkedidx);
}
}
model->updateAllReferences(ModelData::REF_UPD_TYPE_FLIGHT_MODE, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
emit phaseDataChanged();
emit modified();
}
void FlightModePanel::gvOnCustomContextMenuRequested(QPoint pos)
{
QLabel *label = (QLabel *)sender();
gvIdx = label->property("index").toInt();
QPoint globalPos = label->mapToGlobal(pos);
QMenu contextMenu;
contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"), this, SLOT(gvCmCopy()));
contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"), this, SLOT(gvCmCut()));
contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"), this, SLOT(gvCmPaste()))->setEnabled(gvHasClipboardData());
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"), this, SLOT(gvCmClear()));
contextMenu.addSeparator();
contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"), this, SLOT(gvCmInsert()))->setEnabled(gvInsertAllowed());
contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"), this, SLOT(gvCmDelete()))->setEnabled(gvDeleteAllowed());
contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"), this, SLOT(gvCmMoveUp()))->setEnabled(gvMoveUpAllowed());
contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"), this, SLOT(gvCmMoveDown()))->setEnabled(gvMoveDownAllowed());
contextMenu.addSeparator();
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"), this, SLOT(gvCmClearAll()));
contextMenu.exec(globalPos);
}
bool FlightModePanel::gvHasClipboardData() const
{
if ((phaseIdx == 0 && gvHasDefnClipboardData() && gvHasAllValuesClipboardData()) || (phaseIdx > 0 && gvHasValueClipboardData()))
return true;
return false;
}
bool FlightModePanel::gvHasDefnClipboardData(QByteArray * data) const
{
const QClipboard * clipboard = QApplication::clipboard();
const QMimeData * mimeData = clipboard->mimeData();
if (phaseIdx == 0 && mimeData->hasFormat(MIMETYPE_GVAR_PARAMS)) {
if (data) {
data->clear();
data->append(mimeData->data(MIMETYPE_GVAR_PARAMS));
}
return true;
}
return false;
}
bool FlightModePanel::gvHasValueClipboardData(QByteArray * data) const
{
const QClipboard * clipboard = QApplication::clipboard();
const QMimeData * mimeData = clipboard->mimeData();
if (mimeData->hasFormat(MIMETYPE_GVAR_VALUE)) {
if (data) {
data->clear();
data->append(mimeData->data(MIMETYPE_GVAR_VALUE));
}
return true;
}
return false;
}
bool FlightModePanel::gvHasAllValuesClipboardData(QByteArray * data) const
{
const QClipboard * clipboard = QApplication::clipboard();
const QMimeData * mimeData = clipboard->mimeData();
if (phaseIdx == 0 && mimeData->hasFormat(MIMETYPE_GVAR_ALL_VALUES)) {
if (data) {
data->clear();
data->append(mimeData->data(MIMETYPE_GVAR_ALL_VALUES));
}
return true;
}
return false;
}
bool FlightModePanel::gvDeleteAllowed() const
{
return phaseIdx == 0;
}
bool FlightModePanel::gvInsertAllowed() const
{
bool ret = true;
if (phaseIdx == 0) {
if (!model->gvarData[gvCount - 1].isEmpty())
ret = false;
for (int i = 0; i < fmCount; i++) {
if (model->flightModeData[i].gvars[gvCount - 1] != phase.linkedGVarFlightModeZero(i))
ret = false;
}
}
else
ret = false;
return ret;
}
bool FlightModePanel::gvMoveDownAllowed() const
{
return (phaseIdx == 0 && gvIdx < gvCount - 1);
}
bool FlightModePanel::gvMoveUpAllowed() const
{
return (phaseIdx == 0 && gvIdx > 0);
}
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)
return;
}
model->gvarData[gvIdx].clear();
for (int i = 0; i < fmCount; i++) {
model->flightModeData[i].gvars[gvIdx] = model->flightModeData[i].linkedGVarFlightModeZero(i);
}
model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, gvIdx);
}
else {
if (prompt) {
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Global Variable. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
}
phase.gvars[gvIdx] = phase.linkedGVarFlightModeZero(phaseIdx);
}
updateGVar(gvIdx);
emit gvNameChanged();
emit modified();
}
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)
return;
for (int i = 0; i < gvCount; i++) {
model->gvarData[i].clear();
for (int j = 0; j < fmCount; j++) {
model->flightModeData[j].gvars[i] = model->flightModeData[j].linkedGVarFlightModeZero(j);
}
model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_CLEAR, i);
}
}
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)
return;
for (int i = 0; i < gvCount; i++) {
phase.gvars[i] = phase.linkedGVarFlightModeZero(phaseIdx);
}
}
for (int i = 0; i < gvCount; i++) {
updateGVar(i);
}
emit gvNameChanged();
emit modified();
}
void FlightModePanel::gvCmCopy()
{
QMimeData *mimeData = new QMimeData;
QByteArray data;
if (phaseIdx == 0) {
data.append((char*)&model->gvarData[gvIdx], sizeof(GVarData));
mimeData->setData(MIMETYPE_GVAR_PARAMS, data);
QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
data.clear();
for (int j = 0; j < fmCount; j++) {
data.append((char*)&model->flightModeData[j].gvars[gvIdx], sizeof(phase.gvars[0]));
}
mimeData->setData(MIMETYPE_GVAR_ALL_VALUES, data);
QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
mimeData->removeFormat(MIMETYPE_GVAR_VALUE);
QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
}
else {
mimeData->removeFormat(MIMETYPE_GVAR_PARAMS);
QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
mimeData->removeFormat(MIMETYPE_GVAR_ALL_VALUES);
QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
data.clear();
int val = phase.gvars[gvIdx];
if (model->isGVarLinked(phaseIdx, gvIdx))
val = GVAR_MAX_VALUE + 1 + model->getGVarFlightModeIndex(phaseIdx, gvIdx); // store index in case paste is to another flight mode
data.setNum(val);
mimeData->setData(MIMETYPE_GVAR_VALUE, data);
QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
}
}
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)
return;
}
else {
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Cut Global Variable. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
}
gvCmCopy();
gvCmClear(false);
}
void FlightModePanel::gvCmDelete()
{
if (phaseIdx > 0)
return;
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Global Variable. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return;
int maxidx = gvCount - 1;
for (int i = gvIdx; i < maxidx; i++) {
memcpy(&model->gvarData[i], &model->gvarData[i + 1], sizeof(GVarData));
for (int j = 0; j < fmCount; j++) {
model->flightModeData[j].gvars[i] = model->flightModeData[j].gvars[i + 1];
}
}
model->gvarData[maxidx].clear();
for (int j = 0; j < fmCount; j++) {
model->flightModeData[j].gvars[maxidx] = model->flightModeData[j].linkedGVarFlightModeZero(j);
}
model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_SHIFT, gvIdx, 0, -1);
for (int i = 0; i < gvCount; i++) {
updateGVar(i);
}
emit gvNameChanged();
emit modified();
}
void FlightModePanel::gvCmInsert()
{
for (int i = (gvCount - 1); i > gvIdx; i--) {
memcpy(&model->gvarData[i], &model->gvarData[i - 1], sizeof(GVarData));
for (int j = 0; j < fmCount; j++) {
model->flightModeData[j].gvars[i] = model->flightModeData[j].gvars[i - 1];
}
}
model->gvarData[gvIdx].clear();
for (int j = 0; j < fmCount; j++) {
model->flightModeData[j].gvars[gvIdx] = model->flightModeData[j].linkedGVarFlightModeZero(j);
}
model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_SHIFT, gvIdx, 0, 1);
for (int i = 0; i < gvCount; i++) {
updateGVar(i);
}
emit gvNameChanged();
emit modified();
}
void FlightModePanel::gvCmMoveDown()
{
if (phaseIdx == 0)
gvSwapData(gvIdx, gvIdx + 1);
}
void FlightModePanel::gvCmMoveUp()
{
if (phaseIdx == 0)
gvSwapData(gvIdx, gvIdx - 1);
}
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)
return;
if (gvHasDefnClipboardData(&data)) {
memcpy(&model->gvarData[gvIdx], data.constData(), sizeof(GVarData));
}
if (gvHasAllValuesClipboardData(&data)) {
for (int j = 0; j < fmCount; j++) {
int *gvar = &model->flightModeData[j].gvars[gvIdx];
memcpy(gvar, data.mid(j * sizeof(phase.gvars[0]), sizeof(phase.gvars[0])).constData(), sizeof(phase.gvars[0]));
}
}
}
else if (gvHasValueClipboardData(&data)) {
int val = data.toInt();
if (val > GVAR_MAX_VALUE) {
if (phaseIdx > 0)
model->setGVarFlightModeIndexToValue(phaseIdx, gvIdx, val - (GVAR_MAX_VALUE + 1)); // index stored in clipboard
else
phase.gvars[gvIdx] = 0;
}
else
phase.gvars[gvIdx] = val;
}
updateGVar(gvIdx);
emit gvNameChanged();
emit modified();
}
void FlightModePanel::gvSwapData(int idx1, int idx2)
{
if (phaseIdx == 0 && idx1 != idx2) {
GVarData datatmp = model->gvarData[idx2];
GVarData *data1 = &model->gvarData[idx1];
GVarData *data2 = &model->gvarData[idx2];
memcpy(data2, data1, sizeof(GVarData));
memcpy(data1, &datatmp, sizeof(GVarData));
for (int j = 0; j < fmCount; j++) {
int valtmp = model->flightModeData[j].gvars[idx2];
model->flightModeData[j].gvars[idx2] = model->flightModeData[j].gvars[idx1];
model->flightModeData[j].gvars[idx1] = valtmp;
}
model->updateAllReferences(ModelData::REF_UPD_TYPE_GLOBAL_VARIABLE, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
updateGVar(idx1);
updateGVar(idx2);
emit gvNameChanged();
emit modified();
}
}
void FlightModePanel::connectItemModelEvents(const FilteredItemModel * itemModel)
{
connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &FlightModePanel::onItemModelAboutToBeUpdated);
connect(itemModel, &FilteredItemModel::updateComplete, this, &FlightModePanel::onItemModelUpdateComplete);
}
void FlightModePanel::onItemModelAboutToBeUpdated()
{
lock = true;
}
void FlightModePanel::onItemModelUpdateComplete()
{
update();
lock = false;
}
/**********************************************************/
FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware,
CompoundItemModelFactory * sharedItemModels):
ModelPanel(parent, model, generalSettings, firmware),
sharedItemModels(sharedItemModels)
{
rawSwitchFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), RawSwitch::MixesContext);
connectItemModelEvents(rawSwitchFilteredModel);
modesCount = firmware->getCapability(FlightModes);
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);
tab->setProperty("index", i);
connect(tab, &FlightModePanel::modified, this, &FlightModesPanel::modified);
connect(tab, &FlightModePanel::phaseDataChanged, this, &FlightModesPanel::onPhaseNameChanged);
connect(tab, &FlightModePanel::phaseNameChanged, this, &FlightModesPanel::onPhaseNameChanged);
connect(tab, &FlightModePanel::phaseSwitchChanged, this, &FlightModesPanel::updateItemModels);
connect(tab, &FlightModePanel::gvNameChanged, this, &FlightModesPanel::updateItemModels);
connect(this, &FlightModesPanel::updated, tab, &FlightModePanel::update);
tabWidget->addTab(tab, getTabName(i));
panels << tab;
}
connect(tabWidget, &QTabWidget::currentChanged, this, &FlightModesPanel::onTabIndexChanged);
gridLayout->addWidget(tabWidget, 0, 0, 1, 1);
onTabIndexChanged(0);
}
FlightModesPanel::~FlightModesPanel()
{
delete rawSwitchFilteredModel;
}
QString FlightModesPanel::getTabName(int index)
{
QString result = tr("Flight Mode %1").arg(index);
const char *name = model->flightModeData[index].name;
if (firmware->getCapability(FlightModesName) && strlen(name) > 0) {
result += tr(" (%1)").arg(name);
}
else if (index == 0) {
result += tr(" (default)");
}
return result;
}
void FlightModesPanel::onPhaseNameChanged()
{
int index = sender()->property("index").toInt();
tabWidget->setTabText(index, getTabName(index));
updateItemModels();
}
void FlightModesPanel::update()
{
emit updated();
}
void FlightModesPanel::connectItemModelEvents(const FilteredItemModel * itemModel)
{
connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &FlightModesPanel::onItemModelAboutToBeUpdated);
connect(itemModel, &FilteredItemModel::updateComplete, this, &FlightModesPanel::onItemModelUpdateComplete);
}
void FlightModesPanel::onItemModelAboutToBeUpdated()
{
}
void FlightModesPanel::onItemModelUpdateComplete()
{
}
void FlightModesPanel::updateItemModels()
{
sharedItemModels->update(AbstractItemModel::IMUE_FlightModes);
sharedItemModels->update(AbstractItemModel::IMUE_GVars);
}
void FlightModesPanel::onTabIndexChanged(int index)
{
if (index < panels.size())
panels.at(index)->update();
}