#include <Airports/parking.hxx>
#include <Airports/pavement.hxx>
-/* equatorial and polar earth radius */
-const float rec = 6378137; // earth radius, equator (?)
-const float rpol = 6356752.314f; // earth radius, polar (?)
-
-//Returns Earth radius at a given latitude (Ellipsoide equation with two equal axis)
-static float earth_radius_lat( float lat )
-{
- double a = cos(lat)/rec;
- double b = sin(lat)/rpol;
- return 1.0f / sqrt( a * a + b * b );
-}
-
static double distanceToLineSegment(const QVector2D& p, const QVector2D& a,
const QVector2D& b, double* outT = NULL)
{
}
AirportDiagram::AirportDiagram(QWidget* pr) :
-QWidget(pr)
+ BaseDiagram(pr),
+ m_approachDistanceNm(-1.0)
+{
+}
+
+AirportDiagram::~AirportDiagram()
{
- setSizePolicy(QSizePolicy::MinimumExpanding,
- QSizePolicy::MinimumExpanding);
- setMinimumSize(100, 100);
+
}
void AirportDiagram::setAirport(FGAirportRef apt)
{
m_airport = apt;
m_projectionCenter = apt ? apt->geod() : SGGeod();
- m_scale = 1.0;
- m_bounds = QRectF(); // clear
m_runways.clear();
+ m_approachDistanceNm = -1.0;
if (apt) {
buildTaxiways();
buildPavements();
}
+ recomputeBounds(true);
update();
}
update();
}
+void AirportDiagram::setApproachExtensionDistance(double distanceNm)
+{
+ m_approachDistanceNm = distanceNm;
+ recomputeBounds(true);
+ update();
+}
+
void AirportDiagram::addRunway(FGRunwayRef rwy)
{
Q_FOREACH(RunwayData rd, m_runways) {
}
}
- QPointF p1 = project(rwy->geod()),
- p2 = project(rwy->end());
- extendBounds(p1);
- extendBounds(p2);
-
RunwayData r;
- r.p1 = p1;
- r.p2 = p2;
+ r.p1 = project(rwy->geod());
+ r.p2 = project(rwy->end());
r.widthM = qRound(rwy->widthM());
r.runway = rwy;
m_runways.append(r);
+
+ recomputeBounds(false);
update();
}
-void AirportDiagram::addParking(FGParking* park)
+void AirportDiagram::doComputeBounds()
{
- QPointF p = project(park->geod());
- extendBounds(p);
- update();
+ Q_FOREACH(const RunwayData& r, m_runways) {
+ extendBounds(r.p1);
+ extendBounds(r.p2);
+ }
+
+ Q_FOREACH(const TaxiwayData& t, m_taxiways) {
+ extendBounds(t.p1);
+ extendBounds(t.p2);
+ }
+
+ Q_FOREACH(const ParkingData& p, m_parking) {
+ extendBounds(p.pt);
+ }
+
+ if (m_selectedRunway && (m_approachDistanceNm > 0.0)) {
+ double d = SG_NM_TO_METER * m_approachDistanceNm;
+ QPointF pt = project(m_selectedRunway->pointOnCenterline(-d));
+ extendBounds(pt);
+ }
}
-QTransform AirportDiagram::transform() const
+void AirportDiagram::addParking(FGParkingRef park)
{
- // fit bounds within our available space, allowing for a margin
- const int MARGIN = 32; // pixels
- double ratioInX = (width() - MARGIN * 2) / m_bounds.width();
- double ratioInY = (height() - MARGIN * 2) / m_bounds.height();
- double scale = std::min(ratioInX, ratioInY);
-
- QTransform t;
- t.translate(width() / 2, height() / 2); // center projection origin in the widget
- t.scale(scale, scale);
- // center the bounding box (may not be at the origin)
- t.translate(-m_bounds.center().x(), -m_bounds.center().y());
- return t;
+ ParkingData pd = { project(park->geod()), park };
+ m_parking.push_back(pd);
+ recomputeBounds(false);
+ update();
}
-void AirportDiagram::paintEvent(QPaintEvent* pe)
-{
- QPainter p(this);
- p.setRenderHints(QPainter::Antialiasing);
- p.fillRect(rect(), QColor(0x3f, 0x3f, 0x3f));
- // fit bounds within our available space, allowing for a margin
- const int MARGIN = 32; // pixels
- double ratioInX = (width() - MARGIN * 2) / m_bounds.width();
- double ratioInY = (height() - MARGIN * 2) / m_bounds.height();
- double scale = std::min(ratioInX, ratioInY);
+void AirportDiagram::paintContents(QPainter* p)
+{
+ // fit bounds within our available space, allowing for a margin
+// const int MARGIN = 32; // pixels
+ // double ratioInX = (width() - MARGIN * 2) / m_bounds.width();
+ // double ratioInY = (height() - MARGIN * 2) / m_bounds.height();
+ // double scale = std::min(ratioInX, ratioInY);
QTransform t(transform());
- p.setTransform(t);
+ p->setTransform(t);
// pavements
QBrush brush(QColor(0x9f, 0x9f, 0x9f));
Q_FOREACH(const QPainterPath& path, m_pavements) {
- p.drawPath(path);
+ p->drawPath(path);
}
// taxiways
Q_FOREACH(const TaxiwayData& t, m_taxiways) {
QPen pen(QColor(0x9f, 0x9f, 0x9f));
pen.setWidth(t.widthM);
- p.setPen(pen);
- p.drawLine(t.p1, t.p2);
+ p->setPen(pen);
+ p->drawLine(t.p1, t.p2);
}
// runways
QFont f;
f.setPixelSize(14);
- p.setFont(f);
+ p->setFont(f);
Q_FOREACH(const RunwayData& r, m_runways) {
QColor color(Qt::magenta);
color = Qt::yellow;
}
- p.setTransform(t);
+ p->setTransform(t);
QPen pen(color);
pen.setWidth(r.widthM);
- p.setPen(pen);
+ p->setPen(pen);
- p.drawLine(r.p1, r.p2);
+ p->drawLine(r.p1, r.p2);
// draw idents
QString ident = QString::fromStdString(r.runway->ident());
- p.translate(r.p1);
- p.rotate(r.runway->headingDeg());
+ p->translate(r.p1);
+ p->rotate(r.runway->headingDeg());
// invert scaling factor so we can use screen pixel sizes here
- p.scale(1.0 / scale, 1.0/ scale);
+ p->scale(1.0 / m_scale, 1.0/ m_scale);
- p.setPen((r.runway == m_selectedRunway) ? Qt::yellow : Qt::magenta);
- p.drawText(QRect(-100, 5, 200, 200), ident, Qt::AlignHCenter | Qt::AlignTop);
+ p->setPen((r.runway == m_selectedRunway) ? Qt::yellow : Qt::magenta);
+ p->drawText(QRect(-100, 5, 200, 200), ident, Qt::AlignHCenter | Qt::AlignTop);
FGRunway* recip = r.runway->reciprocalRunway();
QString recipIdent = QString::fromStdString(recip->ident());
- p.setTransform(t);
- p.translate(r.p2);
- p.rotate(recip->headingDeg());
- p.scale(1.0 / scale, 1.0/ scale);
+ p->setTransform(t);
+ p->translate(r.p2);
+ p->rotate(recip->headingDeg());
+ p->scale(1.0 / m_scale, 1.0/ m_scale);
+
+ p->setPen((r.runway->reciprocalRunway() == m_selectedRunway) ? Qt::yellow : Qt::magenta);
+ p->drawText(QRect(-100, 5, 200, 200), recipIdent, Qt::AlignHCenter | Qt::AlignTop);
+ }
- p.setPen((r.runway->reciprocalRunway() == m_selectedRunway) ? Qt::yellow : Qt::magenta);
- p.drawText(QRect(-100, 5, 200, 200), recipIdent, Qt::AlignHCenter | Qt::AlignTop);
+ if (m_selectedRunway && (m_approachDistanceNm > 0.0)) {
+ p->setTransform(t);
+ // draw approach extension point
+ double d = SG_NM_TO_METER * m_approachDistanceNm;
+ QPointF pt = project(m_selectedRunway->pointOnCenterline(-d));
+ QPointF pt2 = project(m_selectedRunway->geod());
+ QPen pen(Qt::yellow, 10);
+ p->setPen(pen);
+ p->drawLine(pt, pt2);
}
}
void AirportDiagram::mouseReleaseEvent(QMouseEvent* me)
{
+ if (m_didPan)
+ return; // ignore panning drag+release ops here
+
QTransform t(transform());
double minDist = std::numeric_limits<double>::max();
FGRunwayRef bestRunway;
}
}
-void AirportDiagram::extendBounds(const QPointF& p)
-{
- if (p.x() < m_bounds.left()) {
- m_bounds.setLeft(p.x());
- } else if (p.x() > m_bounds.right()) {
- m_bounds.setRight(p.x());
- }
-
- if (p.y() < m_bounds.top()) {
- m_bounds.setTop(p.y());
- } else if (p.y() > m_bounds.bottom()) {
- m_bounds.setBottom(p.y());
- }
-}
-
-QPointF AirportDiagram::project(const SGGeod& geod) const
-{
- double r = earth_radius_lat(geod.getLatitudeRad());
- double ref_lat = m_projectionCenter.getLatitudeRad(),
- ref_lon = m_projectionCenter.getLongitudeRad(),
- lat = geod.getLatitudeRad(),
- lon = geod.getLongitudeRad(),
- lonDiff = lon - ref_lon;
-
- double c = acos( sin(ref_lat) * sin(lat) + cos(ref_lat) * cos(lat) * cos(lonDiff) );
- if (c == 0.0) {
- // angular distance from center is 0
- return QPointF(0.0, 0.0);
- }
-
- double k = c / sin(c);
- double x, y;
- if (ref_lat == (90 * SG_DEGREES_TO_RADIANS))
- {
- x = (SGD_PI / 2 - lat) * sin(lonDiff);
- y = -(SGD_PI / 2 - lat) * cos(lonDiff);
- }
- else if (ref_lat == -(90 * SG_DEGREES_TO_RADIANS))
- {
- x = (SGD_PI / 2 + lat) * sin(lonDiff);
- y = (SGD_PI / 2 + lat) * cos(lonDiff);
- }
- else
- {
- x = k * cos(lat) * sin(lonDiff);
- y = k * ( cos(ref_lat) * sin(lat) - sin(ref_lat) * cos(lat) * cos(lonDiff) );
- }
-
- return QPointF(x, -y) * r * m_scale;
-}
-
void AirportDiagram::buildTaxiways()
{
m_taxiways.clear();
TaxiwayData td;
td.p1 = project(tx->geod());
td.p2 = project(tx->pointOnCenterline(tx->lengthM()));
- extendBounds(td.p1);
- extendBounds(td.p2);
+
td.widthM = tx->widthM();
m_taxiways.append(td);
}
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#include <QWidget>
-#include <QPainterPath>
+#ifndef GUI_AIRPORT_DIAGRAM_HXX
+#define GUI_AIRPORT_DIAGRAM_HXX
-#include <Airports/airports_fwd.hxx>
+#include "BaseDiagram.hxx"
+
+#include <Airports/parking.hxx>
+#include <Airports/runways.hxx>
#include <simgear/math/sg_geodesy.hxx>
-class AirportDiagram : public QWidget
+class AirportDiagram : public BaseDiagram
{
Q_OBJECT
public:
AirportDiagram(QWidget* pr);
+ virtual ~AirportDiagram();
void setAirport(FGAirportRef apt);
void addRunway(FGRunwayRef rwy);
- void addParking(FGParking* park);
+ void addParking(FGParkingRef park);
FGRunwayRef selectedRunway() const;
void setSelectedRunway(FGRunwayRef r);
+
+ void setApproachExtensionDistance(double distanceNm);
Q_SIGNALS:
void clickedRunway(FGRunwayRef rwy);
+ void clickedParking(FGParkingRef park);
protected:
- virtual void paintEvent(QPaintEvent* pe);
- // wheel event for zoom
-
- // mouse drag for pan
virtual void mouseReleaseEvent(QMouseEvent* me);
+ void paintContents(QPainter*) Q_DECL_OVERRIDE;
+ void doComputeBounds() Q_DECL_OVERRIDE;
private:
- void extendBounds(const QPointF& p);
- QPointF project(const SGGeod& geod) const;
- QTransform transform() const;
-
+
void buildTaxiways();
void buildPavements();
FGAirportRef m_airport;
- SGGeod m_projectionCenter;
- double m_scale;
- QRectF m_bounds;
struct RunwayData {
QPointF p1, p2;
FGRunwayRef runway;
};
- QList<RunwayData> m_runways;
+ QVector<RunwayData> m_runways;
struct TaxiwayData {
QPointF p1, p2;
}
};
- QList<TaxiwayData> m_taxiways;
- QList<QPainterPath> m_pavements;
-
+ QVector<TaxiwayData> m_taxiways;
+ QVector<QPainterPath> m_pavements;
+
+ struct ParkingData
+ {
+ QPointF pt;
+ FGParkingRef parking;
+ };
+
+ QVector<ParkingData> m_parking;
+
+ double m_approachDistanceNm;
FGRunwayRef m_selectedRunway;
};
+
+#endif // of GUI_AIRPORT_DIAGRAM_HXX
--- /dev/null
+// BaseDiagram.cxx - part of GUI launcher using Qt5
+//
+// Written by James Turner, started December 2014.
+//
+// Copyright (C) 2014 James Turner <zakalawe@mac.com>
+//
+// 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 the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+#include "BaseDiagram.hxx"
+
+#include <limits>
+
+#include <QPainter>
+#include <QDebug>
+#include <QVector2D>
+#include <QMouseEvent>
+
+/* equatorial and polar earth radius */
+const float rec = 6378137; // earth radius, equator (?)
+const float rpol = 6356752.314f; // earth radius, polar (?)
+
+//Returns Earth radius at a given latitude (Ellipsoide equation with two equal axis)
+static float earth_radius_lat( float lat )
+{
+ double a = cos(lat)/rec;
+ double b = sin(lat)/rpol;
+ return 1.0f / sqrt( a * a + b * b );
+}
+
+BaseDiagram::BaseDiagram(QWidget* pr) :
+ QWidget(pr),
+ m_autoScalePan(true),
+ m_wheelAngleDeltaAccumulator(0)
+{
+ setSizePolicy(QSizePolicy::MinimumExpanding,
+ QSizePolicy::MinimumExpanding);
+ setMinimumSize(100, 100);
+}
+
+QTransform BaseDiagram::transform() const
+{
+ QTransform t;
+ t.translate(width() / 2, height() / 2); // center projection origin in the widget
+ t.scale(m_scale, m_scale);
+
+ // apply any pan offset that exists
+ t.translate(m_panOffset.x(), m_panOffset.y());
+ // center the bounding box (may not be at the origin)
+ t.translate(-m_bounds.center().x(), -m_bounds.center().y());
+ return t;
+}
+
+void BaseDiagram::paintEvent(QPaintEvent* pe)
+{
+ QPainter p(this);
+ p.setRenderHints(QPainter::Antialiasing);
+ p.fillRect(rect(), QColor(0x3f, 0x3f, 0x3f));
+
+ if (m_autoScalePan) {
+ // fit bounds within our available space, allowing for a margin
+ const int MARGIN = 32; // pixels
+ double ratioInX = (width() - MARGIN * 2) / m_bounds.width();
+ double ratioInY = (height() - MARGIN * 2) / m_bounds.height();
+ m_scale = std::min(ratioInX, ratioInY);
+ }
+
+ QTransform t(transform());
+ p.setTransform(t);
+
+ paintContents(&p);
+}
+
+void BaseDiagram::mousePressEvent(QMouseEvent *me)
+{
+ m_lastMousePos = me->pos();
+ m_didPan = false;
+}
+
+void BaseDiagram::mouseMoveEvent(QMouseEvent *me)
+{
+ m_autoScalePan = false;
+
+ QPointF delta = me->pos() - m_lastMousePos;
+ m_lastMousePos = me->pos();
+
+ // offset is stored in metres so we don't have to modify it when
+ // zooming
+ m_panOffset += (delta / m_scale);
+ m_didPan = true;
+
+ update();
+}
+
+int intSign(int v)
+{
+ return (v == 0) ? 0 : (v < 0) ? -1 : 1;
+}
+
+void BaseDiagram::wheelEvent(QWheelEvent *we)
+{
+ m_autoScalePan = false;
+
+ int delta = we->angleDelta().y();
+ if (intSign(m_wheelAngleDeltaAccumulator) != intSign(delta)) {
+ m_wheelAngleDeltaAccumulator = 0;
+ }
+
+ m_wheelAngleDeltaAccumulator += delta;
+ if (m_wheelAngleDeltaAccumulator > 120) {
+ m_wheelAngleDeltaAccumulator = 0;
+ m_scale *= 2.0;
+ } else if (m_wheelAngleDeltaAccumulator < 120) {
+ m_wheelAngleDeltaAccumulator = 0;
+ m_scale *= 0.5;
+ }
+
+ update();
+}
+
+void BaseDiagram::paintContents(QPainter*)
+{
+
+}
+
+void BaseDiagram::recomputeBounds(bool resetZoom)
+{
+ m_bounds = QRectF();
+ doComputeBounds();
+
+ if (resetZoom) {
+ m_autoScalePan = true;
+ m_scale = 1.0;
+ m_panOffset = QPointF();
+ }
+
+ update();
+}
+
+void BaseDiagram::doComputeBounds()
+{
+ // no-op in the base class
+}
+
+void BaseDiagram::extendBounds(const QPointF& p)
+{
+ if (p.x() < m_bounds.left()) {
+ m_bounds.setLeft(p.x());
+ } else if (p.x() > m_bounds.right()) {
+ m_bounds.setRight(p.x());
+ }
+
+ if (p.y() < m_bounds.top()) {
+ m_bounds.setTop(p.y());
+ } else if (p.y() > m_bounds.bottom()) {
+ m_bounds.setBottom(p.y());
+ }
+}
+
+QPointF BaseDiagram::project(const SGGeod& geod) const
+{
+ double r = earth_radius_lat(geod.getLatitudeRad());
+ double ref_lat = m_projectionCenter.getLatitudeRad(),
+ ref_lon = m_projectionCenter.getLongitudeRad(),
+ lat = geod.getLatitudeRad(),
+ lon = geod.getLongitudeRad(),
+ lonDiff = lon - ref_lon;
+
+ double c = acos( sin(ref_lat) * sin(lat) + cos(ref_lat) * cos(lat) * cos(lonDiff) );
+ if (c == 0.0) {
+ // angular distance from center is 0
+ return QPointF(0.0, 0.0);
+ }
+
+ double k = c / sin(c);
+ double x, y;
+ if (ref_lat == (90 * SG_DEGREES_TO_RADIANS))
+ {
+ x = (SGD_PI / 2 - lat) * sin(lonDiff);
+ y = -(SGD_PI / 2 - lat) * cos(lonDiff);
+ }
+ else if (ref_lat == -(90 * SG_DEGREES_TO_RADIANS))
+ {
+ x = (SGD_PI / 2 + lat) * sin(lonDiff);
+ y = (SGD_PI / 2 + lat) * cos(lonDiff);
+ }
+ else
+ {
+ x = k * cos(lat) * sin(lonDiff);
+ y = k * ( cos(ref_lat) * sin(lat) - sin(ref_lat) * cos(lat) * cos(lonDiff) );
+ }
+
+ return QPointF(x, -y) * r;
+}
--- /dev/null
+// BaseDiagram.hxx - part of GUI launcher using Qt5
+//
+// Written by James Turner, started October 2015.
+//
+// Copyright (C) 2014 James Turner <zakalawe@mac.com>
+//
+// 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 the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+#ifndef GUI_BASEDIAGRAM_HXX
+#define GUI_BASEDIAGRAM_HXX
+
+#include <QWidget>
+#include <QPainterPath>
+
+#include <simgear/math/sg_geodesy.hxx>
+
+class BaseDiagram : public QWidget
+{
+ Q_OBJECT
+public:
+ BaseDiagram(QWidget* pr);
+
+
+
+protected:
+ virtual void paintEvent(QPaintEvent* pe);
+
+ virtual void mousePressEvent(QMouseEvent* me);
+ virtual void mouseMoveEvent(QMouseEvent* me);
+
+ virtual void wheelEvent(QWheelEvent* we);
+
+ virtual void paintContents(QPainter*);
+
+protected:
+ void recomputeBounds(bool resetZoom);
+
+ virtual void doComputeBounds();
+
+ void extendBounds(const QPointF& p);
+ QPointF project(const SGGeod& geod) const;
+ QTransform transform() const;
+
+ SGGeod m_projectionCenter;
+ double m_scale;
+ QRectF m_bounds;
+ bool m_autoScalePan;
+ QPointF m_panOffset, m_lastMousePos;
+ int m_wheelAngleDeltaAccumulator;
+ bool m_didPan;
+};
+
+#endif // of GUI_BASEDIAGRAM_HXX
EditRatingsFilterDialog.ui
SetupRootDialog.ui
AddCatalogDialog.ui
- PathsDialog.ui)
+ PathsDialog.ui
+ LocationWidget.ui)
qt5_add_resources(qrc_sources resources.qrc)
include_directories(${PROJECT_BINARY_DIR}/src/GUI)
add_library(fglauncher QtLauncher.cxx
QtLauncher.hxx
QtLauncher_private.hxx
+ BaseDiagram.cxx
+ BaseDiagram.hxx
AirportDiagram.cxx
AirportDiagram.hxx
+ NavaidDiagram.cxx
+ NavaidDiagram.hxx
EditRatingsFilterDialog.cxx
EditRatingsFilterDialog.hxx
SetupRootDialog.cxx
AddCatalogDialog.hxx
PathsDialog.cxx
PathsDialog.hxx
+ LocationWidget.cxx
+ LocationWidget.hxx
${uic_sources}
${qrc_sources})
</widget>
</item>
<item row="1" column="2">
- <widget class="QLabel" name="airportDescription">
+ <widget class="QLabel" name="locationDescription">
<property name="text">
<string/>
</property>
<number>4</number>
</property>
<item>
- <layout class="QHBoxLayout" name="horizontalLayout_6">
- <item>
- <widget class="QLabel" name="airportIdent">
- <property name="text">
- <string>Search:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="airportEdit">
- <property name="placeholderText">
- <string>Enter an ICAO code, navaid or search by name</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="airportHistory">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- <property name="flat">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QStackedWidget" name="locationStack">
- <property name="currentIndex">
- <number>0</number>
- </property>
- <widget class="QWidget" name="diagramPage">
- <layout class="QGridLayout" name="gridLayout" columnstretch="0,1,1,0">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item row="3" column="0">
- <widget class="QRadioButton" name="parkingRadio">
- <property name="text">
- <string>Parking:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QCheckBox" name="onFinalCheckbox">
- <property name="text">
- <string>On 10-mile final</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QRadioButton" name="runwayRadio">
- <property name="text">
- <string>Runway:</string>
- </property>
- </widget>
- </item>
- <item row="6" column="2">
- <widget class="QSpinBox" name="offsetBearingSpinbox">
- <property name="wrapping">
- <bool>true</bool>
- </property>
- <property name="maximum">
- <number>359</number>
- </property>
- <property name="singleStep">
- <number>5</number>
- </property>
- </widget>
- </item>
- <item row="3" column="1" colspan="3">
- <widget class="QComboBox" name="parkingCombo"/>
- </item>
- <item row="1" column="1" colspan="3">
- <widget class="QComboBox" name="runwayCombo"/>
- </item>
- <item row="6" column="3">
- <widget class="QCheckBox" name="trueBearing">
- <property name="text">
- <string>True</string>
- </property>
- </widget>
- </item>
- <item row="6" column="1">
- <widget class="QLabel" name="offsetBearingLabel">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="text">
- <string>Bearing:</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="5" column="0">
- <widget class="QRadioButton" name="offsetRadioButton">
- <property name="text">
- <string>Bearing and distance offset:</string>
- </property>
- </widget>
- </item>
- <item row="5" column="1">
- <widget class="QLabel" name="offsetDistanceLabel">
- <property name="text">
- <string>Distance:</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="5" column="2">
- <widget class="QDoubleSpinBox" name="offsetNmSpinbox">
- <property name="suffix">
- <string>nm</string>
- </property>
- <property name="decimals">
- <number>1</number>
- </property>
- <property name="maximum">
- <double>10000.000000000000000</double>
- </property>
- <property name="value">
- <double>10.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="0" column="0" colspan="4">
- <widget class="AirportDiagram" name="airportDiagram" native="true">
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="searchResultsPage">
- <layout class="QVBoxLayout" name="verticalLayout_5">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QListView" name="searchList"/>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="searchStatusPage">
- <layout class="QVBoxLayout" name="verticalLayout_6">
- <item>
- <widget class="QLabel" name="searchIcon">
- <property name="text">
- <string>TextLabel</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignBottom|Qt::AlignHCenter</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="searchStatusText">
- <property name="text">
- <string/>
- </property>
- <property name="alignment">
- <set>Qt::AlignHCenter|Qt::AlignTop</set>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </widget>
+ <widget class="LocationWidget" name="location" native="true"/>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>
- <class>AirportDiagram</class>
+ <class>LocationWidget</class>
<extends>QWidget</extends>
- <header location="global">GUI/AirportDiagram.hxx</header>
+ <header location="global">GUI/LocationWidget.hxx</header>
<container>1</container>
</customwidget>
</customwidgets>
--- /dev/null
+// LocationWidget.cxx - GUI launcher dialog using Qt5
+//
+// Written by James Turner, started October 2015.
+//
+// Copyright (C) 2015 James Turner <zakalawe@mac.com>
+//
+// 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 the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+#include "LocationWidget.hxx"
+#include "ui_LocationWidget.h"
+
+#include <QSettings>
+#include <QAbstractListModel>
+#include <QTimer>
+#include <QDebug>
+#include <QToolButton>
+
+#include "AirportDiagram.hxx"
+#include "NavaidDiagram.hxx"
+
+#include <Airports/airport.hxx>
+#include <Airports/dynamics.hxx> // for parking
+#include <Main/globals.hxx>
+#include <Navaids/NavDataCache.hxx>
+#include <Navaids/navrecord.hxx>
+#include <Main/options.hxx>
+#include <Main/fg_init.hxx>
+
+const int MAX_RECENT_AIRPORTS = 32;
+
+using namespace flightgear;
+
+QString fixNavaidName(QString s)
+{
+ // split into words
+ QStringList words = s.split(QChar(' '));
+ QStringList changedWords;
+ Q_FOREACH(QString w, words) {
+ QString up = w.toUpper();
+
+ // expand common abbreviations
+ if (up == "FLD") {
+ changedWords.append("Field");
+ continue;
+ }
+
+ if (up == "MUNI") {
+ changedWords.append("Municipal");
+ continue;
+ }
+
+ if (up == "RGNL") {
+ changedWords.append("Regional");
+ continue;
+ }
+
+ if (up == "CTR") {
+ changedWords.append("Center");
+ continue;
+ }
+
+ if (up == "INTL") {
+ changedWords.append("International");
+ continue;
+ }
+
+ // occurs in many Australian airport names in our DB
+ if (up == "(NSW)") {
+ changedWords.append("(New South Wales)");
+ continue;
+ }
+
+ if ((up == "VOR") || (up == "NDB") || (up == "VOR-DME") || (up == "VORTAC") || (up == "NDB-DME")) {
+ changedWords.append(w);
+ continue;
+ }
+
+ QChar firstChar = w.at(0).toUpper();
+ w = w.mid(1).toLower();
+ w.prepend(firstChar);
+
+ changedWords.append(w);
+ }
+
+ return changedWords.join(QChar(' '));
+}
+
+QString formatGeodAsString(const SGGeod& geod)
+{
+ QChar ns = (geod.getLatitudeDeg() > 0.0) ? 'N' : 'S';
+ QChar ew = (geod.getLongitudeDeg() > 0.0) ? 'E' : 'W';
+
+ return QString::number(fabs(geod.getLongitudeDeg()), 'f',2 ) + ew + " " +
+ QString::number(fabs(geod.getLatitudeDeg()), 'f',2 ) + ns;
+}
+
+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 NavSearchModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ NavSearchModel() :
+ m_searchActive(false)
+ {
+ }
+
+ void setSearch(QString t)
+ {
+ beginResetModel();
+
+ m_items.clear();
+ m_ids.clear();
+
+ std::string term(t.toUpper().toStdString());
+
+ IdentSearchFilter filter;
+ FGPositionedList exactMatches = NavDataCache::instance()->findAllWithIdent(term, &filter, true);
+
+ for (unsigned int i=0; i<exactMatches.size(); ++i) {
+ m_ids.push_back(exactMatches[i]->guid());
+ m_items.push_back(exactMatches[i]);
+ }
+ endResetModel();
+
+
+ m_search.reset(new NavDataCache::ThreadedGUISearch(term));
+ QTimer::singleShot(100, this, &NavSearchModel::onSearchResultsPoll);
+ m_searchActive = true;
+ endResetModel();
+ }
+
+ bool isSearchActive() const
+ {
+ return m_searchActive;
+ }
+
+ virtual int rowCount(const QModelIndex&) const
+ {
+ // if empty, return 1 for special 'no matches'?
+ return m_ids.size();
+ }
+
+ virtual QVariant data(const QModelIndex& index, int role) const
+ {
+ if (!index.isValid())
+ return QVariant();
+
+ FGPositionedRef pos = itemAtRow(index.row());
+ if (role == Qt::DisplayRole) {
+ if (pos->type() == FGPositioned::FIX) {
+ // fixes don't have a name, show position instead
+ return QString("Fix %1 (%2)").arg(QString::fromStdString(pos->ident()))
+ .arg(formatGeodAsString(pos->geod()));
+ } else {
+ QString name = fixNavaidName(QString::fromStdString(pos->name()));
+ return QString("%1: %2").arg(QString::fromStdString(pos->ident())).arg(name);
+ }
+ }
+
+ if (role == Qt::EditRole) {
+ return QString::fromStdString(pos->ident());
+ }
+
+ if (role == Qt::UserRole) {
+ return static_cast<qlonglong>(m_ids[index.row()]);
+ }
+
+ return QVariant();
+ }
+
+ FGPositionedRef itemAtRow(unsigned int row) const
+ {
+ FGPositionedRef pos = m_items[row];
+ if (!pos.valid()) {
+ pos = NavDataCache::instance()->loadById(m_ids[row]);
+ m_items[row] = pos;
+ }
+
+ return pos;
+ }
+Q_SIGNALS:
+ void searchComplete();
+
+private:
+
+
+ void onSearchResultsPoll()
+ {
+ PositionedIDVec newIds = m_search->results();
+
+ 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_items.push_back(FGPositionedRef()); // null ref
+ }
+ endInsertRows();
+
+ if (m_search->isComplete()) {
+ m_searchActive = false;
+ m_search.reset();
+ emit searchComplete();
+ } else {
+ QTimer::singleShot(100, this, &NavSearchModel::onSearchResultsPoll);
+ }
+ }
+
+private:
+ PositionedIDVec m_ids;
+ mutable FGPositionedList m_items;
+ bool m_searchActive;
+ QScopedPointer<NavDataCache::ThreadedGUISearch> m_search;
+};
+
+
+LocationWidget::LocationWidget(QWidget *parent) :
+ QWidget(parent),
+ m_ui(new Ui::LocationWidget)
+{
+ m_ui->setupUi(this);
+
+
+ QIcon historyIcon(":/history-icon");
+ m_ui->searchHistory->setIcon(historyIcon);
+
+ m_ui->searchIcon->setPixmap(QPixmap(":/search-icon"));
+
+ m_searchModel = new NavSearchModel;
+ m_ui->searchResultsList->setModel(m_searchModel);
+ connect(m_ui->searchResultsList, &QListView::clicked,
+ this, &LocationWidget::onSearchResultSelected);
+ connect(m_searchModel, &NavSearchModel::searchComplete,
+ this, &LocationWidget::onSearchComplete);
+
+ connect(m_ui->runwayCombo, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(updateDescription()));
+ connect(m_ui->parkingCombo, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(updateDescription()));
+ connect(m_ui->runwayRadio, SIGNAL(toggled(bool)),
+ this, SLOT(updateDescription()));
+ connect(m_ui->parkingRadio, SIGNAL(toggled(bool)),
+ this, SLOT(updateDescription()));
+ connect(m_ui->onFinalCheckbox, SIGNAL(toggled(bool)),
+ this, SLOT(updateDescription()));
+ connect(m_ui->approachDistanceSpin, SIGNAL(valueChanged(int)),
+ this, SLOT(updateDescription()));
+
+ connect(m_ui->airportDiagram, &AirportDiagram::clickedRunway,
+ this, &LocationWidget::onAirportDiagramClicked);
+
+ connect(m_ui->locationSearchEdit, &QLineEdit::returnPressed,
+ this, &LocationWidget::onSearch);
+
+ connect(m_ui->searchHistory, &QPushButton::clicked,
+ this, &LocationWidget::onPopupHistory);
+
+ connect(m_ui->trueBearing, &QCheckBox::toggled,
+ this, &LocationWidget::onOffsetBearingTrueChanged);
+ connect(m_ui->offsetGroup, &QGroupBox::toggled,
+ this, &LocationWidget::onOffsetEnabledToggled);
+ connect(m_ui->trueBearing, &QCheckBox::toggled, this,
+ &LocationWidget::onOffsetDataChanged);
+ connect(m_ui->offsetBearingSpinbox, SIGNAL(valueChanged(int)),
+ this, SLOT(onOffsetDataChanged()));
+ connect(m_ui->offsetNmSpinbox, SIGNAL(valueChanged(double)),
+ this, SLOT(onOffsetDataChanged()));
+
+ m_backButton = new QToolButton(this);
+ m_backButton->setGeometry(0, 0, 32, 32);
+ m_backButton->setIcon(QIcon(":/search-icon"));
+ m_backButton->raise();
+
+ connect(m_backButton, &QAbstractButton::clicked,
+ this, &LocationWidget::onBackToSearch);
+
+// force various pieces of UI into sync
+ onOffsetEnabledToggled(m_ui->offsetGroup->isChecked());
+ onBackToSearch();
+}
+
+LocationWidget::~LocationWidget()
+{
+ delete m_ui;
+}
+
+void LocationWidget::restoreSettings()
+{
+ QSettings settings;
+ Q_FOREACH(QVariant v, settings.value("recent-locations").toList()) {
+ m_recentAirports.push_back(v.toLongLong());
+ }
+
+ if (!m_recentAirports.empty()) {
+ setBaseLocation(NavDataCache::instance()->loadById(m_recentAirports.front()));
+ }
+
+ updateDescription();
+}
+
+bool LocationWidget::shouldStartPaused() const
+{
+ qWarning() << Q_FUNC_INFO << "implement me";
+ return false;
+}
+
+void LocationWidget::saveSettings()
+{
+ QSettings settings;
+
+ QVariantList locations;
+ Q_FOREACH(PositionedID v, m_recentAirports) {
+ locations.push_back(v);
+ }
+
+ settings.setValue("recent-airports", locations);
+}
+
+void LocationWidget::setLocationOptions()
+{
+ flightgear::Options* opt = flightgear::Options::sharedInstance();
+
+ if (!m_location) {
+ return;
+ }
+
+ if (FGAirport::isAirportType(m_location.ptr())) {
+ FGAirport* apt = static_cast<FGAirport*>(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<int>(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 LocationWidget::onSearch()
+{
+ QString search = m_ui->locationSearchEdit->text();
+ m_searchModel->setSearch(search);
+
+ if (m_searchModel->isSearchActive()) {
+ m_ui->searchStatusText->setText(QString("Searching for '%1'").arg(search));
+ m_ui->searchIcon->setVisible(true);
+ } else if (m_searchModel->rowCount(QModelIndex()) == 1) {
+ setBaseLocation(m_searchModel->itemAtRow(0));
+ }
+}
+
+void LocationWidget::onSearchComplete()
+{
+ QString search = m_ui->locationSearchEdit->text();
+ m_ui->searchIcon->setVisible(false);
+ m_ui->searchStatusText->setText(QString("Results for '%1'").arg(search));
+
+ int numResults = m_searchModel->rowCount(QModelIndex());
+ if (numResults == 0) {
+ m_ui->searchStatusText->setText(QString("No matches for '%1'").arg(search));
+ } else if (numResults == 1) {
+ setBaseLocation(m_searchModel->itemAtRow(0));
+ }
+}
+
+void LocationWidget::onLocationChanged()
+{
+ bool locIsAirport = FGAirport::isAirportType(m_location.ptr());
+ m_backButton->show();
+
+ if (locIsAirport) {
+ m_ui->stack->setCurrentIndex(0);
+ FGAirport* apt = static_cast<FGAirport*>(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; r<apt->numRunways(); ++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->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<qlonglong>(parking));
+
+ m_ui->airportDiagram->addParking(park);
+ }
+ }
+
+
+ } else {// of location is airport
+ // navaid
+ m_ui->stack->setCurrentIndex(1);
+ m_ui->navaidDiagram->setNavaid(m_location);
+ }
+}
+
+void LocationWidget::onOffsetEnabledToggled(bool on)
+{
+ m_ui->offsetDistanceLabel->setEnabled(on);
+// m_ui->offsetNmSpinbox->setEnabled(on);
+// m_ui->offsetBearingSpinbox->setEnabled(on);
+// m_ui->trueBearing->setEnabled(on);
+// m_ui->offsetBearingLabel->setEnabled(on);
+// m_ui->offsetDistanceLabel->setEnabled(on);
+}
+
+void LocationWidget::onAirportDiagramClicked(FGRunwayRef rwy)
+{
+ if (rwy) {
+ m_ui->runwayRadio->setChecked(true);
+ int rwyIndex = m_ui->runwayCombo->findText(QString::fromStdString(rwy->ident()));
+ m_ui->runwayCombo->setCurrentIndex(rwyIndex);
+ m_ui->airportDiagram->setSelectedRunway(rwy);
+ }
+
+ updateDescription();
+}
+
+QString LocationWidget::locationDescription() const
+{
+ if (!m_location)
+ return QString("No location selected");
+
+ bool locIsAirport = FGAirport::isAirportType(m_location.ptr());
+ QString ident = QString::fromStdString(m_location->ident()),
+ name = QString::fromStdString(m_location->name());
+
+ if (locIsAirport) {
+ FGAirport* apt = static_cast<FGAirport*>(m_location.ptr());
+ QString locationOnAirport;
+
+ if (m_ui->runwayRadio->isChecked()) {
+ bool onFinal = m_ui->onFinalCheckbox->isChecked();
+ int comboIndex = m_ui->runwayCombo->currentIndex();
+ QString runwayName = (comboIndex == 0) ?
+ "active runway" :
+ QString("runway %1").arg(m_ui->runwayCombo->currentText());
+
+ if (onFinal) {
+ int finalDistance = m_ui->approachDistanceSpin->value();
+ locationOnAirport = QString("on %2-mile final to %1").arg(runwayName).arg(finalDistance);
+ } else {
+ locationOnAirport = QString("on %1").arg(runwayName);
+ }
+ } else if (m_ui->parkingRadio->isChecked()) {
+ locationOnAirport = QString("at parking position %1").arg(m_ui->parkingCombo->currentText());
+ }
+
+ return QString("%2 (%1): %3").arg(ident).arg(name).arg(locationOnAirport);
+ } else {
+ QString navaidType;
+ switch (m_location->type()) {
+ case FGPositioned::VOR:
+ navaidType = QString("VOR"); break;
+ case FGPositioned::NDB:
+ navaidType = QString("NDB"); break;
+ case FGPositioned::FIX:
+ return QString("at waypoint %1").arg(ident);
+ default:
+ // unsupported type
+ break;
+ }
+
+ return QString("at %1 %2 (%3").arg(navaidType).arg(ident).arg(name);
+ }
+
+ return QString("Implement Me");
+}
+
+
+void LocationWidget::updateDescription()
+{
+ bool locIsAirport = FGAirport::isAirportType(m_location.ptr());
+ if (locIsAirport) {
+ FGAirport* apt = static_cast<FGAirport*>(m_location.ptr());
+
+ if (m_ui->runwayRadio->isChecked()) {
+ int comboIndex = m_ui->runwayCombo->currentIndex();
+ int runwayIndex = m_ui->runwayCombo->itemData(comboIndex).toInt();
+ // we can't figure out the active runway in the launcher (yet)
+ FGRunwayRef rwy = (runwayIndex >= 0) ?
+ apt->getRunwayByIndex(runwayIndex) : FGRunwayRef();
+ m_ui->airportDiagram->setSelectedRunway(rwy);
+ }
+
+ if (m_ui->onFinalCheckbox->isChecked()) {
+ m_ui->airportDiagram->setApproachExtensionDistance(m_ui->approachDistanceSpin->value());
+ } else {
+ m_ui->airportDiagram->setApproachExtensionDistance(0.0);
+ }
+ } else {
+
+ }
+
+#if 0
+
+ QString locationOnAirport;
+ if (m_ui->runwayRadio->isChecked()) {
+
+
+ } else if (m_ui->parkingRadio->isChecked()) {
+ locationOnAirport = QString("at parking position %1").arg(m_ui->parkingCombo->currentText());
+ }
+
+ m_ui->airportDescription->setText();
+#endif
+
+ emit descriptionChanged(locationDescription());
+}
+
+void LocationWidget::onSearchResultSelected(const QModelIndex& index)
+{
+ qDebug() << "selected result:" << index.data();
+ setBaseLocation(m_searchModel->itemAtRow(index.row()));
+}
+
+void LocationWidget::onOffsetBearingTrueChanged(bool on)
+{
+ m_ui->offsetBearingLabel->setText(on ? tr("True bearing:") :
+ tr("Magnetic bearing:"));
+}
+
+
+void LocationWidget::onPopupHistory()
+{
+ if (m_recentAirports.isEmpty()) {
+ return;
+ }
+
+#if 0
+ QMenu m;
+ Q_FOREACH(QString aptCode, m_recentAirports) {
+ FGAirportRef apt = FGAirport::findByIdent(aptCode.toStdString());
+ QString name = QString::fromStdString(apt->name());
+ QAction* act = m.addAction(QString("%1 - %2").arg(aptCode).arg(name));
+ act->setData(aptCode);
+ }
+
+ QPoint popupPos = m_ui->airportHistory->mapToGlobal(m_ui->airportHistory->rect().bottomLeft());
+ QAction* triggered = m.exec(popupPos);
+ if (triggered) {
+ FGAirportRef apt = FGAirport::findByIdent(triggered->data().toString().toStdString());
+ setAirport(apt);
+ m_ui->airportEdit->clear();
+ m_ui->locationStack->setCurrentIndex(0);
+ }
+#endif
+}
+
+void LocationWidget::setBaseLocation(FGPositionedRef ref)
+{
+ if (m_location == ref)
+ return;
+
+ m_location = ref;
+ onLocationChanged();
+
+#if 0
+ if (ref.valid()) {
+ // maintain the recent airport list
+ QString icao = QString::fromStdString(ref->ident());
+ if (m_recentAirports.contains(icao)) {
+ // move to front
+ m_recentAirports.removeOne(icao);
+ m_recentAirports.push_front(icao);
+ } else {
+ // insert and trim list if necessary
+ m_recentAirports.push_front(icao);
+ if (m_recentAirports.size() > MAX_RECENT_AIRPORTS) {
+ m_recentAirports.pop_back();
+ }
+ }
+ }
+#endif
+ updateDescription();
+}
+
+void LocationWidget::onOffsetDataChanged()
+{
+ qDebug() << "implement me";
+}
+
+void LocationWidget::onBackToSearch()
+{
+ m_ui->stack->setCurrentIndex(2);
+ m_backButton->hide();
+}
+
+#include "LocationWidget.moc"
--- /dev/null
+// LocationWidget.hxx - GUI launcher dialog using Qt5
+//
+// Written by James Turner, started October 2015.
+//
+// Copyright (C) 2015 James Turner <zakalawe@mac.com>
+//
+// 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 the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+#ifndef LOCATIONWIDGET_H
+#define LOCATIONWIDGET_H
+
+#include <QWidget>
+
+#include <QToolButton>
+#include <Navaids/positioned.hxx>
+#include <Airports/airports_fwd.hxx>
+
+namespace Ui {
+ class LocationWidget;
+}
+
+class NavSearchModel;
+
+class LocationWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit LocationWidget(QWidget *parent = 0);
+ ~LocationWidget();
+
+ void saveSettings();
+ void restoreSettings();
+
+ QString locationDescription() const;
+
+ void setBaseLocation(FGPositionedRef ref);
+
+ bool shouldStartPaused() const;
+
+ void setLocationOptions();
+Q_SIGNALS:
+ void descriptionChanged(QString t);
+
+private Q_SLOTS:
+ void updateDescription();
+
+ void onLocationChanged();
+
+ void onOffsetDataChanged();
+
+private:
+
+ void onSearch();
+
+
+ void onSearchResultSelected(const QModelIndex& index);
+ void onPopupHistory();
+ void onSearchComplete();
+
+ void onAirportDiagramClicked(FGRunwayRef rwy);
+ void onOffsetBearingTrueChanged(bool on);
+
+
+ Ui::LocationWidget *m_ui;
+
+ NavSearchModel* m_searchModel;
+
+ FGPositionedRef m_location;
+ QVector<PositionedID> m_recentAirports;
+
+ QToolButton* m_backButton;
+
+ void onOffsetEnabledToggled(bool on);
+ void onBackToSearch();
+};
+
+#endif // LOCATIONWIDGET_H
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>LocationWidget</class>
+ <widget class="QWidget" name="LocationWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>864</width>
+ <height>683</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QStackedWidget" name="stack">
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <widget class="QWidget" name="airportPage">
+ <layout class="QGridLayout" name="gridLayout" columnstretch="1,0,0,0">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item row="4" column="0">
+ <widget class="QRadioButton" name="parkingRadio">
+ <property name="text">
+ <string>Parking:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QRadioButton" name="runwayRadio">
+ <property name="text">
+ <string>Runway:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QCheckBox" name="onFinalCheckbox">
+ <property name="text">
+ <string>On final approach at distance:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1" colspan="3">
+ <widget class="QComboBox" name="parkingCombo"/>
+ </item>
+ <item row="3" column="3">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="1" colspan="3">
+ <widget class="QComboBox" name="runwayCombo"/>
+ </item>
+ <item row="1" column="0" colspan="4">
+ <widget class="AirportDiagram" name="airportDiagram" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QSpinBox" name="approachDistanceSpin">
+ <property name="suffix">
+ <string>nm</string>
+ </property>
+ <property name="value">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="navaidPage">
+ <layout class="QGridLayout" name="gridLayout_3" rowstretch="1,0,0,0,0">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item row="2" column="1" colspan="2">
+ <widget class="QSpinBox" name="airspeedSpinbox">
+ <property name="suffix">
+ <string>kts</string>
+ </property>
+ <property name="maximum">
+ <number>9999</number>
+ </property>
+ <property name="value">
+ <number>120</number>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="4" colspan="2">
+ <widget class="QSpinBox" name="altitudeSpinbox">
+ <property name="suffix">
+ <string>ft</string>
+ </property>
+ <property name="minimum">
+ <number>-1000</number>
+ </property>
+ <property name="maximum">
+ <number>120000</number>
+ </property>
+ <property name="singleStep">
+ <number>50</number>
+ </property>
+ <property name="value">
+ <number>5000</number>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="3">
+ <widget class="QLabel" name="altitudeLabel">
+ <property name="text">
+ <string>Altitude:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" rowspan="2" colspan="8">
+ <widget class="NavaidDiagram" name="navaidDiagram" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>200</height>
+ </size>
+ </property>
+ <zorder>offsetGroup</zorder>
+ </widget>
+ </item>
+ <item row="2" column="6" colspan="2">
+ <widget class="QComboBox" name="altitudeModeCombo">
+ <item>
+ <property name="text">
+ <string>Barometric altitude (ASL)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Above ground (AGL)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Flight Level (FL)</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="aispeedLabel">
+ <property name="text">
+ <string>Airspeed:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="8">
+ <widget class="QGroupBox" name="offsetGroup">
+ <property name="title">
+ <string>Offset</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="offsetBearingLabel">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Bearing:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="offsetBearingSpinbox">
+ <property name="wrapping">
+ <bool>true</bool>
+ </property>
+ <property name="maximum">
+ <number>359</number>
+ </property>
+ <property name="singleStep">
+ <number>5</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="trueBearing">
+ <property name="text">
+ <string>True</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="offsetDistanceLabel">
+ <property name="text">
+ <string>Distance:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDoubleSpinBox" name="offsetNmSpinbox">
+ <property name="suffix">
+ <string>nm</string>
+ </property>
+ <property name="decimals">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <double>10000.000000000000000</double>
+ </property>
+ <property name="value">
+ <double>10.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="searchPage">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_6">
+ <item>
+ <widget class="QLabel" name="searchLabel">
+ <property name="text">
+ <string>Search:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="locationSearchEdit">
+ <property name="placeholderText">
+ <string>Enter an ICAO code, navaid or search by name</string>
+ </property>
+ <property name="clearButtonEnabled">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="searchHistory">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="searchStatusText">
+ <property name="text">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignHCenter|Qt::AlignTop</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="searchIcon">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignBottom|Qt::AlignHCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QListView" name="searchResultsList"/>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>AirportDiagram</class>
+ <extends>QWidget</extends>
+ <header location="global">GUI/AirportDiagram.hxx</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>NavaidDiagram</class>
+ <extends>QWidget</extends>
+ <header location="global">GUI/NavaidDiagram.hxx</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
--- /dev/null
+// NavaidDiagram.cxx - part of GUI launcher using Qt5
+//
+// Written by James Turner, started October 2015.
+//
+// Copyright (C) 2014 James Turner <zakalawe@mac.com>
+//
+// 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 the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+#include "NavaidDiagram.hxx"
+
+#include <limits>
+
+#include <QPainter>
+#include <QDebug>
+#include <QVector2D>
+#include <QMouseEvent>
+
+NavaidDiagram::NavaidDiagram(QWidget* pr) :
+ BaseDiagram(pr),
+ m_offsetEnabled(false),
+ m_offsetDistanceNm(5.0),
+ m_offsetBearingDeg(0),
+ m_headingDeg(0)
+{
+
+}
+
+void NavaidDiagram::setNavaid(FGPositionedRef nav)
+{
+ m_navaid = nav;
+ m_projectionCenter = nav ? nav->geod() : SGGeod();
+ m_scale = 1.0;
+ m_bounds = QRectF(); // clear
+ update();
+}
+
+void NavaidDiagram::paintContents(QPainter *)
+{
+
+}
--- /dev/null
+// NavaidDiagram.hxx - part of GUI launcher using Qt5
+//
+// Written by James Turner, started October 2015.
+//
+// Copyright (C) 2014 James Turner <zakalawe@mac.com>
+//
+// 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 the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+#ifndef GUI_NAVAID_DIAGRAM_HXX
+#define GUI_NAVAID_DIAGRAM_HXX
+
+#include "BaseDiagram.hxx"
+#include <QPainterPath>
+
+#include <Navaids/navrecord.hxx>
+#include <simgear/math/sg_geodesy.hxx>
+
+class NavaidDiagram : public BaseDiagram
+{
+ Q_OBJECT
+public:
+ NavaidDiagram(QWidget* pr);
+
+ void setNavaid(FGPositionedRef nav);
+
+ bool isOffsetEnabled() const;
+ void setOffsetEnabled(bool m_offset);
+
+ void setOffsetDistanceNm(double distanceNm);
+ double offsetDistanceNm() const;
+
+ void setOffsetBearingDeg(int bearingDeg);
+ int offsetBearingDeg() const;
+
+ void setHeadingDeg(int headingDeg);
+ void headingDeg() const;
+protected:
+ void paintContents(QPainter *) Q_DECL_OVERRIDE;
+
+private:
+ FGPositionedRef m_navaid;
+
+ bool m_offsetEnabled;
+ double m_offsetDistanceNm;
+ int m_offsetBearingDeg;
+ int m_headingDeg;
+};
+
+#endif // of GUI_NAVAID_DIAGRAM_HXX
#include <Main/globals.hxx>
#include <Navaids/NavDataCache.hxx>
-#include <Airports/airport.hxx>
-#include <Airports/dynamics.hxx> // for parking
#include <Navaids/navrecord.hxx>
#include <Main/options.hxx>
using namespace flightgear;
using namespace simgear::pkg;
-const int MAX_RECENT_AIRPORTS = 32;
const int MAX_RECENT_AIRCRAFT = 20;
namespace { // anonymous namespace
// choosing to fail for now
return QList<Arg>();
}
+ } else if (c == QChar('#')) {
+ state = Comment;
+ break;
} else if (c.isSpace()) {
break;
}
value.append(c);
}
break;
+
+ case Comment:
+ if ((c == QChar('\n')) || (c == QChar('\r'))) {
+ state = Start;
+ break;
+ } else {
+ // nothing to do, eat comment chars
+ }
+ break;
} // of state switch
} // of character loop
Start = 0,
Key,
Value,
- Quoted
+ Quoted,
+ Comment
};
};
} // of anonymous namespace
+<<<<<<< 56d7d049bc0b7361d1799298c38e61084f5d5e3f
class IdentSearchFilter : public FGPositioned::TypeFilter
{
public:
bool m_searchActive;
QScopedPointer<NavDataCache::ThreadedGUISearch> m_search;
};
+=======
+>>>>>>> Work on LocationWidget for Qt launcher
class AircraftProxyModel : public QSortFilterProxyModel
{
this, &QtLauncher::onSubsytemIdleTimeout);
m_subsystemIdleTimer->start();
- m_airportsModel = new AirportSearchModel;
- m_ui->searchList->setModel(m_airportsModel);
- connect(m_ui->searchList, &QListView::clicked,
- this, &QtLauncher::onAirportChoiceSelected);
- connect(m_airportsModel, &AirportSearchModel::searchComplete,
- this, &QtLauncher::onAirportSearchComplete);
-
// create and configure the proxy model
m_aircraftProxy = new AircraftProxyModel(this);
connect(m_ui->ratingsFilterCheck, &QAbstractButton::toggled,
connect(m_ui->aircraftFilter, &QLineEdit::textChanged,
m_aircraftProxy, &QSortFilterProxyModel::setFilterFixedString);
+<<<<<<< 56d7d049bc0b7361d1799298c38e61084f5d5e3f
connect(m_ui->runwayCombo, SIGNAL(currentIndexChanged(int)),
this, SLOT(updateLocationDescription()));
connect(m_ui->parkingCombo, SIGNAL(currentIndexChanged(int)),
connect(m_ui->airportDiagram, &AirportDiagram::clickedRunway,
this, &QtLauncher::onAirportDiagramClicked);
+=======
+>>>>>>> Work on LocationWidget for Qt launcher
connect(m_ui->runButton, SIGNAL(clicked()), this, SLOT(onRun()));
connect(m_ui->quitButton, SIGNAL(clicked()), this, SLOT(onQuit()));
- connect(m_ui->airportEdit, SIGNAL(returnPressed()),
- this, SLOT(onSearchAirports()));
- connect(m_ui->airportHistory, &QPushButton::clicked,
- this, &QtLauncher::onPopupAirportHistory);
connect(m_ui->aircraftHistory, &QPushButton::clicked,
this, &QtLauncher::onPopupAircraftHistory);
+ connect(m_ui->location, &LocationWidget::descriptionChanged,
+ m_ui->locationDescription, &QLabel::setText);
+
QAction* qa = new QAction(this);
qa->setShortcut(QKeySequence("Ctrl+Q"));
connect(qa, &QAction::triggered, this, &QtLauncher::onQuit);
QIcon historyIcon(":/history-icon");
m_ui->aircraftHistory->setIcon(historyIcon);
- m_ui->airportHistory->setIcon(historyIcon);
-
- m_ui->searchIcon->setPixmap(QPixmap(":/search-icon"));
connect(m_ui->timeOfDayCombo, SIGNAL(currentIndexChanged(int)),
this, SLOT(updateSettingsSummary()));
connect(m_ui->pathsButton, &QPushButton::clicked,
this, &QtLauncher::onEditPaths);
-
- connect(m_ui->trueBearing, &QCheckBox::toggled, this, &QtLauncher::onOffsetBearingTrueChanged);
- connect(m_ui->offsetRadioButton, &QRadioButton::toggled,
- this, &QtLauncher::onOffsetRadioToggled);
- connect(m_ui->trueBearing, &QCheckBox::toggled, this, &QtLauncher::onOffsetDataChanged);
- connect(m_ui->offsetBearingSpinbox, SIGNAL(valueChanged(int)), this, SLOT(onOffsetDataChanged()));
- connect(m_ui->offsetNmSpinbox, SIGNAL(valueChanged(double)),
- this, SLOT(onOffsetDataChanged()));
-
restoreSettings();
QSettings settings;
}
updateSelectedAircraft();
-
- Q_FOREACH(QVariant v, settings.value("recent-locations").toList()) {
- m_recentAirports.push_back(v.toLongLong());
- }
-
- if (!m_recentAirports.empty()) {
- setBaseLocation(NavDataCache::instance()->loadById(m_recentAirports.front()));
- }
- updateLocationDescription();
+ m_ui->location->restoreSettings();
// rating filters
m_ui->ratingsFilterCheck->setChecked(settings.value("ratings-filter", true).toBool());
settings.setValue("ratings-filter", m_ui->ratingsFilterCheck->isChecked());
settings.setValue("recent-aircraft", QUrl::toStringList(m_recentAircraft));
- 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());
+
+ m_ui->location->saveSettings();
}
void QtLauncher::setEnableDisableOptionFromCheckbox(QCheckBox* cbox, QString name) const
m_recentAircraft.pop_back();
}
- setLocationOptions();
+ m_ui->location->setLocationOptions();
// time of day
if (m_ui->timeOfDayCombo->currentIndex() != 0) {
saveSettings();
}
-void QtLauncher::setLocationOptions()
-{
- flightgear::Options* opt = flightgear::Options::sharedInstance();
-
- if (!m_location) {
- return;
- }
-
- if (FGAirport::isAirportType(m_location.ptr())) {
- FGAirport* apt = static_cast<FGAirport*>(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<int>(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()
{
reject();
}
+<<<<<<< 56d7d049bc0b7361d1799298c38e61084f5d5e3f
void QtLauncher::onSearchAirports()
{
QString search = m_ui->airportEdit->text();
updateLocationDescription();
}
+=======
+>>>>>>> Work on LocationWidget for Qt launcher
void QtLauncher::onToggleTerrasync(bool enabled)
{
maybeUpdateSelectedAircraft(index);
}
-void QtLauncher::updateLocationDescription()
-{
- if (!m_location) {
- m_ui->airportDescription->setText(QString("No location selected"));
- return;
- }
-
- QString ident = QString::fromStdString(m_location->ident()),
- name = QString::fromStdString(m_location->name());
- QString locationOnAirport;
- if (m_ui->runwayRadio->isChecked()) {
- FGAirport* apt = static_cast<FGAirport*>(m_location.ptr());
- bool onFinal = m_ui->onFinalCheckbox->isChecked();
- int comboIndex = m_ui->runwayCombo->currentIndex();
- QString runwayName = (comboIndex == 0) ?
- "active runway" :
- QString("runway %1").arg(m_ui->runwayCombo->currentText());
-
- if (onFinal) {
- locationOnAirport = QString("on 10-mile final to %1").arg(runwayName);
- } else {
- locationOnAirport = QString("on %1").arg(runwayName);
- }
-
- int runwayIndex = m_ui->runwayCombo->itemData(comboIndex).toInt();
- FGRunwayRef rwy = (runwayIndex >= 0) ?
- 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());
- }
-
- m_ui->airportDescription->setText(QString("%2 (%1): %3").arg(ident).arg(name).arg(locationOnAirport));
-}
-
-void QtLauncher::onAirportChoiceSelected(const QModelIndex& index)
-{
- m_ui->locationStack->setCurrentIndex(0);
- setBaseLocation(m_airportsModel->itemAtRow(index.row()));
-}
-
-void QtLauncher::onOffsetBearingTrueChanged(bool on)
-{
- m_ui->offsetBearingLabel->setText(on ? tr("True bearing:") :
- tr("Magnetic bearing:"));
-}
-
void QtLauncher::onAircraftSelected(const QModelIndex& index)
{
m_selectedAircraft = index.data(AircraftURIRole).toUrl();
}
}
-void QtLauncher::onPopupAirportHistory()
-{
- if (m_recentAirports.isEmpty()) {
- return;
- }
-
-#if 0
- QMenu m;
- Q_FOREACH(QString aptCode, m_recentAirports) {
- FGAirportRef apt = FGAirport::findByIdent(aptCode.toStdString());
- QString name = QString::fromStdString(apt->name());
- QAction* act = m.addAction(QString("%1 - %2").arg(aptCode).arg(name));
- act->setData(aptCode);
- }
-
- QPoint popupPos = m_ui->airportHistory->mapToGlobal(m_ui->airportHistory->rect().bottomLeft());
- QAction* triggered = m.exec(popupPos);
- if (triggered) {
- FGAirportRef apt = FGAirport::findByIdent(triggered->data().toString().toStdString());
- setAirport(apt);
- m_ui->airportEdit->clear();
- m_ui->locationStack->setCurrentIndex(0);
- }
-#endif
-}
-
QModelIndex QtLauncher::proxyIndexForAircraftURI(QUrl uri) const
{
return m_aircraftProxy->mapFromSource(sourceIndexForAircraftURI(uri));
}
}
-void QtLauncher::setBaseLocation(FGPositionedRef ref)
-{
- if (m_location == ref)
- return;
-
- m_location = ref;
- onLocationChanged();
-
-#if 0
- if (ref.valid()) {
- // maintain the recent airport list
- QString icao = QString::fromStdString(ref->ident());
- if (m_recentAirports.contains(icao)) {
- // move to front
- m_recentAirports.removeOne(icao);
- m_recentAirports.push_front(icao);
- } else {
- // insert and trim list if necessary
- m_recentAirports.push_front(icao);
- if (m_recentAirports.size() > MAX_RECENT_AIRPORTS) {
- m_recentAirports.pop_back();
- }
- }
- }
-#endif
-
- updateLocationDescription();
-}
-
void QtLauncher::onEditRatingsFilter()
{
EditRatingsFilterDialog dialog(this);
return globals->packageRoot()->getPackageById(ident.toStdString());
}
-void QtLauncher::onOffsetDataChanged()
-{
- qDebug() << "implement me";
-}
#include "QtLauncher.moc"
#include <QTimer>
#include <QUrl>
-
-#include <Airports/airport.hxx>
#include <simgear/package/Package.hxx>
#include <simgear/package/Catalog.hxx>
class Launcher;
}
-class AirportSearchModel;
class QModelIndex;
class AircraftProxyModel;
class AircraftItemModel;
void onQuit();
- void onSearchAirports();
-
- void onLocationChanged();
- void onAirportChoiceSelected(const QModelIndex& index);
void onAircraftSelected(const QModelIndex& index);
void onRequestPackageInstall(const QModelIndex& index);
void onCancelDownload(const QModelIndex& index);
- void onPopupAirportHistory();
void onPopupAircraftHistory();
void onEditRatingsFilter();
- void updateLocationDescription();
void updateSettingsSummary();
- void onAirportSearchComplete();
void onRembrandtToggled(bool b);
void onToggleTerrasync(bool enabled);
void onEditPaths();
- void onAirportDiagramClicked(FGRunwayRef rwy);
- void onOffsetBearingTrueChanged(bool on);
-
- void onOffsetDataChanged();
- void onOffsetRadioToggled(bool on);
void onAircraftInstalledCompleted(QModelIndex index);
void onAircraftInstallFailed(QModelIndex index, QString errorMessage);
private:
- void setLocationOptions();
- void setBaseLocation(FGPositionedRef ref);
/**
* Check if the passed index is the selected aircraft, and if so, refresh
simgear::pkg::PackageRef packageForAircraftURI(QUrl uri) const;
QScopedPointer<Ui::Launcher> m_ui;
- AirportSearchModel* m_airportsModel;
AircraftProxyModel* m_aircraftProxy;
AircraftItemModel* m_aircraftModel;
- FGPositionedRef m_location;
QUrl m_selectedAircraft;
QList<QUrl> m_recentAircraft;
- QVector<PositionedID> m_recentAirports;
QTimer* m_subsystemIdleTimer;
bool m_inAppMode;