diff --git a/src/blackgui/editors/pbhsform.cpp b/src/blackgui/editors/pbhsform.cpp new file mode 100644 index 000000000..e07079381 --- /dev/null +++ b/src/blackgui/editors/pbhsform.cpp @@ -0,0 +1,224 @@ +/* Copyright (C) 2019 + * swift project Community / Contributors + * + * This file is part of swift Project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated, + * or distributed except according to the terms contained in the LICENSE file. + */ + +#include "pbhsform.h" +#include "ui_pbhsform.h" +#include "blackmisc/stringutils.h" +#include + +using namespace BlackMisc; +using namespace BlackMisc::Aviation; +using namespace BlackMisc::PhysicalQuantities; + +namespace BlackGui +{ + namespace Editors + { + CPbhsForm::CPbhsForm(QWidget *parent) : + CForm(parent), + ui(new Ui::CPbhsForm) + { + ui->setupUi(this); + + ui->le_Bank->setValidator(new QDoubleValidator(-180.0 + CAngleUnit::deg().getEpsilon(), 180.0, 3, ui->le_Bank)); + ui->le_Pitch->setValidator(new QDoubleValidator(-180.0 + CAngleUnit::deg().getEpsilon(), 180.0, 3, ui->le_Pitch)); + + connect(ui->hs_Bank, &QSlider::valueChanged, this, &CPbhsForm::bankSliderChanged); + connect(ui->hs_Pitch, &QSlider::valueChanged, this, &CPbhsForm::pitchSliderChanged); + connect(ui->hs_Heading, &QSlider::valueChanged, this, &CPbhsForm::headingSliderChanged); + connect(ui->le_Bank, &QLineEdit::editingFinished, this, &CPbhsForm::bankEntered); + connect(ui->le_Pitch, &QLineEdit::editingFinished, this, &CPbhsForm::pitchEntered); + connect(ui->le_Heading, &QLineEdit::editingFinished, this, &CPbhsForm::headingEntered); + connect(ui->tb_ResetBank, &QToolButton::clicked, this, &CPbhsForm::resetBank); + connect(ui->tb_ResetPitch, &QToolButton::clicked, this, &CPbhsForm::resetPitch); + connect(ui->tb_ResetHeading, &QToolButton::clicked, this, &CPbhsForm::resetHeading); + connect(ui->pb_SetOwnAircraft, &QPushButton::released, this, &CPbhsForm::changeValues); + } + + CPbhsForm::~CPbhsForm() + { } + + CAngle CPbhsForm::getBankAngle() const + { + return CAngle(getBankAngleDegrees(), CAngleUnit::deg()); + } + + void CPbhsForm::setBankAngle(const CAngle &angle) + { + const int value = angle.valueInteger(CAngleUnit::deg()); + ui->le_Bank->setText(QString::number(value)); + ui->hs_Bank->setValue(value); + } + + double CPbhsForm::getBankAngleDegrees() const + { + const QString v(ui->le_Bank->text().replace(',', '.')); + bool ok; + double vd = v.toDouble(&ok); + if (!ok) { vd = 0.0; } + return CAngle::normalizeDegrees180(vd, RoundDigits); + } + + CAngle CPbhsForm::getPitchAngle() const + { + return CAngle(getPitchAngleDegrees(), CAngleUnit::deg()); + } + + void CPbhsForm::setPitchAngle(const CAngle &angle) + { + const int value = angle.valueInteger(CAngleUnit::deg()); + ui->le_Pitch->setText(QString::number(value)); + ui->hs_Pitch->setValue(value); + } + + double CPbhsForm::getPitchAngleDegrees() const + { + const QString v(ui->le_Pitch->text().replace(',', '.')); + bool ok; + double vd = v.toDouble(&ok); + if (!ok) { vd = 0.0; } + return CAngle::normalizeDegrees180(vd, RoundDigits); + } + + CAngle CPbhsForm::getHeadingAngle() const + { + return CAngle(getHeadingAngleDegrees(), CAngleUnit::deg()); + } + + CHeading CPbhsForm::getHeading() const + { + return CHeading(this->getHeadingAngle(), CHeading::True); + } + + void CPbhsForm::setHeadingAngle(const CAngle &angle) + { + const int value = angle.valueInteger(CAngleUnit::deg()); + ui->le_Heading->setText(QString::number(value)); + ui->hs_Heading->setValue(value); + } + + double CPbhsForm::getHeadingAngleDegrees() const + { + const QString v(ui->le_Heading->text().replace(',', '.')); + bool ok; + double vd = v.toDouble(&ok); + if (!ok) { vd = 0.0; } + return CAngle::normalizeDegrees180(vd, RoundDigits); + } + + CSpeed CPbhsForm::getGroundSpeed() const + { + const int gsKts = ui->sb_GsKts->value(); + return CSpeed(gsKts, CSpeedUnit::kts()); + } + + void CPbhsForm::setSituation(const CAircraftSituation &situation) + { + this->setBankAngle(situation.getBank()); + this->setPitchAngle(situation.getPitch()); + this->setHeadingAngle(situation.getHeading()); + } + + void CPbhsForm::updateSituation(CAircraftSituation &situation) + { + situation.setPitch(this->getPitchAngle()); + situation.setBank(this->getBankAngle()); + situation.setHeading(this->getHeading()); + situation.setGroundSpeed(this->getGroundSpeed()); + } + + void CPbhsForm::setReadOnly(bool readOnly) + { + ui->le_Bank->setReadOnly(readOnly); + ui->le_Heading->setReadOnly(readOnly); + ui->le_Pitch->setReadOnly(readOnly); + + ui->hs_Bank->setEnabled(!readOnly); + ui->hs_Heading->setEnabled(!readOnly); + ui->hs_Pitch->setEnabled(!readOnly); + } + + void CPbhsForm::showSetButton(bool visible) + { + ui->pb_SetOwnAircraft->setVisible(visible); + } + + void CPbhsForm::bankSliderChanged(int value) + { + const int angle = clampAngle(qRound(this->getBankAngleDegrees())); + if (value == angle) { return; } // avoid roundtrips + ui->le_Bank->setText(QString::number(value)); + } + + void CPbhsForm::pitchSliderChanged(int value) + { + const int angle = clampAngle(qRound(this->getPitchAngleDegrees())); + if (value == angle) { return; } // avoid roundtrips + ui->le_Pitch->setText(QString::number(value)); + } + + void CPbhsForm::headingSliderChanged(int value) + { + const int angle = clampAngle(qRound(this->getHeadingAngleDegrees())); + if (value == angle) { return; } // avoid roundtrips + ui->le_Heading->setText(QString::number(value)); + } + + void CPbhsForm::bankEntered() + { + const double ad = this->getBankAngleDegrees(); + QString n = QString::number(ad, 'g', 3 + RoundDigits); + if (ui->le_Pitch->validator()) { dotToLocaleDecimalPoint(n); } + ui->le_Bank->setText(n); + const int angle = clampAngle(qRound(ad)); + if (angle == ui->hs_Bank->value()) { return; } // avoid roundtrips + ui->hs_Bank->setValue(angle); + } + + void CPbhsForm::resetBank() + { + ui->le_Bank->setText("0"); + ui->hs_Bank->setValue(0); + } + + void CPbhsForm::pitchEntered() + { + const double ad = this->getPitchAngleDegrees(); + QString n = QString::number(ad, 'g', 3 + RoundDigits); + if (ui->le_Pitch->validator()) { dotToLocaleDecimalPoint(n); } + ui->le_Pitch->setText(n); + const int angle = clampAngle(qRound(ad)); + if (angle == ui->hs_Pitch->value()) { return; } // avoid roundtrips + ui->hs_Pitch->setValue(angle); + } + + void CPbhsForm::resetPitch() + { + ui->le_Pitch->setText("0"); + ui->hs_Pitch->setValue(0); + } + + void CPbhsForm::headingEntered() + { + const double ad = this->getHeadingAngleDegrees(); + QString n = QString::number(ad, 'g', 3 + RoundDigits); + if (ui->le_Heading->validator()) { dotToLocaleDecimalPoint(n); } + ui->le_Heading->setText(n); + const int angle = clampAngle(qRound(ad)); + if (angle == ui->hs_Heading->value()) { return; } // avoid roundtrips + ui->hs_Heading->setValue(angle); + } + + void CPbhsForm::resetHeading() + { + ui->le_Heading->setText("0"); + ui->hs_Heading->setValue(0); + } + + } // ns +} // ns diff --git a/src/blackgui/editors/pbhsform.h b/src/blackgui/editors/pbhsform.h new file mode 100644 index 000000000..2b01adec2 --- /dev/null +++ b/src/blackgui/editors/pbhsform.h @@ -0,0 +1,112 @@ +/* Copyright (C) 2019 + * swift project Community / Contributors + * + * This file is part of swift Project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated, + * or distributed except according to the terms contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKGUI_EDITORS_PBHSFORM_H +#define BLACKGUI_EDITORS_PBHSFORM_H + +#include "form.h" +#include "blackmisc/aviation/aircraftsituation.h" +#include "blackmisc/aviation/heading.h" +#include "blackmisc/pq/angle.h" +#include "blackmisc/pq/speed.h" +#include +#include + +namespace Ui { class CPbhsForm; } +namespace BlackGui +{ + namespace Editors + { + //! Pitch, bank, heading and speed form + class CPbhsForm : public CForm + { + Q_OBJECT + + public: + //! Ctor + explicit CPbhsForm(QWidget *parent = nullptr); + + //! Dtor + virtual ~CPbhsForm() override; + + //! Get bank angle + BlackMisc::PhysicalQuantities::CAngle getBankAngle() const; + + //! Set bank angle + void setBankAngle(const BlackMisc::PhysicalQuantities::CAngle &angle); + + //! Get pitch angle + BlackMisc::PhysicalQuantities::CAngle getPitchAngle() const; + + //! Set pitch angle + void setPitchAngle(const BlackMisc::PhysicalQuantities::CAngle &angle); + + //! Get heading angle + BlackMisc::PhysicalQuantities::CAngle getHeadingAngle() const; + + //! Get heading + BlackMisc::Aviation::CHeading getHeading() const; + + //! Set heading angle + void setHeadingAngle(const BlackMisc::PhysicalQuantities::CAngle &angle); + + //! Get ground speed + BlackMisc::PhysicalQuantities::CSpeed getGroundSpeed() const; + + //! Set situation + void setSituation(const BlackMisc::Aviation::CAircraftSituation &situation); + + //! Update PBHs in situation + void updateSituation(BlackMisc::Aviation::CAircraftSituation &situation); + + //! \copydoc CForm::setReadOnly + virtual void setReadOnly(bool readOnly) override; + + //! Show the "SET" button + void showSetButton(bool visible); + + signals: + //! Changed values + void changeValues(); + + private: + static constexpr int RoundDigits = 6; //!< rounding + + //! Get bank angle + double getBankAngleDegrees() const; + + //! Get pitch angle + double getPitchAngleDegrees() const; + + //! Get heading angle + double getHeadingAngleDegrees() const; + + //! Values changed from UI @{ + void bankSliderChanged(int value); + void pitchSliderChanged(int value); + void headingSliderChanged(int value); + void pressureSliderChanged(int value); + void bankEntered(); + void resetBank(); + void pitchEntered(); + void resetPitch(); + void headingEntered(); + void resetHeading(); + void presetOwnAircraftSituation(); + //! @} + + static int clampAngle(int in) { return qBound(-179, in, 180); } + + QScopedPointer ui; + }; + } // ns +} // ns + +#endif // guard diff --git a/src/blackgui/editors/pbhsform.ui b/src/blackgui/editors/pbhsform.ui new file mode 100644 index 000000000..3ed2001c1 --- /dev/null +++ b/src/blackgui/editors/pbhsform.ui @@ -0,0 +1,192 @@ + + + CPbhsForm + + + + 0 + 0 + 309 + 116 + + + + Pitch, bank, heading + + + + + + Bank (-179° to 180°): + + + + + + + 0 + + + deg. + + + + + + + ... + + + + :/diagona/icons/diagona/icons/cross-white.png:/diagona/icons/diagona/icons/cross-white.png + + + + + + + -179 + + + 180 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 25 + + + + + + + Pitch (-179° to 180°): + + + + + + + 0 + + + deg. + + + + + + + ... + + + + :/diagona/icons/diagona/icons/cross-white.png:/diagona/icons/diagona/icons/cross-white.png + + + + + + + -179 + + + 180 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 25 + + + + + + + Heading (-179° to 180°): + + + + + + + 0 + + + + + + + ... + + + + :/diagona/icons/diagona/icons/cross-white.png:/diagona/icons/diagona/icons/cross-white.png + + + + + + + -179 + + + 180 + + + Qt::Horizontal + + + + + + + Ground speed (kts): + + + + + + + kts + + + 300 + + + + + + + set + + + + + + + le_Bank + tb_ResetBank + hs_Bank + le_Pitch + tb_ResetPitch + hs_Pitch + le_Heading + tb_ResetHeading + hs_Heading + sb_GsKts + pb_SetOwnAircraft + + + + + +