From 56d7d049bc0b7361d1799298c38e61084f5d5e3f Mon Sep 17 00:00:00 2001 From: James Turner Date: Sat, 24 Oct 2015 19:40:41 -0500 Subject: [PATCH] Launcher GUI for in-air / navaid starts --- src/GUI/QtLauncher.cxx | 278 +++++++++++++++++++-------------- src/GUI/QtLauncher_private.hxx | 11 +- src/Main/positioninit.cxx | 18 ++- src/Navaids/NavDataCache.cxx | 2 +- src/Navaids/positioned.hxx | 2 +- 5 files changed, 187 insertions(+), 124 deletions(-) diff --git a/src/GUI/QtLauncher.cxx b/src/GUI/QtLauncher.cxx index a96ed7abb..e79585fe6 100644 --- a/src/GUI/QtLauncher.cxx +++ b/src/GUI/QtLauncher.cxx @@ -235,6 +235,20 @@ private: } // of anonymous namespace +class IdentSearchFilter : public FGPositioned::TypeFilter +{ +public: + IdentSearchFilter() + { + addType(FGPositioned::AIRPORT); + addType(FGPositioned::SEAPORT); + addType(FGPositioned::HELIPAD); + addType(FGPositioned::VOR); + addType(FGPositioned::FIX); + addType(FGPositioned::NDB); + } +}; + class AirportSearchModel : public QAbstractListModel { Q_OBJECT @@ -248,23 +262,25 @@ public: { beginResetModel(); - m_airports.clear(); + m_items.clear(); m_ids.clear(); std::string term(t.toUpper().toStdString()); - // try ICAO lookup first - FGAirportRef ref = FGAirport::findByIdent(term); - if (ref) { - m_ids.push_back(ref->guid()); - m_airports.push_back(ref); - endResetModel(); - return; + IdentSearchFilter filter; + FGPositionedList exactMatches = NavDataCache::instance()->findAllWithIdent(term, &filter, true); + + for (unsigned int i=0; iguid()); + m_items.push_back(exactMatches[i]); } + endResetModel(); + m_search.reset(new NavDataCache::ThreadedGUISearch(term)); QTimer::singleShot(100, this, SLOT(onSearchResultsPoll())); m_searchActive = true; + endResetModel(); } bool isSearchActive() const @@ -283,19 +299,14 @@ public: if (!index.isValid()) return QVariant(); - FGAirportRef apt = m_airports[index.row()]; - if (!apt.valid()) { - apt = FGPositioned::loadById(m_ids[index.row()]); - m_airports[index.row()] = apt; - } - + FGPositionedRef pos = itemAtRow(index.row()); if (role == Qt::DisplayRole) { - QString name = QString::fromStdString(apt->name()); - return QString("%1: %2").arg(QString::fromStdString(apt->ident())).arg(name); + QString name = QString::fromStdString(pos->name()); + return QString("%1: %2").arg(QString::fromStdString(pos->ident())).arg(name); } if (role == Qt::EditRole) { - return QString::fromStdString(apt->ident()); + return QString::fromStdString(pos->ident()); } if (role == Qt::UserRole) { @@ -305,18 +316,16 @@ public: return QVariant(); } - QString firstIdent() const + FGPositionedRef itemAtRow(unsigned int row) const { - if (m_ids.empty()) - return QString(); - - if (!m_airports.front().valid()) { - m_airports[0] = FGPositioned::loadById(m_ids.front()); + FGPositionedRef pos = m_items[row]; + if (!pos.valid()) { + pos = NavDataCache::instance()->loadById(m_ids[row]); + m_items[row] = pos; } - return QString::fromStdString(m_airports.front()->ident()); + return pos; } - Q_SIGNALS: void searchComplete(); @@ -328,7 +337,7 @@ private slots: beginInsertRows(QModelIndex(), m_ids.size(), newIds.size() - 1); for (unsigned int i=m_ids.size(); i < newIds.size(); ++i) { m_ids.push_back(newIds[i]); - m_airports.push_back(FGAirportRef()); // null ref + m_items.push_back(FGPositionedRef()); // null ref } endInsertRows(); @@ -343,7 +352,7 @@ private slots: private: PositionedIDVec m_ids; - mutable std::vector m_airports; + mutable FGPositionedList m_items; bool m_searchActive; QScopedPointer m_search; }; @@ -531,15 +540,15 @@ QtLauncher::QtLauncher() : m_aircraftProxy, &QSortFilterProxyModel::setFilterFixedString); connect(m_ui->runwayCombo, SIGNAL(currentIndexChanged(int)), - this, SLOT(updateAirportDescription())); + this, SLOT(updateLocationDescription())); connect(m_ui->parkingCombo, SIGNAL(currentIndexChanged(int)), - this, SLOT(updateAirportDescription())); + this, SLOT(updateLocationDescription())); connect(m_ui->runwayRadio, SIGNAL(toggled(bool)), - this, SLOT(updateAirportDescription())); + this, SLOT(updateLocationDescription())); connect(m_ui->parkingRadio, SIGNAL(toggled(bool)), - this, SLOT(updateAirportDescription())); + this, SLOT(updateLocationDescription())); connect(m_ui->onFinalCheckbox, SIGNAL(toggled(bool)), - this, SLOT(updateAirportDescription())); + this, SLOT(updateLocationDescription())); connect(m_ui->airportDiagram, &AirportDiagram::clickedRunway, @@ -724,12 +733,14 @@ void QtLauncher::restoreSettings() updateSelectedAircraft(); - // ICAO identifiers - m_recentAirports = settings.value("recent-airports").toStringList(); + Q_FOREACH(QVariant v, settings.value("recent-locations").toList()) { + m_recentAirports.push_back(v.toLongLong()); + } + if (!m_recentAirports.empty()) { - setAirport(FGAirport::findByIdent(m_recentAirports.front().toStdString())); + setBaseLocation(NavDataCache::instance()->loadById(m_recentAirports.front())); } - updateAirportDescription(); + updateLocationDescription(); // rating filters m_ui->ratingsFilterCheck->setChecked(settings.value("ratings-filter", true).toBool()); @@ -755,7 +766,13 @@ void QtLauncher::saveSettings() settings.setValue("start-paused", m_ui->startPausedCheck->isChecked()); settings.setValue("ratings-filter", m_ui->ratingsFilterCheck->isChecked()); settings.setValue("recent-aircraft", QUrl::toStringList(m_recentAircraft)); - settings.setValue("recent-airports", m_recentAirports); + + QVariantList locations; + Q_FOREACH(PositionedID v, m_recentAirports) { + locations.push_back(v); + } + + settings.setValue("recent-airports", locations); settings.setValue("timeofday", m_ui->timeOfDayCombo->currentIndex()); settings.setValue("season", m_ui->seasonCombo->currentIndex()); settings.setValue("additional-args", m_ui->commandLineArgs->toPlainText()); @@ -819,26 +836,7 @@ void QtLauncher::onRun() m_recentAircraft.pop_back(); } - // airport / location - if (m_selectedAirport) { - opt->addOption("airport", m_selectedAirport->ident()); - } - - if (m_ui->runwayRadio->isChecked()) { - int index = m_ui->runwayCombo->itemData(m_ui->runwayCombo->currentIndex()).toInt(); - if ((index >= 0) && m_selectedAirport) { - // explicit runway choice - opt->addOption("runway", m_selectedAirport->getRunwayByIndex(index)->ident()); - } - - if (m_ui->onFinalCheckbox->isChecked()) { - opt->addOption("glideslope", "3.0"); - opt->addOption("offset-distance", "10.0"); // in nautical miles - } - } else if (m_ui->parkingRadio->isChecked()) { - // parking selection - opt->addOption("parkpos", m_ui->parkingCombo->currentText().toStdString()); - } + setLocationOptions(); // time of day if (m_ui->timeOfDayCombo->currentIndex() != 0) { @@ -897,6 +895,54 @@ void QtLauncher::onRun() saveSettings(); } +void QtLauncher::setLocationOptions() +{ + flightgear::Options* opt = flightgear::Options::sharedInstance(); + + if (!m_location) { + return; + } + + if (FGAirport::isAirportType(m_location.ptr())) { + FGAirport* apt = static_cast(m_location.ptr()); + opt->addOption("airport", apt->ident()); + + if (m_ui->runwayRadio->isChecked()) { + int index = m_ui->runwayCombo->itemData(m_ui->runwayCombo->currentIndex()).toInt(); + if (index >= 0) { + // explicit runway choice + opt->addOption("runway", apt->getRunwayByIndex(index)->ident()); + } + + if (m_ui->onFinalCheckbox->isChecked()) { + opt->addOption("glideslope", "3.0"); + opt->addOption("offset-distance", "10.0"); // in nautical miles + } + } else if (m_ui->parkingRadio->isChecked()) { + // parking selection + opt->addOption("parkpos", m_ui->parkingCombo->currentText().toStdString()); + } + // of location is an airport + } + + FGPositioned::Type ty = m_location->type(); + switch (ty) { + case FGPositioned::VOR: + case FGPositioned::NDB: + case FGPositioned::FIX: + // set disambiguation property + globals->get_props()->setIntValue("/sim/presets/navaid-id", + static_cast(m_location->guid())); + + // we always set 'fix', but really this is just to force positionInit + // code to check for the navaid-id value above. + opt->addOption("fix", m_location->ident()); + break; + default: + break; + } +} + void QtLauncher::onApply() { accept(); @@ -951,8 +997,7 @@ void QtLauncher::onSearchAirports() m_ui->searchStatusText->setText(QString("Searching for '%1'").arg(search)); m_ui->locationStack->setCurrentIndex(2); } else if (m_airportsModel->rowCount(QModelIndex()) == 1) { - QString ident = m_airportsModel->firstIdent(); - setAirport(FGAirport::findByIdent(ident.toStdString())); + setBaseLocation(m_airportsModel->itemAtRow(0)); m_ui->locationStack->setCurrentIndex(0); } } @@ -963,60 +1008,62 @@ void QtLauncher::onAirportSearchComplete() if (numResults == 0) { m_ui->searchStatusText->setText(QString("No matching airports for '%1'").arg(m_ui->airportEdit->text())); } else if (numResults == 1) { - QString ident = m_airportsModel->firstIdent(); - setAirport(FGAirport::findByIdent(ident.toStdString())); + setBaseLocation(m_airportsModel->itemAtRow(0)); m_ui->locationStack->setCurrentIndex(0); } else { m_ui->locationStack->setCurrentIndex(1); } } -void QtLauncher::onAirportChanged() +void QtLauncher::onLocationChanged() { - m_ui->runwayCombo->setEnabled(m_selectedAirport); - m_ui->parkingCombo->setEnabled(m_selectedAirport); - m_ui->airportDiagram->setAirport(m_selectedAirport); + bool locIsAirport = FGAirport::isAirportType(m_location.ptr()); + + m_ui->runwayCombo->setEnabled(locIsAirport); + m_ui->parkingCombo->setEnabled(locIsAirport); + if (locIsAirport) { + FGAirport* apt = static_cast(m_location.ptr()); + m_ui->airportDiagram->setAirport(apt); + + m_ui->runwayRadio->setChecked(true); // default back to runway mode + // unless multiplayer is enabled ? + m_ui->airportDiagram->setEnabled(true); + + m_ui->runwayCombo->clear(); + m_ui->runwayCombo->addItem("Automatic", -1); + for (unsigned int r=0; rnumRunways(); ++r) { + FGRunwayRef rwy = apt->getRunwayByIndex(r); + // add runway with index as data role + m_ui->runwayCombo->addItem(QString::fromStdString(rwy->ident()), r); + + m_ui->airportDiagram->addRunway(rwy); + } - m_ui->runwayRadio->setChecked(true); // default back to runway mode - // unelss multiplayer is enabled ? + m_ui->parkingCombo->clear(); + FGAirportDynamics* dynamics = apt->getDynamics(); + PositionedIDVec parkings = NavDataCache::instance()->airportItemsOfType(m_location->guid(), + FGPositioned::PARKING); + if (parkings.empty()) { + m_ui->parkingCombo->setEnabled(false); + m_ui->parkingRadio->setEnabled(false); + } else { + m_ui->parkingCombo->setEnabled(true); + m_ui->parkingRadio->setEnabled(true); + Q_FOREACH(PositionedID parking, parkings) { + FGParking* park = dynamics->getParking(parking); + m_ui->parkingCombo->addItem(QString::fromStdString(park->getName()), + static_cast(parking)); + + m_ui->airportDiagram->addParking(park); + } + } - if (!m_selectedAirport) { - m_ui->airportDescription->setText(QString()); - m_ui->airportDiagram->setEnabled(false); - return; - } - m_ui->airportDiagram->setEnabled(true); + } // of location is aiport + - m_ui->runwayCombo->clear(); - m_ui->runwayCombo->addItem("Automatic", -1); - for (unsigned int r=0; rnumRunways(); ++r) { - FGRunwayRef rwy = m_selectedAirport->getRunwayByIndex(r); - // add runway with index as data role - m_ui->runwayCombo->addItem(QString::fromStdString(rwy->ident()), r); - m_ui->airportDiagram->addRunway(rwy); - } - m_ui->parkingCombo->clear(); - FGAirportDynamics* dynamics = m_selectedAirport->getDynamics(); - PositionedIDVec parkings = NavDataCache::instance()->airportItemsOfType( - m_selectedAirport->guid(), - FGPositioned::PARKING); - if (parkings.empty()) { - m_ui->parkingCombo->setEnabled(false); - m_ui->parkingRadio->setEnabled(false); - } else { - m_ui->parkingCombo->setEnabled(true); - m_ui->parkingRadio->setEnabled(true); - Q_FOREACH(PositionedID parking, parkings) { - FGParking* park = dynamics->getParking(parking); - m_ui->parkingCombo->addItem(QString::fromStdString(park->getName()), - static_cast(parking)); - - m_ui->airportDiagram->addParking(park); - } - } } void QtLauncher::onOffsetRadioToggled(bool on) @@ -1036,7 +1083,7 @@ void QtLauncher::onAirportDiagramClicked(FGRunwayRef rwy) m_ui->runwayCombo->setCurrentIndex(rwyIndex); } - updateAirportDescription(); + updateLocationDescription(); } void QtLauncher::onToggleTerrasync(bool enabled) @@ -1095,17 +1142,18 @@ void QtLauncher::onAircraftInstallFailed(QModelIndex index, QString errorMessage maybeUpdateSelectedAircraft(index); } -void QtLauncher::updateAirportDescription() +void QtLauncher::updateLocationDescription() { - if (!m_selectedAirport) { - m_ui->airportDescription->setText(QString("No airport selected")); + if (!m_location) { + m_ui->airportDescription->setText(QString("No location selected")); return; } - QString ident = QString::fromStdString(m_selectedAirport->ident()), - name = QString::fromStdString(m_selectedAirport->name()); + QString ident = QString::fromStdString(m_location->ident()), + name = QString::fromStdString(m_location->name()); QString locationOnAirport; if (m_ui->runwayRadio->isChecked()) { + FGAirport* apt = static_cast(m_location.ptr()); bool onFinal = m_ui->onFinalCheckbox->isChecked(); int comboIndex = m_ui->runwayCombo->currentIndex(); QString runwayName = (comboIndex == 0) ? @@ -1120,7 +1168,7 @@ void QtLauncher::updateAirportDescription() int runwayIndex = m_ui->runwayCombo->itemData(comboIndex).toInt(); FGRunwayRef rwy = (runwayIndex >= 0) ? - m_selectedAirport->getRunwayByIndex(runwayIndex) : FGRunwayRef(); + apt->getRunwayByIndex(runwayIndex) : FGRunwayRef(); m_ui->airportDiagram->setSelectedRunway(rwy); } else if (m_ui->parkingRadio->isChecked()) { locationOnAirport = QString("at parking position %1").arg(m_ui->parkingCombo->currentText()); @@ -1132,7 +1180,7 @@ void QtLauncher::updateAirportDescription() void QtLauncher::onAirportChoiceSelected(const QModelIndex& index) { m_ui->locationStack->setCurrentIndex(0); - setAirport(FGPositioned::loadById(index.data(Qt::UserRole).toULongLong())); + setBaseLocation(m_airportsModel->itemAtRow(index.row())); } void QtLauncher::onOffsetBearingTrueChanged(bool on) @@ -1202,6 +1250,7 @@ void QtLauncher::onPopupAirportHistory() return; } +#if 0 QMenu m; Q_FOREACH(QString aptCode, m_recentAirports) { FGAirportRef apt = FGAirport::findByIdent(aptCode.toStdString()); @@ -1218,6 +1267,7 @@ void QtLauncher::onPopupAirportHistory() m_ui->airportEdit->clear(); m_ui->locationStack->setCurrentIndex(0); } +#endif } QModelIndex QtLauncher::proxyIndexForAircraftURI(QUrl uri) const @@ -1261,14 +1311,15 @@ void QtLauncher::onPopupAircraftHistory() } } -void QtLauncher::setAirport(FGAirportRef ref) +void QtLauncher::setBaseLocation(FGPositionedRef ref) { - if (m_selectedAirport == ref) + if (m_location == ref) return; - m_selectedAirport = ref; - onAirportChanged(); + m_location = ref; + onLocationChanged(); +#if 0 if (ref.valid()) { // maintain the recent airport list QString icao = QString::fromStdString(ref->ident()); @@ -1284,8 +1335,9 @@ void QtLauncher::setAirport(FGAirportRef ref) } } } +#endif - updateAirportDescription(); + updateLocationDescription(); } void QtLauncher::onEditRatingsFilter() diff --git a/src/GUI/QtLauncher_private.hxx b/src/GUI/QtLauncher_private.hxx index 17f7a1c4c..7eb6b3854 100644 --- a/src/GUI/QtLauncher_private.hxx +++ b/src/GUI/QtLauncher_private.hxx @@ -66,7 +66,7 @@ private slots: void onSearchAirports(); - void onAirportChanged(); + void onLocationChanged(); void onAirportChoiceSelected(const QModelIndex& index); void onAircraftSelected(const QModelIndex& index); @@ -78,7 +78,7 @@ private slots: void onEditRatingsFilter(); - void updateAirportDescription(); + void updateLocationDescription(); void updateSettingsSummary(); void onAirportSearchComplete(); @@ -99,7 +99,8 @@ private slots: void onAircraftInstalledCompleted(QModelIndex index); void onAircraftInstallFailed(QModelIndex index, QString errorMessage); private: - void setAirport(FGAirportRef ref); + void setLocationOptions(); + void setBaseLocation(FGPositionedRef ref); /** * Check if the passed index is the selected aircraft, and if so, refresh @@ -122,11 +123,11 @@ private: AirportSearchModel* m_airportsModel; AircraftProxyModel* m_aircraftProxy; AircraftItemModel* m_aircraftModel; - FGAirportRef m_selectedAirport; + FGPositionedRef m_location; QUrl m_selectedAircraft; QList m_recentAircraft; - QStringList m_recentAirports; + QVector m_recentAirports; QTimer* m_subsystemIdleTimer; bool m_inAppMode; diff --git a/src/Main/positioninit.cxx b/src/Main/positioninit.cxx index 6acbe2159..59000c10b 100644 --- a/src/Main/positioninit.cxx +++ b/src/Main/positioninit.cxx @@ -430,10 +430,16 @@ static bool fgSetPosFromCarrier( const string& carrier, const string& posid ) { } // Set current_options lon/lat given an airport id and heading (degrees) -static bool fgSetPosFromFix( const string& id ) +static bool fgSetPosFromFix( const string& id, PositionedID guid ) { - FGPositioned::TypeFilter fixFilter(FGPositioned::FIX); - FGPositioned* fix = FGPositioned::findFirstWithIdent(id, &fixFilter); + FGPositioned* fix = NULL; + if (guid != 0) { + fix = FGPositioned::loadById(guid); + } else { + FGPositioned::TypeFilter fixFilter(FGPositioned::FIX); + fix = FGPositioned::findFirstWithIdent(id, &fixFilter); + } + if (!fix) { SG_LOG( SG_GENERAL, SG_ALERT, "Failed to locate fix = " << id ); return false; @@ -491,6 +497,10 @@ bool initPosition() string carrier = fgGetString("/sim/presets/carrier"); string parkpos = fgGetString("/sim/presets/parkpos"); string fix = fgGetString("/sim/presets/fix"); + + // the launcher sets this to precisely identify a navaid + PositionedID navaidId = fgGetInt("/sim/presets/navaid-id"); + SGPropertyNode *hdg_preset = fgGetNode("/sim/presets/heading-deg", true); double hdg = hdg_preset->getDoubleValue(); @@ -569,7 +579,7 @@ bool initPosition() if ( !set_pos && !fix.empty() ) { // a Fix is requested - if ( fgSetPosFromFix( fix ) ) { + if ( fgSetPosFromFix( fix, navaidId ) ) { set_pos = true; } } diff --git a/src/Navaids/NavDataCache.cxx b/src/Navaids/NavDataCache.cxx index e18c382bc..4942b902d 100644 --- a/src/Navaids/NavDataCache.cxx +++ b/src/Navaids/NavDataCache.cxx @@ -2325,7 +2325,7 @@ NavDataCache::ThreadedGUISearch::ThreadedGUISearch(const std::string& term) : sqlite3_open_v2(pathUtf8.c_str(), &d->db, openFlags, NULL); std::string sql = "SELECT rowid FROM positioned WHERE name LIKE '%" + term - + "%' AND type >= 1 AND type <= 3"; + + "%' AND ((type >= 1 AND type <= 3) OR ((type >= 9 AND type <= 11))) "; sqlite3_prepare_v2(d->db, sql.c_str(), sql.length(), &d->query, NULL); d->start(); diff --git a/src/Navaids/positioned.hxx b/src/Navaids/positioned.hxx index 012edb0b1..59b23b1dd 100644 --- a/src/Navaids/positioned.hxx +++ b/src/Navaids/positioned.hxx @@ -1,4 +1,4 @@ -// positioned.hxx - base class for objects which are positioned +// positioned.hxx - base class for objects which are positioned // // Copyright (C) 2008 James Turner // -- 2.39.5