swift
Loading...
Searching...
No Matches
coordinateform.cpp
1// SPDX-FileCopyrightText: Copyright (C) 2017 swift Project Community / Contributors
2// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3
4#include "coordinateform.h"
5
6#include <QIntValidator>
7
8#include "ui_coordinateform.h"
9
13#include "gui/guiapplication.h"
15
16using namespace swift::gui;
17using namespace swift::misc;
18using namespace swift::misc::geo;
19using namespace swift::misc::aviation;
20using namespace swift::misc::physical_quantities;
21
22namespace swift::gui::editors
23{
25 {
26 ui->setupUi(this);
27
28 ui->lblp_LatCheck->setToolTips("ok", "wrong format");
29 ui->lblp_LngCheck->setToolTips("ok", "wrong format");
30 ui->lblp_ElvCheck->setToolTips("ok", "wrong format");
31
32 ui->le_LatDeg->setValidator(new QIntValidator(-90, 90, ui->le_LatDeg));
33 ui->le_LatMin->setValidator(new QIntValidator(0, 60, ui->le_LatMin));
34 ui->le_LatSec->setValidator(new QIntValidator(0, 60, ui->le_LatSec));
35 ui->le_LatSecFrag->setValidator(new QIntValidator(0, 10E7, ui->le_LatSecFrag));
36
37 ui->le_LngDeg->setValidator(new QIntValidator(-180, 180, ui->le_LngDeg));
38 ui->le_LngMin->setValidator(new QIntValidator(0, 60, ui->le_LngMin));
39 ui->le_LngSec->setValidator(new QIntValidator(0, 60, ui->le_LngSec));
40 ui->le_LngSecFrag->setValidator(new QIntValidator(0, 10E7, ui->le_LngSecFrag));
41
42 connect(ui->le_Latitude, &QLineEdit::editingFinished, this, &CCoordinateForm::latEntered);
43 connect(ui->le_Longitude, &QLineEdit::editingFinished, this, &CCoordinateForm::lngEntered);
44 connect(ui->le_Elevation, &QLineEdit::editingFinished, this, &CCoordinateForm::elvEntered);
45
46 connect(ui->le_LatDeg, &QLineEdit::editingFinished, this, &CCoordinateForm::latCombinedEntered);
47 connect(ui->le_LatMin, &QLineEdit::editingFinished, this, &CCoordinateForm::latCombinedEntered);
48 connect(ui->le_LatSec, &QLineEdit::editingFinished, this, &CCoordinateForm::latCombinedEntered);
49 connect(ui->le_LatSecFrag, &QLineEdit::editingFinished, this, &CCoordinateForm::latCombinedEntered);
50
51 connect(ui->le_LngDeg, &QLineEdit::editingFinished, this, &CCoordinateForm::lngCombinedEntered);
52 connect(ui->le_LngMin, &QLineEdit::editingFinished, this, &CCoordinateForm::lngCombinedEntered);
53 connect(ui->le_LngSec, &QLineEdit::editingFinished, this, &CCoordinateForm::lngCombinedEntered);
54 connect(ui->le_LngSecFrag, &QLineEdit::editingFinished, this, &CCoordinateForm::lngCombinedEntered);
55
56 connect(ui->le_Location, &QLineEdit::returnPressed, this, &CCoordinateForm::locationEntered);
57
59 connect(ui->pb_OwnAircraft, &QPushButton::pressed, this, &CCoordinateForm::presetOwnAircraftPosition);
60
61 const CCoordinateGeodetic c;
62 this->setCoordinate(c);
63 }
64
66
68 {
69 if (coordinate == m_coordinate)
70 {
71 return false;
72 }
73 m_coordinate = coordinate;
74
75 const CLatitude lat = coordinate.latitude();
76 const QString latWgs = lat.toWgs84();
77 ui->le_Latitude->setText(latWgs);
78 ui->le_Latitude->setToolTip(QString::number(lat.value(CAngleUnit::deg())));
79 ui->lblp_LatCheck->setTicked(!lat.isNull());
80 if (latWgs.contains('S'))
81 {
82 ui->rb_S->setChecked(true);
83 }
84 else
85 {
86 ui->rb_N->setChecked(true);
87 }
88
89 const CLongitude lng = coordinate.longitude();
90 const QString lngWgs = lng.toWgs84();
91 ui->le_Longitude->setText(lngWgs);
92 ui->le_Longitude->setToolTip(QString::number(lng.value(CAngleUnit::deg())));
93 ui->lblp_LngCheck->setTicked(!lng.isNull());
94 if (lngWgs.contains('W'))
95 {
96 ui->rb_W->setChecked(true);
97 }
98 else
99 {
100 ui->rb_E->setChecked(true);
101 }
102
104 ui->le_LatDeg->setText(latParts.degAsString());
105 ui->le_LatMin->setText(latParts.minAsString());
106 ui->le_LatSec->setText(latParts.secAsString());
107 ui->le_LatSecFrag->setText(latParts.fractionalSecAsString(6));
108
110 ui->le_LngDeg->setText(lngParts.degAsString());
111 ui->le_LngMin->setText(lngParts.minAsString());
112 ui->le_LngSec->setText(lngParts.secAsString());
113 ui->le_LngSecFrag->setText(lngParts.fractionalSecAsString(6));
114
115 const QString elvString = coordinate.geodeticHeightAsString();
116 ui->le_Elevation->setText(elvString);
117 ui->lblp_ElvCheck->setTicked(!elvString.isEmpty());
118
119 std::array<double, 3> v = coordinate.normalVectorDouble();
120 ui->le_X->setText(QString::number(v[0]));
121 ui->le_Y->setText(QString::number(v[1]));
122 ui->le_Z->setText(QString::number(v[2]));
123 ui->le_X->home(false);
124 ui->le_Y->home(false);
125 ui->le_Z->home(false);
126
127 return true;
128 }
129
131 {
132 ui->le_Elevation->setReadOnly(readonly);
133 ui->le_LatDeg->setReadOnly(readonly);
134 ui->le_Latitude->setReadOnly(readonly);
135 ui->le_LatMin->setReadOnly(readonly);
136 ui->le_LatSec->setReadOnly(readonly);
137 ui->le_LatSecFrag->setReadOnly(readonly);
138 ui->le_LngDeg->setReadOnly(readonly);
139 ui->le_LngMin->setReadOnly(readonly);
140 ui->le_LngSec->setReadOnly(readonly);
141 ui->le_LngSecFrag->setReadOnly(readonly);
142 ui->le_Longitude->setReadOnly(readonly);
143
144 ui->rb_E->setEnabled(!readonly);
145 ui->rb_N->setEnabled(!readonly);
146 ui->rb_S->setEnabled(!readonly);
147 ui->rb_W->setEnabled(!readonly);
148
149 ui->le_Location->setReadOnly(readonly);
150 ui->le_Location->setVisible(!readonly); // does not make sense to show it in ro, no reverse lookup
151 ui->lbl_Location->setVisible(!readonly);
152
153 this->forceStyleSheetUpdate();
154 }
155
157 {
158 // not implemented
159 Q_UNUSED(nested);
161 return ml;
162 }
163
164 void CCoordinateForm::showSetButton(bool visible) { ui->pb_Set->setVisible(visible); }
165
167 {
168 ui->le_Elevation->setVisible(show);
169 ui->lbl_Elevation->setVisible(show);
170 ui->lblp_ElvCheck->setVisible(show);
171 m_coordinate.setGeodeticHeightToNull();
172 }
173
174 void CCoordinateForm::locationEntered()
175 {
176 const QString l = ui->le_Location->text().trimmed().simplified().toUpper();
177
178 // location based on swift data
179 if (sApp && sApp->hasWebDataServices())
180 {
181 CAirport airport;
182
183 // airport ICAO
184 if (l.length() == 4 && sApp->getWebDataServices()->getAirportsCount() > 0)
185 {
186 airport = sApp->getWebDataServices()->getAirportForIcaoDesignator(l);
187 if (airport.hasValidDbKey())
188 {
189 this->setCoordinate(airport);
190 return;
191 }
192 }
193
194 airport = sApp->getWebDataServices()->getAirportForNameOrLocation(l);
195 if (airport.hasValidDbKey())
196 {
197 this->setCoordinate(airport);
198 return;
199 }
200 }
201 // 33°59′42″S 150°57′06″E
202 if (l.contains(' '))
203 {
204 QString lat, lng;
205 const QStringList parts = l.split(' ');
206 for (const QString &p : parts)
207 {
208 if (p.contains('S') || p.contains('N'))
209 {
210 lat = p;
211 }
212 else if (p.contains('E') || p.contains('W'))
213 {
214 lng = p;
215 }
216 }
217 if (!lat.isEmpty() && !lng.isEmpty())
218 {
219 CCoordinateGeodetic c = m_coordinate;
220 c.setLatLongFromWgs84(lat, lng);
221 this->setCoordinate(c);
222 }
223 }
224 }
225
226 void CCoordinateForm::latEntered()
227 {
228 const QString ls = ui->le_Latitude->text();
229 const CLatitude l = CLatitude::fromWgs84(ls);
230 ui->lblp_LatCheck->setTicked(!l.isNull());
231 CCoordinateGeodetic c = m_coordinate;
232 c.setLatitude(l);
233 this->setCoordinate(c);
234 }
235
236 void CCoordinateForm::latCombinedEntered()
237 {
238 bool ok {};
239 int deg = ui->le_LatDeg->text().trimmed().toInt(&ok);
240 if (!ok) return;
241
242 int min = ui->le_LatMin->text().trimmed().toInt(&ok);
243 if (!ok) return;
244
245 const QString secStr = ui->le_LatSec->text().trimmed() + "." + ui->le_LatSecFrag->text().trimmed();
246 double sec = secStr.toDouble(&ok);
247 if (!ok) return;
248
249 CAngle::unifySign(deg, min, sec);
250 const CAngle a(deg, min, sec);
251 CLatitude lat(a);
252 lat.roundToEpsilon();
253 CCoordinateGeodetic c = m_coordinate;
254 c.setLatitude(lat);
255 this->setCoordinate(c);
256 }
257
258 void CCoordinateForm::lngEntered()
259 {
260 const QString ls = ui->le_Longitude->text();
261 const CLongitude l = CLongitude::fromWgs84(ls);
262 ui->lblp_LatCheck->setTicked(!l.isNull());
263 CCoordinateGeodetic c = m_coordinate;
264 c.setLongitude(l);
265 this->setCoordinate(c);
266 }
267
268 void CCoordinateForm::lngCombinedEntered()
269 {
270 bool ok {};
271 int deg = ui->le_LngDeg->text().trimmed().toInt(&ok);
272 if (!ok) return;
273
274 int min = ui->le_LngMin->text().trimmed().toInt(&ok);
275 if (!ok) return;
276
277 const QString secStr = ui->le_LngSec->text().trimmed() + "." + ui->le_LngSecFrag->text().trimmed();
278 double sec = secStr.toDouble(&ok);
279 if (!ok) return;
280
281 CAngle::unifySign(deg, min, sec);
282 const CAngle a(deg, min, sec);
283 CLongitude lng(a);
284 lng.roundToEpsilon();
285 CCoordinateGeodetic c = m_coordinate;
286 c.setLongitude(lng);
287 this->setCoordinate(c);
288 }
289
290 void CCoordinateForm::elvEntered()
291 {
292 const QString e = ui->le_Elevation->text().trimmed();
293 CAltitude a;
295 ui->lblp_ElvCheck->setTicked(!e.isNull());
296 CCoordinateGeodetic c = m_coordinate;
298 this->setCoordinate(c);
299 }
300
301 void CCoordinateForm::presetOwnAircraftPosition()
302 {
303 if (!sGui || sGui->isShuttingDown())
304 {
305 return;
306 }
308 {
309 return;
310 }
311 const CCoordinateGeodetic coordinate = sGui->getIContextOwnAircraft()->getOwnAircraft().getSituation();
312 this->setCoordinate(coordinate);
313 }
314} // namespace swift::gui::editors
static void unifySign(int degrees, int &minutes, double &seconds)
Minutes and secods will get same sign as degrees.
Definition angle.cpp:30
static CAngleUnit deg()
Degrees.
Definition units.h:276
const context::IContextOwnAircraft * getIContextOwnAircraft() const
Direct access to contexts if a CCoreFacade has been initialized.
bool isShuttingDown() const
Is application shutting down?
virtual swift::misc::simulation::CSimulatedAircraft getOwnAircraft() const =0
Get own aircraft.
void showElevation(bool show)
Show elevation.
swift::misc::CStatusMessageList validate(bool nested=false) const
Validate, empty list means OK.
void showSetButton(bool visible)
Set button visible.
void setReadOnly(bool readonly)
Set editable.
void changedCoordinate()
Change coordinate.
bool setCoordinate(const swift::misc::geo::ICoordinateGeodetic &coordinate)
Set the coordinate.
CCoordinateForm(QWidget *parent=nullptr)
Ctor.
void forceStyleSheetUpdate()
Forces a stylesheet update.
Definition form.cpp:53
CForm(QWidget *parent=nullptr)
Constructor.
Definition form.cpp:17
Status messages, e.g. from Core -> GUI.
Value object encapsulating information about an airpot.
Definition airport.h:36
void parseFromString(const QString &value)
Parse value from string.
Definition altitude.cpp:179
bool hasValidDbKey() const
Has valid DB key.
Definition datastore.h:102
void setLatLongFromWgs84(const QString &latitude, const QString &longitude)
Set latitude and longitude.
void setLatitude(const CLatitude &latitude)
Set latitude.
void setGeodeticHeight(const aviation::CAltitude &height)
Set height (ellipsoidal or geodetic height).
void setLongitude(const CLongitude &longitude)
Set longitude.
QString toWgs84(int fractionalDigits=3) const
To WGS84 string.
Definition latitude.h:32
QString toWgs84(int withFragmentSecDigits=3) const
To WGS84 string.
Definition longitude.h:32
Geodetic coordinate, a position in 3D space relative to the reference geoid.
virtual CLongitude longitude() const =0
Longitude.
virtual std::array< double, 3 > normalVectorDouble() const =0
Normal vector with double precision.
QString geodeticHeightAsString() const
Height as string.
virtual CLatitude latitude() const =0
Latitude.
DegMinSecFractionalSec asSexagesimalDegMinSec(bool range180Degrees=false) const
As individual values.
Definition angle.cpp:47
double value(MU unit) const
Value in given unit.
const aviation::CAircraftSituation & getSituation() const
Get situation.
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
GUI related classes.
Free functions in swift::misc.
void editingFinished()
void returnPressed()
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
bool isNull() const const
qsizetype length() const const
QString number(double n, char format, int precision)
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
double toDouble(bool *ok) const const
QString trimmed() const const
QWidget(QWidget *parent, Qt::WindowFlags f)
void show()
QString fractionalSecAsString(int width=-1) const
Fractional seconds as string.
Definition angle.h:53