Launcher: location page in QtQuick
This moves the last page into QQ2 implementation, in preparation for making the top-level UI be a QQuickWindow.
This commit is contained in:
parent
7e8b1b67e7
commit
b2f90fbfa4
34 changed files with 3168 additions and 2034 deletions
|
@ -16,8 +16,10 @@ using namespace flightgear;
|
|||
* FGTaxiNode
|
||||
*************************************************************************/
|
||||
|
||||
FGTaxiNode::FGTaxiNode(int index, const SGGeod& pos, bool aOnRunway, int aHoldType) :
|
||||
FGPositioned(TRANSIENT_ID, FGPositioned::PARKING, "", pos),
|
||||
FGTaxiNode::FGTaxiNode(int index, const SGGeod& pos,
|
||||
bool aOnRunway, int aHoldType,
|
||||
const std::string& ident) :
|
||||
FGPositioned(TRANSIENT_ID, FGPositioned::PARKING, ident, pos),
|
||||
m_index(index),
|
||||
isOnRunway(aOnRunway),
|
||||
holdType(aHoldType),
|
||||
|
|
|
@ -31,7 +31,8 @@ protected:
|
|||
bool m_isPushback;
|
||||
|
||||
public:
|
||||
FGTaxiNode(int index, const SGGeod& pos, bool aOnRunway, int aHoldType);
|
||||
FGTaxiNode(int index, const SGGeod& pos, bool aOnRunway, int aHoldType,
|
||||
const std::string& ident = {});
|
||||
virtual ~FGTaxiNode();
|
||||
|
||||
void setElevation(double val);
|
||||
|
|
|
@ -42,10 +42,9 @@ FGParking::FGParking(int index,
|
|||
const std::string& name,
|
||||
const std::string& aType,
|
||||
const std::string& codes) :
|
||||
FGTaxiNode(index, pos, false, 0),
|
||||
FGTaxiNode(index, pos, false, 0, name),
|
||||
heading(aHeading),
|
||||
radius(aRadius),
|
||||
parkingName(name),
|
||||
type(aType),
|
||||
airlineCodes(codes)
|
||||
{
|
||||
|
|
|
@ -42,7 +42,6 @@ class FGParking : public FGTaxiNode
|
|||
private:
|
||||
const double heading;
|
||||
const double radius;
|
||||
const std::string parkingName;
|
||||
const std::string type;
|
||||
const std::string airlineCodes;
|
||||
FGTaxiNodeRef pushBackPoint;
|
||||
|
@ -64,10 +63,7 @@ public:
|
|||
|
||||
std::string getType () const { return type; };
|
||||
std::string getCodes () const { return airlineCodes;};
|
||||
std::string getName () const { return parkingName; };
|
||||
|
||||
// TODO do parkings have different name and ident?
|
||||
virtual const std::string& name() const { return parkingName; }
|
||||
std::string getName () const { return ident(); };
|
||||
|
||||
void setPushBackPoint(const FGTaxiNodeRef& node);
|
||||
FGTaxiNodeRef getPushBackPoint () { return pushBackPoint; };
|
||||
|
|
|
@ -33,8 +33,12 @@
|
|||
#include <Airports/runways.hxx>
|
||||
#include <Airports/parking.hxx>
|
||||
#include <Airports/pavement.hxx>
|
||||
#include <Airports/groundnetwork.hxx>
|
||||
|
||||
#include <Navaids/navrecord.hxx>
|
||||
#include <Navaids/NavDataCache.hxx>
|
||||
|
||||
#include "QmlPositioned.hxx"
|
||||
|
||||
static double distanceToLineSegment(const QVector2D& p, const QVector2D& a,
|
||||
const QVector2D& b, double* outT = NULL)
|
||||
|
@ -86,7 +90,7 @@ static double unitLengthAfterMapping(const QTransform& t)
|
|||
return QVector2D(tVec).length();
|
||||
}
|
||||
|
||||
AirportDiagram::AirportDiagram(QWidget* pr) :
|
||||
AirportDiagram::AirportDiagram(QQuickItem* pr) :
|
||||
BaseDiagram(pr),
|
||||
m_approachDistanceNm(-1.0)
|
||||
{
|
||||
|
@ -133,10 +137,29 @@ void AirportDiagram::setAirport(FGAirportRef apt)
|
|||
m_airport = apt;
|
||||
m_projectionCenter = apt ? apt->geod() : SGGeod();
|
||||
m_runways.clear();
|
||||
m_approachDistanceNm = -1.0; m_parking.clear();
|
||||
m_parking.clear();
|
||||
m_helipads.clear();
|
||||
|
||||
if (apt) {
|
||||
if (apt->type() == FGPositioned::HELIPORT) {
|
||||
for (unsigned int r=0; r<apt->numHelipads(); ++r) {
|
||||
FGHelipadRef pad = apt->getHelipadByIndex(r);
|
||||
// add pad with index as data role
|
||||
addHelipad(pad);
|
||||
}
|
||||
} else {
|
||||
for (unsigned int r=0; r<apt->numRunways(); ++r) {
|
||||
addRunway(apt->getRunwayByIndex(r));
|
||||
}
|
||||
}
|
||||
|
||||
FGGroundNetwork* ground = apt->groundNetwork();
|
||||
if (ground && ground->exists()) {
|
||||
for (auto park : ground->allParkings()) {
|
||||
addParking(park);
|
||||
}
|
||||
} // of was able to get ground-network
|
||||
|
||||
buildTaxiways();
|
||||
buildPavements();
|
||||
}
|
||||
|
@ -148,48 +171,23 @@ void AirportDiagram::setAirport(FGAirportRef apt)
|
|||
update();
|
||||
}
|
||||
|
||||
FGRunwayRef AirportDiagram::selectedRunway() const
|
||||
void AirportDiagram::setSelection(QmlPositioned* pos)
|
||||
{
|
||||
return m_selectedRunway;
|
||||
}
|
||||
|
||||
void AirportDiagram::setSelectedRunway(FGRunwayRef r)
|
||||
{
|
||||
if (r == m_selectedRunway) {
|
||||
if (pos && (m_selection == pos->inner())) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_selectedParking.clear();
|
||||
m_selectedHelipad.clear();
|
||||
m_selectedRunway = r;
|
||||
update();
|
||||
}
|
||||
|
||||
void AirportDiagram::setSelectedHelipad(FGHelipadRef pad)
|
||||
{
|
||||
if (pad == m_selectedHelipad) {
|
||||
return;
|
||||
if (!pos) {
|
||||
m_selection.clear();
|
||||
} else {
|
||||
m_selection = pos->inner();
|
||||
}
|
||||
|
||||
m_selectedParking.clear();
|
||||
m_selectedRunway.clear();
|
||||
m_selectedHelipad = pad;
|
||||
emit selectionChanged();
|
||||
recomputeBounds(true);
|
||||
update();
|
||||
}
|
||||
|
||||
void AirportDiagram::setSelectedParking(FGParkingRef park)
|
||||
{
|
||||
if (m_selectedParking == park) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_selectedRunway.clear();
|
||||
m_selectedHelipad.clear();
|
||||
m_selectedParking = park;
|
||||
update();
|
||||
}
|
||||
|
||||
void AirportDiagram::setApproachExtensionDistance(double distanceNm)
|
||||
void AirportDiagram::setApproachExtensionNm(double distanceNm)
|
||||
{
|
||||
if (m_approachDistanceNm == distanceNm) {
|
||||
return;
|
||||
|
@ -198,6 +196,38 @@ void AirportDiagram::setApproachExtensionDistance(double distanceNm)
|
|||
m_approachDistanceNm = distanceNm;
|
||||
recomputeBounds(true);
|
||||
update();
|
||||
emit approachExtensionChanged();
|
||||
}
|
||||
|
||||
double AirportDiagram::approachExtensionNm() const
|
||||
{
|
||||
return m_approachDistanceNm;
|
||||
}
|
||||
|
||||
QmlPositioned* AirportDiagram::selection() const
|
||||
{
|
||||
if (!m_selection)
|
||||
return nullptr;
|
||||
|
||||
return new QmlPositioned{m_selection};
|
||||
}
|
||||
|
||||
qlonglong AirportDiagram::airportGuid() const
|
||||
{
|
||||
if (!m_airport)
|
||||
return 0;
|
||||
return m_airport->guid();
|
||||
}
|
||||
|
||||
void AirportDiagram::setAirportGuid(qlonglong guid)
|
||||
{
|
||||
if (guid == -1) {
|
||||
m_airport.clear();
|
||||
} else {
|
||||
m_airport = fgpositioned_cast<FGAirport>(flightgear::NavDataCache::instance()->loadById(guid));
|
||||
}
|
||||
setAirport(m_airport);
|
||||
emit airportChanged();
|
||||
}
|
||||
|
||||
void AirportDiagram::addRunway(FGRunwayRef rwy)
|
||||
|
@ -233,16 +263,17 @@ void AirportDiagram::doComputeBounds()
|
|||
}
|
||||
|
||||
Q_FOREACH(const ParkingData& p, m_parking) {
|
||||
extendBounds(p.pt);
|
||||
extendBounds(p.pt, 10.0);
|
||||
}
|
||||
|
||||
Q_FOREACH(const HelipadData& p, m_helipads) {
|
||||
extendBounds(p.pt);
|
||||
extendBounds(p.pt, 20.0);
|
||||
}
|
||||
|
||||
if (m_selectedRunway && (m_approachDistanceNm > 0.0)) {
|
||||
FGRunway* runwaySelection = fgpositioned_cast<FGRunway>(m_selection);
|
||||
if (runwaySelection && (m_approachDistanceNm > 0.0)) {
|
||||
double d = SG_NM_TO_METER * m_approachDistanceNm;
|
||||
QPointF pt = project(m_selectedRunway->pointOnCenterline(-d));
|
||||
QPointF pt = project(runwaySelection->pointOnCenterline(-d));
|
||||
extendBounds(pt);
|
||||
}
|
||||
}
|
||||
|
@ -263,11 +294,9 @@ void AirportDiagram::addHelipad(FGHelipadRef pad)
|
|||
update();
|
||||
}
|
||||
|
||||
|
||||
void AirportDiagram::paintContents(QPainter* p)
|
||||
{
|
||||
QTransform t = p->transform();
|
||||
|
||||
// pavements
|
||||
QBrush brush(QColor(0x9f, 0x9f, 0x9f));
|
||||
Q_FOREACH(const QPainterPath& path, m_pavements) {
|
||||
|
@ -305,11 +334,13 @@ void AirportDiagram::paintContents(QPainter* p)
|
|||
SGGeod aircraftPos;
|
||||
int headingDeg;
|
||||
|
||||
FGRunway* runwaySelection = fgpositioned_cast<FGRunway>(m_selection);
|
||||
|
||||
// now draw the runways for real
|
||||
Q_FOREACH(const RunwayData& r, m_runways) {
|
||||
|
||||
QColor color(Qt::magenta);
|
||||
if ((r.runway == m_selectedRunway) || (r.runway->reciprocalRunway() == m_selectedRunway)) {
|
||||
if ((r.runway == runwaySelection) || (r.runway->reciprocalRunway() == runwaySelection)) {
|
||||
color = Qt::yellow;
|
||||
}
|
||||
|
||||
|
@ -329,7 +360,7 @@ void AirportDiagram::paintContents(QPainter* p)
|
|||
// invert scaling factor so we can use screen pixel sizes here
|
||||
p->scale(1.0 / m_scale, 1.0/ m_scale);
|
||||
|
||||
p->setPen((r.runway == m_selectedRunway) ? Qt::yellow : Qt::magenta);
|
||||
p->setPen((r.runway == runwaySelection) ? Qt::yellow : Qt::magenta);
|
||||
p->drawText(QRect(-100, 5, 200, 200), ident, Qt::AlignHCenter | Qt::AlignTop);
|
||||
|
||||
FGRunway* recip = r.runway->reciprocalRunway();
|
||||
|
@ -340,28 +371,28 @@ void AirportDiagram::paintContents(QPainter* p)
|
|||
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->setPen((r.runway->reciprocalRunway() == runwaySelection) ? Qt::yellow : Qt::magenta);
|
||||
p->drawText(QRect(-100, 5, 200, 200), recipIdent, Qt::AlignHCenter | Qt::AlignTop);
|
||||
}
|
||||
|
||||
if (m_selectedRunway) {
|
||||
if (runwaySelection) {
|
||||
drawAircraft = true;
|
||||
aircraftPos = m_selectedRunway->geod();
|
||||
headingDeg = m_selectedRunway->headingDeg();
|
||||
aircraftPos = runwaySelection->geod();
|
||||
headingDeg = runwaySelection->headingDeg();
|
||||
}
|
||||
|
||||
if (m_selectedRunway && (m_approachDistanceNm > 0.0)) {
|
||||
if (runwaySelection && (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());
|
||||
QPointF pt = project(runwaySelection->pointOnCenterline(-d));
|
||||
QPointF pt2 = project(runwaySelection->geod());
|
||||
QPen pen(Qt::yellow);
|
||||
pen.setWidth(2.0 / m_scale);
|
||||
p->setPen(pen);
|
||||
p->drawLine(pt, pt2);
|
||||
|
||||
aircraftPos = m_selectedRunway->pointOnCenterline(-d);
|
||||
aircraftPos = runwaySelection->pointOnCenterline(-d);
|
||||
}
|
||||
|
||||
if (drawAircraft) {
|
||||
|
@ -388,23 +419,26 @@ void AirportDiagram::paintContents(QPainter* p)
|
|||
|
||||
void AirportDiagram::drawHelipads(QPainter* painter)
|
||||
{
|
||||
QTransform t = painter->transform();
|
||||
FGHelipad* selectedHelipad = fgpositioned_cast<FGHelipad>(m_selection);
|
||||
|
||||
Q_FOREACH(const HelipadData& p, m_helipads) {
|
||||
painter->setTransform(t);
|
||||
painter->save();
|
||||
painter->translate(p.pt);
|
||||
|
||||
if (p.helipad == m_selectedHelipad) {
|
||||
if (p.helipad == selectedHelipad) {
|
||||
painter->setBrush(Qt::yellow);
|
||||
} else {
|
||||
painter->setBrush(Qt::magenta);
|
||||
}
|
||||
|
||||
painter->drawPath(m_helipadIconPath);
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
|
||||
void AirportDiagram::drawParking(QPainter* painter, const ParkingData& p) const
|
||||
{
|
||||
painter->save();
|
||||
painter->translate(p.pt);
|
||||
|
||||
double hdg = p.parking->getHeading();
|
||||
|
@ -420,8 +454,10 @@ void AirportDiagram::drawParking(QPainter* painter, const ParkingData& p) const
|
|||
}
|
||||
|
||||
painter->rotate(hdg);
|
||||
painter->setPen(Qt::NoPen);
|
||||
|
||||
if (p.parking == m_selectedParking) {
|
||||
FGParking* selectedParking = fgpositioned_cast<FGParking>(m_selection);
|
||||
if (p.parking == selectedParking) {
|
||||
painter->setBrush(Qt::yellow);
|
||||
} else {
|
||||
painter->setBrush(QColor(255, 196, 196)); // kind of pink
|
||||
|
@ -431,7 +467,7 @@ void AirportDiagram::drawParking(QPainter* painter, const ParkingData& p) const
|
|||
|
||||
// ensure the selection colour is quite visible, by not filling
|
||||
// with white when selected
|
||||
if (p.parking != m_selectedParking) {
|
||||
if (p.parking != selectedParking) {
|
||||
painter->fillRect(labelRect, Qt::white);
|
||||
}
|
||||
|
||||
|
@ -450,39 +486,39 @@ void AirportDiagram::drawParking(QPainter* painter, const ParkingData& p) const
|
|||
// draw text
|
||||
painter->setPen(Qt::black);
|
||||
painter->drawText(labelRect, textFlags, parkingName);
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
AirportDiagram::ParkingData AirportDiagram::findParkingData(const FGParkingRef &pk) const
|
||||
{
|
||||
FGParking* selectedParking = fgpositioned_cast<FGParking>(m_selection);
|
||||
if (!selectedParking)
|
||||
return {};
|
||||
|
||||
Q_FOREACH(const ParkingData& p, m_parking) {
|
||||
if (p.parking == m_selectedParking) {
|
||||
if (p.parking == selectedParking) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
return ParkingData();
|
||||
return {};
|
||||
}
|
||||
|
||||
void AirportDiagram::drawParkings(QPainter* painter) const
|
||||
{
|
||||
painter->save();
|
||||
QTransform t = painter->transform();
|
||||
FGParking* selectedParking = fgpositioned_cast<FGParking>(m_selection);
|
||||
|
||||
Q_FOREACH(const ParkingData& p, m_parking) {
|
||||
if (p.parking == m_selectedParking) {
|
||||
if (p.parking == selectedParking) {
|
||||
continue; // skip and draw last
|
||||
}
|
||||
|
||||
painter->setTransform(t);
|
||||
drawParking(painter, p);
|
||||
}
|
||||
|
||||
if (m_selectedParking) {
|
||||
painter->setTransform(t);
|
||||
drawParking(painter, findParkingData(m_selectedParking));
|
||||
if (selectedParking) {
|
||||
drawParking(painter, findParkingData(selectedParking));
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void AirportDiagram::drawILS(QPainter* painter, FGRunwayRef runway) const
|
||||
|
@ -514,12 +550,14 @@ void AirportDiagram::drawILS(QPainter* painter, FGRunwayRef runway) const
|
|||
|
||||
void AirportDiagram::mouseReleaseEvent(QMouseEvent* me)
|
||||
{
|
||||
if (me->button() != Qt::LeftButton) {
|
||||
return;
|
||||
}
|
||||
|
||||
me->accept();
|
||||
QTransform t(transform());
|
||||
double minWidth = 8.0 * unitLengthAfterMapping(t.inverted());
|
||||
#if 0
|
||||
QImage img(width(), height(), QImage::Format_ARGB32);
|
||||
QPainter imgPaint(&img);
|
||||
imgPaint.setPen(QPen(Qt::cyan, 1));
|
||||
#endif
|
||||
|
||||
Q_FOREACH(const RunwayData& r, m_runways) {
|
||||
QPainterPath pp = pathForRunway(r, t, minWidth);
|
||||
|
@ -528,11 +566,8 @@ void AirportDiagram::mouseReleaseEvent(QMouseEvent* me)
|
|||
QPointF p1(t.map(r.p1)), p2(t.map(r.p2));
|
||||
double param;
|
||||
distanceToLineSegment(QVector2D(me->pos()), QVector2D(p1), QVector2D(p2), ¶m);
|
||||
if (param > 0.5) {
|
||||
emit clickedRunway(r.runway->reciprocalRunway());
|
||||
} else {
|
||||
emit clickedRunway(r.runway);
|
||||
}
|
||||
const FGRunwayRef clickedRunway = (param > 0.5) ? FGRunwayRef{r.runway->reciprocalRunway()} : r.runway;
|
||||
emit clicked(new QmlPositioned{clickedRunway});
|
||||
return;
|
||||
}
|
||||
} // of runways iteration
|
||||
|
@ -540,18 +575,22 @@ void AirportDiagram::mouseReleaseEvent(QMouseEvent* me)
|
|||
Q_FOREACH(const ParkingData& parking, m_parking) {
|
||||
QPainterPath pp = pathForParking(parking, t);
|
||||
if (pp.contains(me->pos())) {
|
||||
emit clickedParking(parking.parking);
|
||||
emit clicked(new QmlPositioned{parking.parking});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Q_FOREACH(const HelipadData& pad, m_helipads) {
|
||||
QPainterPath pp = pathForHelipad(pad, t);
|
||||
//imgPaint.drawPath(pp);
|
||||
if (pp.contains(me->pos())) {
|
||||
emit clickedHelipad(pad.helipad);
|
||||
emit clicked(new QmlPositioned{pad.helipad});
|
||||
return;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
img.save("/Users/jmt/Desktop/img.png");
|
||||
#endif
|
||||
}
|
||||
|
||||
QPainterPath AirportDiagram::pathForRunway(const RunwayData& r, const QTransform& t,
|
||||
|
|
|
@ -23,15 +23,25 @@
|
|||
|
||||
#include "BaseDiagram.hxx"
|
||||
|
||||
#include <QPixmap>
|
||||
|
||||
#include <Airports/parking.hxx>
|
||||
#include <Airports/runways.hxx>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
|
||||
// forward decls
|
||||
class QmlPositioned;
|
||||
|
||||
class AirportDiagram : public BaseDiagram
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QmlPositioned* selection READ selection WRITE setSelection NOTIFY selectionChanged)
|
||||
Q_PROPERTY(qlonglong airport READ airportGuid WRITE setAirportGuid NOTIFY airportChanged)
|
||||
|
||||
Q_PROPERTY(double approachExtensionNm READ approachExtensionNm WRITE setApproachExtensionNm NOTIFY approachExtensionChanged)
|
||||
public:
|
||||
AirportDiagram(QWidget* pr);
|
||||
AirportDiagram(QQuickItem* pr = nullptr);
|
||||
virtual ~AirportDiagram();
|
||||
|
||||
void setAirport(FGAirportRef apt);
|
||||
|
@ -40,24 +50,30 @@ public:
|
|||
void addParking(FGParkingRef park);
|
||||
void addHelipad(FGHelipadRef pad);
|
||||
|
||||
FGRunwayRef selectedRunway() const;
|
||||
void setSelectedRunway(FGRunwayRef r);
|
||||
QmlPositioned* selection() const;
|
||||
|
||||
void setSelectedHelipad(FGHelipadRef pad);
|
||||
void setSelectedParking(FGParkingRef park);
|
||||
void setSelection(QmlPositioned* pos);
|
||||
|
||||
void setApproachExtensionNm(double distanceNm);
|
||||
double approachExtensionNm() const;
|
||||
|
||||
qlonglong airportGuid() const;
|
||||
void setAirportGuid(qlonglong guid);
|
||||
|
||||
void setApproachExtensionDistance(double distanceNm);
|
||||
Q_SIGNALS:
|
||||
void clickedRunway(FGRunwayRef rwy);
|
||||
void clickedHelipad(FGHelipadRef pad);
|
||||
void clickedParking(FGParkingRef park);
|
||||
void clicked(QmlPositioned* pos);
|
||||
|
||||
void selectionChanged();
|
||||
void airportChanged();
|
||||
void approachExtensionChanged();
|
||||
|
||||
protected:
|
||||
|
||||
virtual void mouseReleaseEvent(QMouseEvent* me);
|
||||
void mouseReleaseEvent(QMouseEvent* me) override;
|
||||
|
||||
void paintContents(QPainter*) Q_DECL_OVERRIDE;
|
||||
void paintContents(QPainter*) override;
|
||||
|
||||
void doComputeBounds() Q_DECL_OVERRIDE;
|
||||
void doComputeBounds() override;
|
||||
private:
|
||||
struct RunwayData {
|
||||
QPointF p1, p2;
|
||||
|
@ -115,11 +131,9 @@ private:
|
|||
QPainterPath m_parkingIconPath, // arrow points right
|
||||
m_parkingIconLeftPath; // arrow points left
|
||||
double m_approachDistanceNm;
|
||||
FGRunwayRef m_selectedRunway;
|
||||
FGParkingRef m_selectedParking;
|
||||
FGHelipadRef m_selectedHelipad;
|
||||
|
||||
QPainterPath m_helipadIconPath;
|
||||
FGPositionedRef m_selection;
|
||||
};
|
||||
|
||||
#endif // of GUI_AIRPORT_DIAGRAM_HXX
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <QDebug>
|
||||
#include <QVector2D>
|
||||
#include <QMouseEvent>
|
||||
#include <QPaintDevice>
|
||||
|
||||
#include <Navaids/navrecord.hxx>
|
||||
#include <Navaids/positioned.hxx>
|
||||
|
@ -39,6 +40,7 @@ const double rec = 6378137; // earth radius, equator (?)
|
|||
const double rpol = 6356752.314; // earth radius, polar (?)
|
||||
|
||||
const double MINIMUM_SCALE = 0.002;
|
||||
const double MAXIMUM_SCALE = 2.0;
|
||||
|
||||
//Returns Earth radius at a given latitude (Ellipsoide equation with two equal axis)
|
||||
static double earth_radius_lat( double lat )
|
||||
|
@ -48,14 +50,15 @@ static double earth_radius_lat( double lat )
|
|||
return 1.0 / sqrt( a * a + b * b );
|
||||
}
|
||||
|
||||
BaseDiagram::BaseDiagram(QWidget* pr) :
|
||||
QWidget(pr),
|
||||
BaseDiagram::BaseDiagram(QQuickItem* pr) :
|
||||
QQuickPaintedItem(pr),
|
||||
m_autoScalePan(true),
|
||||
m_wheelAngleDeltaAccumulator(0)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::MinimumExpanding,
|
||||
QSizePolicy::MinimumExpanding);
|
||||
setMinimumSize(100, 100);
|
||||
setAcceptedMouseButtons(Qt::LeftButton);
|
||||
setFlag(ItemHasContents);
|
||||
setOpaquePainting(true);
|
||||
setAntialiasing(true);
|
||||
}
|
||||
|
||||
QTransform BaseDiagram::transform() const
|
||||
|
@ -98,11 +101,15 @@ void BaseDiagram::extendRect(QRectF &r, const QPointF &p)
|
|||
}
|
||||
}
|
||||
|
||||
void BaseDiagram::paintEvent(QPaintEvent*)
|
||||
QRect BaseDiagram::rect() const
|
||||
{
|
||||
QPainter p(this);
|
||||
p.setRenderHints(QPainter::Antialiasing);
|
||||
p.fillRect(rect(), QColor(0x3f, 0x3f, 0x3f));
|
||||
return QRect(0, 0, width(), height());
|
||||
}
|
||||
|
||||
void BaseDiagram::paint(QPainter* p)
|
||||
{
|
||||
//p->setRenderHints(QPainter::Antialiasing);
|
||||
p->fillRect(rect(), QColor(0x3f, 0x3f, 0x3f));
|
||||
|
||||
if (m_autoScalePan) {
|
||||
// fit bounds within our available space, allowing for a margin
|
||||
|
@ -110,24 +117,26 @@ void BaseDiagram::paintEvent(QPaintEvent*)
|
|||
double ratioInX = (width() - MARGIN * 2) / m_bounds.width();
|
||||
double ratioInY = (height() - MARGIN * 2) / m_bounds.height();
|
||||
m_scale = std::min(ratioInX, ratioInY);
|
||||
SG_CLAMP_RANGE(m_scale, MINIMUM_SCALE, MAXIMUM_SCALE);
|
||||
}
|
||||
|
||||
QTransform t(transform());
|
||||
p.setTransform(t);
|
||||
m_baseDeviceTransform = p->deviceTransform();
|
||||
m_viewportTransform = transform();
|
||||
p->setWorldTransform(m_viewportTransform * m_baseDeviceTransform);
|
||||
|
||||
paintPolygonData(&p);
|
||||
|
||||
paintNavaids(&p);
|
||||
|
||||
paintContents(&p);
|
||||
paintPolygonData(p);
|
||||
paintNavaids(p);
|
||||
paintContents(p);
|
||||
}
|
||||
|
||||
void BaseDiagram::paintAirplaneIcon(QPainter* painter, const SGGeod& geod, int headingDeg)
|
||||
{
|
||||
QPointF pos = project(geod);
|
||||
QPixmap pix(":/airplane-icon");
|
||||
pos = painter->transform().map(pos);
|
||||
painter->resetTransform();
|
||||
pos = m_viewportTransform.map(pos);
|
||||
painter->save();
|
||||
painter->setWorldTransform(m_baseDeviceTransform);
|
||||
|
||||
painter->translate(pos.x(), pos.y());
|
||||
painter->rotate(headingDeg);
|
||||
|
||||
|
@ -135,16 +144,17 @@ void BaseDiagram::paintAirplaneIcon(QPainter* painter, const SGGeod& geod, int h
|
|||
QRect airplaneIconRect = pix.rect();
|
||||
airplaneIconRect.moveCenter(QPoint(0,0));
|
||||
painter->drawPixmap(airplaneIconRect, pix);
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void BaseDiagram::paintPolygonData(QPainter* painter)
|
||||
{
|
||||
QTransform xf = painter->transform();
|
||||
QTransform invT = xf.inverted();
|
||||
|
||||
SGGeod topLeft = unproject(invT.map(rect().topLeft()), m_projectionCenter);
|
||||
SGGeod viewCenter = unproject(invT.map(rect().center()), m_projectionCenter);
|
||||
SGGeod bottomRight = unproject(invT.map(rect().bottomRight()), m_projectionCenter);
|
||||
QTransform invT = m_viewportTransform.inverted();
|
||||
const auto geom = rect();
|
||||
SGGeod topLeft = unproject(invT.map(geom.topLeft()), m_projectionCenter);
|
||||
SGGeod viewCenter = unproject(invT.map(geom.center()), m_projectionCenter);
|
||||
SGGeod bottomRight = unproject(invT.map(geom.bottomRight()), m_projectionCenter);
|
||||
|
||||
double drawRangeNm = std::max(SGGeodesy::distanceNm(viewCenter, topLeft),
|
||||
SGGeodesy::distanceNm(viewCenter, bottomRight));
|
||||
|
@ -155,35 +165,31 @@ void BaseDiagram::paintPolygonData(QPainter* painter)
|
|||
QPen waterPen(QColor(64, 64, 255), 1);
|
||||
waterPen.setCosmetic(true);
|
||||
painter->setPen(waterPen);
|
||||
flightgear::PolyLineList::const_iterator it;
|
||||
for (it=lines.begin(); it != lines.end(); ++it) {
|
||||
paintGeodVec(painter, (*it)->points());
|
||||
for (auto line : lines) {
|
||||
paintGeodVec(painter, line->points());
|
||||
}
|
||||
|
||||
lines = flightgear::PolyLine::linesNearPos(viewCenter, drawRangeNm,
|
||||
flightgear::PolyLine::URBAN);
|
||||
for (it=lines.begin(); it != lines.end(); ++it) {
|
||||
fillClosedGeodVec(painter, QColor(192, 192, 96), (*it)->points());
|
||||
for (auto line : lines) {
|
||||
fillClosedGeodVec(painter, QColor(192, 192, 96), line->points());
|
||||
}
|
||||
|
||||
lines = flightgear::PolyLine::linesNearPos(viewCenter, drawRangeNm,
|
||||
flightgear::PolyLine::RIVER);
|
||||
|
||||
painter->setPen(waterPen);
|
||||
for (it=lines.begin(); it != lines.end(); ++it) {
|
||||
paintGeodVec(painter, (*it)->points());
|
||||
for (auto line : lines) {
|
||||
paintGeodVec(painter, line->points());
|
||||
}
|
||||
|
||||
|
||||
lines = flightgear::PolyLine::linesNearPos(viewCenter, drawRangeNm,
|
||||
flightgear::PolyLine::LAKE);
|
||||
|
||||
for (it=lines.begin(); it != lines.end(); ++it) {
|
||||
fillClosedGeodVec(painter, QColor(128, 128, 255),
|
||||
(*it)->points());
|
||||
for (auto line : lines) {
|
||||
fillClosedGeodVec(painter, QColor(128, 128, 255), line->points());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void BaseDiagram::paintGeodVec(QPainter* painter, const flightgear::SGGeodVec& vec)
|
||||
|
@ -216,17 +222,17 @@ class MapFilter : public FGPositioned::TypeFilter
|
|||
{
|
||||
public:
|
||||
|
||||
MapFilter(LauncherAircraftType aircraft)
|
||||
MapFilter(LauncherController::AircraftType aircraft)
|
||||
{
|
||||
// addType(FGPositioned::FIX);
|
||||
addType(FGPositioned::NDB);
|
||||
addType(FGPositioned::VOR);
|
||||
|
||||
if (aircraft == Helicopter) {
|
||||
if (aircraft == LauncherController::Helicopter) {
|
||||
addType(FGPositioned::HELIPAD);
|
||||
}
|
||||
|
||||
if (aircraft == Seaplane) {
|
||||
if (aircraft == LauncherController::Seaplane) {
|
||||
addType(FGPositioned::SEAPORT);
|
||||
} else {
|
||||
addType(FGPositioned::AIRPORT);
|
||||
|
@ -252,12 +258,11 @@ public:
|
|||
void BaseDiagram::splitItems(const FGPositionedList& in, FGPositionedList& navaids,
|
||||
FGPositionedList& ports)
|
||||
{
|
||||
FGPositionedList::const_iterator it = in.begin();
|
||||
for (; it != in.end(); ++it) {
|
||||
if (FGPositioned::isAirportType(it->ptr())) {
|
||||
ports.push_back(*it);
|
||||
for (auto p : in) {
|
||||
if (FGPositioned::isAirportType(p)) {
|
||||
ports.push_back(p);
|
||||
} else {
|
||||
navaids.push_back(*it);
|
||||
navaids.push_back(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -273,10 +278,8 @@ bool orderAirportsByRunwayLength(const FGPositionedRef& a,
|
|||
|
||||
void BaseDiagram::paintNavaids(QPainter* painter)
|
||||
{
|
||||
QTransform xf = painter->transform();
|
||||
painter->setTransform(QTransform()); // reset to identity
|
||||
QTransform invT = xf.inverted();
|
||||
|
||||
painter->save();
|
||||
QTransform invT = m_viewportTransform.inverted();
|
||||
|
||||
SGGeod topLeft = unproject(invT.map(rect().topLeft()), m_projectionCenter);
|
||||
SGGeod viewCenter = unproject(invT.map(rect().center()), m_projectionCenter);
|
||||
|
@ -300,19 +303,17 @@ void BaseDiagram::paintNavaids(QPainter* painter)
|
|||
|
||||
m_labelRects.clear();
|
||||
m_labelRects.reserve(items.size());
|
||||
painter->setTransform(m_baseDeviceTransform);
|
||||
|
||||
FGPositionedList::const_iterator it;
|
||||
for (it = ports.begin(); it != ports.end(); ++it) {
|
||||
paintNavaid(painter, xf, *it);
|
||||
for (auto port : ports) {
|
||||
paintNavaid(painter, port);
|
||||
}
|
||||
|
||||
for (it = navaids.begin(); it != navaids.end(); ++it) {
|
||||
paintNavaid(painter, xf, *it);
|
||||
for (auto nav : navaids) {
|
||||
paintNavaid(painter, nav);
|
||||
}
|
||||
|
||||
|
||||
// restore transform
|
||||
painter->setTransform(xf);
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
QRect boundsOfLines(const QVector<QLineF>& lines)
|
||||
|
@ -325,7 +326,7 @@ QRect boundsOfLines(const QVector<QLineF>& lines)
|
|||
return r;
|
||||
}
|
||||
|
||||
void BaseDiagram::paintNavaid(QPainter* painter, const QTransform& t, const FGPositionedRef &pos)
|
||||
void BaseDiagram::paintNavaid(QPainter* painter, const FGPositionedRef &pos)
|
||||
{
|
||||
if (isNavaidIgnored(pos))
|
||||
return;
|
||||
|
@ -341,9 +342,11 @@ void BaseDiagram::paintNavaid(QPainter* painter, const QTransform& t, const FGPo
|
|||
if (apt->hasHardRunwayOfLengthFt(minRunwayLengthFt)) {
|
||||
|
||||
drawAsIcon = false;
|
||||
painter->setTransform(t);
|
||||
QVector<QLineF> lines = projectAirportRuwaysWithCenter(apt, m_projectionCenter);
|
||||
|
||||
painter->save();
|
||||
painter->setTransform(m_viewportTransform * m_baseDeviceTransform);
|
||||
|
||||
QPen pen(QColor(0x03, 0x83, 0xbf), 8);
|
||||
pen.setCosmetic(true);
|
||||
painter->setPen(pen);
|
||||
|
@ -354,15 +357,15 @@ void BaseDiagram::paintNavaid(QPainter* painter, const QTransform& t, const FGPo
|
|||
painter->setPen(linePen);
|
||||
painter->drawLines(lines);
|
||||
|
||||
painter->resetTransform();
|
||||
iconRect = m_viewportTransform.mapRect(boundsOfLines(lines));
|
||||
|
||||
iconRect = t.mapRect(boundsOfLines(lines));
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
|
||||
if (drawAsIcon) {
|
||||
QPixmap pm = iconForPositioned(pos);
|
||||
QPointF loc = t.map(project(pos->geod()));
|
||||
QPointF loc = m_viewportTransform.map(project(pos->geod()));
|
||||
iconRect = pm.rect();
|
||||
iconRect.moveCenter(loc.toPoint());
|
||||
painter->drawPixmap(iconRect, pm);
|
||||
|
@ -510,8 +513,13 @@ QRect BaseDiagram::labelPositioned(const QRect& itemRect,
|
|||
|
||||
void BaseDiagram::mousePressEvent(QMouseEvent *me)
|
||||
{
|
||||
if (!hasActiveFocus()) {
|
||||
forceActiveFocus(Qt::MouseFocusReason);
|
||||
}
|
||||
|
||||
m_lastMousePos = me->pos();
|
||||
m_didPan = false;
|
||||
me->accept();
|
||||
}
|
||||
|
||||
void BaseDiagram::mouseMoveEvent(QMouseEvent *me)
|
||||
|
@ -558,7 +566,7 @@ void BaseDiagram::wheelEvent(QWheelEvent *we)
|
|||
m_scale *= 0.75;
|
||||
}
|
||||
|
||||
SG_CLAMP_RANGE(m_scale, MINIMUM_SCALE, 1.0);
|
||||
SG_CLAMP_RANGE(m_scale, MINIMUM_SCALE, MAXIMUM_SCALE);
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -585,7 +593,7 @@ void BaseDiagram::doComputeBounds()
|
|||
// no-op in the base class
|
||||
}
|
||||
|
||||
void BaseDiagram::extendBounds(const QPointF& p)
|
||||
void BaseDiagram::extendBounds(const QPointF& p, double radiusM)
|
||||
{
|
||||
// this check added after a bug where apt.dat reports SCSL as
|
||||
// https://airportguide.com/airport/info/AG0003 (British Columbia)
|
||||
|
@ -598,7 +606,12 @@ void BaseDiagram::extendBounds(const QPointF& p)
|
|||
return;
|
||||
}
|
||||
|
||||
if (radiusM > 0.0) {
|
||||
extendRect(m_bounds, p - QPointF(radiusM, radiusM));
|
||||
extendRect(m_bounds, p + QPointF(radiusM, radiusM));
|
||||
} else {
|
||||
extendRect(m_bounds, p);
|
||||
}
|
||||
}
|
||||
|
||||
QPointF BaseDiagram::project(const SGGeod& geod, const SGGeod& center)
|
||||
|
@ -787,7 +800,7 @@ QVector<QLineF> BaseDiagram::projectAirportRuwaysWithCenter(FGAirportRef apt, co
|
|||
return r;
|
||||
}
|
||||
|
||||
void BaseDiagram::setAircraftType(LauncherAircraftType type)
|
||||
void BaseDiagram::setAircraftType(LauncherController::AircraftType type)
|
||||
{
|
||||
m_aircraftType = type;
|
||||
update();
|
||||
|
|
|
@ -21,23 +21,23 @@
|
|||
#ifndef GUI_BASEDIAGRAM_HXX
|
||||
#define GUI_BASEDIAGRAM_HXX
|
||||
|
||||
#include <QWidget>
|
||||
#include <QPainterPath>
|
||||
#include <QHash>
|
||||
#include <QQuickPaintedItem>
|
||||
#include <QTransform>
|
||||
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
|
||||
#include <Navaids/positioned.hxx>
|
||||
#include <Airports/airport.hxx>
|
||||
#include <Navaids/PolyLine.hxx>
|
||||
#include "LauncherController.hxx"
|
||||
|
||||
#include "QtLauncher_fwd.hxx"
|
||||
|
||||
class BaseDiagram : public QWidget
|
||||
class BaseDiagram : public QQuickPaintedItem
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BaseDiagram(QWidget* pr);
|
||||
BaseDiagram(QQuickItem* pr = nullptr);
|
||||
|
||||
enum IconOption
|
||||
{
|
||||
|
@ -54,14 +54,16 @@ public:
|
|||
static QVector<QLineF> projectAirportRuwaysIntoRect(FGAirportRef apt, const QRectF& bounds);
|
||||
static QVector<QLineF> projectAirportRuwaysWithCenter(FGAirportRef apt, const SGGeod &c);
|
||||
|
||||
void setAircraftType(LauncherAircraftType type);
|
||||
void setAircraftType(LauncherController::AircraftType type);
|
||||
|
||||
QRect rect() const;
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* pe);
|
||||
void paint(QPainter* p) override;
|
||||
|
||||
virtual void mousePressEvent(QMouseEvent* me);
|
||||
virtual void mouseMoveEvent(QMouseEvent* me);
|
||||
void mousePressEvent(QMouseEvent* me) override;
|
||||
void mouseMoveEvent(QMouseEvent* me) override;
|
||||
|
||||
virtual void wheelEvent(QWheelEvent* we);
|
||||
void wheelEvent(QWheelEvent* we) override;
|
||||
|
||||
virtual void paintContents(QPainter*);
|
||||
|
||||
|
@ -71,7 +73,7 @@ protected:
|
|||
|
||||
virtual void doComputeBounds();
|
||||
|
||||
void extendBounds(const QPointF& p);
|
||||
void extendBounds(const QPointF& p, double radiusM = 1.0);
|
||||
QPointF project(const SGGeod& geod) const;
|
||||
QTransform transform() const;
|
||||
|
||||
|
@ -85,7 +87,7 @@ protected:
|
|||
QPointF m_panOffset, m_lastMousePos;
|
||||
int m_wheelAngleDeltaAccumulator;
|
||||
bool m_didPan;
|
||||
LauncherAircraftType m_aircraftType;
|
||||
LauncherController::AircraftType m_aircraftType = LauncherController::Airplane;
|
||||
|
||||
static void extendRect(QRectF& r, const QPointF& p);
|
||||
|
||||
|
@ -118,6 +120,8 @@ private:
|
|||
int & flags /* out parameter */) const;
|
||||
QRect labelPositioned(const QRect &itemRect, const QSize &bounds, LabelPosition lp) const;
|
||||
|
||||
QTransform m_baseDeviceTransform;
|
||||
QTransform m_viewportTransform;
|
||||
QVector<FGPositionedRef> m_ignored;
|
||||
|
||||
mutable QHash<PositionedID, LabelPosition> m_labelPositions;
|
||||
|
@ -126,9 +130,7 @@ private:
|
|||
static int textFlagsForLabelPosition(LabelPosition pos);
|
||||
|
||||
void splitItems(const FGPositionedList &in, FGPositionedList &navaids, FGPositionedList &ports);
|
||||
void paintNavaid(QPainter *painter,
|
||||
const QTransform& t,
|
||||
const FGPositionedRef &pos);
|
||||
void paintNavaid(QPainter *painter, const FGPositionedRef &pos);
|
||||
void paintPolygonData(QPainter *painter);
|
||||
void paintGeodVec(QPainter *painter, const flightgear::SGGeodVec &vec);
|
||||
void fillClosedGeodVec(QPainter *painter, const QColor &color, const flightgear::SGGeodVec &vec);
|
||||
|
|
|
@ -69,7 +69,6 @@ endif()
|
|||
if (HAVE_QT)
|
||||
qt5_wrap_ui(uic_sources Launcher.ui
|
||||
SetupRootDialog.ui
|
||||
LocationWidget.ui
|
||||
InstallSceneryDialog.ui
|
||||
)
|
||||
qt5_add_resources(qrc_sources resources.qrc)
|
||||
|
@ -90,14 +89,14 @@ if (HAVE_QT)
|
|||
AircraftModel.cxx
|
||||
CatalogListModel.cxx
|
||||
CatalogListModel.hxx
|
||||
LocationWidget.cxx
|
||||
LocationWidget.hxx
|
||||
QtMessageBox.cxx
|
||||
QtMessageBox.hxx
|
||||
QtFileDialog.cxx
|
||||
QtFileDialog.hxx
|
||||
InstallSceneryDialog.hxx
|
||||
InstallSceneryDialog.cxx
|
||||
LocationController.cxx
|
||||
LocationController.hxx
|
||||
ToolboxButton.cpp
|
||||
ToolboxButton.h
|
||||
LauncherArgumentTokenizer.cxx
|
||||
|
@ -122,6 +121,8 @@ if (HAVE_QT)
|
|||
LauncherController.hxx
|
||||
AddOnsController.cxx
|
||||
AddOnsController.hxx
|
||||
PixmapImageItem.cxx
|
||||
PixmapImageItem.hxx
|
||||
${uic_sources}
|
||||
${qrc_sources}
|
||||
${qml_sources})
|
||||
|
@ -150,6 +151,12 @@ if (HAVE_QT)
|
|||
ThumbnailImageItem.hxx
|
||||
PopupWindowTracker.cxx
|
||||
PopupWindowTracker.hxx
|
||||
QmlPositioned.hxx
|
||||
QmlPositioned.cxx
|
||||
QmlNavCacheWrapper.hxx
|
||||
QmlNavCacheWrapper.cxx
|
||||
QmlRadioButtonHelper.cxx
|
||||
QmlRadioButtonHelper.hxx
|
||||
)
|
||||
|
||||
set_property(TARGET fgqmlui PROPERTY AUTOMOC ON)
|
||||
|
|
|
@ -299,7 +299,9 @@
|
|||
</widget>
|
||||
|
||||
|
||||
<widget class="LocationWidget" name="location"/>
|
||||
<widget class="QQuickWidget" name="location">
|
||||
|
||||
</widget>
|
||||
|
||||
<widget class="QQuickWidget" name="environmentPage">
|
||||
</widget>
|
||||
|
@ -360,12 +362,6 @@
|
|||
<extends>QWidget</extends>
|
||||
<header>QtQuickWidgets/QQuickWidget</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>LocationWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">GUI/LocationWidget.hxx</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ToolboxButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <QMessageBox>
|
||||
#include <QSettings>
|
||||
#include <QQuickWindow>
|
||||
#include <QQmlComponent>
|
||||
|
||||
// simgear headers
|
||||
#include <simgear/package/Install.hxx>
|
||||
|
@ -38,26 +39,29 @@
|
|||
#include "DefaultAircraftLocator.hxx"
|
||||
#include "LaunchConfig.hxx"
|
||||
#include "AircraftModel.hxx"
|
||||
|
||||
// remove me once location widget is ported to Quick
|
||||
#include "LocationWidget.hxx"
|
||||
#include "LocationController.hxx"
|
||||
#include "QmlPositioned.hxx"
|
||||
#include "PixmapImageItem.hxx"
|
||||
#include "AirportDiagram.hxx"
|
||||
#include "NavaidDiagram.hxx"
|
||||
#include "QmlRadioButtonHelper.hxx"
|
||||
|
||||
using namespace simgear::pkg;
|
||||
|
||||
|
||||
LauncherController::LauncherController(QObject *parent,
|
||||
LocationWidget* loc) :
|
||||
QObject(parent),
|
||||
m_locationWidget_FIXME(loc)
|
||||
LauncherController::LauncherController(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
m_serversModel = new MPServersModel(this);
|
||||
m_location = new LocationController(this);
|
||||
m_locationHistory = new RecentLocationsModel(this);
|
||||
m_selectedAircraftInfo = new QmlAircraftInfo(this);
|
||||
|
||||
m_config = new LaunchConfig(this);
|
||||
connect(m_config, &LaunchConfig::collect, this, &LauncherController::collectAircraftArgs);
|
||||
|
||||
connect(m_locationWidget_FIXME, &LocationWidget::descriptionChanged,
|
||||
m_location->setLaunchConfig(m_config);
|
||||
connect(m_location, &LocationController::descriptionChanged,
|
||||
this, &LauncherController::summaryChanged);
|
||||
|
||||
initQML();
|
||||
|
@ -91,6 +95,9 @@ LauncherController::LauncherController(QObject *parent,
|
|||
|
||||
void LauncherController::initQML()
|
||||
{
|
||||
qmlRegisterUncreatableType<LauncherController>("FlightGear.Launcher", 1, 0, "LauncherController", "no");
|
||||
qmlRegisterUncreatableType<LocationController>("FlightGear.Launcher", 1, 0, "LocationController", "no");
|
||||
|
||||
qmlRegisterType<LauncherArgumentTokenizer>("FlightGear.Launcher", 1, 0, "ArgumentTokenizer");
|
||||
qmlRegisterUncreatableType<QAbstractItemModel>("FlightGear.Launcher", 1, 0, "QAIM", "no");
|
||||
qmlRegisterUncreatableType<AircraftProxyModel>("FlightGear.Launcher", 1, 0, "AircraftProxyModel", "no");
|
||||
|
@ -108,6 +115,15 @@ void LauncherController::initQML()
|
|||
qmlRegisterType<ThumbnailImageItem>("FlightGear.Launcher", 1, 0, "ThumbnailImage");
|
||||
qmlRegisterType<PreviewImageItem>("FlightGear.Launcher", 1, 0, "PreviewImage");
|
||||
|
||||
qmlRegisterType<QmlPositioned>("FlightGear", 1, 0, "Positioned");
|
||||
// this is a Q_GADGET, but we need to register it for use in return types, etc
|
||||
qRegisterMetaType<QmlGeod>();
|
||||
|
||||
qmlRegisterType<PixmapImageItem>("FlightGear", 1, 0, "PixmapImage");
|
||||
qmlRegisterType<AirportDiagram>("FlightGear", 1, 0, "AirportDiagram");
|
||||
qmlRegisterType<NavaidDiagram>("FlightGear", 1, 0, "NavaidDiagram");
|
||||
qmlRegisterType<QmlRadioButtonGroup>("FlightGear", 1, 0, "RadioButtonGroup");
|
||||
|
||||
QNetworkDiskCache* diskCache = new QNetworkDiskCache(this);
|
||||
SGPath cachePath = globals->get_fg_home() / "PreviewsCache";
|
||||
diskCache->setCacheDirectory(QString::fromStdString(cachePath.utf8Str()));
|
||||
|
@ -132,7 +148,7 @@ void LauncherController::restoreSettings()
|
|||
}
|
||||
|
||||
|
||||
m_locationWidget_FIXME->restoreSettings();
|
||||
m_location->restoreSettings();
|
||||
QVariantMap currentLocation = m_locationHistory->mostRecent();
|
||||
if (currentLocation.isEmpty()) {
|
||||
// use the default
|
||||
|
@ -143,7 +159,7 @@ void LauncherController::restoreSettings()
|
|||
currentLocation["location-apt-runway"] = "active";
|
||||
} // otherwise we failed to find the default airport in the nav-db :(
|
||||
}
|
||||
m_locationWidget_FIXME->restoreLocation(currentLocation);
|
||||
m_location->restoreLocation(currentLocation);
|
||||
|
||||
updateSelectedAircraft();
|
||||
m_serversModel->requestRestore();
|
||||
|
@ -199,7 +215,7 @@ void LauncherController::doRun()
|
|||
|
||||
m_aircraftHistory->insert(m_selectedAircraft);
|
||||
|
||||
QVariant locSet = m_locationWidget_FIXME->saveLocation();
|
||||
QVariant locSet = m_location->saveLocation();
|
||||
m_locationHistory->insert(locSet);
|
||||
|
||||
// aircraft paths
|
||||
|
@ -257,8 +273,7 @@ void LauncherController::doApply()
|
|||
globals->get_props()->setStringValue("/sim/aircraft-dir", aircraftDir);
|
||||
}
|
||||
|
||||
// location
|
||||
m_locationWidget_FIXME->setLocationProperties();
|
||||
m_location->setLocationProperties();
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
|
@ -268,13 +283,12 @@ QString LauncherController::selectAircraftStateAutomatically()
|
|||
if (!m_selectedAircraftInfo)
|
||||
return {};
|
||||
|
||||
if (m_locationWidget_FIXME->isAirborneLocation()) {
|
||||
if (m_selectedAircraftInfo->hasState("approach"))
|
||||
if (m_location->isAirborneLocation() && m_selectedAircraftInfo->hasState("approach"))
|
||||
{
|
||||
return "approach";
|
||||
}
|
||||
|
||||
if (m_locationWidget_FIXME->isParkedLocation()) {
|
||||
if (m_selectedAircraftInfo->hasState("parked"))
|
||||
if (m_location->isParkedLocation() && m_selectedAircraftInfo->hasState("parked")) {
|
||||
return "parked";
|
||||
} else {
|
||||
// also try 'engines-running'?
|
||||
|
@ -299,14 +313,12 @@ void LauncherController::updateSelectedAircraft()
|
|||
m_selectedAircraftInfo->setUri(m_selectedAircraft);
|
||||
QModelIndex index = m_aircraftModel->indexOfAircraftURI(m_selectedAircraft);
|
||||
if (index.isValid()) {
|
||||
LauncherAircraftType aircraftType = Airplane;
|
||||
m_aircraftType = Airplane;
|
||||
if (index.data(AircraftIsHelicopterRole).toBool()) {
|
||||
aircraftType = Helicopter;
|
||||
m_aircraftType = Helicopter;
|
||||
} else if (index.data(AircraftIsSeaplaneRole).toBool()) {
|
||||
aircraftType = Seaplane;
|
||||
m_aircraftType = Seaplane;
|
||||
}
|
||||
|
||||
m_locationWidget_FIXME->setAircraftType(aircraftType);
|
||||
}
|
||||
|
||||
emit canFlyChanged();
|
||||
|
@ -380,10 +392,9 @@ QmlAircraftInfo *LauncherController::selectedAircraftInfo() const
|
|||
|
||||
void LauncherController::restoreLocation(QVariant var)
|
||||
{
|
||||
m_locationWidget_FIXME->restoreLocation(var.toMap());
|
||||
m_location->restoreLocation(var.toMap());
|
||||
}
|
||||
|
||||
|
||||
QUrl LauncherController::selectedAircraft() const
|
||||
{
|
||||
return m_selectedAircraft;
|
||||
|
@ -458,11 +469,6 @@ QStringList LauncherController::combinedSummary() const
|
|||
return m_settingsSummary + m_environmentSummary;
|
||||
}
|
||||
|
||||
QString LauncherController::locationDescription() const
|
||||
{
|
||||
return m_locationWidget_FIXME->locationDescription();
|
||||
}
|
||||
|
||||
simgear::pkg::PackageRef LauncherController::packageForAircraftURI(QUrl uri) const
|
||||
{
|
||||
if (uri.scheme() != "package") {
|
||||
|
|
|
@ -35,9 +35,9 @@ class RecentAircraftModel;
|
|||
class RecentLocationsModel;
|
||||
class MPServersModel;
|
||||
class AircraftItemModel;
|
||||
class LocationWidget;
|
||||
class QQuickItem;
|
||||
class LaunchConfig;
|
||||
class LocationController;
|
||||
|
||||
class LauncherController : public QObject
|
||||
{
|
||||
|
@ -49,6 +49,8 @@ class LauncherController : public QObject
|
|||
|
||||
Q_PROPERTY(AircraftItemModel* baseAircraftModel MEMBER m_aircraftModel CONSTANT)
|
||||
|
||||
Q_PROPERTY(LocationController* location MEMBER m_location CONSTANT)
|
||||
|
||||
Q_PROPERTY(MPServersModel* mpServersModel MEMBER m_serversModel CONSTANT)
|
||||
|
||||
Q_PROPERTY(QUrl selectedAircraft READ selectedAircraft WRITE setSelectedAircraft NOTIFY selectedAircraftChanged)
|
||||
|
@ -61,7 +63,6 @@ class LauncherController : public QObject
|
|||
Q_PROPERTY(QStringList settingsSummary READ settingsSummary WRITE setSettingsSummary NOTIFY summaryChanged)
|
||||
Q_PROPERTY(QStringList environmentSummary READ environmentSummary WRITE setEnvironmentSummary NOTIFY summaryChanged)
|
||||
|
||||
Q_PROPERTY(QString locationDescription READ locationDescription NOTIFY summaryChanged)
|
||||
Q_PROPERTY(QStringList combinedSummary READ combinedSummary NOTIFY summaryChanged)
|
||||
|
||||
Q_PROPERTY(QString versionString READ versionString CONSTANT)
|
||||
|
@ -70,9 +71,10 @@ class LauncherController : public QObject
|
|||
Q_PROPERTY(RecentLocationsModel* locationHistory READ locationHistory CONSTANT)
|
||||
|
||||
Q_PROPERTY(bool canFly READ canFly NOTIFY canFlyChanged)
|
||||
|
||||
Q_PROPERTY(AircraftType aircraftType READ aircraftType NOTIFY selectedAircraftChanged)
|
||||
public:
|
||||
explicit LauncherController(QObject *parent,
|
||||
LocationWidget* loc);
|
||||
explicit LauncherController(QObject *parent);
|
||||
|
||||
void initQML();
|
||||
|
||||
|
@ -114,8 +116,6 @@ public:
|
|||
|
||||
QStringList combinedSummary() const;
|
||||
|
||||
QString locationDescription() const;
|
||||
|
||||
QString versionString() const;
|
||||
|
||||
RecentAircraftModel* aircraftHistory();
|
||||
|
@ -144,6 +144,22 @@ public:
|
|||
|
||||
void restoreSettings();
|
||||
void saveSettings();
|
||||
|
||||
LocationController* location() const
|
||||
{ return m_location; }
|
||||
|
||||
enum AircraftType
|
||||
{
|
||||
Airplane = 0,
|
||||
Seaplane,
|
||||
Helicopter,
|
||||
Airship
|
||||
};
|
||||
|
||||
Q_ENUM(AircraftType)
|
||||
|
||||
AircraftType aircraftType() const
|
||||
{ return m_aircraftType; }
|
||||
signals:
|
||||
|
||||
void selectedAircraftChanged(QUrl selectedAircraft);
|
||||
|
@ -195,8 +211,10 @@ private:
|
|||
AircraftProxyModel* m_aircraftSearchModel;
|
||||
AircraftProxyModel* m_browseAircraftModel;
|
||||
MPServersModel* m_serversModel = nullptr;
|
||||
LocationController* m_location = nullptr;
|
||||
|
||||
QUrl m_selectedAircraft;
|
||||
AircraftType m_aircraftType = Airplane;
|
||||
int m_ratingFilters[4] = {3, 3, 3, 3};
|
||||
LaunchConfig* m_config = nullptr;
|
||||
QmlAircraftInfo* m_selectedAircraftInfo = nullptr;
|
||||
|
@ -204,8 +222,6 @@ private:
|
|||
QStringList m_settingsSummary, m_environmentSummary;
|
||||
RecentAircraftModel* m_aircraftHistory = nullptr;
|
||||
RecentLocationsModel* m_locationHistory = nullptr;
|
||||
|
||||
LocationWidget* m_locationWidget_FIXME = nullptr;
|
||||
};
|
||||
|
||||
#endif // LAUNCHERCONTROLLER_HXX
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "DefaultAircraftLocator.hxx"
|
||||
#include "AddOnsController.hxx"
|
||||
#include "CatalogListModel.hxx"
|
||||
#include "LocationController.hxx"
|
||||
|
||||
#include "ui_Launcher.h"
|
||||
|
||||
|
@ -69,14 +70,12 @@ LauncherMainWindow::LauncherMainWindow() :
|
|||
|
||||
#endif
|
||||
|
||||
m_controller = new LauncherController(this, m_ui->location);
|
||||
m_controller = new LauncherController(this);
|
||||
m_controller->initQML();
|
||||
|
||||
connect(m_controller, &LauncherController::canFlyChanged,
|
||||
this, &LauncherMainWindow::onCanFlyChanged);
|
||||
|
||||
m_ui->location->setLaunchConfig(m_controller->config());
|
||||
|
||||
QMenu* toolsMenu = mb->addMenu(tr("Tools"));
|
||||
QAction* restoreDefaultsAction = toolsMenu->addAction(tr("Restore defaults..."));
|
||||
connect(restoreDefaultsAction, &QAction::triggered,
|
||||
|
@ -143,6 +142,18 @@ LauncherMainWindow::LauncherMainWindow() :
|
|||
this, &LauncherMainWindow::onQuickStatusChanged);
|
||||
m_ui->aircraftList->setSource(QUrl("qrc:///qml/AircraftList.qml"));
|
||||
|
||||
/////////////
|
||||
// location
|
||||
m_ui->location->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
||||
m_ui->location->engine()->addImportPath("qrc:///");
|
||||
m_ui->location->engine()->rootContext()->setContextProperty("_launcher", m_controller);
|
||||
m_ui->location->engine()->rootContext()->setContextProperty("_config", m_controller->config());
|
||||
m_ui->location->engine()->rootContext()->setContextProperty("_location", m_controller->location());
|
||||
connect( m_ui->location, &QQuickWidget::statusChanged,
|
||||
this, &LauncherMainWindow::onQuickStatusChanged);
|
||||
m_ui->location->setSource(QUrl("qrc:///qml/Location.qml"));
|
||||
|
||||
/////////////
|
||||
// settings
|
||||
m_ui->settings->engine()->addImportPath("qrc:///");
|
||||
QQmlContext* settingsContext = m_ui->settings->engine()->rootContext();
|
||||
|
|
1116
src/GUI/LocationController.cxx
Normal file
1116
src/GUI/LocationController.cxx
Normal file
File diff suppressed because it is too large
Load diff
203
src/GUI/LocationController.hxx
Normal file
203
src/GUI/LocationController.hxx
Normal file
|
@ -0,0 +1,203 @@
|
|||
// LocationController.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 LOCATION_CONTROLLER_HXX
|
||||
#define LOCATION_CONTROLLER_HXX
|
||||
|
||||
#include <QObjectList>
|
||||
|
||||
#include <Navaids/positioned.hxx>
|
||||
#include <Airports/airports_fwd.hxx>
|
||||
|
||||
#include "QtLauncher_fwd.hxx"
|
||||
#include "LaunchConfig.hxx"
|
||||
#include "QmlPositioned.hxx"
|
||||
|
||||
class NavSearchModel;
|
||||
|
||||
class LocationController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString description READ description NOTIFY descriptionChanged)
|
||||
|
||||
Q_PROPERTY(NavSearchModel* searchModel MEMBER m_searchModel CONSTANT)
|
||||
|
||||
Q_PROPERTY(QList<QObject*> airportRunways READ airportRunways NOTIFY baseLocationChanged)
|
||||
Q_PROPERTY(QList<QObject*> airportParkings READ airportParkings NOTIFY baseLocationChanged)
|
||||
|
||||
Q_PROPERTY(bool offsetEnabled READ offsetEnabled WRITE setOffsetEnabled NOTIFY offsetChanged)
|
||||
Q_PROPERTY(int offsetRadial READ offsetRadial WRITE setOffsetRadial NOTIFY offsetChanged)
|
||||
Q_PROPERTY(bool offsetBearingIsTrue MEMBER m_offsetBearingIsTrue NOTIFY offsetChanged)
|
||||
Q_PROPERTY(double offsetNm READ offsetNm WRITE setOffsetNm NOTIFY offsetChanged)
|
||||
|
||||
Q_PROPERTY(int headingDeg MEMBER m_headingDeg NOTIFY configChanged)
|
||||
Q_PROPERTY(int altitudeFt MEMBER m_altitudeFt NOTIFY configChanged)
|
||||
Q_PROPERTY(int airspeedKnots MEMBER m_airspeedKnots NOTIFY configChanged)
|
||||
Q_PROPERTY(bool onFinal READ onFinal WRITE setOnFinal NOTIFY configChanged)
|
||||
|
||||
Q_PROPERTY(bool isAirportLocation READ isAirportLocation NOTIFY baseLocationChanged)
|
||||
Q_PROPERTY(bool useActiveRunway READ useActiveRunway WRITE setUseActiveRunway NOTIFY configChanged)
|
||||
Q_PROPERTY(bool useAvailableParking READ useAvailableParking WRITE setUseAvailableParking NOTIFY configChanged)
|
||||
|
||||
Q_PROPERTY(bool tuneNAV1 READ tuneNAV1 WRITE setTuneNAV1 NOTIFY configChanged)
|
||||
Q_PROPERTY(QmlGeod baseGeod READ baseGeod WRITE setBaseGeod NOTIFY baseLocationChanged)
|
||||
|
||||
Q_PROPERTY(QmlPositioned* detail READ detail CONSTANT)
|
||||
public:
|
||||
explicit LocationController(QObject *parent = nullptr);
|
||||
~LocationController();
|
||||
|
||||
void setLaunchConfig(LaunchConfig* config);
|
||||
|
||||
QString description() const;
|
||||
|
||||
void setBaseLocation(FGPositionedRef ref);
|
||||
|
||||
bool shouldStartPaused() const;
|
||||
|
||||
void setLocationProperties();
|
||||
|
||||
void restoreLocation(QVariantMap l);
|
||||
QVariantMap saveLocation() const;
|
||||
|
||||
void restoreSettings();
|
||||
|
||||
/// used to automatically select aircraft state
|
||||
bool isParkedLocation() const;
|
||||
|
||||
/// used to automatically select aircraft state
|
||||
bool isAirborneLocation() const;
|
||||
|
||||
int offsetRadial() const;
|
||||
|
||||
double offsetNm() const
|
||||
{
|
||||
return m_offsetNm;
|
||||
}
|
||||
|
||||
Q_INVOKABLE void setBaseLocation(QmlPositioned* pos);
|
||||
|
||||
Q_INVOKABLE void setDetailLocation(QmlPositioned* pos);
|
||||
|
||||
QmlGeod baseGeod() const;
|
||||
void setBaseGeod(QmlGeod geod);
|
||||
|
||||
bool isAirportLocation() const;
|
||||
|
||||
bool offsetEnabled() const
|
||||
{
|
||||
return m_offsetEnabled;
|
||||
}
|
||||
|
||||
bool onFinal() const
|
||||
{
|
||||
return m_onFinal;
|
||||
}
|
||||
|
||||
void setUseActiveRunway(bool b);
|
||||
|
||||
bool useActiveRunway() const
|
||||
{
|
||||
return m_useActiveRunway;
|
||||
}
|
||||
|
||||
Q_INVOKABLE void addToRecent(QmlPositioned* pos);
|
||||
|
||||
QObjectList airportRunways() const;
|
||||
QObjectList airportParkings() const;
|
||||
|
||||
Q_INVOKABLE void showHistoryInSearchModel();
|
||||
|
||||
Q_INVOKABLE QmlGeod parseStringAsGeod(QString string) const;
|
||||
|
||||
bool tuneNAV1() const
|
||||
{
|
||||
return m_tuneNAV1;
|
||||
}
|
||||
|
||||
QmlPositioned* detail() const;
|
||||
|
||||
bool useAvailableParking() const
|
||||
{
|
||||
return m_useAvailableParking;
|
||||
}
|
||||
|
||||
public slots:
|
||||
void setOffsetRadial(int offsetRadial);
|
||||
|
||||
void setOffsetNm(double offsetNm);
|
||||
|
||||
void setOffsetEnabled(bool offsetEnabled);
|
||||
|
||||
void setOnFinal(bool onFinal);
|
||||
|
||||
void setTuneNAV1(bool tuneNAV1);
|
||||
|
||||
void setUseAvailableParking(bool useAvailableParking);
|
||||
|
||||
Q_SIGNALS:
|
||||
void descriptionChanged();
|
||||
void offsetChanged();
|
||||
void baseLocationChanged();
|
||||
void configChanged();
|
||||
|
||||
private Q_SLOTS:
|
||||
void onCollectConfig();
|
||||
private:
|
||||
|
||||
void onSearchComplete();
|
||||
|
||||
void onAirportRunwayClicked(FGRunwayRef rwy);
|
||||
void onAirportParkingClicked(FGParkingRef park);
|
||||
|
||||
|
||||
void addToRecent(FGPositionedRef pos);
|
||||
|
||||
void setNavRadioOption();
|
||||
|
||||
void applyPositionOffset();
|
||||
|
||||
NavSearchModel* m_searchModel = nullptr;
|
||||
|
||||
FGPositionedRef m_location;
|
||||
FGAirportRef m_airportLocation; // valid if m_location is an FGAirport
|
||||
FGPositionedRef m_detailLocation; // parking stand or runway detail
|
||||
bool m_locationIsLatLon = false;
|
||||
SGGeod m_geodLocation;
|
||||
|
||||
FGPositionedList m_recentLocations;
|
||||
LaunchConfig* m_config = nullptr;
|
||||
QmlPositioned* m_detailQml = nullptr;
|
||||
|
||||
bool m_offsetEnabled = false;
|
||||
int m_offsetRadial = 0;
|
||||
double m_offsetNm = 0.0;
|
||||
bool m_offsetBearingIsTrue = false;
|
||||
int m_headingDeg = 0;
|
||||
int m_altitudeFt= -9999;
|
||||
int m_airspeedKnots = 120;
|
||||
bool m_onFinal = false;
|
||||
bool m_useActiveRunway = true;
|
||||
bool m_tuneNAV1;
|
||||
bool m_useAvailableParking;
|
||||
};
|
||||
|
||||
#endif // LOCATION_CONTROLLER_HXX
|
File diff suppressed because it is too large
Load diff
|
@ -1,117 +0,0 @@
|
|||
// 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>
|
||||
|
||||
#include "LaunchConfig.hxx"
|
||||
#include "QtLauncher_fwd.hxx"
|
||||
|
||||
namespace Ui {
|
||||
class LocationWidget;
|
||||
}
|
||||
|
||||
class NavSearchModel;
|
||||
|
||||
class LocationWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LocationWidget(QWidget *parent = 0);
|
||||
~LocationWidget();
|
||||
|
||||
void setLaunchConfig(LaunchConfig* config);
|
||||
|
||||
QString locationDescription() const;
|
||||
|
||||
void setBaseLocation(FGPositionedRef ref);
|
||||
|
||||
void setAircraftType(LauncherAircraftType ty);
|
||||
|
||||
bool shouldStartPaused() const;
|
||||
|
||||
void setLocationProperties();
|
||||
|
||||
void restoreLocation(QVariantMap l);
|
||||
QVariantMap saveLocation() const;
|
||||
|
||||
void restoreSettings();
|
||||
|
||||
/// used to automatically select aircraft state
|
||||
bool isParkedLocation() const;
|
||||
|
||||
/// used to automatically select aircraft state
|
||||
bool isAirborneLocation() const;
|
||||
Q_SIGNALS:
|
||||
void descriptionChanged(QString t);
|
||||
|
||||
private Q_SLOTS:
|
||||
void updateDescription();
|
||||
void onLocationChanged();
|
||||
void onOffsetDataChanged();
|
||||
void onHeadingChanged();
|
||||
|
||||
void onCollectConfig();
|
||||
private:
|
||||
|
||||
void onSearch();
|
||||
void onSearchResultSelected(const QModelIndex& index);
|
||||
void onSearchComplete();
|
||||
|
||||
void onAirportRunwayClicked(FGRunwayRef rwy);
|
||||
void onAirportParkingClicked(FGParkingRef park);
|
||||
void onAirportHelipadClicked(FGHelipadRef pad);
|
||||
|
||||
void onOffsetBearingTrueChanged(bool on);
|
||||
|
||||
void addToRecent(FGPositionedRef pos);
|
||||
|
||||
void onOffsetEnabledToggled(bool on);
|
||||
void onBackToSearch();
|
||||
void setNavRadioOption();
|
||||
void onShowHistory();
|
||||
|
||||
void applyPositionOffset();
|
||||
|
||||
Ui::LocationWidget *m_ui;
|
||||
|
||||
NavSearchModel* m_searchModel;
|
||||
|
||||
FGPositionedRef m_location;
|
||||
bool m_locationIsLatLon;
|
||||
SGGeod m_geodLocation;
|
||||
|
||||
QToolButton* m_backButton;
|
||||
|
||||
FGPositionedList m_recentLocations;
|
||||
LauncherAircraftType m_aircraftType;
|
||||
|
||||
LaunchConfig* m_config = nullptr;
|
||||
};
|
||||
|
||||
#endif // LOCATIONWIDGET_H
|
|
@ -1,442 +0,0 @@
|
|||
<?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>0</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="5" column="2">
|
||||
<widget class="QSpinBox" name="approachDistanceSpin">
|
||||
<property name="suffix">
|
||||
<string>nm</string>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QRadioButton" name="parkingRadio">
|
||||
<property name="text">
|
||||
<string>Parking:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QRadioButton" name="runwayRadio">
|
||||
<property name="text">
|
||||
<string>Runway:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1" colspan="3">
|
||||
<widget class="QComboBox" name="parkingCombo"/>
|
||||
</item>
|
||||
<item row="5" 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="4" column="1" colspan="3">
|
||||
<widget class="QComboBox" name="runwayCombo"/>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QCheckBox" name="onFinalCheckbox">
|
||||
<property name="text">
|
||||
<string>On final approach at distance:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="4">
|
||||
<widget class="QLabel" name="titleLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" 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="navaidPage">
|
||||
<layout class="QGridLayout" name="gridLayout_3" rowstretch="0,1,0,0,0,0" columnstretch="1,0,0,1,0,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="4" column="6" 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="4" column="8" 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="4" column="5">
|
||||
<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="5" column="0" colspan="10">
|
||||
<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" stretch="1,0,0,1,0">
|
||||
<property name="leftMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="offsetBearingLabel">
|
||||
<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>
|
||||
<item row="4" 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="4" column="3">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Heading:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="4">
|
||||
<widget class="QSpinBox" name="headingSpinbox">
|
||||
<property name="wrapping">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>359</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" 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="0" column="0" colspan="10">
|
||||
<widget class="QLabel" name="navTitleLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="10">
|
||||
<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>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="searchPage">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<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 name, then press Enter</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" stretch="1,0">
|
||||
<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="minimumSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<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>
|
|
@ -27,7 +27,9 @@
|
|||
#include <QVector2D>
|
||||
#include <QMouseEvent>
|
||||
|
||||
NavaidDiagram::NavaidDiagram(QWidget* pr) :
|
||||
#include <Navaids/NavDataCache.hxx>
|
||||
|
||||
NavaidDiagram::NavaidDiagram(QQuickItem* pr) :
|
||||
BaseDiagram(pr),
|
||||
m_offsetEnabled(false),
|
||||
m_offsetDistanceNm(5.0),
|
||||
|
@ -37,12 +39,28 @@ NavaidDiagram::NavaidDiagram(QWidget* pr) :
|
|||
|
||||
}
|
||||
|
||||
void NavaidDiagram::setNavaid(FGPositionedRef nav)
|
||||
void NavaidDiagram::setNavaid(qlonglong nav)
|
||||
{
|
||||
m_navaid = nav;
|
||||
m_projectionCenter = nav ? nav->geod() : SGGeod();
|
||||
m_geod = nav->geod();
|
||||
m_navaid = fgpositioned_cast<FGNavRecord>(flightgear::NavDataCache::instance()->loadById(nav));
|
||||
m_projectionCenter = m_navaid ? m_navaid->geod() : SGGeod();
|
||||
m_geod = m_projectionCenter;
|
||||
recomputeBounds(true);
|
||||
emit locationChanged();
|
||||
}
|
||||
|
||||
qlonglong NavaidDiagram::navaid() const
|
||||
{
|
||||
return m_navaid->guid();
|
||||
}
|
||||
|
||||
void NavaidDiagram::setGeod(QmlGeod geod)
|
||||
{
|
||||
setGeod(geod.geod());
|
||||
}
|
||||
|
||||
QmlGeod NavaidDiagram::geod() const
|
||||
{
|
||||
return QmlGeod(m_geod);
|
||||
}
|
||||
|
||||
void NavaidDiagram::setGeod(const SGGeod &geod)
|
||||
|
@ -51,6 +69,7 @@ void NavaidDiagram::setGeod(const SGGeod &geod)
|
|||
m_geod = geod;
|
||||
m_projectionCenter = m_geod;
|
||||
recomputeBounds(true);
|
||||
emit locationChanged();
|
||||
}
|
||||
|
||||
void NavaidDiagram::setOffsetEnabled(bool offset)
|
||||
|
@ -59,24 +78,28 @@ void NavaidDiagram::setOffsetEnabled(bool offset)
|
|||
return;
|
||||
m_offsetEnabled = offset;
|
||||
recomputeBounds(true);
|
||||
emit offsetChanged();
|
||||
}
|
||||
|
||||
void NavaidDiagram::setOffsetDistanceNm(double distanceNm)
|
||||
{
|
||||
m_offsetDistanceNm = distanceNm;
|
||||
update();
|
||||
emit offsetChanged();
|
||||
}
|
||||
|
||||
void NavaidDiagram::setOffsetBearingDeg(int bearingDeg)
|
||||
{
|
||||
m_offsetBearingDeg = bearingDeg;
|
||||
update();
|
||||
emit offsetChanged();
|
||||
}
|
||||
|
||||
void NavaidDiagram::setHeadingDeg(int headingDeg)
|
||||
{
|
||||
m_headingDeg = headingDeg;
|
||||
update();
|
||||
emit offsetChanged();
|
||||
}
|
||||
|
||||
void NavaidDiagram::paintContents(QPainter *painter)
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#define GUI_NAVAID_DIAGRAM_HXX
|
||||
|
||||
#include "BaseDiagram.hxx"
|
||||
#include <QPainterPath>
|
||||
#include "QmlPositioned.hxx"
|
||||
|
||||
#include <Navaids/navrecord.hxx>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
|
@ -30,28 +30,50 @@
|
|||
class NavaidDiagram : public BaseDiagram
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
NavaidDiagram(QWidget* pr);
|
||||
|
||||
void setNavaid(FGPositionedRef nav);
|
||||
Q_PROPERTY(qlonglong navaid READ navaid WRITE setNavaid NOTIFY locationChanged)
|
||||
Q_PROPERTY(QmlGeod geod READ geod WRITE setGeod NOTIFY locationChanged)
|
||||
|
||||
Q_PROPERTY(int headingDeg READ headingDeg WRITE setHeadingDeg NOTIFY offsetChanged)
|
||||
Q_PROPERTY(int offsetBearingDeg READ offsetBearingDeg WRITE setOffsetBearingDeg NOTIFY offsetChanged)
|
||||
Q_PROPERTY(bool offsetEnabled READ isOffsetEnabled WRITE setOffsetEnabled NOTIFY offsetChanged)
|
||||
Q_PROPERTY(double offsetDistanceNm READ offsetDistanceNm WRITE setOffsetDistanceNm NOTIFY offsetChanged)
|
||||
public:
|
||||
NavaidDiagram(QQuickItem* pr = nullptr);
|
||||
|
||||
void setNavaid(qlonglong nav);
|
||||
qlonglong navaid() const;
|
||||
|
||||
void setGeod(QmlGeod geod);
|
||||
QmlGeod geod() const;
|
||||
|
||||
void setGeod(const SGGeod& geod);
|
||||
|
||||
bool isOffsetEnabled() const;
|
||||
bool isOffsetEnabled() const
|
||||
{ return m_offsetEnabled; }
|
||||
|
||||
void setOffsetEnabled(bool offset);
|
||||
|
||||
void setOffsetDistanceNm(double distanceNm);
|
||||
double offsetDistanceNm() const;
|
||||
double offsetDistanceNm() const
|
||||
{ return m_offsetDistanceNm; }
|
||||
|
||||
void setOffsetBearingDeg(int bearingDeg);
|
||||
int offsetBearingDeg() const;
|
||||
int offsetBearingDeg() const
|
||||
{ return m_offsetBearingDeg; }
|
||||
|
||||
void setHeadingDeg(int headingDeg);
|
||||
void headingDeg() const;
|
||||
protected:
|
||||
void paintContents(QPainter *) Q_DECL_OVERRIDE;
|
||||
int headingDeg() const
|
||||
{ return m_headingDeg; }
|
||||
|
||||
void doComputeBounds() Q_DECL_OVERRIDE;
|
||||
signals:
|
||||
void locationChanged();
|
||||
void offsetChanged();
|
||||
|
||||
protected:
|
||||
void paintContents(QPainter *) override;
|
||||
|
||||
void doComputeBounds() override;
|
||||
private:
|
||||
FGPositionedRef m_navaid;
|
||||
SGGeod m_geod;
|
||||
|
|
50
src/GUI/PixmapImageItem.cxx
Normal file
50
src/GUI/PixmapImageItem.cxx
Normal file
|
@ -0,0 +1,50 @@
|
|||
// PixmapImageItem.cxx - display a QPixmap/QImage directly
|
||||
//
|
||||
// Written by James Turner, started April 2018.
|
||||
//
|
||||
// Copyright (C) 2018 James Turner <james@flightgear.org>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by 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 "PixmapImageItem.hxx"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
PixmapImageItem::PixmapImageItem(QQuickItem* parent) :
|
||||
QQuickPaintedItem(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PixmapImageItem::paint(QPainter *painter)
|
||||
{
|
||||
if (_image.isNull())
|
||||
return;
|
||||
|
||||
QRect rect(0, 0, width(), height());
|
||||
painter->drawImage(rect, _image);
|
||||
}
|
||||
|
||||
void PixmapImageItem::setImage(QImage img)
|
||||
{
|
||||
if (img == _image)
|
||||
return;
|
||||
|
||||
_image = img;
|
||||
update();
|
||||
const auto sz = img.size();
|
||||
setImplicitSize(sz.width(), sz.height());
|
||||
emit imageChanged();
|
||||
}
|
50
src/GUI/PixmapImageItem.hxx
Normal file
50
src/GUI/PixmapImageItem.hxx
Normal file
|
@ -0,0 +1,50 @@
|
|||
// PixmapImageItem.hxx - display a QPixmap/QImage directly
|
||||
//
|
||||
// Written by James Turner, started April 2018.
|
||||
//
|
||||
// Copyright (C) 2018 James Turner <james@flightgear.org>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by 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 PIXMAPIMAGEITEM_HXX
|
||||
#define PIXMAPIMAGEITEM_HXX
|
||||
|
||||
#include <QQuickPaintedItem>
|
||||
#include <QImage>
|
||||
|
||||
class PixmapImageItem : public QQuickPaintedItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QImage image READ image WRITE setImage NOTIFY imageChanged)
|
||||
public:
|
||||
PixmapImageItem(QQuickItem* parent = nullptr);
|
||||
|
||||
void paint(QPainter* painter) override;
|
||||
|
||||
QImage image() const
|
||||
{ return _image; }
|
||||
|
||||
void setImage(QImage img);
|
||||
|
||||
signals:
|
||||
void imageChanged();
|
||||
|
||||
private:
|
||||
QImage _image;
|
||||
};
|
||||
|
||||
#endif // PIXMAPIMAGEITEM_HXX
|
26
src/GUI/QmlNavCacheWrapper.cxx
Normal file
26
src/GUI/QmlNavCacheWrapper.cxx
Normal file
|
@ -0,0 +1,26 @@
|
|||
// QmlNavCacheWrapper.cxx - Expose NavData to Qml
|
||||
//
|
||||
// Written by James Turner, started April 2018.
|
||||
//
|
||||
// Copyright (C) 2018 James Turner <james@flightgear.org>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by 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 "QmlNavCacheWrapper.hxx"
|
||||
|
||||
QmlNavCacheWrapper::QmlNavCacheWrapper()
|
||||
{
|
||||
|
||||
}
|
38
src/GUI/QmlNavCacheWrapper.hxx
Normal file
38
src/GUI/QmlNavCacheWrapper.hxx
Normal file
|
@ -0,0 +1,38 @@
|
|||
// QmlNavCacheWrapper.hxx - Expose NavData to Qml
|
||||
//
|
||||
// Written by James Turner, started April 2018.
|
||||
//
|
||||
// Copyright (C) 2018 James Turner <james@flightgear.org>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by 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 QMLNAVCACHEWRAPPER_HXX
|
||||
#define QMLNAVCACHEWRAPPER_HXX
|
||||
|
||||
#include <QObject>
|
||||
|
||||
/**
|
||||
* @brief QmlNavCacheWrapper wraps and exposes NavData to Qml as singleton
|
||||
* service
|
||||
*/
|
||||
class QmlNavCacheWrapper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
QmlNavCacheWrapper();
|
||||
};
|
||||
|
||||
#endif // QMLNAVCACHEWRAPPER_HXX
|
317
src/GUI/QmlPositioned.cxx
Normal file
317
src/GUI/QmlPositioned.cxx
Normal file
|
@ -0,0 +1,317 @@
|
|||
// QmlPositioned.cxx - Expose NavData to Qml
|
||||
//
|
||||
// Written by James Turner, started April 2018.
|
||||
//
|
||||
// Copyright (C) 2018 James Turner <james@flightgear.org>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by 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 "QmlPositioned.hxx"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <Navaids/NavDataCache.hxx>
|
||||
#include <Navaids/navrecord.hxx>
|
||||
#include <Airports/airport.hxx>
|
||||
#include <Airports/groundnetwork.hxx>
|
||||
#include <Airports/runways.hxx>
|
||||
|
||||
using namespace flightgear;
|
||||
|
||||
QmlGeod::QmlGeod() :
|
||||
m_data(SGGeod::fromDeg(-9999.0, -9999.0))
|
||||
{
|
||||
}
|
||||
|
||||
QmlGeod::QmlGeod(const SGGeod &geod) :
|
||||
m_data(geod)
|
||||
{
|
||||
}
|
||||
|
||||
double QmlGeod::latitudeDeg() const
|
||||
{
|
||||
return m_data.getLatitudeDeg();
|
||||
}
|
||||
|
||||
double QmlGeod::longitudeDeg() const
|
||||
{
|
||||
return m_data.getLongitudeDeg();
|
||||
}
|
||||
|
||||
double QmlGeod::latitudeRad() const
|
||||
{
|
||||
return m_data.getLatitudeRad();
|
||||
}
|
||||
|
||||
double QmlGeod::longitudeRad() const
|
||||
{
|
||||
return m_data.getLongitudeRad();
|
||||
}
|
||||
|
||||
double QmlGeod::elevationFt() const
|
||||
{
|
||||
return m_data.getElevationFt();
|
||||
}
|
||||
|
||||
bool QmlGeod::valid() const
|
||||
{
|
||||
return m_data.isValid();
|
||||
}
|
||||
|
||||
double QmlGeod::elevationM() const
|
||||
{
|
||||
return m_data.getElevationM();
|
||||
}
|
||||
|
||||
void QmlGeod::setLatitudeDeg(double latitudeDeg)
|
||||
{
|
||||
if (qFuzzyCompare(m_data.getLatitudeDeg(), latitudeDeg))
|
||||
return;
|
||||
|
||||
m_data.setLatitudeDeg(latitudeDeg);
|
||||
// emit latitudeChanged();
|
||||
}
|
||||
|
||||
void QmlGeod::setLongitudeDeg(double longitudeDeg)
|
||||
{
|
||||
if (qFuzzyCompare(m_data.getLongitudeDeg(), longitudeDeg))
|
||||
return;
|
||||
|
||||
m_data.setLongitudeDeg(longitudeDeg);
|
||||
// emit longitudeChanged();
|
||||
}
|
||||
|
||||
void QmlGeod::setLatitudeRad(double latitudeRad)
|
||||
{
|
||||
if (qFuzzyCompare(m_data.getLatitudeRad(), latitudeRad))
|
||||
return;
|
||||
|
||||
m_data.setLatitudeRad(latitudeRad);
|
||||
// emit latitudeChanged();
|
||||
}
|
||||
|
||||
void QmlGeod::setLongitudeRad(double longitudeRad)
|
||||
{
|
||||
if (qFuzzyCompare(m_data.getLongitudeRad(), longitudeRad))
|
||||
return;
|
||||
|
||||
m_data.setLongitudeRad(longitudeRad);
|
||||
// emit longitudeChanged();
|
||||
}
|
||||
|
||||
void QmlGeod::setElevationM(double elevationM)
|
||||
{
|
||||
if (qFuzzyCompare(m_data.getElevationM(), elevationM))
|
||||
return;
|
||||
|
||||
m_data.setElevationM(elevationM);
|
||||
// emit elevationChanged();
|
||||
}
|
||||
|
||||
void QmlGeod::setElevationFt(double elevationFt)
|
||||
{
|
||||
if (qFuzzyCompare(m_data.getElevationFt(), elevationFt))
|
||||
return;
|
||||
|
||||
m_data.setElevationFt(elevationFt);
|
||||
// emit elevationChanged();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QmlPositioned::QmlPositioned(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QmlPositioned::QmlPositioned(FGPositionedRef p) :
|
||||
m_pos(p)
|
||||
{
|
||||
}
|
||||
|
||||
void QmlPositioned::setInner(FGPositionedRef p)
|
||||
{
|
||||
if (!p) {
|
||||
m_pos.clear();
|
||||
} else {
|
||||
m_pos = p;
|
||||
}
|
||||
}
|
||||
|
||||
FGPositionedRef QmlPositioned::inner() const
|
||||
{
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
bool QmlPositioned::valid() const
|
||||
{
|
||||
return m_pos.valid();
|
||||
}
|
||||
|
||||
QString QmlPositioned::ident() const
|
||||
{
|
||||
if (!m_pos)
|
||||
return {};
|
||||
|
||||
return QString::fromStdString(m_pos->ident());
|
||||
}
|
||||
|
||||
QString QmlPositioned::name() const
|
||||
{
|
||||
if (!m_pos)
|
||||
return {};
|
||||
|
||||
return QString::fromStdString(m_pos->name());
|
||||
}
|
||||
|
||||
qlonglong QmlPositioned::guid() const
|
||||
{
|
||||
if (!m_pos)
|
||||
return 0;
|
||||
|
||||
return m_pos->guid();
|
||||
}
|
||||
|
||||
QmlPositioned::Type QmlPositioned::type() const
|
||||
{
|
||||
if (!m_pos)
|
||||
return Invalid;
|
||||
|
||||
return static_cast<Type>(m_pos->type());
|
||||
}
|
||||
|
||||
void QmlPositioned::setGuid(qlonglong guid)
|
||||
{
|
||||
if (m_pos && (m_pos->guid()) == guid)
|
||||
return;
|
||||
|
||||
m_pos = NavDataCache::instance()->loadById(guid);
|
||||
|
||||
emit guidChanged();
|
||||
emit infoChanged();
|
||||
}
|
||||
|
||||
bool QmlPositioned::isAirportType() const
|
||||
{
|
||||
return FGPositioned::isAirportType(m_pos.get());
|
||||
}
|
||||
|
||||
bool QmlPositioned::isRunwayType() const
|
||||
{
|
||||
return FGPositioned::isRunwayType(m_pos.get());
|
||||
}
|
||||
|
||||
bool QmlPositioned::isNavaidType() const
|
||||
{
|
||||
return FGPositioned::isNavaidType(m_pos.get());
|
||||
}
|
||||
|
||||
QmlGeod* QmlPositioned::geod() const
|
||||
{
|
||||
if (!m_pos)
|
||||
return nullptr;
|
||||
|
||||
return new QmlGeod(m_pos->geod());
|
||||
}
|
||||
|
||||
double QmlPositioned::navaidFrequencyMHz() const
|
||||
{
|
||||
FGNavRecord* nav = fgpositioned_cast<FGNavRecord>(m_pos);
|
||||
if (!nav)
|
||||
return 0.0;
|
||||
|
||||
qWarning() << Q_FUNC_INFO << "check me!";
|
||||
return nav->get_freq() / 1000.0;
|
||||
}
|
||||
|
||||
double QmlPositioned::navaidRangeNm() const
|
||||
{
|
||||
FGNavRecord* nav = fgpositioned_cast<FGNavRecord>(m_pos);
|
||||
if (!nav)
|
||||
return 0.0;
|
||||
|
||||
return nav->get_range();
|
||||
}
|
||||
|
||||
QmlPositioned *QmlPositioned::navaidRunway() const
|
||||
{
|
||||
FGNavRecord* nav = fgpositioned_cast<FGNavRecord>(m_pos);
|
||||
if (!nav || !nav->runway())
|
||||
return nullptr;
|
||||
|
||||
return new QmlPositioned(nav->runway());
|
||||
}
|
||||
|
||||
QmlPositioned *QmlPositioned::colocatedDME() const
|
||||
{
|
||||
FGNavRecord* nav = fgpositioned_cast<FGNavRecord>(m_pos);
|
||||
if (!nav || !nav->hasDME())
|
||||
return nullptr;
|
||||
|
||||
return new QmlPositioned(flightgear::NavDataCache::instance()->loadById(nav->colocatedDME()));
|
||||
}
|
||||
|
||||
QmlPositioned *QmlPositioned::owningAirport() const
|
||||
{
|
||||
FGRunway* runway = fgpositioned_cast<FGRunway>(m_pos);
|
||||
if (runway) {
|
||||
return new QmlPositioned(runway->airport());
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
double QmlPositioned::runwayHeadingDeg() const
|
||||
{
|
||||
FGRunway* runway = fgpositioned_cast<FGRunway>(m_pos);
|
||||
if (runway) {
|
||||
return runway->headingDeg();
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double QmlPositioned::runwayLengthFt() const
|
||||
{
|
||||
FGRunway* runway = fgpositioned_cast<FGRunway>(m_pos);
|
||||
if (runway) {
|
||||
return runway->lengthFt();
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
bool QmlPositioned::equals(QmlPositioned *other) const
|
||||
{
|
||||
return (other && (other->inner() == inner()));
|
||||
}
|
||||
|
||||
bool QmlPositioned::airportHasParkings() const
|
||||
{
|
||||
if (!isAirportType())
|
||||
return false;
|
||||
|
||||
FGAirport* apt = fgpositioned_cast<FGAirport>(m_pos);
|
||||
if (!apt)
|
||||
return false;
|
||||
|
||||
return !apt->groundNetwork()->allParkings().empty();
|
||||
}
|
||||
|
||||
bool operator==(const QmlPositioned& p1, const QmlPositioned& p2)
|
||||
{
|
||||
return p1.inner() == p2.inner();
|
||||
}
|
||||
|
186
src/GUI/QmlPositioned.hxx
Normal file
186
src/GUI/QmlPositioned.hxx
Normal file
|
@ -0,0 +1,186 @@
|
|||
// QmlPositioned.hxx - Expose NavData to Qml
|
||||
//
|
||||
// Written by James Turner, started April 2018.
|
||||
//
|
||||
// Copyright (C) 2018 James Turner <james@flightgear.org>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by 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 QMLPOSITIONED_HXX
|
||||
#define QMLPOSITIONED_HXX
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <Navaids/positioned.hxx>
|
||||
|
||||
/**
|
||||
* @brief Expose an SGGeod as Qml-friendly class
|
||||
*/
|
||||
class QmlGeod
|
||||
{
|
||||
Q_GADGET
|
||||
|
||||
|
||||
Q_PROPERTY(double latitudeDeg READ latitudeDeg WRITE setLatitudeDeg)
|
||||
Q_PROPERTY(double longitudeDeg READ longitudeDeg WRITE setLongitudeDeg)
|
||||
|
||||
Q_PROPERTY(double latitudeRad READ latitudeRad WRITE setLatitudeRad)
|
||||
Q_PROPERTY(double longitudeRad READ longitudeRad WRITE setLongitudeRad)
|
||||
|
||||
Q_PROPERTY(double elevationM READ elevationM WRITE setElevationM)
|
||||
Q_PROPERTY(double elevationFt READ elevationFt WRITE setElevationFt)
|
||||
|
||||
Q_PROPERTY(bool valid READ valid)
|
||||
public:
|
||||
QmlGeod();
|
||||
QmlGeod(const SGGeod& geod);
|
||||
|
||||
SGGeod geod() const
|
||||
{ return m_data; }
|
||||
|
||||
|
||||
double latitudeDeg() const;
|
||||
double longitudeDeg() const;
|
||||
double latitudeRad() const;
|
||||
double longitudeRad() const;
|
||||
double elevationM() const;
|
||||
double elevationFt() const;
|
||||
|
||||
bool valid() const;
|
||||
public slots:
|
||||
void setLatitudeDeg(double latitudeDeg);
|
||||
void setLongitudeDeg(double longitudeDeg);
|
||||
void setLatitudeRad(double latitudeRad);
|
||||
void setLongitudeRad(double longitudeRad);
|
||||
void setElevationM(double elevationM);
|
||||
void setElevationFt(double elevationFt);
|
||||
|
||||
private:
|
||||
SGGeod m_data;
|
||||
};
|
||||
|
||||
|
||||
Q_DECLARE_METATYPE(QmlGeod)
|
||||
|
||||
class QmlPositioned : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QmlPositioned(QObject *parent = nullptr);
|
||||
|
||||
explicit QmlPositioned(FGPositionedRef p);
|
||||
|
||||
// proxy FGPositioned type values
|
||||
enum Type {
|
||||
Invalid = FGPositioned::INVALID,
|
||||
Airport = FGPositioned::AIRPORT,
|
||||
Heliport = FGPositioned::HELIPORT,
|
||||
Seaport = FGPositioned::SEAPORT,
|
||||
Runway = FGPositioned::RUNWAY,
|
||||
Helipad = FGPositioned::HELIPAD,
|
||||
Taxiway = FGPositioned::TAXIWAY,
|
||||
Pavement = FGPositioned::PAVEMENT,
|
||||
Waypoint = FGPositioned::WAYPOINT,
|
||||
Fix = FGPositioned::FIX,
|
||||
NDB = FGPositioned::NDB,
|
||||
VOR = FGPositioned::VOR,
|
||||
ILS = FGPositioned::ILS,
|
||||
Localizer = FGPositioned::LOC,
|
||||
Glideslope = FGPositioned::GS,
|
||||
OuterMarker = FGPositioned::OM,
|
||||
MiddleMarker = FGPositioned::MM,
|
||||
InnerMarker = FGPositioned::IM,
|
||||
DME = FGPositioned::DME,
|
||||
TACAN = FGPositioned::TACAN,
|
||||
MobileTACAN = FGPositioned::MOBILE_TACAN,
|
||||
Tower = FGPositioned::TOWER,
|
||||
Parking = FGPositioned::PARKING,
|
||||
Country = FGPositioned::COUNTRY,
|
||||
City = FGPositioned::CITY,
|
||||
Town = FGPositioned::TOWN,
|
||||
Village = FGPositioned::VILLAGE
|
||||
};
|
||||
|
||||
Q_ENUM(Type)
|
||||
|
||||
Q_PROPERTY(QString ident READ ident NOTIFY infoChanged)
|
||||
Q_PROPERTY(QString name READ name NOTIFY infoChanged)
|
||||
Q_PROPERTY(Type type READ type NOTIFY infoChanged)
|
||||
|
||||
Q_PROPERTY(bool valid READ valid NOTIFY infoChanged)
|
||||
Q_PROPERTY(QmlGeod* geod READ geod NOTIFY infoChanged)
|
||||
Q_PROPERTY(qlonglong guid READ guid WRITE setGuid NOTIFY guidChanged)
|
||||
|
||||
Q_PROPERTY(bool isAirportType READ isAirportType NOTIFY infoChanged)
|
||||
Q_PROPERTY(bool isRunwayType READ isRunwayType NOTIFY infoChanged)
|
||||
Q_PROPERTY(bool isNavaidType READ isNavaidType NOTIFY infoChanged)
|
||||
|
||||
Q_PROPERTY(double navaidFrequencyMHz READ navaidFrequencyMHz NOTIFY infoChanged)
|
||||
Q_PROPERTY(double navaidRangeNm READ navaidRangeNm NOTIFY infoChanged)
|
||||
|
||||
Q_PROPERTY(QmlPositioned* colocatedDME READ colocatedDME NOTIFY infoChanged)
|
||||
Q_PROPERTY(QmlPositioned* navaidRunway READ navaidRunway NOTIFY infoChanged)
|
||||
Q_PROPERTY(QmlPositioned* owningAirport READ owningAirport NOTIFY infoChanged)
|
||||
|
||||
Q_PROPERTY(double runwayHeadingDeg READ runwayHeadingDeg NOTIFY infoChanged)
|
||||
Q_PROPERTY(double runwayLengthFt READ runwayLengthFt NOTIFY infoChanged)
|
||||
|
||||
Q_PROPERTY(bool airportHasParkings READ airportHasParkings NOTIFY infoChanged)
|
||||
|
||||
void setInner(FGPositionedRef p);
|
||||
FGPositionedRef inner() const;
|
||||
bool valid() const;
|
||||
|
||||
QString ident() const;
|
||||
QString name() const;
|
||||
qlonglong guid() const;
|
||||
Type type() const;
|
||||
|
||||
bool isAirportType() const;
|
||||
bool isRunwayType() const;
|
||||
bool isNavaidType() const;
|
||||
|
||||
QmlGeod* geod() const;
|
||||
|
||||
double navaidFrequencyMHz() const;
|
||||
double navaidRangeNm() const;
|
||||
|
||||
QmlPositioned* navaidRunway() const;
|
||||
QmlPositioned* colocatedDME() const;
|
||||
|
||||
// owning airport if one exists
|
||||
QmlPositioned* owningAirport() const;
|
||||
|
||||
double runwayHeadingDeg() const;
|
||||
double runwayLengthFt() const;
|
||||
|
||||
Q_INVOKABLE bool equals(QmlPositioned* other) const;
|
||||
|
||||
bool airportHasParkings() const;
|
||||
|
||||
public slots:
|
||||
void setGuid(qlonglong guid);
|
||||
|
||||
signals:
|
||||
void guidChanged();
|
||||
void infoChanged();
|
||||
|
||||
private:
|
||||
FGPositionedRef m_pos;
|
||||
};
|
||||
|
||||
bool operator==(const QmlPositioned& p1, const QmlPositioned& p2);
|
||||
|
||||
#endif // QMLPOSITIONED_HXX
|
|
@ -1,15 +1,11 @@
|
|||
#ifndef QTGUI_FWD_H
|
||||
#define QTGUI_FWD_H
|
||||
|
||||
enum LauncherAircraftType
|
||||
{
|
||||
Airplane = 0,
|
||||
Seaplane,
|
||||
Helicopter,
|
||||
Airship
|
||||
};
|
||||
#include <QString>
|
||||
|
||||
extern QString fixNavaidName(QString s);
|
||||
|
||||
|
||||
|
||||
#endif // QTGUI_FWD_H
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ FocusScope {
|
|||
property alias prefix: prefix.text
|
||||
property alias maxDigits: edit.maximumLength
|
||||
property int step: 1
|
||||
property bool live: false
|
||||
|
||||
implicitHeight: editFrame.height
|
||||
// we have a margin between the frame and the label, and on each
|
||||
|
@ -25,8 +26,11 @@ FocusScope {
|
|||
function incrementValue()
|
||||
{
|
||||
if (edit.activeFocus) {
|
||||
value = Math.min(parseFloat(edit.text) + root.step, root.max)
|
||||
edit.text = value
|
||||
var newValue = Math.min(parseFloat(edit.text) + root.step, root.max)
|
||||
edit.text = newValue
|
||||
if (live) {
|
||||
commit(newValue);
|
||||
}
|
||||
} else {
|
||||
commit(Math.min(value + root.step, root.max))
|
||||
}
|
||||
|
@ -35,8 +39,11 @@ FocusScope {
|
|||
function decrementValue()
|
||||
{
|
||||
if (edit.activeFocus) {
|
||||
value = Math.max(parseFloat(edit.text) - root.step, root.min)
|
||||
edit.text = value
|
||||
var newValue = Math.max(parseFloat(edit.text) - root.step, root.min)
|
||||
edit.text = newValue
|
||||
if (live) {
|
||||
commit(newValue);
|
||||
}
|
||||
} else {
|
||||
commit(Math.max(value - root.step, root.min))
|
||||
}
|
||||
|
@ -75,6 +82,17 @@ FocusScope {
|
|||
}
|
||||
}
|
||||
|
||||
// timer to commit the value when in live mode
|
||||
Timer {
|
||||
id: liveEditTimer
|
||||
interval: 800
|
||||
onTriggered: {
|
||||
if (edit.activeFocus) {
|
||||
commit(parseInt(edit.text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Binding {
|
||||
when: !edit.activeFocus
|
||||
target: edit
|
||||
|
@ -133,6 +151,13 @@ FocusScope {
|
|||
selectAll();
|
||||
} else {
|
||||
commit(parseFloat(text))
|
||||
liveEditTimer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
onTextChanged: {
|
||||
if (activeFocus && root.live) {
|
||||
liveEditTimer.restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ FocusScope {
|
|||
property alias prefix: prefix.text
|
||||
property alias maxDigits: edit.maximumLength
|
||||
property int step: 1
|
||||
property bool live: false
|
||||
|
||||
implicitHeight: editFrame.height
|
||||
// we have a margin between the frame and the label, and on each
|
||||
|
@ -23,8 +24,11 @@ FocusScope {
|
|||
function incrementValue()
|
||||
{
|
||||
if (edit.activeFocus) {
|
||||
value = Math.min(parseInt(edit.text) + root.step, root.max)
|
||||
edit.text = value
|
||||
var newValue = Math.min(parseInt(edit.text) + root.step, root.max)
|
||||
edit.text = newValue
|
||||
if (live) {
|
||||
commit(newValue);
|
||||
}
|
||||
} else {
|
||||
commit(Math.min(value + root.step, root.max))
|
||||
}
|
||||
|
@ -33,8 +37,11 @@ FocusScope {
|
|||
function decrementValue()
|
||||
{
|
||||
if (edit.activeFocus) {
|
||||
value = Math.max(parseInt(edit.text) - root.step, root.min)
|
||||
edit.text = value
|
||||
var newValue = Math.max(parseInt(edit.text) - root.step, root.min)
|
||||
edit.text = newValue
|
||||
if (live) {
|
||||
commit(newValue);
|
||||
}
|
||||
} else {
|
||||
commit(Math.max(value - root.step, root.min))
|
||||
}
|
||||
|
@ -73,6 +80,17 @@ FocusScope {
|
|||
}
|
||||
}
|
||||
|
||||
// timer to commit the value when in live mode
|
||||
Timer {
|
||||
id: liveEditTimer
|
||||
interval: 800
|
||||
onTriggered: {
|
||||
if (edit.activeFocus) {
|
||||
commit(parseInt(edit.text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Binding {
|
||||
when: !edit.activeFocus
|
||||
target: edit
|
||||
|
@ -131,6 +149,13 @@ FocusScope {
|
|||
selectAll();
|
||||
} else {
|
||||
commit(parseInt(text))
|
||||
liveEditTimer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
onTextChanged: {
|
||||
if (activeFocus && root.live) {
|
||||
liveEditTimer.restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
248
src/GUI/qml/Location.qml
Normal file
248
src/GUI/qml/Location.qml
Normal file
|
@ -0,0 +1,248 @@
|
|||
import QtQuick 2.4
|
||||
import FlightGear 1.0
|
||||
import FlightGear.Launcher 1.0
|
||||
import "."
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property bool __searchActive: false
|
||||
property string lastSearch
|
||||
|
||||
function backToSearch()
|
||||
{
|
||||
detailLoader.sourceComponent = null
|
||||
}
|
||||
|
||||
function selectLocation(guid, type)
|
||||
{
|
||||
selectedLocation.guid = guid;
|
||||
_location.setBaseLocation(selectedLocation)
|
||||
_location.addToRecent(selectedLocation);
|
||||
|
||||
if (selectedLocation.isAirportType) {
|
||||
detailLoader.sourceComponent = airportDetails
|
||||
} else {
|
||||
detailLoader.sourceComponent = navaidDetails
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
_location.showHistoryInSearchModel()
|
||||
}
|
||||
|
||||
Positioned {
|
||||
id: selectedLocation
|
||||
}
|
||||
|
||||
Component {
|
||||
id: airportDetails
|
||||
LocationAirportView {
|
||||
id: airportView
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Component {
|
||||
id: navaidDetails
|
||||
LocationNavaidView {
|
||||
id: navaidView
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "white"
|
||||
}
|
||||
|
||||
Component {
|
||||
id: locationSearchDelegate
|
||||
Rectangle {
|
||||
id: delegateRoot
|
||||
height: delegateContent.height + Style.margin
|
||||
width: searchView.width
|
||||
|
||||
function itemDescription()
|
||||
{
|
||||
if (model.type === Positioned.Fix) return model.ident
|
||||
|
||||
if (model.type === Positioned.VOR) {
|
||||
var freq = (model.frequency / 100).toFixed(3);
|
||||
return "%1 - %2 (%3 MHz)".arg(model.ident).arg(model.name).arg(freq);
|
||||
}
|
||||
|
||||
// general case
|
||||
return "%1 - %2".arg(model.ident).arg(model.name);
|
||||
}
|
||||
|
||||
|
||||
Item {
|
||||
id: delegateContent
|
||||
height: Math.max(delegateIcon.height, delegateText.height)
|
||||
width: parent.width
|
||||
|
||||
Rectangle {
|
||||
visible: delegateMouse.containsMouse
|
||||
color: "#cfcfcf"
|
||||
}
|
||||
|
||||
PixmapImage {
|
||||
id: delegateIcon
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Style.margin
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
image: model.icon
|
||||
}
|
||||
|
||||
Text {
|
||||
id: delegateText
|
||||
anchors.right: parent.right
|
||||
anchors.left: delegateIcon.right
|
||||
anchors.rightMargin: Style.margin
|
||||
anchors.leftMargin: Style.margin
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: delegateRoot.itemDescription();
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: delegateMouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
root.selectLocation(model.guid, model.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: footer
|
||||
height: Style.margin
|
||||
width: parent.width
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
Rectangle {
|
||||
color: Style.frameColor
|
||||
height: 1
|
||||
width: parent.width - Style.strutSize
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SearchButton {
|
||||
id: searchButton
|
||||
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.margins: Style.margin
|
||||
|
||||
autoSubmit: false
|
||||
placeholder: qsTr("Enter a navaid or airport ID, name or a latitude & longitude");
|
||||
|
||||
onSearch: {
|
||||
// when th search term is cleared, show the history
|
||||
if (term == "") {
|
||||
_location.showHistoryInSearchModel();
|
||||
return;
|
||||
}
|
||||
|
||||
var geod = _location.parseStringAsGeod(term)
|
||||
if (geod.valid) {
|
||||
console.info("REMOVE-ME: Setting lat-lon location")
|
||||
_location.baseGeod = geod
|
||||
selectedLocation.guid = 0;
|
||||
detailLoader.sourceComponent = navaidDetails
|
||||
return;
|
||||
}
|
||||
|
||||
root.lastSearch = term;
|
||||
_location.searchModel.setSearch(term, _launcher.aircraftType)
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: headerSplit
|
||||
color: Style.frameColor
|
||||
height: 1
|
||||
width: parent.width - Style.inset
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: searchButton.bottom
|
||||
anchors.topMargin: Style.margin
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: searchView
|
||||
anchors.top: headerSplit.bottom
|
||||
anchors.topMargin: Style.margin
|
||||
width: parent.width
|
||||
anchors.bottom: parent.bottom
|
||||
model: _location.searchModel
|
||||
delegate: locationSearchDelegate
|
||||
clip: true
|
||||
|
||||
header: Item {
|
||||
visible: _location.searchModel.isSearchActive
|
||||
width: parent.width
|
||||
height: visible ? 50 : 0
|
||||
|
||||
Text {
|
||||
text: qsTr("Searching")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.horizontalCenter
|
||||
}
|
||||
|
||||
AnimatedImage {
|
||||
source: "qrc://linear-spinner"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.horizontalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
footer: Item {
|
||||
width: parent.width
|
||||
height: noResultsText.height
|
||||
visible: (parent.count === 0) && !_location.searchModel.isSearchActive
|
||||
Text {
|
||||
id: noResultsText
|
||||
width: parent.width
|
||||
text: qsTr("No results for found search '%1'").arg(root.lastSearch)
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// scrollbar
|
||||
|
||||
Loader {
|
||||
id: detailLoader
|
||||
anchors.fill: parent
|
||||
visible: sourceComponent != null
|
||||
|
||||
onStatusChanged: {
|
||||
if (status == Loader.Ready) {
|
||||
if (selectedLocation.valid) {
|
||||
item.location = selectedLocation.guid
|
||||
} else {
|
||||
// lon-lat
|
||||
item.geod = _location.baseGeod
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
anchors { left: parent.left; top: parent.top; margins: Style.margin }
|
||||
width: Style.strutSize
|
||||
visible: detailLoader.visible
|
||||
|
||||
id: backButton
|
||||
text: "< Back"
|
||||
onClicked: {
|
||||
root.backToSearch();
|
||||
}
|
||||
}
|
||||
}
|
278
src/GUI/qml/LocationAirportView.qml
Normal file
278
src/GUI/qml/LocationAirportView.qml
Normal file
|
@ -0,0 +1,278 @@
|
|||
import QtQuick 2.4
|
||||
import FlightGear 1.0
|
||||
import FlightGear.Launcher 1.0
|
||||
import "."
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property alias location: airportData.guid
|
||||
|
||||
Positioned {
|
||||
id: airportData
|
||||
onGuidChanged: _location.setBaseLocation(this)
|
||||
}
|
||||
|
||||
readonly property bool isHeliport: airportData.type === Positioned.Heliport
|
||||
readonly property bool haveParking: airportData.airportHasParkings
|
||||
|
||||
AirportDiagram {
|
||||
id: diagram
|
||||
anchors.fill: parent
|
||||
airport: airportData.guid
|
||||
|
||||
onClicked: {
|
||||
if (pos === null)
|
||||
return;
|
||||
|
||||
_location.setDetailLocation(pos)
|
||||
diagram.selection = pos
|
||||
syncUIFromController();
|
||||
}
|
||||
|
||||
approachExtensionNm: _location.onFinal ? _location.offsetNm : -1.0
|
||||
}
|
||||
|
||||
// not very declarative, try to remove this over time
|
||||
function syncUIFromController()
|
||||
{
|
||||
runwayRadio.selected = (_location.detail.isRunwayType);
|
||||
parkingRadio.selected = (_location.detail.type == Positioned.Parking);
|
||||
|
||||
if (_location.detail.isRunwayType) {
|
||||
runwayChoice.syncCurrentIndex();
|
||||
} else if (_location.detail.type == Positioned.Parking) {
|
||||
parkingChoice.syncCurrentIndex();
|
||||
}
|
||||
}
|
||||
|
||||
RadioButtonGroup {
|
||||
id: radioGroup
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
syncUIFromController();
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: panel
|
||||
|
||||
color: "transparent"
|
||||
border.width: 1
|
||||
border.color: Style.frameColor
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
margins: Style.strutSize
|
||||
}
|
||||
|
||||
height: selectionGrid.height + Style.margin * 2
|
||||
|
||||
// set opacity here only, so we don't make the whole summary pannel translucent
|
||||
Rectangle {
|
||||
id: background
|
||||
anchors.fill: parent
|
||||
z: -1
|
||||
opacity: Style.panelOpacity
|
||||
color: "white"
|
||||
}
|
||||
|
||||
Column {
|
||||
id: selectionGrid
|
||||
spacing: Style.margin
|
||||
width: parent.width
|
||||
|
||||
Text { // heading text
|
||||
id: airportHeading
|
||||
width: parent.width
|
||||
text: isHeliport ? qsTr("Heliport: ") + airportData.ident + " / " + airportData.name
|
||||
: qsTr("Airport: ") + airportData.ident + " / " + airportData.name
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Style.margin
|
||||
|
||||
RadioButton {
|
||||
id: runwayRadio
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
group: radioGroup
|
||||
|
||||
onClicked: {
|
||||
if (selected) runwayChoice.setLocation();
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: isHeliport ? qsTr("Pad") : qsTr("Runway")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
PopupChoice {
|
||||
id: runwayChoice
|
||||
model: _location.airportRunways
|
||||
displayRole: "ident"
|
||||
width: parent.width * 0.5
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
headerText: qsTr("Active")
|
||||
enabled: runwayRadio.selected
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
setLocation();
|
||||
}
|
||||
|
||||
function setLocation()
|
||||
{
|
||||
if (currentIndex == -1) {
|
||||
_location.useActiveRunway = true;
|
||||
diagram.selection = null;
|
||||
} else {
|
||||
_location.setDetailLocation(_location.airportRunways[currentIndex])
|
||||
diagram.selection = _location.airportRunways[currentIndex]
|
||||
}
|
||||
}
|
||||
|
||||
function syncCurrentIndex()
|
||||
{
|
||||
if (_location.useActiveRunway) {
|
||||
currentIndex = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i=0; i < _location.airportRunways.length; ++i) {
|
||||
if (_location.airportRunways[i].equals(_location.detail)) {
|
||||
currentIndex = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// not found, default to active
|
||||
currentIndex = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// runway offset row
|
||||
Row {
|
||||
x: Style.strutSize
|
||||
|
||||
// no offset for helipads
|
||||
visible: !isHeliport
|
||||
|
||||
ToggleSwitch {
|
||||
id: onFinalToggle
|
||||
label: qsTr("On final approach at ")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
checked: _location.onFinal
|
||||
enabled:runwayRadio.selected
|
||||
onCheckedChanged: _location.onFinal = checked
|
||||
}
|
||||
|
||||
DoubleSpinbox {
|
||||
id: offsetNmEdit
|
||||
value: _location.offsetNm
|
||||
onCommit: _location.offsetNm = newValue;
|
||||
|
||||
suffix: "Nm"
|
||||
min: 0.0
|
||||
max: 40.0
|
||||
decimals: 1
|
||||
maxDigits: 5
|
||||
live: true
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
enabled: runwayRadio.selected && onFinalToggle.checked
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr(" from the threshold")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
ToggleSwitch {
|
||||
x: Style.strutSize
|
||||
// no localizer for helipads
|
||||
visible: !isHeliport
|
||||
|
||||
// enable if selected runway has ILS
|
||||
label: qsTr("Tune navigation radio (NAV1) to runway localizer")
|
||||
checked: _location.tuneNAV1
|
||||
|
||||
onCheckedChanged: {
|
||||
_location.tuneNAV1 = checked
|
||||
}
|
||||
}
|
||||
|
||||
// parking row
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Style.margin
|
||||
|
||||
// hide if there's no parking locations defined for this airport
|
||||
visible: haveParking
|
||||
|
||||
RadioButton {
|
||||
id: parkingRadio
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
group: radioGroup
|
||||
|
||||
onClicked: {
|
||||
if (selected) parkingChoice.setLocation();
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Parking")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
PopupChoice {
|
||||
id: parkingChoice
|
||||
model: _location.airportParkings
|
||||
displayRole: "name"
|
||||
width: parent.width * 0.5
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
headerText: qsTr("Available")
|
||||
enabled: parkingRadio.selected
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
setLocation();
|
||||
}
|
||||
|
||||
function syncCurrentIndex()
|
||||
{
|
||||
if (_location.useAvailableParking) {
|
||||
currentIndex = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i=0; i < _location.airportParkings.length; ++i) {
|
||||
if (_location.airportParkings[i].equals(_location.detail)) {
|
||||
currentIndex = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// not found, default to available
|
||||
currentIndex = -1;
|
||||
}
|
||||
|
||||
function setLocation()
|
||||
{
|
||||
if (currentIndex == -1) {
|
||||
_location.useAvailableParking = true;
|
||||
diagram.selection = null;
|
||||
} else {
|
||||
_location.setDetailLocation(_location.airportParkings[currentIndex])
|
||||
diagram.selection = _location.airportParkings[currentIndex]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // main layout column
|
||||
} // main panel rectangle
|
||||
}
|
182
src/GUI/qml/LocationNavaidView.qml
Normal file
182
src/GUI/qml/LocationNavaidView.qml
Normal file
|
@ -0,0 +1,182 @@
|
|||
import QtQuick 2.4
|
||||
import FlightGear 1.0
|
||||
import FlightGear.Launcher 1.0
|
||||
import "."
|
||||
|
||||
Item {
|
||||
property alias location: navaidData.guid
|
||||
property alias geod: diagram.geod
|
||||
|
||||
Positioned {
|
||||
id: navaidData
|
||||
onGuidChanged: {
|
||||
if (guid > 0) {
|
||||
diagram.navaid = guid
|
||||
_location.setBaseLocation(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NavaidDiagram {
|
||||
id: diagram
|
||||
anchors.fill: parent
|
||||
|
||||
offsetEnabled: _location.offsetEnabled
|
||||
offsetBearingDeg: _location.offsetRadial
|
||||
offsetDistanceNm: _location.offsetNm
|
||||
headingDeg: _location.headingDeg
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: panel
|
||||
|
||||
color: "transparent"
|
||||
border.width: 1
|
||||
border.color: Style.frameColor
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
margins: Style.strutSize
|
||||
}
|
||||
|
||||
height: selectionGrid.height + Style.margin * 2
|
||||
|
||||
// set opacity here only, so we don't make the whole summary pannel translucent
|
||||
Rectangle {
|
||||
id: background
|
||||
anchors.fill: parent
|
||||
z: -1
|
||||
opacity: Style.panelOpacity
|
||||
color: "white"
|
||||
}
|
||||
|
||||
Column {
|
||||
id: selectionGrid
|
||||
spacing: Style.margin
|
||||
width: parent.width
|
||||
|
||||
Text { // heading text
|
||||
visible: navaidData.valid
|
||||
id: heading
|
||||
width: parent.width
|
||||
text: "Navaid: " + navaidData.ident + " / " + navaidData.name
|
||||
}
|
||||
|
||||
Row {
|
||||
height: childrenRect.height
|
||||
width: parent.width
|
||||
spacing: Style.margin
|
||||
|
||||
IntegerSpinbox {
|
||||
label: qsTr("Airspeed:")
|
||||
suffix: "kts"
|
||||
min: 0
|
||||
max: 10000 // more for spaceships?
|
||||
step: 5
|
||||
maxDigits: 5
|
||||
value: _location.airspeedKnots
|
||||
onCommit: _location.airspeedKnots = newValue
|
||||
}
|
||||
|
||||
IntegerSpinbox {
|
||||
label: qsTr("Heading:")
|
||||
suffix: "deg" // FIXME use Unicode degree symbol
|
||||
min: 0
|
||||
max: 359
|
||||
live: true
|
||||
maxDigits: 3
|
||||
value: _location.headingDeg
|
||||
onCommit: _location.headingDeg = newValue
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
height: childrenRect.height
|
||||
width: parent.width
|
||||
spacing: Style.margin
|
||||
|
||||
IntegerSpinbox {
|
||||
label: qsTr("Altitude:")
|
||||
suffix: "ft"
|
||||
min: -1000 // Dead Sea, Schiphol
|
||||
max: 200000
|
||||
step: 100
|
||||
maxDigits: 6
|
||||
|
||||
visible: !altitudeTypeChoice.isFlightLevel
|
||||
value: _location.altitudeFt
|
||||
onCommit: _location.altitudeFt = newValue
|
||||
}
|
||||
|
||||
IntegerSpinbox {
|
||||
label: qsTr("Altitude:")
|
||||
prefix: "FL"
|
||||
min: 0
|
||||
max: 1000
|
||||
step: 10
|
||||
maxDigits: 3
|
||||
visible: altitudeTypeChoice.isFlightLevel
|
||||
}
|
||||
|
||||
PopupChoice {
|
||||
id: altitudeTypeChoice
|
||||
|
||||
readonly property bool isFlightLevel: (currentIndex == 2)
|
||||
|
||||
model: [qsTr("Above mean sea-level (MSL)"),
|
||||
qsTr("Above ground (AGL)"),
|
||||
qsTr("Flight-level")]
|
||||
}
|
||||
}
|
||||
|
||||
// offset row
|
||||
Row {
|
||||
x: Style.strutSize
|
||||
|
||||
ToggleSwitch {
|
||||
id: offsetToggle
|
||||
label: qsTr("Offset ")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
checked: _location.offsetEnabled
|
||||
onCheckedChanged: {
|
||||
_location.offsetEnabled = checked
|
||||
}
|
||||
}
|
||||
|
||||
DoubleSpinbox {
|
||||
id: offsetNmEdit
|
||||
value: _location.offsetNm
|
||||
onCommit: _location.offsetNm = newValue
|
||||
min: 0.0
|
||||
max: 40.0
|
||||
suffix: "Nm"
|
||||
maxDigits: 5
|
||||
decimals: 1
|
||||
live: true
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
enabled: offsetToggle.checked
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr(" on bearing ")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
IntegerSpinbox {
|
||||
id: offsetBearingEdit
|
||||
suffix: "deg" // FIXME use Unicode degree symbol
|
||||
min: 0
|
||||
max: 359
|
||||
maxDigits: 3
|
||||
live: true
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
enabled: offsetToggle.checked
|
||||
value: _location.offsetRadial
|
||||
onCommit: _location.offsetRadial = newValue
|
||||
}
|
||||
}
|
||||
} // main layout column
|
||||
} // main panel rectangle
|
||||
}
|
|
@ -18,6 +18,13 @@ Item {
|
|||
color: "magenta"
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: _launcher
|
||||
onAircraftTypeChanged: {
|
||||
console.info("Aircraft type is now:" + _launcher.aircraftType)
|
||||
}
|
||||
}
|
||||
|
||||
PreviewImage {
|
||||
id: preview
|
||||
anchors.centerIn: parent
|
||||
|
@ -151,7 +158,8 @@ Item {
|
|||
// TODO - make clickable, jump to to the aircraft in the installed
|
||||
// aircraft list
|
||||
Text {
|
||||
text: _launcher.selectedAircraftInfo.name
|
||||
text: _launcher.selectedAircraftInfo.name === "" ?
|
||||
qsTr("No aircraft selected") : _launcher.selectedAircraftInfo.name
|
||||
font.pixelSize: Style.headingFontPixelSize
|
||||
}
|
||||
|
||||
|
@ -265,8 +273,9 @@ Item {
|
|||
|
||||
// TODO - make clickable, jump to the location page
|
||||
Text {
|
||||
text: _launcher.locationDescription
|
||||
text: _launcher.location.description
|
||||
font.pixelSize: Style.headingFontPixelSize
|
||||
width: summaryGrid.middleColumnWidth
|
||||
}
|
||||
|
||||
HistoryPopup {
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
<file>qml/DateTimeValueEdit.qml</file>
|
||||
<file>qml/SettingsDateTimePicker.qml</file>
|
||||
<file>qml/Summary.qml</file>
|
||||
<file>qml/Location.qml</file>
|
||||
<file>qml/HistoryPopup.qml</file>
|
||||
<file>qml/AddOns.qml</file>
|
||||
<file>qml/DragToReorderButton.qml</file>
|
||||
|
@ -86,6 +87,8 @@
|
|||
<file>qml/PathListDelegate.qml</file>
|
||||
<file>qml/AddCatalogPanel.qml</file>
|
||||
<file>qml/LineEdit.qml</file>
|
||||
<file>qml/LocationAirportView.qml</file>
|
||||
<file>qml/LocationNavaidView.qml</file>
|
||||
<file alias="linear-spinner">qml/icons8-linear-spinner.gif</file>
|
||||
<file>qml/RadioButton.qml</file>
|
||||
<file>qml/IntegerSpinbox.qml</file>
|
||||
|
|
Loading…
Reference in a new issue