4#include <QAbstractListModel>
7#include <QQmlComponent>
11#include <simgear/misc/sg_path.hxx>
47 return _fp->numLegs();
52 const auto leg = _fp->legAtIndex(index.row());
56 const auto wp = leg->waypoint();
59 case Qt::DisplayRole: {
60 if (wp->type() ==
"via") {
62 return QString::fromStdString(wp->source()->ident());
65 return QString::fromStdString(leg->waypoint()->ident());
75 if (wp->type() ==
"via") {
79 awy =
static_cast<Airway*
>(wp->owner());
82 return awy ? QString::fromStdString(awy->ident()) : QVariant{};
86 if (leg->waypoint()->source()) {
87 return QString::fromStdString(leg->waypoint()->source()->ident());
95 const double f = n->get_freq() / 100.0;
106 if (leg->waypoint()->source()) {
107 return QString::fromStdString(leg->waypoint()->source()->name());
113 return QString::fromStdString(leg->waypoint()->type());
116 return leg->altitudeFt();
119 return leg->altitudeRestriction();
137 QHash<int, QByteArray> result = QAbstractListModel::roleNames();
139 result[Qt::DisplayRole] =
"label";
155 return _fp->numLegs();
181 p->waypointsChanged();
201 qmlRegisterUncreatableType<LegsModel>(
"FlightGear", 1, 0,
"LegsModel",
"singleton");
203 _fp->addDelegate(_delegate.get());
205 _legs->setFlightPlan(_fp);
213 _fp->removeDelegate(_delegate.get());
219 _fp->removeDelegate(_delegate.get());
221 _fp->addDelegate(_delegate.get());
222 _legs->setFlightPlan(fp);
232 bool ok = fp->load(SGPath(path.toUtf8().data()));
234 qWarning() <<
"Failed to load flightplan " << path;
238 _fp->removeDelegate(_delegate.get());
240 _fp->addDelegate(_delegate.get());
241 _legs->setFlightPlan(fp);
253 SGPath
p(path.toUtf8().data());
257void FlightPlanController::onCollectConfig()
262 SGPath
p =
globals->get_fg_home() /
"launcher.fgfp";
265 _config->
setArg(
"flight-plan",
p.utf8Str());
268void FlightPlanController::onSave()
270 std::ostringstream ss;
272 _config->setValueForKey(
"",
"fp", QString::fromStdString(ss.str()));
275void FlightPlanController::onRestore()
277 _enabled = _config->getValueForKey(
"",
"fp-enabled",
false).toBool();
282 std::string fpArgPath =
options->valueForOption(
"flight-plan");
283 SGPath fp = SGPath::fromUtf8(fpArgPath);
287 std::string planXML = _config->getValueForKey(
"",
"fp", QString()).toString().toStdString();
288 if (!planXML.empty()) {
289 std::istringstream ss(planXML);
298 if (_fp->cruiseFlightLevel() > 0) {
302 if (_fp->cruiseAltitudeM() > 0) {
311 const int ival =
static_cast<int>(alt.
value);
314 if (_fp->cruiseFlightLevel() == ival) {
317 _fp->setCruiseFlightLevel(ival);
321 if (_fp->cruiseAltitudeFt() == ival) {
324 _fp->setCruiseAltitudeFt(ival);
328 if (_fp->cruiseAltitudeM() == ival) {
331 _fp->setCruiseAltitudeM(ival);
335 qWarning() <<
"Unsupported cruise altitude units" << alt.
unit;
344 if (_fp->numLegs() == 0) {
345 return tr(
"No flight-plan");
348 return tr(
"From %1 (%2) to %3 (%4)")
357 if (!_fp->departureAirport())
365 if (!_fp->destinationAirport())
373 if (!_fp->alternate())
381 if (_fp->cruiseSpeedMach() > 0.0) {
385 if (_fp->cruiseSpeedKPH() > 0) {
394 return static_cast<FlightRules>(_fp->flightRules());
399 return static_cast<FlightType>(_fp->flightType());
414 return QString::fromStdString(_fp->callsign());
419 return QString::fromStdString(_fp->remarks());
424 return QString::fromStdString(_fp->icaoAircraftType());
429 const auto stdS = s.toStdString();
430 if (_fp->callsign() == stdS)
433 _fp->setCallsign(stdS);
439 const auto stdR = r.toStdString();
440 if (_fp->remarks() == stdR)
443 _fp->setRemarks(stdR);
449 const auto stdT = ty.toStdString();
450 if (_fp->icaoAircraftType() == stdT)
453 _fp->setIcaoAircraftType(stdT);
459 return _fp->estimatedDurationMinutes();
469 bool ok = _fp->parseICAORouteString(routeDesc.toStdString());
475 if (!_fp->departureAirport() || !_fp->destinationAirport()) {
476 qWarning() <<
"departure or destination not set";
482 auto fromNode = net->findClosestNode(_fp->departureAirport()->geod());
483 auto toNode = net->findClosestNode(_fp->destinationAirport()->geod());
484 if (!fromNode.first) {
485 qWarning() <<
"Couldn't find airway network transition for "
486 << QString::fromStdString(_fp->departureAirport()->ident());
491 qWarning() <<
"Couldn't find airway network transition for "
492 << QString::fromStdString(_fp->destinationAirport()->ident());
499 bool ok = net->route(fromWp, toWp, path);
501 qWarning() <<
"unable to find a route";
506 _fp->insertWayptAtIndex(fromWp, -1);
507 _fp->insertWayptsAtIndex(path, -1);
508 _fp->insertWayptAtIndex(toWp, -1);
520 return QString::fromStdString(_fp->asICAORouteString());
525 if (_fp->estimatedDurationMinutes() == mins)
528 _fp->setEstimatedDurationMinutes(mins);
534 _fp->computeDurationMinutes();
541 QString lastUsedDir = settings.value(
"flightplan-lastdir",
"").toString();
543 QString file = QFileDialog::getOpenFileName(
nullptr, tr(
"Load a flight-plan"),
544 lastUsedDir,
"*.fgfp *.gpx");
549 settings.setValue(
"flightplan-lastdir", fi.absolutePath());
557 QString lastUsedDir = settings.value(
"flightplan-lastdir",
"").toString();
559 QString file = QFileDialog::getSaveFileName(
nullptr, tr(
"Save flight-plan"),
560 lastUsedDir,
"*.fgfp");
563 if (!file.endsWith(
".fgfp")) {
568 settings.setValue(
"flightplan-lastdir", fi.absolutePath());
576 _fp->clearDeparture();
578 if (apt->
inner() == _fp->departureAirport())
590 if (apt->
inner() == _fp->destinationAirport())
595 _fp->clearDestination();
604 if (apt->
inner() == _fp->alternate())
609 _fp->setAlternate(
nullptr);
617 switch (speed.
unit) {
623 _fp->setCruiseSpeedMach(speed.
value);
627 const int knotsVal =
static_cast<int>(speed.
value);
628 if (_fp->cruiseSpeedKnots() == knotsVal) {
632 _fp->setCruiseSpeedKnots(knotsVal);
636 const int kmhVal =
static_cast<int>(speed.
value);
637 if (_fp->cruiseSpeedKPH() == kmhVal) {
641 _fp->setCruiseSpeedKPH(kmhVal);
645 qWarning() <<
"Unsupported cruise speed units" << speed.
unit;
const int LegTerminatorNavNameRole
const int LegAltitudeFtRole
const int LegAltitudeTypeRole
const int LegTerminatorNavFrequencyRole
const int LegDistanceRole
const int LegAirwayIdentRole
const int LegTerminatorTypeRole
const int LegTerminatorNavRole
bool options(int, char **)
void cruiseChanged() override
void waypointsChanged() override
void departureChanged() override
void arrivalChanged() override
void setDeparture(QmlPositioned *destinationAirport)
QuantityValue totalDistanceNm
void setFlightType(FlightType ty)
void setAircraftType(QString ty)
Q_INVOKABLE bool tryParseRoute(QString routeDesc)
QmlPositioned * destination
int estimatedDurationMinutes
Q_INVOKABLE bool tryGenerateRoute()
QmlPositioned * alternate
void setFlightRules(FlightRules r)
void setDestination(QmlPositioned *destinationAirport)
void setCallsign(QString s)
Q_INVOKABLE bool loadPlan()
void setAlternate(QmlPositioned *apt)
bool saveToPath(QString path) const
bool loadFromPath(QString path)
FlightPlanController(QObject *parent, LaunchConfig *config)
Q_INVOKABLE void clearRoute()
void enabledChanged(bool enabled)
void setRemarks(QString r)
void setCruiseAltitude(QuantityValue alt)
QuantityValue cruiseAltitude
QmlPositioned * departure
QuantityValue cruiseSpeed
void setEstimatedDurationMinutes(int mins)
virtual ~FlightPlanController()
void setCruiseSpeed(QuantityValue cruiseSpeed)
Q_INVOKABLE void setArg(QString name, QString value=QString(), Origin origin=Launcher)
int rowCount(const QModelIndex &parent) const override
QHash< int, QByteArray > roleNames() const override
void setFlightPlan(flightgear::FlightPlanRef f)
QVariant data(const QModelIndex &index, int role) const override
FGPositionedRef inner() const
static Network * highLevel()
static FlightPlanRef createRoute()
@factory to create a FlightPlan with isRoute=true
Waypoint based upon a navaid.
static Options * sharedInstance()
FlightPlan.hxx - defines a full flight-plan object, including departure, cruise, arrival information ...
SGSharedPtr< FlightPlan > FlightPlanRef
SGSharedPtr< Waypt > WayptRef
SGSharedPtr< Airway > AirwayRef
@ WPT_VIA
waypoint prodcued by expanding a VIA segment
std::vector< WayptRef > WayptVec
T * fgpositioned_cast(FGPositioned *p)