Improved launcher metric units support
For our Russian friends, especially. Also add preliminary support for above-field elevations (needs FG changes)
This commit is contained in:
parent
d052dc2576
commit
2cd3036488
7 changed files with 83 additions and 23 deletions
|
@ -682,6 +682,9 @@ void LocationController::applyAirspeed()
|
|||
if (m_speedEnabled && (m_airspeed.unit != Units::NoUnits)) {
|
||||
if (m_airspeed.unit == Units::Knots) {
|
||||
m_config->setArg("vc", QString::number(m_airspeed.value));
|
||||
} else if (m_airspeed.unit == Units::KilometersPerHour) {
|
||||
const double vc = m_airspeed.convertToUnit(Units::Knots).value;
|
||||
m_config->setArg("vc", QString::number(vc));
|
||||
} else if (m_airspeed.unit == Units::Mach) {
|
||||
m_config->setArg("mach", QString::number(m_airspeed.value));
|
||||
} else {
|
||||
|
@ -704,7 +707,7 @@ void LocationController::applyPositionOffset()
|
|||
// flip direction of azimuth to balance the flip done in fgApplyStartOffset
|
||||
// I don't know why that flip exists but changing it there will break
|
||||
// command-line compatability so compensating here instead
|
||||
int offsetAzimuth = m_offsetRadial.value - 180;
|
||||
int offsetAzimuth = static_cast<int>(m_offsetRadial.value) - 180;
|
||||
m_config->setArg("offset-azimuth", QString::number(offsetAzimuth));
|
||||
const double offsetNm = m_offsetDistance.convertToUnit(Units::NauticalMiles).value;
|
||||
m_config->setArg("offset-distance", QString::number(offsetNm));
|
||||
|
@ -733,6 +736,15 @@ void LocationController::applyAltitude()
|
|||
// FIXME - allow the sim to accept real FlightLevel arguments
|
||||
m_config->setArg("altitude", QString::number(m_altitude.value * 100));
|
||||
break;
|
||||
|
||||
case Units::FeetAboveFieldElevation:
|
||||
m_config->setArg("altitude", QString::number(m_altitude.value));
|
||||
break;
|
||||
|
||||
case Units::MetersMSL:
|
||||
const double ftMSL = m_altitude.convertToUnit(Units::FeetMSL).value;
|
||||
m_config->setArg("altitude", QString::number(ftMSL));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
|
||||
#include <simgear/constants.h>
|
||||
|
||||
|
@ -70,10 +71,12 @@ std::vector<UnitData> static_unitData = {
|
|||
{ "", "", "" }, // noUnits
|
||||
{ "ft", "feet above sea-level (MSL)", "000000", false, -2000, 180000, 50},
|
||||
{ "ft AGL", "feet above ground level (AGL)", "000000", false, 0, 180000, 50},
|
||||
{ "ft above field", "feet above airfield", "000000", false, 0, 180000, 50},
|
||||
{ "FL", "Flight-level", "000", true /* prefix */, 0.0, 500.0, 5.0},
|
||||
{ "m", "meters above sea-level (MSL)", "000000", false, -500, 100000, 50},
|
||||
{ "kts", "Knots", "9999", false, 0, 999999, 10.0},
|
||||
{ "M", "Mach", "00.000", true /* prefix */, 0.0, 99.0, 0.05, false /* no wrap */, 3 /* decimal places */},
|
||||
{ "KM/H", "Kilometers/hour", "9999", false, 0, 999999, 10.0},
|
||||
{ "°True", "degrees true", "000", false, 0, 359, 5.0, true /* wraps */},
|
||||
{ "°Mag", "degrees magnetic", "000", false, 0, 359, 5.0, true /* wraps */},
|
||||
{ "UTC", "Universal coordinated time", ""},
|
||||
|
@ -91,11 +94,12 @@ std::vector<UnitsModel::UnitVec> static_modeData = {
|
|||
{ Units::FeetMSL, Units::FlightLevel},
|
||||
{ Units::FeetMSL, Units::FeetAGL, Units::FlightLevel},
|
||||
{ Units::FeetMSL, Units::MetersMSL, Units::FlightLevel},
|
||||
{ Units::Knots, Units::Mach },
|
||||
{ Units::Knots },
|
||||
{ Units::Knots, Units::Mach, Units::KilometersPerHour },
|
||||
{ Units::Knots, Units::KilometersPerHour },
|
||||
{ Units::DegreesMagnetic, Units::DegreesTrue },
|
||||
{ Units::TimeLocal, Units::TimeUTC},
|
||||
{ Units::NauticalMiles }
|
||||
{ Units::NauticalMiles, Units::Kilometers },
|
||||
{ Units::FeetMSL, Units::MetersMSL, Units::FeetAboveFieldElevation},
|
||||
};
|
||||
|
||||
const int UnitLongNameRole = Qt::UserRole + 1;
|
||||
|
@ -115,7 +119,7 @@ UnitsModel::UnitsModel()
|
|||
|
||||
int UnitsModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return m_enabledUnits.size();
|
||||
return static_cast<int>(m_enabledUnits.size());
|
||||
}
|
||||
|
||||
QVariant UnitsModel::data(const QModelIndex &index, int role) const
|
||||
|
@ -194,7 +198,13 @@ Units::Type UnitsModel::selectedUnit() const
|
|||
|
||||
int UnitsModel::numChoices() const
|
||||
{
|
||||
return m_enabledUnits.size();
|
||||
return static_cast<int>(m_enabledUnits.size());
|
||||
}
|
||||
|
||||
bool UnitsModel::isUnitInMode(int unit) const
|
||||
{
|
||||
auto it = std::find(m_enabledUnits.begin(), m_enabledUnits.end(), unit);
|
||||
return it != m_enabledUnits.end();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> UnitsModel::roleNames() const
|
||||
|
@ -274,9 +284,9 @@ void UnitsModel::setSelectedUnit(int u)
|
|||
return;
|
||||
}
|
||||
|
||||
int index = std::distance(m_enabledUnits.begin(), it);
|
||||
auto index = std::distance(m_enabledUnits.begin(), it);
|
||||
if (index != m_activeIndex) {
|
||||
m_activeIndex = index;
|
||||
m_activeIndex = static_cast<quint32>(index);
|
||||
emit selectionChanged(m_activeIndex);
|
||||
}
|
||||
}
|
||||
|
@ -331,16 +341,28 @@ QuantityValue QuantityValue::convertToUnit(Units::Type u) const
|
|||
return {u, value * 100};
|
||||
} else if (unit == Units::MetersMSL) {
|
||||
return {u, value * SG_METER_TO_FEET};
|
||||
} else if ((unit == Units::FeetAGL) || (unit == Units::FeetAboveFieldElevation)) {
|
||||
return {u, value};
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Units::FeetAboveFieldElevation:
|
||||
case Units::FeetAGL:
|
||||
// treat as FeetMSL
|
||||
return {u, convertToUnit(Units::FeetMSL).value};
|
||||
|
||||
case Units::MetersMSL:
|
||||
return {u, convertToUnit(Units::FeetMSL).value * SG_FEET_TO_METER};
|
||||
|
||||
case Units::Mach:
|
||||
{
|
||||
if (unit == Units::Knots) {
|
||||
// obviously this depends on altitude, let's
|
||||
// use the value at sea level for now
|
||||
return {u, value / 667.0};
|
||||
} else if (unit == Units::KilometersPerHour) {
|
||||
return convertToUnit(Units::Knots).convertToUnit(u);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -351,10 +373,20 @@ QuantityValue QuantityValue::convertToUnit(Units::Type u) const
|
|||
// obviously this depends on altitude, let's
|
||||
// use the value at sea level for now
|
||||
return {u, value * 667.0};
|
||||
} else if (unit == Units::KilometersPerHour) {
|
||||
return {u, value * SG_KMH_TO_MPS * SG_MPS_TO_KT};
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Units::KilometersPerHour:
|
||||
if (unit == Units::Knots) {
|
||||
return {u, value * SG_KT_TO_MPS * SG_MPS_TO_KMH};
|
||||
} else {
|
||||
// round-trip via Knots
|
||||
return convertToUnit(Units::Knots).convertToUnit(u);
|
||||
}
|
||||
|
||||
case Units::DegreesMagnetic:
|
||||
case Units::DegreesTrue:
|
||||
{
|
||||
|
@ -367,15 +399,11 @@ QuantityValue QuantityValue::convertToUnit(Units::Type u) const
|
|||
}
|
||||
|
||||
case Units::FlightLevel:
|
||||
{
|
||||
if (unit == Units::FeetMSL) {
|
||||
return {u, static_cast<double>(static_cast<int>(value / 100))};
|
||||
} else {
|
||||
return convertToUnit(Units::FeetMSL).convertToUnit(u);
|
||||
}
|
||||
if (unit == Units::MetersMSL) {
|
||||
return {u, static_cast<double>(static_cast<int>(value * SG_METER_TO_FEET / 100))};
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
qWarning() << Q_FUNC_INFO << "unhandled case:" << u << "from" << unit;
|
||||
|
|
|
@ -45,10 +45,12 @@ public:
|
|||
NoUnits = 0,
|
||||
FeetMSL,
|
||||
FeetAGL,
|
||||
FeetAboveFieldElevation,
|
||||
FlightLevel,
|
||||
MetersMSL,
|
||||
Knots,
|
||||
Mach,
|
||||
KilometersPerHour,
|
||||
DegreesTrue,
|
||||
DegreesMagnetic,
|
||||
TimeUTC,
|
||||
|
@ -64,11 +66,12 @@ public:
|
|||
Altitude = 0, // MSL, FlightLevel
|
||||
AltitudeIncludingAGL,
|
||||
AltitudeIncludingMeters,
|
||||
Speed, // Mach or knots
|
||||
SpeedOnlyKnots = 4,
|
||||
Speed, // Mach or knots or KM/H
|
||||
SpeedWithoutMach = 4,
|
||||
Heading, // degrees true or magnetic
|
||||
Timezone,
|
||||
Distance = 7 // Nm only for now
|
||||
Distance = 7, // Nm or Kilometers only for now
|
||||
AltitudeIncludingMetersAndAboveField,
|
||||
};
|
||||
|
||||
Q_ENUMS(Mode)
|
||||
|
@ -150,7 +153,7 @@ public:
|
|||
|
||||
int selectedIndex() const
|
||||
{
|
||||
return m_activeIndex;
|
||||
return static_cast<int>(m_activeIndex);
|
||||
}
|
||||
|
||||
double minValue() const;
|
||||
|
@ -165,6 +168,8 @@ public:
|
|||
QString shortText() const;
|
||||
Units::Type selectedUnit() const;
|
||||
int numChoices() const;
|
||||
|
||||
Q_INVOKABLE bool isUnitInMode(int unit) const;
|
||||
public slots:
|
||||
void setMode(Units::Mode mode);
|
||||
|
||||
|
@ -178,7 +183,7 @@ signals:
|
|||
|
||||
private:
|
||||
Units::Mode m_mode = Units::Altitude;
|
||||
int m_activeIndex = 0;
|
||||
quint32 m_activeIndex = 0;
|
||||
UnitVec m_enabledUnits;
|
||||
};
|
||||
|
||||
|
|
|
@ -221,7 +221,7 @@ Item {
|
|||
NumericalEdit {
|
||||
id: airspeedSpinbox
|
||||
label: qsTr("Airspeed:")
|
||||
unitsMode: Units.SpeedOnlyKnots
|
||||
unitsMode: Units.SpeedWithoutMach
|
||||
enabled: _location.speedEnabled && onFinalBox.enableOnFinal
|
||||
quantity: _location.airspeed
|
||||
onCommit: _location.airspeed = newValue
|
||||
|
|
|
@ -8,6 +8,7 @@ Row {
|
|||
height: childrenRect.height
|
||||
spacing: Style.margin
|
||||
property bool enabled: true
|
||||
property alias unitsMode: edit.unitsMode
|
||||
|
||||
ToggleSwitch {
|
||||
id: altitudeToggle
|
||||
|
@ -23,9 +24,11 @@ Row {
|
|||
readonly property bool __rowEnabled: root.enabled && _location.altitudeEnabled
|
||||
|
||||
NumericalEdit {
|
||||
id: edit
|
||||
label: qsTr("Altitude:")
|
||||
enabled: __rowEnabled
|
||||
quantity: _location.altitude
|
||||
onCommit: _location.altitude = newValue
|
||||
unitsMode: Units.AltitudeIncludingMetersAndAboveField
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,6 +120,7 @@ Item {
|
|||
LocationAltitudeRow
|
||||
{
|
||||
width: parent.width
|
||||
unitsMode: Units.AltitudeIncludingMeters
|
||||
}
|
||||
|
||||
// offset row
|
||||
|
|
|
@ -102,7 +102,10 @@ FocusScope {
|
|||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (quantity.unit === Units.NoUnits) {
|
||||
// ensure any initial value is accepted by our mode.
|
||||
// this stops people passing in completely wrong quantities
|
||||
if (!units.isUnitInMode(quantity.unit)) {
|
||||
console.warn("NumericalEdit: was inited with incorrect unit");
|
||||
var q = quantity;
|
||||
q.unit = units.selectedUnit;
|
||||
commit(q);
|
||||
|
@ -110,8 +113,16 @@ FocusScope {
|
|||
}
|
||||
|
||||
onQuantityChanged: {
|
||||
// ensure our units model is in sync
|
||||
units.selectedUnit = quantity.unit
|
||||
if (units.isUnitInMode(quantity.unit)) {
|
||||
// ensure our units model is in sync
|
||||
units.selectedUnit = quantity.unit
|
||||
} else {
|
||||
console.warn("Passed illegal quantity");
|
||||
// reset back to something permitted
|
||||
var q = quantity;
|
||||
q.unit = units.selectedUnit;
|
||||
commit(q);
|
||||
}
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
|
|
Loading…
Add table
Reference in a new issue