diff --git a/src/common/htmlinfobuilder.cpp b/src/common/htmlinfobuilder.cpp index b9f5665a..eea94655 100644 --- a/src/common/htmlinfobuilder.cpp +++ b/src/common/htmlinfobuilder.cpp @@ -552,15 +552,17 @@ void HtmlInfoBuilder::nearestText(const MapAirport& airport, HtmlBuilder& html) airportTitle(airport, html, -1, true /* procedures */); // Get nearest airports that have procedures ==================================== - const MapResultIndex *nearestAirports = + const MapResultIndex *nearestAirportsNav = airportQueryNav->getNearestProcAirports(airport.position, airport.ident, NEAREST_MAX_DISTANCE_AIRPORT_NM); - if(!nearestMapObjectsText(airport, html, nearestAirports, tr("Nearest Airports with Procedures"), false, true, NEAREST_MAX_NUM_AIRPORT)) + + if(!nearestMapObjectsText(airport, html, nearestAirportsNav, tr("Nearest Airports with Procedures"), false, true, + NEAREST_MAX_NUM_AIRPORT)) html.p().b(tr("No airports with procedures within a radius of %1.").arg(Unit::distNm(NEAREST_MAX_DISTANCE_AIRPORT_NM * 4.f))).pEnd(); // Get nearest VOR and NDB ==================================== MapResultIndex *nearestNavaids = mapWidget->getMapQuery()->getNearestNavaids(airport.position, NEAREST_MAX_DISTANCE_NAVAID_NM, - map::VOR | map::NDB | map::ILS, 3 /* max ILS */, 4.f /* max ILS dist NM */); + map::VOR | map::NDB | map::ILS, 3 /* maxIls */, 4.f /* maxIlsDistNm */); if(!nearestMapObjectsText(airport, html, nearestNavaids, tr("Nearest Radio Navaids"), true, false, NEAREST_MAX_NUM_NAVAID)) html.p().b(tr("No navaids within a radius of %1.").arg(Unit::distNm(NEAREST_MAX_DISTANCE_NAVAID_NM * 4.f))).pEnd(); @@ -608,11 +610,10 @@ void HtmlInfoBuilder::nearestMapObjectsTextRow(const MapAirport& airport, HtmlBu trEnd(); } -bool HtmlInfoBuilder::nearestMapObjectsText(const MapAirport& airport, HtmlBuilder& html, - const map::MapResultIndex *nearest, const QString& header, - bool frequencyCol, bool airportCol, int maxRows) const +bool HtmlInfoBuilder::nearestMapObjectsText(const MapAirport& airport, HtmlBuilder& html, const map::MapResultIndex *nearestNav, + const QString& header, bool frequencyCol, bool airportCol, int maxRows) const { - if(nearest != nullptr && !nearest->isEmpty()) + if(nearestNav != nullptr && !nearestNav->isEmpty()) { html.br().br().text(header, ahtml::BOLD | ahtml::BIG); html.table(); @@ -636,46 +637,44 @@ bool HtmlInfoBuilder::nearestMapObjectsText(const MapAirport& airport, HtmlBuild // Go through mixed list of map objects ============================================ int row = 1; - for(const map::MapBase *base : *nearest) + for(const map::MapBase *baseNav : *nearestNav) { if(row++ > maxRows) // Stop at max break; // Airport ====================================== - const map::MapAirport *ap = base->asPtr(); - if(ap != nullptr) + const map::MapAirport *apNav = baseNav->asPtr(); + if(apNav != nullptr) { + // Airport comes from navdatabase having procedures - convert to simulator airport to get sim name // Convert navdatabase airport to simulator - map::MapAirport simAp = mapWidget->getMapQuery()->getAirportSim(*ap); + map::MapAirport apSim = mapWidget->getMapQuery()->getAirportSim(*apNav); // Omit center airport used as reference - if(simAp.isValid() && simAp.id != airport.id) - nearestMapObjectsTextRow(airport, html, QString(), simAp.displayIdent(), simAp.name, - QString(), &simAp, simAp.magvar, frequencyCol, airportCol); + if(apSim.isValid() && apSim.id != airport.id) + nearestMapObjectsTextRow(airport, html, QString(), apSim.displayIdent(), apSim.name, QString(), &apSim, apSim.magvar, + frequencyCol, airportCol); } - const map::MapVor *vor = base->asPtr(); + const map::MapVor *vor = baseNav->asPtr(); if(vor != nullptr) - nearestMapObjectsTextRow(airport, html, map::vorType(*vor), vor->ident, vor->name, - locale.toString(vor->frequency / 1000., 'f', - 2), vor, vor->magvar, frequencyCol, airportCol); + nearestMapObjectsTextRow(airport, html, map::vorType(*vor), vor->ident, vor->name, locale.toString(vor->frequency / 1000., 'f', 2), + vor, vor->magvar, frequencyCol, airportCol); - const map::MapNdb *ndb = base->asPtr(); + const map::MapNdb *ndb = baseNav->asPtr(); if(ndb != nullptr) - nearestMapObjectsTextRow(airport, html, tr("NDB"), ndb->ident, ndb->name, - locale.toString(ndb->frequency / 100., 'f', - 1), ndb, ndb->magvar, frequencyCol, airportCol); + nearestMapObjectsTextRow(airport, html, tr("NDB"), ndb->ident, ndb->name, locale.toString(ndb->frequency / 100., 'f', 1), + ndb, ndb->magvar, frequencyCol, airportCol); - const map::MapWaypoint *waypoint = base->asPtr(); + const map::MapWaypoint *waypoint = baseNav->asPtr(); if(waypoint != nullptr) - nearestMapObjectsTextRow(airport, html, tr("Waypoint"), waypoint->ident, QString(), - QString(), waypoint, waypoint->magvar, frequencyCol, airportCol); + nearestMapObjectsTextRow(airport, html, tr("Waypoint"), waypoint->ident, QString(), QString(), waypoint, waypoint->magvar, + frequencyCol, airportCol); - const map::MapIls *ils = base->asPtr(); + const map::MapIls *ils = baseNav->asPtr(); if(ils != nullptr && !ils->isAnyGlsRnp()) - nearestMapObjectsTextRow(airport, html, map::ilsType(*ils, true /* gs */, true /* dme */, tr(", ")), - ils->ident, ils->name, + nearestMapObjectsTextRow(airport, html, map::ilsType(*ils, true /* gs */, true /* dme */, tr(", ")), ils->ident, ils->name, ils->freqMHzLocale(), ils, ils->magvar, frequencyCol, airportCol); } html.tableEnd(); diff --git a/src/common/htmlinfobuilder.h b/src/common/htmlinfobuilder.h index 81d5236f..8b7a2bcd 100644 --- a/src/common/htmlinfobuilder.h +++ b/src/common/htmlinfobuilder.h @@ -326,7 +326,7 @@ class HtmlInfoBuilder void head(atools::util::HtmlBuilder& html, const QString& text) const; bool nearestMapObjectsText(const map::MapAirport& airport, atools::util::HtmlBuilder& html, - const map::MapResultIndex *nearest, const QString& header, bool frequencyCol, + const map::MapResultIndex *nearestNav, const QString& header, bool frequencyCol, bool airportCol, int maxRows) const; void nearestMapObjectsTextRow(const map::MapAirport& airport, atools::util::HtmlBuilder& html, const QString& type, diff --git a/src/common/maptypesfactory.cpp b/src/common/maptypesfactory.cpp index 044a0f70..80423264 100644 --- a/src/common/maptypesfactory.cpp +++ b/src/common/maptypesfactory.cpp @@ -23,24 +23,11 @@ #include "io/binaryutil.h" #include "sql/sqlrecord.h" #include "fs/util/fsutil.h" -#include "app/navapp.h" - -#include using namespace atools::geo; using atools::sql::SqlRecord; using namespace map; -MapTypesFactory::MapTypesFactory() -{ - -} - -MapTypesFactory::~MapTypesFactory() -{ - -} - void MapTypesFactory::fillAirport(const SqlRecord& record, map::MapAirport& airport, bool complete, bool nav, bool xplane) { fillAirportBase(record, airport, complete); @@ -187,6 +174,8 @@ map::MapAirportFlags MapTypesFactory::fillAirportFlags(const SqlRecord& record, if(!overview) { + // The procedure flag is not accurate for mixed mode databases and is updated later on by + // AirportQuery::hasAirportProcedures() flags |= airportFlag(record, "num_approach", AP_PROCEDURE); flags |= airportFlag(record, "num_runway_light", AP_LIGHT); flags |= airportFlag(record, "num_runway_end_ils", AP_ILS); diff --git a/src/common/maptypesfactory.h b/src/common/maptypesfactory.h index f1ac1736..a5214e06 100644 --- a/src/common/maptypesfactory.h +++ b/src/common/maptypesfactory.h @@ -1,5 +1,5 @@ /***************************************************************************** -* Copyright 2015-2020 Alexander Barthel alex@littlenavmap.org +* Copyright 2015-2023 Alexander Barthel alex@littlenavmap.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -54,9 +54,6 @@ struct MapAirportMsa; class MapTypesFactory { public: - MapTypesFactory(); - ~MapTypesFactory(); - /* * Populate airport object. * @param complete if false only id and position are present in the record. Used for creating the object @@ -102,13 +99,9 @@ class MapTypesFactory private: void fillVorBase(const atools::sql::SqlRecord& record, map::MapVor& vor); - void fillAirportBase(const atools::sql::SqlRecord& record, map::MapAirport& ap, bool complete); - - map::MapAirportFlags airportFlag(const atools::sql::SqlRecord& record, const QString& field, - map::MapAirportFlags airportFlag); + map::MapAirportFlags airportFlag(const atools::sql::SqlRecord& record, const QString& field, map::MapAirportFlags airportFlag); map::MapAirportFlags fillAirportFlags(const atools::sql::SqlRecord& record, bool overview); - map::MapType strToType(const QString& navType); }; diff --git a/src/query/airportquery.cpp b/src/query/airportquery.cpp index 6734598b..a92b4af8 100644 --- a/src/query/airportquery.cpp +++ b/src/query/airportquery.cpp @@ -101,6 +101,41 @@ AirportQuery::~AirportQuery() delete mapTypesFactory; } +void AirportQuery::loadAirportProcedureCache() +{ + // Load all airport idents having procedures from navdatabase + airportsWithProceduresIdent.clear(); + airportsWithProceduresIata.clear(); + + if(navdata && NavApp::isNavdataMixed()) + { + SqlQuery query(db); + query.exec("select ident, iata from airport where num_approach > 0"); + while(query.next()) + { + airportsWithProceduresIdent.insert(query.valueStr(0)); + airportsWithProceduresIata.insert(query.valueStr(1)); + } + } +} + +void AirportQuery::correctAirportProcedureFlag(MapAirport& airport) +{ + if(!airportsWithProceduresIdent.isEmpty()) + airport.flags.setFlag(map::AP_PROCEDURE, hasAirportProcedures(airport.ident, airport.iata)); +} + +bool AirportQuery::hasAirportProcedures(const QString& ident, const QString& iata) +{ + if(!ident.isEmpty() && airportsWithProceduresIdent.contains(ident)) + return true; + + if(!iata.isEmpty() && airportsWithProceduresIata.contains(iata)) + return true; + + return false; +} + void AirportQuery::getAirportAdminNamesById(int airportId, QString& city, QString& state, QString& country) { if(!query::valid(Q_FUNC_INFO, airportAdminByIdQuery)) @@ -144,6 +179,9 @@ void AirportQuery::getAirportById(map::MapAirport& airport, int airportId) mapTypesFactory->fillAirport(airportByIdQuery->record(), *ap, true /* complete */, navdata, NavApp::isAirportDatabaseXPlane(navdata)); airportByIdQuery->finish(); + if(!navdata) + NavApp::getAirportQueryNav()->correctAirportProcedureFlag(ap); + airport = *ap; airportIdCache.insert(airportId, ap); } @@ -177,6 +215,8 @@ void AirportQuery::getAirportByIdent(map::MapAirport& airport, const QString& id mapTypesFactory->fillAirport(airportByIdentQuery->record(), *ap, true /* complete */, navdata, NavApp::isAirportDatabaseXPlane(navdata)); airportByIdentQuery->finish(); + if(!navdata) + NavApp::getAirportQueryNav()->correctAirportProcedureFlag(ap); airport = *ap; airportIdentCache.insert(ident, ap); @@ -202,10 +242,12 @@ void AirportQuery::getAirportsByTruncatedIdent(QList& airports, airportsByTruncatedIdentQuery->exec(); while(airportsByTruncatedIdentQuery->next()) { - map::MapAirport ap; - mapTypesFactory->fillAirport(airportsByTruncatedIdentQuery->record(), ap, true /* complete */, navdata, + map::MapAirport airport; + mapTypesFactory->fillAirport(airportsByTruncatedIdentQuery->record(), airport, true /* complete */, navdata, NavApp::isAirportDatabaseXPlane(navdata)); - airports.append(ap); + if(!navdata) + NavApp::getAirportQueryNav()->correctAirportProcedureFlag(airport); + airports.append(airport); } } @@ -264,6 +306,8 @@ void AirportQuery::getAirportsByOfficialIdent(QList& airports, map::MapAirport airport; mapTypesFactory->fillAirport(airportByOfficialQuery->record(), airport, true /* complete */, navdata, NavApp::isAirportDatabaseXPlane(navdata)); + if(!navdata) + NavApp::getAirportQueryNav()->correctAirportProcedureFlag(airport); airports.append(airport); } } @@ -331,9 +375,11 @@ void AirportQuery::getAirportFuzzy(map::MapAirport& airport, const map::MapAirpo ageo::Rect rect(airportCopy.position, ageo::nmToMeter(10.f), true /* fast */); query::fetchObjectsForRect(rect, airportByPosQuery, [ =, &airports](atools::sql::SqlQuery *query) -> void { - map::MapAirport obj; - mapTypesFactory->fillAirport(query->record(), obj, true /* complete */, navdata, NavApp::isAirportDatabaseXPlane(navdata)); - airports.append(obj); + map::MapAirport a; + mapTypesFactory->fillAirport(query->record(), a, true /* complete */, navdata, NavApp::isAirportDatabaseXPlane(navdata)); + if(!navdata) + NavApp::getAirportQueryNav()->correctAirportProcedureFlag(ap); + airports.append(a); }); } @@ -948,6 +994,8 @@ void AirportQuery::getRunwaysAndAirports(map::MapResultIndex& runwayAirports, co { map::MapAirport airport; mapTypesFactory->fillAirport(query.record(), airport, false /* complete */, navdata, xp); + if(!navdata) + NavApp::getAirportQueryNav()->correctAirportProcedureFlag(airport); runwayAirports.add(map::MapResult::createFromMapBase(&airport)); } } @@ -1363,6 +1411,8 @@ void AirportQuery::initQueries() "join runway_end p on r.primary_end_id = p.runway_end_id " "join runway_end s on r.secondary_end_id = s.runway_end_id " "where r.airport_id = :airportId"); + + loadAirportProcedureCache(); } void AirportQuery::deInitQueries() @@ -1376,6 +1426,9 @@ void AirportQuery::deInitQueries() airportIdentCache.clear(); airportIdCache.clear(); airportFuzzyIdCache.clear(); + airportsWithProceduresIdent.clear(); + airportsWithProceduresIata.clear(); + nearestAirportCache.clear(); delete runwayOverviewQuery; runwayOverviewQuery = nullptr; diff --git a/src/query/airportquery.h b/src/query/airportquery.h index 56553dcd..3bcb49cf 100644 --- a/src/query/airportquery.h +++ b/src/query/airportquery.h @@ -19,7 +19,9 @@ #define LITTLENAVMAP_AIRPORTQUERY_H #include "common/mapflags.h" + #include +#include namespace Marble { class GeoDataLatLonBox; @@ -123,6 +125,15 @@ class AirportQuery /* Used as callback for loading METAR data to fetch airport coordinates for nearest. Looks for either ident or icao. */ atools::geo::Pos getAirportPosByIdentOrIcao(const QString& identOrIcao); + /* Checks ident or IATA from hash if the airport has procedures and applies the flag. + * Fast but not 100 percent accurate for airports with not matching idents since no fuzzy search is done. */ + void correctAirportProcedureFlag(map::MapAirport& airport); + + void correctAirportProcedureFlag(map::MapAirport *airport) + { + correctAirportProcedureFlag(*airport); + } + /* true if airport has procedures. Airport must be available in this database (sim or nav). */ bool hasProcedures(const map::MapAirport& airport) const; @@ -226,6 +237,13 @@ class AirportQuery void getRunwaysAndAirports(map::MapResultIndex& runwayAirports, const atools::geo::Rect& rect, const atools::geo::Pos& pos, bool noRunway); + /* Load all airport idents of airports with procedures if this is a navdata query object */ + void loadAirportProcedureCache(); + + /* Checks ident or IATA from hash if the airport has procedures. + * Fast but not 100 percent accurate for airports with not matching idents since no fuzzy search is done. */ + bool hasAirportProcedures(const QString& ident, const QString& iata); + /* true if third party navdata */ bool navdata; @@ -243,6 +261,7 @@ class AirportQuery QCache airportIdentCache; QCache airportIdCache, airportFuzzyIdCache; QCache nearestAirportCache; + QSet airportsWithProceduresIdent, airportsWithProceduresIata; /* Available ident columns in airport table. Set to true if column exists and has not null values. */ bool icaoCol = false, faaCol = false, iataCol = false, localCol = false; diff --git a/src/query/mapquery.cpp b/src/query/mapquery.cpp index efedb573..86ebd9d7 100644 --- a/src/query/mapquery.cpp +++ b/src/query/mapquery.cpp @@ -261,11 +261,11 @@ void MapQuery::resolveWaypointNavaids(const QList& allWaypoints, QH } } -map::MapResultIndex *MapQuery::getNearestNavaids(const Pos& pos, float distanceNm, map::MapTypes type, int maxIls, float maxIlsDist) +map::MapResultIndex *MapQuery::getNearestNavaids(const Pos& pos, float distanceNm, map::MapTypes type, int maxIls, float maxIlsDistNm) { - map::MapResultIndex *nearest = nearestNavaidsInternal(pos, distanceNm, type, maxIls, maxIlsDist); + map::MapResultIndex *nearest = nearestNavaidsInternal(pos, distanceNm, type, maxIls, maxIlsDistNm); if(nearest == nullptr || nearest->size() < 5) - nearest = nearestNavaidsInternal(pos, distanceNm * 4.f, type, maxIls, maxIlsDist); + nearest = nearestNavaidsInternal(pos, distanceNm * 4.f, type, maxIls, maxIlsDistNm); return nearest; } @@ -1230,6 +1230,8 @@ const QList *MapQuery::fetchAirports(const Marble::GeoDataLatLo if(!query::valid(Q_FUNC_INFO, query)) return nullptr; + AirportQuery *airportQueryNav = NavApp::getAirportQueryNav(); + if(airportCache.list.isEmpty() && !lazy) { bool navdata = NavApp::isNavdataAll(); @@ -1246,15 +1248,18 @@ const QList *MapQuery::fetchAirports(const Marble::GeoDataLatLo query->exec(); while(query->next()) { - MapAirport ap; + MapAirport airport; if(overview) // Fill only a part of the object - mapTypesFactory->fillAirportForOverview(query->record(), ap, navdata, NavApp::isAirportDatabaseXPlane(navdata)); + mapTypesFactory->fillAirportForOverview(query->record(), airport, navdata, NavApp::isAirportDatabaseXPlane(navdata)); else - mapTypesFactory->fillAirport(query->record(), ap, true /* complete */, navdata, NavApp::isAirportDatabaseXPlane(navdata)); + mapTypesFactory->fillAirport(query->record(), airport, true /* complete */, navdata, NavApp::isAirportDatabaseXPlane(navdata)); + + // Need to update airport procedure flag for mixed mode databases to enable procedure filter on map + airportQueryNav->correctAirportProcedureFlag(airport); - ids.insert(ap.id); - airportCache.list.append(ap); + ids.insert(airport.id); + airportCache.list.append(airport); } } @@ -1265,16 +1270,20 @@ const QList *MapQuery::fetchAirports(const Marble::GeoDataLatLo airportAddonByRectQuery->exec(); while(airportAddonByRectQuery->next()) { - MapAirport ap; + MapAirport airport; if(overview) // Fill only a part of the object - mapTypesFactory->fillAirportForOverview(airportAddonByRectQuery->record(), ap, navdata, + mapTypesFactory->fillAirportForOverview(airportAddonByRectQuery->record(), airport, navdata, NavApp::isAirportDatabaseXPlane(navdata)); else - mapTypesFactory->fillAirport(airportAddonByRectQuery->record(), ap, true /* complete */, navdata, + mapTypesFactory->fillAirport(airportAddonByRectQuery->record(), airport, true /* complete */, navdata, NavApp::isAirportDatabaseXPlane(navdata)); - if(!ids.contains(ap.id)) - airportCache.list.append(ap); + + // Need to update airport procedure flag for mixed mode databases to enable procedure filter on map + airportQueryNav->correctAirportProcedureFlag(airport); + + if(!ids.contains(airport.id)) + airportCache.list.append(airport); } } } diff --git a/src/query/mapquery.h b/src/query/mapquery.h index f6b50fa4..ae788011 100644 --- a/src/query/mapquery.h +++ b/src/query/mapquery.h @@ -175,7 +175,7 @@ class MapQuery * All sorted by distance to pos with a maximum distance distanceNm * Uses distance * 4 and searches again if nothing was found.*/ map::MapResultIndex *getNearestNavaids(const atools::geo::Pos& pos, float distanceNm, - map::MapTypes type, int maxIls, float maxIlsDist); + map::MapTypes type, int maxIls, float maxIlsDistNm); /* * Fetch airports for a map coordinate rectangle. @@ -245,7 +245,8 @@ class MapQuery /* Create and prepare all queries */ void deInitQueries(); - /* Check in navdatabase (Navigraph or other) if airport has procedures */ + /* Check in navdatabase (Navigraph or other) if airport has procedures. + * Slow but does a fuzzy search to find airport in navdata */ bool hasProcedures(const map::MapAirport& airport) const; bool hasArrivalProcedures(const map::MapAirport& airport) const; bool hasDepartureProcedures(const map::MapAirport& airport) const; diff --git a/src/search/airportsearch.cpp b/src/search/airportsearch.cpp index ab670871..de62dd7e 100644 --- a/src/search/airportsearch.cpp +++ b/src/search/airportsearch.cpp @@ -618,6 +618,7 @@ void AirportSearch::getSelectedMapObjects(map::MapResult& result) const rec.appendField("rating", QVariant::Int); MapTypesFactory factory; + AirportQuery *airportQueryNav = NavApp::getAirportQueryNav(); // Fill the result with incomplete airport objects (only id and lat/lon) const QItemSelection& selection = controller->getSelection(); @@ -626,7 +627,7 @@ void AirportSearch::getSelectedMapObjects(map::MapResult& result) const { for(int row = rng.top(); row <= rng.bottom(); ++row) { - map::MapAirport ap; + map::MapAirport airport; QVariant idVar = controller->getRawData(row, idColumnName); if(idVar.isValid()) { @@ -639,8 +640,10 @@ void AirportSearch::getSelectedMapObjects(map::MapResult& result) const qDebug() << Q_FUNC_INFO << "range" << range << "row" << row << rec; #endif // Not fully populated - factory.fillAirport(rec, ap, false /* complete */, false /* nav */, NavApp::isAirportDatabaseXPlane(false /* navdata */)); - result.airports.append(ap); + factory.fillAirport(rec, airport, false /* complete */, false /* nav */, NavApp::isAirportDatabaseXPlane(false /* navdata */)); + airportQueryNav->correctAirportProcedureFlag(airport); + + result.airports.append(airport); } else qWarning() << Q_FUNC_INFO << "Invalid selection: range" << range << "row" << row << "col" << idColumnName << idVar; diff --git a/src/search/proceduresearch.cpp b/src/search/proceduresearch.cpp index 2555b5fd..3c25e9f0 100644 --- a/src/search/proceduresearch.cpp +++ b/src/search/proceduresearch.cpp @@ -368,7 +368,7 @@ void ProcedureSearch::updateHeaderLabel() { QString procs; - QList items = treeWidget->selectedItems(); + const QList items = treeWidget->selectedItems(); for(QTreeWidgetItem *item : items) procs.append(procedureAndTransitionText(item)); @@ -500,7 +500,7 @@ void ProcedureSearch::updateFilterBoxes() QList runwaylist = runways.values(); std::sort(runwaylist.begin(), runwaylist.end()); - for(const QString& rw : runwaylist) + for(const QString& rw : qAsConst(runwaylist)) { if(rw.isEmpty()) ui->comboBoxProcedureRunwayFilter->addItem(tr("No Runway"), rw); @@ -802,7 +802,7 @@ void ProcedureSearch::itemSelectionChangedInternal(bool noFollow) #endif Ui::MainWindow *ui = NavApp::getMainUi(); - QList selectedItems = treeWidget->selectedItems(); + const QList selectedItems = treeWidget->selectedItems(); if(selectedItems.isEmpty() || NavApp::getSearchController()->getCurrentSearchTabId() != tabIndex) { emit procedureSelected(proc::MapProcedureRef());