Work on LocationWidget for Qt launcher
This commit is contained in:
parent
56d7d049bc
commit
09cac14089
13 changed files with 1677 additions and 566 deletions
|
@ -32,18 +32,6 @@
|
|||
#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)
|
||||
{
|
||||
|
@ -89,26 +77,29 @@ static double distanceToLineSegment(const QVector2D& p, const QVector2D& a,
|
|||
}
|
||||
|
||||
AirportDiagram::AirportDiagram(QWidget* pr) :
|
||||
QWidget(pr)
|
||||
BaseDiagram(pr),
|
||||
m_approachDistanceNm(-1.0)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::MinimumExpanding,
|
||||
QSizePolicy::MinimumExpanding);
|
||||
setMinimumSize(100, 100);
|
||||
}
|
||||
|
||||
AirportDiagram::~AirportDiagram()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -127,6 +118,13 @@ void AirportDiagram::setSelectedRunway(FGRunwayRef r)
|
|||
update();
|
||||
}
|
||||
|
||||
void AirportDiagram::setApproachExtensionDistance(double distanceNm)
|
||||
{
|
||||
m_approachDistanceNm = distanceNm;
|
||||
recomputeBounds(true);
|
||||
update();
|
||||
}
|
||||
|
||||
void AirportDiagram::addRunway(FGRunwayRef rwy)
|
||||
{
|
||||
Q_FOREACH(RunwayData rd, m_runways) {
|
||||
|
@ -135,76 +133,78 @@ void AirportDiagram::addRunway(FGRunwayRef rwy)
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void AirportDiagram::addParking(FGParkingRef park)
|
||||
{
|
||||
ParkingData pd = { project(park->geod()), park };
|
||||
m_parking.push_back(pd);
|
||||
recomputeBounds(false);
|
||||
update();
|
||||
}
|
||||
|
||||
QTransform AirportDiagram::transform() const
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
void AirportDiagram::paintEvent(QPaintEvent* pe)
|
||||
void AirportDiagram::paintContents(QPainter* p)
|
||||
{
|
||||
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);
|
||||
// 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);
|
||||
|
@ -212,40 +212,54 @@ void AirportDiagram::paintEvent(QPaintEvent* pe)
|
|||
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;
|
||||
|
@ -271,57 +285,6 @@ void AirportDiagram::mouseReleaseEvent(QMouseEvent* me)
|
|||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
@ -331,8 +294,7 @@ void AirportDiagram::buildTaxiways()
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -18,49 +18,48 @@
|
|||
// 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;
|
||||
|
@ -68,7 +67,7 @@ private:
|
|||
FGRunwayRef runway;
|
||||
};
|
||||
|
||||
QList<RunwayData> m_runways;
|
||||
QVector<RunwayData> m_runways;
|
||||
|
||||
struct TaxiwayData {
|
||||
QPointF p1, p2;
|
||||
|
@ -80,8 +79,19 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
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
|
||||
|
|
205
src/GUI/BaseDiagram.cxx
Normal file
205
src/GUI/BaseDiagram.cxx
Normal file
|
@ -0,0 +1,205 @@
|
|||
// 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;
|
||||
}
|
65
src/GUI/BaseDiagram.hxx
Normal file
65
src/GUI/BaseDiagram.hxx
Normal file
|
@ -0,0 +1,65 @@
|
|||
// 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
|
|
@ -74,7 +74,8 @@ if (HAVE_QT)
|
|||
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)
|
||||
|
@ -82,8 +83,12 @@ if (HAVE_QT)
|
|||
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
|
||||
|
@ -98,6 +103,8 @@ if (HAVE_QT)
|
|||
AddCatalogDialog.hxx
|
||||
PathsDialog.cxx
|
||||
PathsDialog.hxx
|
||||
LocationWidget.cxx
|
||||
LocationWidget.hxx
|
||||
${uic_sources}
|
||||
${qrc_sources})
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="airportDescription">
|
||||
<widget class="QLabel" name="locationDescription">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
|
@ -231,207 +231,7 @@
|
|||
<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>
|
||||
|
@ -721,9 +521,9 @@
|
|||
</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>
|
||||
|
|
660
src/GUI/LocationWidget.cxx
Normal file
660
src/GUI/LocationWidget.cxx
Normal file
|
@ -0,0 +1,660 @@
|
|||
// 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"
|
90
src/GUI/LocationWidget.hxx
Normal file
90
src/GUI/LocationWidget.hxx
Normal file
|
@ -0,0 +1,90 @@
|
|||
// 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
|
385
src/GUI/LocationWidget.ui
Normal file
385
src/GUI/LocationWidget.ui
Normal file
|
@ -0,0 +1,385 @@
|
|||
<?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>
|
52
src/GUI/NavaidDiagram.cxx
Normal file
52
src/GUI/NavaidDiagram.cxx
Normal file
|
@ -0,0 +1,52 @@
|
|||
// 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 *)
|
||||
{
|
||||
|
||||
}
|
61
src/GUI/NavaidDiagram.hxx
Normal file
61
src/GUI/NavaidDiagram.hxx
Normal file
|
@ -0,0 +1,61 @@
|
|||
// 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
|
|
@ -63,8 +63,6 @@
|
|||
|
||||
#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>
|
||||
|
@ -75,7 +73,6 @@
|
|||
using namespace flightgear;
|
||||
using namespace simgear::pkg;
|
||||
|
||||
const int MAX_RECENT_AIRPORTS = 32;
|
||||
const int MAX_RECENT_AIRCRAFT = 20;
|
||||
|
||||
namespace { // anonymous namespace
|
||||
|
@ -170,6 +167,9 @@ public:
|
|||
// choosing to fail for now
|
||||
return QList<Arg>();
|
||||
}
|
||||
} else if (c == QChar('#')) {
|
||||
state = Comment;
|
||||
break;
|
||||
} else if (c.isSpace()) {
|
||||
break;
|
||||
}
|
||||
|
@ -211,6 +211,15 @@ public:
|
|||
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
|
||||
|
||||
|
@ -229,12 +238,14 @@ private:
|
|||
Start = 0,
|
||||
Key,
|
||||
Value,
|
||||
Quoted
|
||||
Quoted,
|
||||
Comment
|
||||
};
|
||||
};
|
||||
|
||||
} // of anonymous namespace
|
||||
|
||||
<<<<<<< 56d7d049bc0b7361d1799298c38e61084f5d5e3f
|
||||
class IdentSearchFilter : public FGPositioned::TypeFilter
|
||||
{
|
||||
public:
|
||||
|
@ -356,6 +367,8 @@ private:
|
|||
bool m_searchActive;
|
||||
QScopedPointer<NavDataCache::ThreadedGUISearch> m_search;
|
||||
};
|
||||
=======
|
||||
>>>>>>> Work on LocationWidget for Qt launcher
|
||||
|
||||
class AircraftProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
|
@ -525,13 +538,6 @@ QtLauncher::QtLauncher() :
|
|||
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,
|
||||
|
@ -539,6 +545,7 @@ QtLauncher::QtLauncher() :
|
|||
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)),
|
||||
|
@ -553,17 +560,18 @@ QtLauncher::QtLauncher() :
|
|||
|
||||
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);
|
||||
|
@ -574,9 +582,6 @@ QtLauncher::QtLauncher() :
|
|||
|
||||
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()));
|
||||
|
@ -629,15 +634,6 @@ QtLauncher::QtLauncher() :
|
|||
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;
|
||||
|
@ -732,15 +728,7 @@ void QtLauncher::restoreSettings()
|
|||
}
|
||||
|
||||
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());
|
||||
|
@ -767,15 +755,11 @@ void QtLauncher::saveSettings()
|
|||
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
|
||||
|
@ -836,7 +820,7 @@ void QtLauncher::onRun()
|
|||
m_recentAircraft.pop_back();
|
||||
}
|
||||
|
||||
setLocationOptions();
|
||||
m_ui->location->setLocationOptions();
|
||||
|
||||
// time of day
|
||||
if (m_ui->timeOfDayCombo->currentIndex() != 0) {
|
||||
|
@ -895,53 +879,6 @@ void QtLauncher::onRun()
|
|||
saveSettings();
|
||||
}
|
||||
|
||||
void QtLauncher::setLocationOptions()
|
||||
{
|
||||
flightgear::Options* opt = flightgear::Options::sharedInstance();
|
||||
|
||||
if (!m_location) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (FGAirport::isAirportType(m_location.ptr())) {
|
||||
FGAirport* apt = static_cast<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()
|
||||
{
|
||||
|
@ -988,6 +925,7 @@ void QtLauncher::onQuit()
|
|||
reject();
|
||||
}
|
||||
|
||||
<<<<<<< 56d7d049bc0b7361d1799298c38e61084f5d5e3f
|
||||
void QtLauncher::onSearchAirports()
|
||||
{
|
||||
QString search = m_ui->airportEdit->text();
|
||||
|
@ -1085,6 +1023,8 @@ void QtLauncher::onAirportDiagramClicked(FGRunwayRef rwy)
|
|||
|
||||
updateLocationDescription();
|
||||
}
|
||||
=======
|
||||
>>>>>>> Work on LocationWidget for Qt launcher
|
||||
|
||||
void QtLauncher::onToggleTerrasync(bool enabled)
|
||||
{
|
||||
|
@ -1142,53 +1082,6 @@ void QtLauncher::onAircraftInstallFailed(QModelIndex index, QString errorMessage
|
|||
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();
|
||||
|
@ -1244,32 +1137,6 @@ void QtLauncher::updateSelectedAircraft()
|
|||
}
|
||||
}
|
||||
|
||||
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));
|
||||
|
@ -1311,35 +1178,6 @@ void QtLauncher::onPopupAircraftHistory()
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -1427,9 +1265,5 @@ simgear::pkg::PackageRef QtLauncher::packageForAircraftURI(QUrl uri) const
|
|||
return globals->packageRoot()->getPackageById(ident.toStdString());
|
||||
}
|
||||
|
||||
void QtLauncher::onOffsetDataChanged()
|
||||
{
|
||||
qDebug() << "implement me";
|
||||
}
|
||||
|
||||
#include "QtLauncher.moc"
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
|
||||
|
||||
#include <Airports/airport.hxx>
|
||||
#include <simgear/package/Package.hxx>
|
||||
#include <simgear/package/Catalog.hxx>
|
||||
|
||||
|
@ -38,7 +36,6 @@ namespace Ui
|
|||
class Launcher;
|
||||
}
|
||||
|
||||
class AirportSearchModel;
|
||||
class QModelIndex;
|
||||
class AircraftProxyModel;
|
||||
class AircraftItemModel;
|
||||
|
@ -64,24 +61,17 @@ private slots:
|
|||
|
||||
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);
|
||||
|
@ -90,17 +80,10 @@ private slots:
|
|||
|
||||
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
|
||||
|
@ -120,14 +103,11 @@ private:
|
|||
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;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue