]> git.mxchange.org Git - flightgear.git/commitdiff
Cap number of airports displayed in diagrams
authorJames Turner <zakalawe@mac.com>
Tue, 17 Nov 2015 07:36:54 +0000 (07:36 +0000)
committerJames Turner <zakalawe@mac.com>
Mon, 23 Nov 2015 00:48:21 +0000 (00:48 +0000)
- restrict heliports / seaports by aircraft type
- prioritise by runway length
- clean up airport label names

src/GUI/AircraftModel.cxx
src/GUI/AircraftModel.hxx
src/GUI/BaseDiagram.cxx
src/GUI/BaseDiagram.hxx
src/GUI/LocationWidget.cxx
src/GUI/LocationWidget.hxx
src/GUI/QtLauncher.cxx
src/GUI/QtLauncher_fwd.hxx [new file with mode: 0644]

index bc0bdadca82f4413e3b6f49020c0ad2efd8d9915..9febfc703572505ddf1697ecc6876e505ae20f8b 100644 (file)
@@ -47,14 +47,18 @@ const int STANDARD_THUMBNAIL_WIDTH = 172;
 using namespace simgear::pkg;
 
 AircraftItem::AircraftItem() :
-    excluded(false)
+    excluded(false),
+    usesHeliports(false),
+    usesSeaports(false)
 {
     // oh for C++11 initialisers
     for (int i=0; i<4; ++i) ratings[i] = 0;
 }
 
 AircraftItem::AircraftItem(QDir dir, QString filePath) :
-    excluded(false)
+    excluded(false),
+    usesHeliports(false),
+    usesSeaports(false)
 {
     for (int i=0; i<4; ++i) ratings[i] = 0;
 
@@ -89,6 +93,21 @@ AircraftItem::AircraftItem(QDir dir, QString filePath) :
     if (sim->hasChild("variant-of")) {
         variantOf = sim->getStringValue("variant-of");
     }
+
+    if (sim->hasChild("tags")) {
+        SGPropertyNode_ptr tagsNode = sim->getChild("tags");
+        int nChildren = tagsNode->nChildren();
+        for (int i = 0; i < nChildren; i++) {
+            const SGPropertyNode* c = tagsNode->getChild(i);
+            if (strcmp(c->getName(), "tag") == 0) {
+                const char* tagName = c->getStringValue();
+                usesHeliports |= (strcmp(tagName, "helicopter") == 0);
+                // could also consider vtol tag?
+                usesSeaports |= (strcmp(tagName, "seaplane") == 0);
+                usesSeaports |= (strcmp(tagName, "floats") == 0);
+            }
+        } // of tags iteration
+    } // of set-xml has tags
 }
 
 QString AircraftItem::baseName() const
@@ -574,6 +593,10 @@ QVariant AircraftItemModel::dataFromItem(AircraftItemPtr item, quint32 variantIn
             "I'm just a poor boy, I need no sympathy because I'm easy come, easy go."
             "Litte high, little low. Anywhere the wind blows.";
 #endif
+    } else if (role == AircraftIsHelicopterRole) {
+        return item->usesHeliports;
+    } else if (role == AircraftIsSeaplaneRole) {
+        return item->usesSeaports;
     }
 
     return QVariant();
index c6a85e83631fe73688c83da9783fc20bcd2d3166..b49527ed80bea3c630ec4eec3339ce6ab9ef4694 100644 (file)
@@ -46,6 +46,8 @@ const int AircraftPackageSizeRole = Qt::UserRole + 12;
 const int AircraftInstallDownloadedSizeRole = Qt::UserRole + 13;
 const int AircraftURIRole = Qt::UserRole + 14;
 const int AircraftThumbnailSizeRole = Qt::UserRole + 15;
+const int AircraftIsHelicopterRole = Qt::UserRole + 16;
+const int AircraftIsSeaplaneRole = Qt::UserRole + 17;
 
 const int AircraftRatingRole = Qt::UserRole + 100;
 const int AircraftVariantDescriptionRole = Qt::UserRole + 200;
@@ -79,8 +81,9 @@ struct AircraftItem
     int ratings[4];
     QString variantOf;
     QDateTime pathModTime;
-
     QList<AircraftItemPtr> variants;
+    bool usesHeliports;
+    bool usesSeaports;
 private:
     mutable QPixmap m_thumbnail;
 };
index 0db4a88c1f63918be42b5f3dfe12ef57a76ac202..e268e4cd4ff4ca8157900b07b0c92ca64b355e08 100644 (file)
@@ -31,6 +31,8 @@
 #include <Navaids/positioned.hxx>
 #include <Airports/airport.hxx>
 
+#include "QtLauncher_fwd.hxx"
+
 /* equatorial and polar earth radius */
 const float rec  = 6378137;          // earth radius, equator (?)
 const float rpol = 6356752.314f;      // earth radius, polar   (?)
@@ -133,30 +135,61 @@ void BaseDiagram::paintAirplaneIcon(QPainter* painter, const SGGeod& geod, int h
 class MapFilter : public FGPositioned::TypeFilter
 {
 public:
-    MapFilter()
+
+    MapFilter(LauncherAircraftType aircraft)
     {
       //  addType(FGPositioned::FIX);
-        addType(FGPositioned::AIRPORT);
-        addType(FGPositioned::HELIPORT);
-        addType(FGPositioned::SEAPORT);
         addType(FGPositioned::NDB);
         addType(FGPositioned::VOR);
+
+        if (aircraft == Helicopter) {
+            addType(FGPositioned::HELIPAD);
+        }
+
+        if (aircraft == Seaplane) {
+            addType(FGPositioned::SEAPORT);
+        } else {
+            addType(FGPositioned::AIRPORT);
+        }
     }
 
     virtual bool pass(FGPositioned* aPos) const
     {
         bool ok = TypeFilter::pass(aPos);
+        // fix-filtering code disabled since fixed are entirely disabled
+#if 0
         if (ok && (aPos->type() == FGPositioned::FIX)) {
             // ignore fixes which end in digits
             if (aPos->ident().length() > 4 && isdigit(aPos->ident()[3]) && isdigit(aPos->ident()[4])) {
                 return false;
             }
         }
-
+#endif
         return ok;
     }
 };
 
+void BaseDiagram::splitItems(const FGPositionedList& in, FGPositionedList& navaids,
+                             FGPositionedList& ports)
+{
+    FGPositionedList::const_iterator it = in.begin();
+    for (; it != in.end(); ++it) {
+        if (FGAirport::isAirportType(it->ptr())) {
+            ports.push_back(*it);
+        } else {
+            navaids.push_back(*it);
+        }
+    }
+}
+
+bool orderAirportsByRunwayLength(const FGPositionedRef& a,
+                                 const FGPositionedRef& b)
+{
+    FGAirport* aptA = static_cast<FGAirport*>(a.ptr());
+    FGAirport* aptB = static_cast<FGAirport*>(b.ptr());
+
+    return aptA->longestRunway()->lengthFt() > aptB->longestRunway()->lengthFt();
+}
 
 void BaseDiagram::paintNavaids(QPainter* painter)
 {
@@ -169,85 +202,104 @@ void BaseDiagram::paintNavaids(QPainter* painter)
     SGGeod viewCenter = unproject(invT.map(rect().center()), m_projectionCenter);
     SGGeod bottomRight = unproject(invT.map(rect().bottomRight()), m_projectionCenter);
 
-    double minRunwayLengthFt = (16 / m_scale) * SG_METER_TO_FEET;
-
     double drawRangeNm = std::max(SGGeodesy::distanceNm(viewCenter, topLeft),
                                   SGGeodesy::distanceNm(viewCenter, bottomRight));
 
-    MapFilter f;
+    MapFilter f(m_aircraftType);
     FGPositionedList items = FGPositioned::findWithinRange(viewCenter, drawRangeNm, &f);
 
+    FGPositionedList navaids, ports;
+    splitItems(items, navaids, ports);
+
+    if (ports.size() >= 40) {
+        FGPositionedList::iterator middle = ports.begin() + 40;
+        std::partial_sort(ports.begin(), middle, ports.end(),
+                          orderAirportsByRunwayLength);
+        ports.resize(40);
+    }
+
     m_labelRects.clear();
     m_labelRects.reserve(items.size());
 
     FGPositionedList::const_iterator it;
-    for (it = items.begin(); it != items.end(); ++it) {
-        FGPositionedRef pos(*it);
-        bool drawAsIcon = true;
-        if (isNavaidIgnored(pos))
-            continue;
-
-        FGPositioned::Type ty(pos->type());
-        if (ty == FGPositioned::AIRPORT) {
-            FGAirport* apt = static_cast<FGAirport*>(pos.ptr());
-            if (apt->hasHardRunwayOfLengthFt(minRunwayLengthFt)) {
-
-                drawAsIcon = false;
-                painter->setTransform(xf);
-                QVector<QLineF> lines = projectAirportRuwaysWithCenter(apt, m_projectionCenter);
-
-                QPen pen(QColor(0x03, 0x83, 0xbf), 8);
-                pen.setCosmetic(true);
-                painter->setPen(pen);
-                painter->drawLines(lines);
-
-                QPen linePen(Qt::white, 2);
-                linePen.setCosmetic(true);
-                painter->setPen(linePen);
-                painter->drawLines(lines);
-
-                painter->resetTransform();
-            }
-        }
+    for (it = ports.begin(); it != ports.end(); ++it) {
+        paintNavaid(painter, xf, *it);
+    }
 
-        if (drawAsIcon) {
-            QPixmap pm = iconForPositioned(pos);
-            QPointF loc = xf.map(project(pos->geod()));
-            QRect iconRect = pm.rect();
-            iconRect.moveCenter(loc.toPoint());
-            painter->drawPixmap(iconRect, pm);
-            bool isNDB = (ty == FGPositioned::NDB);
-
-       // compute label text so we can measure it
-            QString label;
-            if (FGAirport::isAirportType(pos.ptr())) {
-                label = QString::fromStdString((*it)->name());
-            } else {
-                label = QString::fromStdString((*it)->ident());
-            }
+    for (it = navaids.begin(); it != navaids.end(); ++it) {
+        paintNavaid(painter, xf, *it);
+    }
 
-            if (ty == FGPositioned::NDB) {
-                FGNavRecord* nav = static_cast<FGNavRecord*>(pos.ptr());
-                label.append("\n").append(QString::number(nav->get_freq() / 100));
-            } else if (ty == FGPositioned::VOR) {
-                FGNavRecord* nav = static_cast<FGNavRecord*>(pos.ptr());
-                label.append("\n").append(QString::number(nav->get_freq() / 100.0, 'f', 1));
-            }
 
-            QRect textBounds = painter->boundingRect(QRect(0, 0, 100, 100),
-                                                     Qt::TextWordWrap, label);
-            int textFlags;
-            textBounds = rectAndFlagsForLabel(pos->guid(), iconRect,
-                                              textBounds.size(),
-                                              textFlags);
+    // restore transform
+    painter->setTransform(xf);
+}
+
+void BaseDiagram::paintNavaid(QPainter* painter, const QTransform& t, const FGPositionedRef &pos)
+{
+    bool drawAsIcon = true;
+    if (isNavaidIgnored(pos))
+        return;
+
+    const double minRunwayLengthFt = (16 / m_scale) * SG_METER_TO_FEET;
+    FGPositioned::Type ty(pos->type());
+    if (ty == FGPositioned::AIRPORT) {
+        FGAirport* apt = static_cast<FGAirport*>(pos.ptr());
+        if (apt->hasHardRunwayOfLengthFt(minRunwayLengthFt)) {
+
+            drawAsIcon = false;
+            painter->setTransform(t);
+            QVector<QLineF> lines = projectAirportRuwaysWithCenter(apt, m_projectionCenter);
+
+            QPen pen(QColor(0x03, 0x83, 0xbf), 8);
+            pen.setCosmetic(true);
+            painter->setPen(pen);
+            painter->drawLines(lines);
+
+            QPen linePen(Qt::white, 2);
+            linePen.setCosmetic(true);
+            painter->setPen(linePen);
+            painter->drawLines(lines);
 
-            painter->setPen(isNDB ? QColor(0x9b, 0x5d, 0xa2) : QColor(0x03, 0x83, 0xbf));
-            painter->drawText(textBounds, textFlags, label);
+            painter->resetTransform();
         }
     }
 
-    // restore transform
-    painter->setTransform(xf);
+    if (drawAsIcon) {
+        QPixmap pm = iconForPositioned(pos);
+        QPointF loc = t.map(project(pos->geod()));
+        QRect iconRect = pm.rect();
+        iconRect.moveCenter(loc.toPoint());
+        painter->drawPixmap(iconRect, pm);
+        bool isNDB = (ty == FGPositioned::NDB);
+
+   // compute label text so we can measure it
+        QString label;
+        if (FGAirport::isAirportType(pos.ptr())) {
+            label = QString::fromStdString(pos->name());
+            label = fixNavaidName(label);
+        } else {
+            label = QString::fromStdString(pos->ident());
+        }
+
+        if (ty == FGPositioned::NDB) {
+            FGNavRecord* nav = static_cast<FGNavRecord*>(pos.ptr());
+            label.append("\n").append(QString::number(nav->get_freq() / 100));
+        } else if (ty == FGPositioned::VOR) {
+            FGNavRecord* nav = static_cast<FGNavRecord*>(pos.ptr());
+            label.append("\n").append(QString::number(nav->get_freq() / 100.0, 'f', 1));
+        }
+
+        QRect textBounds = painter->boundingRect(QRect(0, 0, 100, 100),
+                                                 Qt::TextWordWrap, label);
+        int textFlags;
+        textBounds = rectAndFlagsForLabel(pos->guid(), iconRect,
+                                          textBounds.size(),
+                                          textFlags);
+
+        painter->setPen(isNDB ? QColor(0x9b, 0x5d, 0xa2) : QColor(0x03, 0x83, 0xbf));
+        painter->drawText(textBounds, textFlags, label);
+    }
 }
 
 bool BaseDiagram::isNavaidIgnored(const FGPositionedRef &pos) const
@@ -626,6 +678,12 @@ QVector<QLineF> BaseDiagram::projectAirportRuwaysWithCenter(FGAirportRef apt, co
     return r;
 }
 
+void BaseDiagram::setAircraftType(LauncherAircraftType type)
+{
+    m_aircraftType = type;
+    update();
+}
+
 QVector<QLineF> BaseDiagram::projectAirportRuwaysIntoRect(FGAirportRef apt, const QRectF &bounds)
 {
     QVector<QLineF> r = projectAirportRuwaysWithCenter(apt, apt->geod());
index ce7291a6016a3b11fa84c3c760306b32c20dfb95..9cbb81102fbde8a45b8132e56235b086513a9297 100644 (file)
@@ -30,6 +30,8 @@
 #include <Navaids/positioned.hxx>
 #include <Airports/airport.hxx>
 
+#include "QtLauncher_fwd.hxx"
+
 class BaseDiagram : public QWidget
 {
     Q_OBJECT
@@ -50,6 +52,8 @@ public:
 
     static QVector<QLineF> projectAirportRuwaysIntoRect(FGAirportRef apt, const QRectF& bounds);
     static QVector<QLineF> projectAirportRuwaysWithCenter(FGAirportRef apt, const SGGeod &c);
+
+    void setAircraftType(LauncherAircraftType type);
 protected:
     virtual void paintEvent(QPaintEvent* pe);
 
@@ -80,6 +84,7 @@ protected:
     QPointF m_panOffset, m_lastMousePos;
     int m_wheelAngleDeltaAccumulator;
     bool m_didPan;
+    LauncherAircraftType m_aircraftType;
 
     static void extendRect(QRectF& r, const QPointF& p);
 
@@ -118,6 +123,11 @@ private:
     mutable QVector<QRect> m_labelRects;
 
     static int textFlagsForLabelPosition(LabelPosition pos);
+
+    void splitItems(const FGPositionedList &in, FGPositionedList &navaids, FGPositionedList &ports);
+    void paintNavaid(QPainter *painter,
+                     const QTransform& t,
+                     const FGPositionedRef &pos);
 };
 
 Q_DECLARE_OPERATORS_FOR_FLAGS(BaseDiagram::IconOptions)
index 2f4dfc2bae5a3b2c600e7c78e24de4b5b069a0c8..533c76623d5313138f2600dbcc3663ef7da9d8f2 100644 (file)
@@ -59,11 +59,21 @@ QString fixNavaidName(QString s)
             continue;
         }
 
-        if (up == "MUNI") {
+        if (up == "CO") {
+            changedWords.append("County");
+            continue;
+        }
+
+        if ((up == "MUNI") || (up == "MUN")) {
             changedWords.append("Municipal");
             continue;
         }
 
+        if (up == "MEM") {
+            changedWords.append("Memorial");
+            continue;
+        }
+
         if (up == "RGNL") {
             changedWords.append("Regional");
             continue;
@@ -85,11 +95,19 @@ QString fixNavaidName(QString s)
             continue;
         }
 
-        if ((up == "VOR") || (up == "NDB") || (up == "VOR-DME") || (up == "VORTAC") || (up == "NDB-DME")) {
+        if ((up == "VOR") || (up == "NDB")
+                || (up == "VOR-DME") || (up == "VORTAC")
+                || (up == "NDB-DME")
+                || (up == "AFB") || (up == "RAF"))
+        {
             changedWords.append(w);
             continue;
         }
 
+        if ((up =="[X]") || (up == "[H]") || (up == "[S]")) {
+            continue; // consume
+        }
+
         QChar firstChar = w.at(0).toUpper();
         w = w.mid(1).toLower();
         w.prepend(firstChar);
@@ -171,14 +189,21 @@ FGPositionedList loadPositionedList(QVariant v)
 class IdentSearchFilter : public FGPositioned::TypeFilter
 {
 public:
-    IdentSearchFilter()
+    IdentSearchFilter(LauncherAircraftType aircraft)
     {
-        addType(FGPositioned::AIRPORT);
-        addType(FGPositioned::SEAPORT);
-        addType(FGPositioned::HELIPAD);
         addType(FGPositioned::VOR);
         addType(FGPositioned::FIX);
         addType(FGPositioned::NDB);
+
+        if (aircraft == Helicopter) {
+            addType(FGPositioned::HELIPAD);
+        }
+
+        if (aircraft == Seaplane) {
+            addType(FGPositioned::SEAPORT);
+        } else {
+            addType(FGPositioned::AIRPORT);
+        }
     }
 };
 
@@ -191,7 +216,7 @@ public:
     {
     }
 
-    void setSearch(QString t)
+    void setSearch(QString t, LauncherAircraftType aircraft)
     {
         beginResetModel();
 
@@ -200,7 +225,7 @@ public:
 
         std::string term(t.toUpper().toStdString());
 
-        IdentSearchFilter filter;
+        IdentSearchFilter filter(aircraft);
         FGPositionedList exactMatches = NavDataCache::instance()->findAllWithIdent(term, &filter, true);
 
         for (unsigned int i=0; i<exactMatches.size(); ++i) {
@@ -318,7 +343,8 @@ private:
 
 LocationWidget::LocationWidget(QWidget *parent) :
     QWidget(parent),
-    m_ui(new Ui::LocationWidget)
+    m_ui(new Ui::LocationWidget),
+    m_aircraftType(Airplane)
 {
     m_ui->setupUi(this);
 
@@ -596,7 +622,7 @@ void LocationWidget::onSearch()
         return;
     }
 
-    m_searchModel->setSearch(search);
+    m_searchModel->setSearch(search, m_aircraftType);
 
     if (m_searchModel->isSearchActive()) {
         m_ui->searchStatusText->setText(QString("Searching for '%1'").arg(search));
@@ -868,6 +894,14 @@ void LocationWidget::setBaseLocation(FGPositionedRef ref)
     updateDescription();
 }
 
+void LocationWidget::setAircraftType(LauncherAircraftType ty)
+{
+    m_aircraftType = ty;
+    // nothing happens until next search
+    m_ui->navaidDiagram->setAircraftType(ty);
+    m_ui->airportDiagram->setAircraftType(ty);
+}
+
 void LocationWidget::onOffsetDataChanged()
 {
     m_ui->navaidDiagram->setOffsetEnabled(m_ui->offsetGroup->isChecked());
index 5df4d62a25633ce895f4c80a14507480a09fceb4..5dd0eb65ed8b13db0679c55704fb22d55a37d7ea 100644 (file)
@@ -28,6 +28,8 @@
 #include <Navaids/positioned.hxx>
 #include <Airports/airports_fwd.hxx>
 
+#include "QtLauncher_fwd.hxx"
+
 namespace Ui {
     class LocationWidget;
 }
@@ -49,6 +51,8 @@ public:
 
     void setBaseLocation(FGPositionedRef ref);
 
+    void setAircraftType(LauncherAircraftType ty);
+
     bool shouldStartPaused() const;
 
     void setLocationOptions();
@@ -87,8 +91,7 @@ private:
     QToolButton* m_backButton;
 
     FGPositionedList m_recentLocations;
-
-
+    LauncherAircraftType m_aircraftType;
 };
 
 #endif // LOCATIONWIDGET_H
index 842a369668883e72c8317d8130eb5b877b5611e6..e3b9e6f07b273ea4c99f9d6271ac28d820b5ece1 100644 (file)
@@ -864,7 +864,6 @@ void QtLauncher::onAircraftInstallFailed(QModelIndex index, QString errorMessage
 void QtLauncher::onAircraftSelected(const QModelIndex& index)
 {
     m_selectedAircraft = index.data(AircraftURIRole).toUrl();
-    qDebug() << "selected aircraft is now" << m_selectedAircraft;
     updateSelectedAircraft();
 }
 
@@ -910,6 +909,15 @@ void QtLauncher::updateSelectedAircraft()
         int status = index.data(AircraftPackageStatusRole).toInt();
         bool canRun = (status == PackageInstalled);
         m_ui->runButton->setEnabled(canRun);
+
+        LauncherAircraftType aircraftType = Airplane;
+        if (index.data(AircraftIsHelicopterRole).toBool()) {
+            aircraftType = Helicopter;
+        } else if (index.data(AircraftIsSeaplaneRole).toBool()) {
+            aircraftType = Seaplane;
+        }
+
+        m_ui->location->setAircraftType(aircraftType);
     } else {
         m_ui->thumbnail->setPixmap(QPixmap());
         m_ui->aircraftDescription->setText("");
diff --git a/src/GUI/QtLauncher_fwd.hxx b/src/GUI/QtLauncher_fwd.hxx
new file mode 100644 (file)
index 0000000..cb80f48
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef QTGUI_FWD_H
+#define QTGUI_FWD_H
+
+enum LauncherAircraftType
+{
+    Airplane = 0,
+    Seaplane,
+    Helicopter,
+    Airship
+};
+
+extern QString fixNavaidName(QString s);
+
+#endif // QTGUI_FWD_H
+