1 /**********************************************************************************************
2 Copyright (C) 2008 Oliver Eichler <oliver.eichler@gmx.de>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
17
18 **********************************************************************************************/
19 #include "CMainWindow.h"
20 #include "gis/GeoMath.h"
21 #include "gis/proj_x.h"
22 #include "units/CUnitImperial.h"
23 #include "units/CUnitMetric.h"
24 #include "units/CUnitNautic.h"
25
26 #include <QtWidgets>
27 const IUnit* IUnit::m_self = nullptr;
28
29 const QPointF NOPOINTF(NOFLOAT, NOFLOAT);
30 const QPoint NOPOINT (NOINT, NOINT);
31
32 IUnit::tz_mode_e IUnit::timeZoneMode = IUnit::eTZUtc;
33 IUnit::coord_format_e IUnit::coordFormat = IUnit::eCoordFormat1;
34 QByteArray IUnit::timeZone = "UTC";
35 bool IUnit::useShortFormat = false;
36
37 const char* IUnit::tblTimezone[] =
38 {
39 "Africa/Abidjan",
40 "Africa/Accra",
41 "Africa/Addis_Ababa",
42 "Africa/Algiers",
43 "Africa/Asmara",
44 "Africa/Bamako",
45 "Africa/Bangui",
46 "Africa/Banjul",
47 "Africa/Bissau",
48 "Africa/Blantyre",
49 "Africa/Brazzaville",
50 "Africa/Bujumbura",
51 "Africa/Cairo",
52 "Africa/Casablanca",
53 "Africa/Conakry",
54 "Africa/Dakar",
55 "Africa/Dar_es_Salaam",
56 "Africa/Djibouti",
57 "Africa/Douala",
58 "Africa/El_Aaiun",
59 "Africa/Freetown",
60 "Africa/Gaborone",
61 "Africa/Harare",
62 "Africa/Johannesburg",
63 "Africa/Kampala",
64 "Africa/Khartoum",
65 "Africa/Kigali",
66 "Africa/Kinshasa",
67 "Africa/Lagos",
68 "Africa/Libreville",
69 "Africa/Lome",
70 "Africa/Luanda",
71 "Africa/Lubumbashi",
72 "Africa/Lusaka",
73 "Africa/Malabo",
74 "Africa/Maputo",
75 "Africa/Maseru",
76 "Africa/Mbabane",
77 "Africa/Mogadishu",
78 "Africa/Monrovia",
79 "Africa/Nairobi",
80 "Africa/Ndjamena",
81 "Africa/Niamey",
82 "Africa/Nouakchott",
83 "Africa/Ouagadougou",
84 "Africa/Porto-Novo",
85 "Africa/Sao_Tome",
86 "Africa/Tripoli",
87 "Africa/Tunis",
88 "Africa/Windhoek",
89 "America/Adak",
90 "America/Anguilla",
91 "America/Antigua",
92 "America/Araguaina",
93 "America/Argentina/Buenos_Aires",
94 "America/Argentina/Catamarca",
95 "America/Argentina/Cordoba",
96 "America/Argentina/Jujuy",
97 "America/Argentina/La_Rioja",
98 "America/Argentina/Mendoza",
99 "America/Argentina/Rio_Gallegos",
100 "America/Argentina/San_Juan",
101 "America/Argentina/San_Luis",
102 "America/Argentina/Tucuman",
103 "America/Argentina/Ushuaia",
104 "America/Aruba",
105 "America/Asuncion",
106 "America/Atikokan",
107 "America/Bahia",
108 "America/Barbados",
109 "America/Belem",
110 "America/Belize",
111 "America/Blanc-Sablon",
112 "America/Boa_Vista",
113 "America/Bogota",
114 "America/Boise",
115 "America/Cambridge_Bay",
116 "America/Campo_Grande",
117 "America/Cancun",
118 "America/Caracas",
119 "America/Cayenne",
120 "America/Cayman",
121 "America/Chicago",
122 "America/Chihuahua",
123 "America/Coral_Harbour",
124 "America/Costa_Rica",
125 "America/Cuiaba",
126 "America/Curacao",
127 "America/Dawson",
128 "America/Dawson_Creek",
129 "America/Denver",
130 "America/Dominica",
131 "America/Edmonton",
132 "America/Eirunepe",
133 "America/El_Salvador",
134 "America/Fortaleza",
135 "America/Glace_Bay",
136 "America/Goose_Bay",
137 "America/Grand_Turk",
138 "America/Grenada",
139 "America/Guadeloupe",
140 "America/Guatemala",
141 "America/Guayaquil",
142 "America/Guyana",
143 "America/Halifax",
144 "America/Havana",
145 "America/Hermosillo",
146 "America/Indiana/Indianapolis",
147 "America/Indiana/Knox",
148 "America/Indiana/Marengo",
149 "America/Indiana/Petersburg",
150 "America/Indiana/Vevay",
151 "America/Indiana/Vincennes",
152 "America/Indiana/Winamac",
153 "America/Inuvik",
154 "America/Iqaluit",
155 "America/Jamaica",
156 "America/Juneau",
157 "America/Kentucky/Louisville",
158 "America/Kentucky/Monticello",
159 "America/La_Paz",
160 "America/Lima",
161 "America/Los_Angeles",
162 "America/Maceio",
163 "America/Managua",
164 "America/Manaus",
165 "America/Marigot",
166 "America/Martinique",
167 "America/Mazatlan",
168 "America/Menominee",
169 "America/Merida",
170 "America/Mexico_City",
171 "America/Miquelon",
172 "America/Moncton",
173 "America/Monterrey",
174 "America/Montevideo",
175 "America/Montreal",
176 "America/Montserrat",
177 "America/Nassau",
178 "America/New_York",
179 "America/Nipigon",
180 "America/Noronha",
181 "America/North_Dakota/Center",
182 "America/North_Dakota/Salem",
183 "America/Panama",
184 "America/Pangnirtung",
185 "America/Paramaribo",
186 "America/Phoenix",
187 "America/Port-au-Prince",
188 "America/Port_of_Spain",
189 "America/Porto_Velho",
190 "America/Puerto_Rico",
191 "America/Rainy_River",
192 "America/Rankin_Inlet",
193 "America/Recife",
194 "America/Regina",
195 "America/Resolute",
196 "America/Rio_Branco",
197 "America/Santarem",
198 "America/Santiago",
199 "America/Santo_Domingo",
200 "America/Sao_Paulo",
201 "America/St_Barthelemy",
202 "America/St_Johns",
203 "America/St_Kitts",
204 "America/St_Lucia",
205 "America/St_Thomas",
206 "America/St_Vincent",
207 "America/Tegucigalpa",
208 "America/Thunder_Bay",
209 "America/Tijuana",
210 "America/Toronto",
211 "America/Tortola",
212 "America/Vancouver",
213 "America/Whitehorse",
214 "America/Winnipeg",
215 "America/Yellowknife",
216 "Ameriica/Swift_Current",
217 "Arctic/Longyearbyen",
218 "Asia/Aden",
219 "Asia/Almaty",
220 "Asia/Amman",
221 "Asia/Anadyr",
222 "Asia/Aqtau",
223 "Asia/Aqtobe",
224 "Asia/Ashgabat",
225 "Asia/Baghdad",
226 "Asia/Bahrain",
227 "Asia/Baku",
228 "Asia/Bangkok",
229 "Asia/Beirut",
230 "Asia/Bishkek",
231 "Asia/Brunei",
232 "Asia/Choibalsan",
233 "Asia/Chongqing",
234 "Asia/Colombo",
235 "Asia/Damascus",
236 "Asia/Dhaka",
237 "Asia/Dili",
238 "Asia/Dubai",
239 "Asia/Dushanbe",
240 "Asia/Gaza",
241 "Asia/Harbin",
242 "Asia/Ho_Chi_Minh",
243 "Asia/Hong_Kong",
244 "Asia/Hovd",
245 "Asia/Irkutsk",
246 "Asia/Jakarta",
247 "Asia/Jayapura",
248 "Asia/Jerusalem",
249 "Asia/Kabul",
250 "Asia/Kamchatka",
251 "Asia/Karachi",
252 "Asia/Kashgar",
253 "Asia/Katmandu",
254 "Asia/Kolkata",
255 "Asia/Krasnoyarsk",
256 "Asia/Kuala_Lumpur",
257 "Asia/Kuching",
258 "Asia/Kuwait",
259 "Asia/Macau",
260 "Asia/Magadan",
261 "Asia/Makassar",
262 "Asia/Manila",
263 "Asia/Muscat",
264 "Asia/Nicosia",
265 "Asia/Novosibirsk",
266 "Asia/Omsk",
267 "Asia/Oral",
268 "Asia/Phnom_Penh",
269 "Asia/Pontianak",
270 "Asia/Pyongyang",
271 "Asia/Qatar",
272 "Asia/Qyzylorda",
273 "Asia/Rangoon",
274 "Asia/Riyadh",
275 "Asia/Sakhalin",
276 "Asia/Samarkand",
277 "Asia/Seoul",
278 "Asia/Shanghai",
279 "Asia/Singapore",
280 "Asia/Taipei",
281 "Asia/Tashkent",
282 "Asia/Tbilisi",
283 "Asia/Tehran",
284 "Asia/Thimphu",
285 "Asia/Tokyo",
286 "Asia/Ulaanbaatar",
287 "Asia/Urumqi",
288 "Asia/Vientiane",
289 "Asia/Vladivostok",
290 "Asia/Yakutsk",
291 "Asia/Yekaterinburg",
292 "Asia/Yerevan",
293 "Atlantic/Azores",
294 "Atlantic/Bermuda",
295 "Atlantic/Canary",
296 "Atlantic/Cape_Verde",
297 "Atlantic/Faroe",
298 "Atlantic/Madeira",
299 "Atlantic/Reykjavik",
300 "Atlantic/South_Georgia",
301 "Atlantic/St_Helena",
302 "Atlantic/Stanley",
303 "Australia/Adelaide",
304 "Australia/Brisbane",
305 "Australia/Broken_Hill",
306 "Australia/Currie",
307 "Australia/Darwin",
308 "Australia/Eucla",
309 "Australia/Hobart",
310 "Australia/Lindeman",
311 "Australia/Lord_Howe",
312 "Australia/Melbourne",
313 "Australia/Perth",
314 "Australia/Sydney",
315 "Europe/Amsterdam",
316 "Europe/Andorra",
317 "Europe/Athens",
318 "Europe/Belgrade",
319 "Europe/Berlin",
320 "Europe/Bratislava",
321 "Europe/Brussels",
322 "Europe/Bucharest",
323 "Europe/Budapest",
324 "Europe/Chisinau",
325 "Europe/Copenhagen",
326 "Europe/Dublin",
327 "Europe/Gibraltar",
328 "Europe/Guernsey",
329 "Europe/Helsinki",
330 "Europe/Isle_of_Man",
331 "Europe/Istanbul",
332 "Europe/Jersey",
333 "Europe/Kaliningrad",
334 "Europe/Kiev",
335 "Europe/Lisbon",
336 "Europe/Ljubljana",
337 "Europe/London",
338 "Europe/Luxembourg",
339 "Europe/Madrid",
340 "Europe/Malta",
341 "Europe/Marienhamn",
342 "Europe/Minsk",
343 "Europe/Monaco",
344 "Europe/Moscow",
345 "Europe/Oslo",
346 "Europe/Paris",
347 "Europe/Podgorica",
348 "Europe/Prague",
349 "Europe/Riga",
350 "Europe/Rome",
351 "Europe/Samara",
352 "Europe/San_Marino",
353 "Europe/Sarajevo",
354 "Europe/Simferopol",
355 "Europe/Skopje",
356 "Europe/Sofia",
357 "Europe/Stockholm",
358 "Europe/Tallinn",
359 "Europe/Tirane",
360 "Europe/Uzhgorod",
361 "Europe/Vaduz",
362 "Europe/Vatican",
363 "Europe/Vienna",
364 "Europe/Vilnius",
365 "Europe/Volgograd",
366 "Europe/Warsaw",
367 "Europe/Zagreb",
368 "Europe/Zaporozhye",
369 "Europe/Zurich",
370 "Indian/Antananarivo",
371 "Indian/Chagos",
372 "Indian/Christmas",
373 "Indian/Cocos",
374 "Indian/Comoro",
375 "Indian/Kerguelen",
376 "Indian/Mahe",
377 "Indian/Maldives",
378 "Indian/Mauritius",
379 "Indian/Mayotte",
380 "Indian/Reunion",
381 "Pacific/Apia",
382 "Pacific/Auckland",
383 "Pacific/Chatham",
384 "Pacific/Easter",
385 "Pacific/Efate",
386 "Pacific/Enderbury",
387 "Pacific/Fakaofo",
388 "Pacific/Fiji",
389 "Pacific/Funafuti",
390 "Pacific/Galapagos",
391 "Pacific/Gambier",
392 "Pacific/Guadalcanal",
393 "Pacific/Guam",
394 "Pacific/Honolulu",
395 "Pacific/Johnston",
396 "Pacific/Kiritimati",
397 "Pacific/Kosrae",
398 "Pacific/Kwajalein",
399 "Pacific/Majuro",
400 "Pacific/Marquesas",
401 "Pacific/Midway",
402 "Pacific/Nauru",
403 "Pacific/Niue",
404 "Pacific/Norfolk",
405 "Pacific/Noumea",
406 "Pacific/Pago_Pago",
407 "Pacific/Palau",
408 "Pacific/Pitcairn",
409 "Pacific/Ponape",
410 "Pacific/Port_Moresby",
411 "Pacific/Rarotonga",
412 "Pacific/Saipan",
413 "Pacific/Tahiti",
414 "Pacific/Tarawa",
415 "Pacific/Tongatapu",
416 "Pacific/Truk",
417 "Pacific/Wake",
418 "Pacific/Wallis",
419 0
420 };
421
422 const int N_TIMEZONES = sizeof(IUnit::tblTimezone) / sizeof(const char*);
423
424 const QRegExp IUnit::reCoord1("^\\s*([N|S]){1}\\W*([0-9]+)\\W*([0-9]+\\.[0-9]+)\\s+([E|W|O]){1}\\W*([0-9]+)\\W*([0-9]+\\.[0-9]+)\\s*$");
425
426 const QRegExp IUnit::reCoord2("^\\s*([N|S]){1}\\s*([0-9]+\\.[0-9]+)\\W*\\s+([E|W|O]){1}\\s*([0-9]+\\.[0-9]+)\\W*\\s*$");
427
428 const QRegExp IUnit::reCoord3("^\\s*([-0-9]+\\.[0-9]+)\\s+([-0-9]+\\.[0-9]+)\\s*$");
429
430 const QRegExp IUnit::reCoord4("^\\s*([N|S]){1}\\s*([0-9]+)\\W+([0-9]+)\\W+([0-9]+\\.[0-9]+)\\W*([E|W|O]){1}\\W*([0-9]+)\\W+([0-9]+)\\W+([0-9]+\\.[0-9]+)\\W*\\s*$");
431
432 const QRegExp IUnit::reCoord5("^\\s*([-0-9]+\\.[0-9]+)([N|S])\\s+([-0-9]+\\.[0-9]+)([W|E])\\s*$");
433
IUnit(const type_e & type,const QString & baseunit,const qreal basefactor,const QString & speedunit,const qreal speedfactor,QObject * parent)434 IUnit::IUnit(const type_e& type, const QString& baseunit, const qreal basefactor, const QString& speedunit, const qreal speedfactor, QObject* parent)
435 : QObject(parent)
436 , type(type)
437 , baseunit(baseunit)
438 , basefactor(basefactor)
439 , speedunit(speedunit)
440 , speedfactor(speedfactor)
441 {
442 //there can be only one...
443 if(nullptr != m_self)
444 {
445 delete m_self;
446 }
447 m_self = this;
448 }
449
450
setUnitType(type_e t,QObject * parent)451 void IUnit::setUnitType(type_e t, QObject* parent)
452 {
453 switch(t)
454 {
455 case eTypeMetric:
456 new CUnitMetric(parent);
457 break;
458
459 case eTypeImperial:
460 new CUnitImperial(parent);
461 break;
462
463 case eTypeNautic:
464 new CUnitNautic(parent);
465 break;
466 }
467
468 QSettings cfg;
469 cfg.setValue("Units/type", t);
470 }
471
meter2speed(qreal meter,QString & val,QString & unit) const472 void IUnit::meter2speed(qreal meter, QString& val, QString& unit) const
473 {
474 val.sprintf("%2.2f", meter * speedfactor);
475 unit = speedunit;
476 }
477
seconds2time(quint32 ttime,QString & val,QString & unit) const478 void IUnit::seconds2time(quint32 ttime, QString& val, QString& unit) const
479 {
480 QTime time(0, 0, 0);
481 quint32 days = ttime / 86400;
482
483 time = time.addSecs(ttime);
484
485 if(days)
486 {
487 val = QString("%1:").arg(days) + time.toString("HH:mm:ss");
488 unit = "d";
489 }
490 else
491 {
492 val = time.toString("HH:mm:ss");
493 unit = "h";
494 }
495 }
496
parseTimestamp(const QString & time,QDateTime & datetime)497 bool IUnit::parseTimestamp(const QString& time, QDateTime& datetime)
498 {
499 int tzoffset;
500 datetime = parseTimestamp(time, tzoffset);
501
502 return datetime.isValid();
503 }
504
505
parseTimestamp(const QString & timetext,int & tzoffset)506 QDateTime IUnit::parseTimestamp(const QString& timetext, int& tzoffset)
507 {
508 const QRegExp tzRE("[-+]\\d\\d:\\d\\d$");
509 int i;
510
511 tzoffset = 0;
512
513 QString format = "yyyy-MM-dd'T'hh:mm:ss";
514
515 i = timetext.indexOf(".");
516 if (i != NOIDX)
517 {
518 if(timetext[i + 1] == '0')
519 {
520 format += ".zzz";
521 }
522 else
523 {
524 format += ".z";
525 }
526 }
527
528 // trailing "Z" explicitly declares the timestamp to be UTC
529 if (timetext.indexOf("Z") != NOIDX)
530 {
531 format += "'Z'";
532 }
533 else if ((i = tzRE.indexIn(timetext)) != NOIDX)
534 {
535 // trailing timezone offset [-+]HH:MM present
536 // This does not match the original intentions of the GPX
537 // file format but appears to be found occasionally in
538 // the wild. Try our best parsing it.
539
540 // add the literal string to the format so fromString()
541 // will succeed
542 format += "'";
543 format += timetext.rightRef(6);
544 format += "'";
545
546 // calculate the offset
547 int offsetHours(timetext.midRef(i + 1, 2).toUInt());
548 int offsetMinutes(timetext.midRef(i + 4, 2).toUInt());
549 if (timetext[i] == '-')
550 {
551 tzoffset = -(60 * offsetHours + offsetMinutes);
552 }
553 else
554 {
555 tzoffset = 60 * offsetHours + offsetMinutes;
556 }
557 tzoffset *= 60; // seconds
558 }
559
560 QDateTime datetime = QDateTime::fromString(timetext, format);
561 datetime.setOffsetFromUtc(tzoffset);
562
563 return datetime;
564 }
565
datetime2string(const QDateTime & time,bool shortDate,const QPointF & pos)566 QString IUnit::datetime2string(const QDateTime& time, bool shortDate, const QPointF& pos)
567 {
568 QTimeZone tz;
569
570 tz_mode_e tmpMode = (pos != NOPOINTF) ? timeZoneMode : eTZLocal;
571
572 switch(tmpMode)
573 {
574 case eTZUtc:
575 tz = QTimeZone("UTC");
576 break;
577
578 case eTZLocal:
579 tz = QTimeZone(QTimeZone::systemTimeZoneId());
580 break;
581
582 case eTZAuto:
583 tz = QTimeZone(pos2timezone(pos));
584 break;
585
586 case eTZSelected:
587 tz = QTimeZone(timeZone);
588 break;
589 }
590
591 QDateTime tmp = time.toTimeZone(tz);
592 return tmp.toString((shortDate | useShortFormat) ? Qt::ISODate : Qt::SystemLocaleLongDate);
593 }
594
pos2timezone(const QPointF & pos)595 QByteArray IUnit::pos2timezone(const QPointF& pos)
596 {
597 static QImage imgTimezone = QPixmap(":/pics/timezones.png").toImage();
598
599 int x = qRound(2048.0 / 360.0 * (180.0 + pos.x() * RAD_TO_DEG));
600 int y = qRound(1024.0 / 180.0 * (90.0 - pos.y() * RAD_TO_DEG));
601
602 QRgb rgb = imgTimezone.pixel(x, y);
603
604 if(qRed(rgb) == 0 && qGreen(rgb) == 0)
605 {
606 return "UTC";
607 }
608
609 int tz = ((qRed(rgb) & 248) << 1) + ((qGreen(rgb) >> 4) & 15);
610 if(tz >= N_TIMEZONES)
611 {
612 return 0;
613 }
614
615 return tblTimezone[tz];
616 }
617
degToStr(const qreal & x,const qreal & y,QString & str)618 bool IUnit::degToStr(const qreal& x, const qreal& y, QString& str)
619 {
620 if(x < -180 || 180 < x)
621 {
622 return false;
623 }
624
625 if(y < -90 || 90 < y)
626 {
627 return false;
628 }
629
630 switch(coordFormat)
631 {
632 case eCoordFormat1:
633 {
634 qint32 degN, degE;
635 qreal minN, minE;
636
637 bool signLat = GPS_Math_Deg_To_DegMin(y, °N, &minN);
638 bool signLon = GPS_Math_Deg_To_DegMin(x, °E, &minE);
639
640 const QString& lat = signLat ? "S" : "N";
641 const QString& lng = signLon ? "W" : "E";
642 str.sprintf("%s%02d° %06.3f %s%03d° %06.3f", lat.toUtf8().data(), qAbs(degN), minN, lng.toUtf8().data(), qAbs(degE), minE);
643 break;
644 }
645
646 case eCoordFormat2:
647 {
648 const QString& lat = (y < 0) ? "S" : "N";
649 const QString& lng = (x < 0) ? "W" : "E";
650 str.sprintf("%s%02.6f° %s%03.6f°", lat.toUtf8().data(), qAbs(y), lng.toUtf8().data(), qAbs(x));
651 break;
652 }
653
654 case eCoordFormat3:
655 {
656 qint32 degN, degE;
657 qreal minN, minE;
658
659 bool signLat = GPS_Math_Deg_To_DegMin(y, °N, &minN);
660 bool signLon = GPS_Math_Deg_To_DegMin(x, °E, &minE);
661
662 qreal secN = (minN - qFloor(minN)) * 60;
663 qreal secE = (minE - qFloor(minE)) * 60;
664
665 const QString& lat = signLat ? "S" : "N";
666 const QString& lng = signLon ? "W" : "E";
667 str.sprintf("%s%02d° %02d' %02.2f'' %s%03d° %02d' %02.2f''", lat.toUtf8().data(), qAbs(degN), qFloor(minN), secN, lng.toUtf8().data(), qAbs(degE), qFloor(minE), secE);
668 break;
669 }
670 }
671
672 return true;
673 }
674
strToDeg(const QString & str,qreal & lon,qreal & lat)675 bool IUnit::strToDeg(const QString& str, qreal& lon, qreal& lat)
676 {
677 if(reCoord2.exactMatch(str))
678 {
679 bool signLat = reCoord2.cap(1) == "S";
680 qreal absLat = reCoord2.cap(2).toDouble();
681 lat = signLat ? -absLat : absLat;
682
683 bool signLon = reCoord2.cap(3) == "W";
684 qreal absLon = reCoord2.cap(4).toDouble();
685 lon = signLon ? -absLon : absLon;
686 }
687 else if(reCoord1.exactMatch(str))
688 {
689 bool signLat = reCoord1.cap(1) == "S";
690 int degLat = reCoord1.cap(2).toInt();
691 qreal minLat = reCoord1.cap(3).toDouble();
692
693 GPS_Math_DegMin_To_Deg(signLat, degLat, minLat, lat);
694
695 bool signLon = reCoord1.cap(4) == "W";
696 int degLon = reCoord1.cap(5).toInt();
697 qreal minLon = reCoord1.cap(6).toDouble();
698
699 GPS_Math_DegMin_To_Deg(signLon, degLon, minLon, lon);
700 }
701 else if(reCoord3.exactMatch(str))
702 {
703 lat = reCoord3.cap(1).toDouble();
704 lon = reCoord3.cap(2).toDouble();
705 }
706 else if(reCoord4.exactMatch(str))
707 {
708 bool signLat = reCoord4.cap(1) == "S";
709 int degLat = reCoord4.cap(2).toInt();
710 int minLat = reCoord4.cap(3).toInt();
711 qreal secLat = reCoord4.cap(4).toFloat();
712
713 GPS_Math_DegMinSec_To_Deg(signLat, degLat, minLat, secLat, lat);
714
715 bool signLon = reCoord4.cap(5) == "W";
716 int degLon = reCoord4.cap(6).toInt();
717 int minLon = reCoord4.cap(7).toInt();
718 qreal secLon = reCoord4.cap(8).toFloat();
719
720 GPS_Math_DegMinSec_To_Deg(signLon, degLon, minLon, secLon, lon);
721 }
722 else if(reCoord5.exactMatch(str))
723 {
724 bool signLon = reCoord4.cap(4) == "W";
725 bool signLat = reCoord4.cap(2) == "S";
726 lat = reCoord5.cap(1).toDouble();
727 lon = reCoord5.cap(3).toDouble();
728
729 if(signLon)
730 {
731 lon = -lon;
732 }
733 if(signLat)
734 {
735 lat = -lat;
736 }
737 }
738 else
739 {
740 QMessageBox::warning(&CMainWindow::self(), tr("Error"), tr("Bad position format. Must be: \"[N|S] ddd mm.sss [W|E] ddd mm.sss\" or \"[N|S] ddd.ddd [W|E] ddd.ddd\""), QMessageBox::Ok, QMessageBox::NoButton);
741 return false;
742 }
743
744 if(fabs(lon) > 180.0 || fabs(lat) > 90.0)
745 {
746 QMessageBox::warning(&CMainWindow::self(), tr("Error"), tr("Position values out of bounds. "), QMessageBox::Ok, QMessageBox::NoButton);
747 return false;
748 }
749
750 return true;
751 }
752
isValidCoordString(const QString & str)753 bool IUnit::isValidCoordString(const QString& str)
754 {
755 if(reCoord1.exactMatch(str))
756 {
757 return true;
758 }
759 else if(reCoord2.exactMatch(str))
760 {
761 return true;
762 }
763 else if(reCoord3.exactMatch(str))
764 {
765 return true;
766 }
767 else if(reCoord4.exactMatch(str))
768 {
769 return true;
770 }
771 else if(reCoord5.exactMatch(str))
772 {
773 return true;
774 }
775 return false;
776 }
777