OpenCPN Partial API docs
Loading...
Searching...
No Matches
kml.cpp
Go to the documentation of this file.
1/**************************************************************************
2 * Copyright (C) 2012 by David S. Register *
3 * Copyright (C) 2012 Jesper Weissglass *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 **************************************************************************/
20
27#include "config.h"
28
29#include <wx/wxprec.h>
30
31#ifndef WX_PRECOMP
32#include <wx/wx.h>
33#endif
34
35#include <vector>
36#include <sstream>
37#include <string>
38
39#include <wx/clipbrd.h>
40#include <wx/datetime.h>
41#include <wx/file.h>
42#include <wx/log.h>
43#include <wx/string.h>
44
45#include "model/ocpn_types.h"
46#include "model/own_ship.h"
47#include "model/route.h"
48#include "model/track.h"
49
50#include "kml.h"
51#include "navutil.h"
52#include "ocpn_frame.h"
53#include "tinyxml.h"
54
55int Kml::seqCounter = 0;
56bool Kml::insertQtVlmExtendedData = false;
57
58int Kml::ParseCoordinates(TiXmlNode* node, dPointList& points) {
59 TiXmlElement* e = node->FirstChildElement("coordinates");
60 if (!e) {
61 wxString msg("KML Parser found no <coordinates> for the element: ");
62 msg << wxString(node->ToElement()->Value(), wxConvUTF8);
63 wxLogMessage(msg);
64 return 0;
65 }
66
67 // Parse "long,lat,z" format.
68
69 dPoint point;
70
71 std::stringstream ss(e->GetText());
72 std::string txtCoord;
73
74 while (1) {
75 if (!std::getline(ss, txtCoord, ',')) break;
76 ;
77 if (txtCoord.length() == 0) break;
78
79 point.x = atof(txtCoord.c_str());
80 std::getline(ss, txtCoord, ',');
81 point.y = atof(txtCoord.c_str());
82 std::getline(ss, txtCoord, ' ');
83 point.z = atof(txtCoord.c_str());
84
85 points.push_back(point);
86 }
87 return points.size();
88}
89
90KmlPastebufferType Kml::ParseTrack(TiXmlNode* node, wxString& name) {
91 parsedTrack = new Track();
92 parsedTrack->SetName(name);
93
94 if (0 == strncmp(node->ToElement()->Value(), "LineString", 10)) {
95 dPointList coordinates;
96 if (ParseCoordinates(node, coordinates) > 2) {
97 TrackPoint* trackpoint = NULL;
98
99 for (unsigned int i = 0; i < coordinates.size(); i++) {
100 trackpoint = new TrackPoint(coordinates[i].y, coordinates[i].x);
101 parsedTrack->AddPoint(trackpoint);
102 }
103 }
104 return KML_PASTE_TRACK;
105 }
106
107 if (0 == strncmp(node->ToElement()->Value(), "gx:Track", 8)) {
108 TrackPoint* trackpoint = NULL;
109 TiXmlElement* point = node->FirstChildElement("gx:coord");
110 int pointCounter = 0;
111
112 for (; point; point = point->NextSiblingElement("gx:coord")) {
113 double lat, lon;
114 std::stringstream ss(point->GetText());
115 std::string txtCoord;
116 std::getline(ss, txtCoord, ' ');
117 lon = atof(txtCoord.c_str());
118 std::getline(ss, txtCoord, ' ');
119 lat = atof(txtCoord.c_str());
120
121 parsedTrack->AddPoint(new TrackPoint(lat, lon));
122 pointCounter++;
123 }
124
125 TiXmlElement* when = node->FirstChildElement("when");
126
127 wxDateTime whenTime;
128
129 int i = 0;
130 for (; when; when = when->NextSiblingElement("when")) {
131 trackpoint = parsedTrack->GetPoint(i);
132 if (!trackpoint) continue;
133 whenTime.ParseFormat(wxString(when->GetText(), wxConvUTF8),
134 "%Y-%m-%dT%H:%M:%SZ");
135 trackpoint->SetCreateTime(whenTime);
136 i++;
137 }
138
139 return KML_PASTE_TRACK;
140 }
141 return KML_PASTE_INVALID;
142}
143
144KmlPastebufferType Kml::ParseOnePlacemarkPoint(TiXmlNode* node,
145 wxString& name) {
146 double newLat = 0., newLon = 0.;
147 dPointList coordinates;
148
149 if (ParseCoordinates(node->ToElement(), coordinates)) {
150 newLat = coordinates[0].y;
151 newLon = coordinates[0].x;
152 }
153
154 if (newLat == 0.0 && newLon == 0.0) {
155 wxString msg("KML Parser failed to convert <Point> coordinates.");
156 wxLogMessage(msg);
157 return KML_PASTE_INVALID;
158 }
159 wxString pointName = "";
160 TiXmlElement* e = node->Parent()->FirstChild("name")->ToElement();
161 if (e) pointName = wxString(e->GetText(), wxConvUTF8);
162
163 wxString pointDescr = "";
164 e = node->Parent()->FirstChildElement("description");
165
166 // If the <description> is an XML element we must convert it to text,
167 // otherwise it gets lost.
168 if (e) {
169 TiXmlNode* n = e->FirstChild();
170 if (n) switch (n->Type()) {
171 case TiXmlNode::TINYXML_TEXT:
172 pointDescr = wxString(e->GetText(), wxConvUTF8);
173 break;
174 case TiXmlNode::TINYXML_ELEMENT:
175 TiXmlPrinter printer;
176 printer.SetIndent("\t");
177 n->Accept(&printer);
178 pointDescr = wxString(printer.CStr(), wxConvUTF8);
179 break;
180 }
181 }
182
183 // Extended data will override description.
184 TiXmlNode* n = node->Parent()->FirstChild("ExtendedData");
185 if (n) {
186 TiXmlPrinter printer;
187 printer.SetIndent("\t");
188 n->Accept(&printer);
189 pointDescr = wxString(printer.CStr(), wxConvUTF8);
190 }
191
192 // XXX leak ?
193 parsedRoutePoint = new RoutePoint();
194 parsedRoutePoint->m_lat = newLat;
195 parsedRoutePoint->m_lon = newLon;
196 parsedRoutePoint->m_bIsolatedMark = true;
197 parsedRoutePoint->m_bPtIsSelected = false;
198 parsedRoutePoint->m_MarkDescription = pointDescr;
199 parsedRoutePoint->SetName(pointName);
200
201 return KML_PASTE_WAYPOINT;
202}
203
204KmlPastebufferType Kml::ParsePasteBuffer() {
205 if (!wxTheClipboard->IsOpened())
206 if (!wxTheClipboard->Open()) return KML_PASTE_INVALID;
207
208 wxTextDataObject data;
209 wxTheClipboard->GetData(data);
210 kmlText = data.GetText();
211 wxTheClipboard->Close();
212
213 if (kmlText.Find("<kml") == wxNOT_FOUND) return KML_PASTE_INVALID;
214
215 TiXmlDocument doc;
216 if (!doc.Parse(kmlText.mb_str(wxConvUTF8), 0, TIXML_ENCODING_UTF8)) {
217 wxLogError(wxString(doc.ErrorDesc(), wxConvUTF8));
218 return KML_PASTE_INVALID;
219 }
220 if (0 != strncmp(doc.RootElement()->Value(), "kml", 3))
221 return KML_PASTE_INVALID;
222
223 TiXmlHandle docHandle(doc.RootElement());
224
225 // We may or may not have a <document> depending on what the user copied.
226 TiXmlElement* placemark =
227 docHandle.FirstChild("Document").FirstChild("Placemark").ToElement();
228 if (!placemark) {
229 placemark = docHandle.FirstChild("Placemark").ToElement();
230 }
231 if (!placemark) {
232 wxString msg("KML Parser found no <Placemark> tag in the KML.");
233 wxLogMessage(msg);
234 return KML_PASTE_INVALID;
235 }
236
237 int pointCounter = 0;
238 wxString name;
239 for (; placemark; placemark = placemark->NextSiblingElement()) {
240 TiXmlElement* e = placemark->FirstChildElement("name");
241 if (e) name = wxString(e->GetText(), wxConvUTF8);
242 pointCounter++;
243 }
244
245 if (pointCounter == 1) {
246 // Is it a single waypoint?
247 TiXmlNode* element = docHandle.FirstChild("Document")
248 .FirstChild("Placemark")
249 .FirstChild("Point")
250 .ToNode();
251 if (!element)
252 element = docHandle.FirstChild("Placemark").FirstChild("Point").ToNode();
253 if (element) return ParseOnePlacemarkPoint(element, name);
254
255 // Is it a dumb <LineString> track?
256 element = docHandle.FirstChild("Document")
257 .FirstChild("Placemark")
258 .FirstChild("LineString")
259 .ToNode();
260 if (!element)
261 element =
262 docHandle.FirstChild("Placemark").FirstChild("LineString").ToNode();
263 if (element) return ParseTrack(element, name);
264
265 // Is it a smart extended <gx:track> track?
266 element = docHandle.FirstChild("Document")
267 .FirstChild("Placemark")
268 .FirstChild("gx:Track")
269 .ToNode();
270 if (!element)
271 element =
272 docHandle.FirstChild("Placemark").FirstChild("gx:Track").ToNode();
273 if (element) return ParseTrack(element, name);
274
275 wxString msg(
276 "KML Parser found a single <Placemark> in the KML, but no useable "
277 "data in it.");
278 wxLogMessage(msg);
279 return KML_PASTE_INVALID;
280 }
281
282 // Here we go with a full route.
283
284 parsedRoute = new Route();
285 bool foundPoints = false;
286 bool foundTrack = false;
287 TiXmlElement* element =
288 docHandle.FirstChild("Document").FirstChild("name").ToElement();
289 if (element)
290 parsedRoute->m_RouteNameString = wxString(element->GetText(), wxConvUTF8);
291
292 placemark =
293 docHandle.FirstChild("Document").FirstChild("Placemark").ToElement();
294 for (; placemark; placemark = placemark->NextSiblingElement()) {
295 TiXmlNode* n = placemark->FirstChild("Point");
296 if (n) {
297 if (ParseOnePlacemarkPoint(n->ToElement(), name) == KML_PASTE_WAYPOINT) {
298 parsedRoute->AddPoint(new RoutePoint(parsedRoutePoint));
299 delete parsedRoutePoint;
300 parsedRoutePoint = 0;
301 foundPoints = true;
302 }
303 }
304
305 n = placemark->FirstChild("LineString");
306 if (n) {
307 ParseTrack(n->ToElement(), name);
308 foundTrack = true;
309 }
310 n = placemark->FirstChild("gx:Track");
311 if (n) {
312 ParseTrack(n->ToElement(), name);
313 foundTrack = true;
314 }
315 }
316
317 if (foundPoints && parsedRoute->GetnPoints() < 2) {
318 wxString msg("KML Parser did not find enough <Point>s to make a route.");
319 wxLogMessage(msg);
320 foundPoints = false;
321 }
322
323 if (foundPoints && !foundTrack) return KML_PASTE_ROUTE;
324 if (foundPoints && foundTrack) return KML_PASTE_ROUTE_TRACK;
325 if (!foundPoints && foundTrack) return KML_PASTE_TRACK;
326 return KML_PASTE_INVALID;
327}
328
329TiXmlElement* Kml::StandardHead(TiXmlDocument& xmlDoc, wxString name) {
330 TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "UTF-8", "");
331 xmlDoc.LinkEndChild(decl);
332
333 TiXmlElement* kml = new TiXmlElement("kml");
334 kml->SetAttribute("xmlns:atom", "http://www.w3.org/2005/Atom");
335 kml->SetAttribute("xmlns", "http://www.opengis.net/kml/2.2");
336 kml->SetAttribute("xmlns:gx", "http://www.google.com/kml/ext/2.2");
337 kml->SetAttribute("xmlns:kml", "http://www.opengis.net/kml/2.2");
338
339 if (insertQtVlmExtendedData)
340 kml->SetAttribute("xmlns:vlm", "http://virtual-loup-de-mer.org");
341
342 xmlDoc.LinkEndChild(kml);
343
344 TiXmlElement* document = new TiXmlElement("Document");
345 kml->LinkEndChild(document);
346 TiXmlElement* docName = new TiXmlElement("name");
347 document->LinkEndChild(docName);
348 TiXmlText* docNameVal = new TiXmlText(name.mb_str(wxConvUTF8));
349 docName->LinkEndChild(docNameVal);
350 return document;
351}
352
353std::string Kml::PointPlacemark(TiXmlElement* document,
354 RoutePoint* routepoint) {
355 TiXmlElement* pmPoint = new TiXmlElement("Placemark");
356 document->LinkEndChild(pmPoint);
357 TiXmlElement* pmPointName = new TiXmlElement("name");
358 pmPoint->LinkEndChild(pmPointName);
359 TiXmlText* pmPointNameVal =
360 new TiXmlText(routepoint->GetName().mb_str(wxConvUTF8));
361 pmPointName->LinkEndChild(pmPointNameVal);
362
363 TiXmlElement* pointDescr = new TiXmlElement("description");
364 pmPoint->LinkEndChild(pointDescr);
365
366 bool descrIsPlainText = true;
367 wxCharBuffer descrString = routepoint->m_MarkDescription.mb_str(wxConvUTF8);
368
369 if (insertQtVlmExtendedData) {
370 // Does the RoutePoint description parse as XML with an <ExtendedData> root
371 // tag?
372 TiXmlDocument descrDoc;
373 TiXmlElement* extendedData;
374 if (descrDoc.Parse(descrString, 0, TIXML_ENCODING_UTF8)) {
375 if (0 == strncmp(descrDoc.RootElement()->Value(), "ExtendedData", 12)) {
376 descrIsPlainText = false;
377 extendedData = descrDoc.RootElement();
378 TiXmlHandle docHandle(&descrDoc);
379 TiXmlElement* seq = docHandle.FirstChild("ExtendedData")
380 .FirstChild("vlm:sequence")
381 .ToElement();
382 if (!seq) {
383 seq = new TiXmlElement("vlm:sequence");
384 TiXmlText* snVal = new TiXmlText(
385 wxString::Format("%04d", seqCounter).mb_str(wxConvUTF8));
386 seq->LinkEndChild(snVal);
387 descrDoc.RootElement()->LinkEndChild(seq);
388 }
389 pmPoint->LinkEndChild(descrDoc.RootElement()->Clone());
390 }
391 }
392 if (descrIsPlainText) {
393 // We want Sequence names but there was some non-parsing stuff in the
394 // description. Push that into a sub-tag of an XML formatted description.
395 extendedData = new TiXmlElement("ExtendedData");
396 pmPoint->LinkEndChild(extendedData);
397 TiXmlElement* seq = new TiXmlElement("vlm:sequence");
398 extendedData->LinkEndChild(seq);
399 TiXmlText* snVal = new TiXmlText(
400 wxString::Format("%04d", seqCounter).mb_str(wxConvUTF8));
401 seq->LinkEndChild(snVal);
402
403 if (routepoint->m_MarkDescription.Length()) {
404 TiXmlElement* data = new TiXmlElement("Data");
405 data->SetAttribute("name", "Description");
406 extendedData->LinkEndChild(data);
407
408 TiXmlElement* value = new TiXmlElement("value");
409 data->LinkEndChild(value);
410 TiXmlText* txtVal = new TiXmlText(descrString);
411 value->LinkEndChild(txtVal);
412 }
413 }
414 if (extendedData && seqCounter == 0) {
415 const wxCharBuffer ownshipPos =
416 wxString::Format("%f %f", gLon, gLat).mb_str(wxConvUTF8);
417 TiXmlHandle h(extendedData);
418 TiXmlElement* route = h.FirstChild("vlm:route").ToElement();
419 TiXmlElement* ownship =
420 h.FirstChild("vlm:route").FirstChild("ownship").ToElement();
421 if (route) {
422 if (ownship) {
423 TiXmlText* owns = ownship->FirstChild()->ToText();
424 if (owns) {
425 owns->SetValue(ownshipPos);
426 } else {
427 owns = new TiXmlText(ownshipPos);
428 ownship->LinkEndChild(owns);
429 }
430 } else {
431 ownship = new TiXmlElement("ownship");
432 route->LinkEndChild(ownship);
433 TiXmlText* owns = new TiXmlText(ownshipPos);
434 ownship->LinkEndChild(owns);
435 }
436 } else {
437 route = new TiXmlElement("vlm:route");
438 extendedData->LinkEndChild(route);
439 ownship = new TiXmlElement("ownship");
440 route->LinkEndChild(ownship);
441 TiXmlText* owns = new TiXmlText(ownshipPos);
442 ownship->LinkEndChild(owns);
443 }
444 }
445 }
446
447 else {
448 // Add description as dumb text.
449 TiXmlText* pointDescrVal = new TiXmlText(descrString);
450 pointDescr->LinkEndChild(pointDescrVal);
451 }
452
453 TiXmlElement* point = new TiXmlElement("Point");
454 pmPoint->LinkEndChild(point);
455
456 TiXmlElement* pointCoord = new TiXmlElement("coordinates");
457 point->LinkEndChild(pointCoord);
458
459 std::stringstream pointCoordStr;
460 pointCoordStr << routepoint->m_lon << "," << routepoint->m_lat << ",0. ";
461
462 TiXmlText* pointText = new TiXmlText(pointCoordStr.str());
463 pointCoord->LinkEndChild(pointText);
464
465 return pointCoordStr.str();
466}
467
468wxString Kml::MakeKmlFromRoute(Route* route, bool insertSeq) {
469 insertQtVlmExtendedData = insertSeq;
470 seqCounter = 0;
471 TiXmlDocument xmlDoc;
472 wxString name = _("OpenCPN Route");
473 if (route->m_RouteNameString.Length()) name = route->m_RouteNameString;
474 TiXmlElement* document = StandardHead(xmlDoc, name);
475
476 std::stringstream lineStringCoords;
477
478 RoutePointList* pointList = route->pRoutePointList;
479 for (RoutePoint* routepoint : *pointList) {
480 lineStringCoords << PointPlacemark(document, routepoint);
481 seqCounter++;
482 }
483
484 TiXmlElement* pmPath = new TiXmlElement("Placemark");
485 document->LinkEndChild(pmPath);
486
487 TiXmlElement* pmName = new TiXmlElement("name");
488 pmPath->LinkEndChild(pmName);
489 TiXmlText* pmNameVal = new TiXmlText("Path");
490 pmName->LinkEndChild(pmNameVal);
491
492 TiXmlElement* linestring = new TiXmlElement("LineString");
493 pmPath->LinkEndChild(linestring);
494
495 TiXmlElement* coordinates = new TiXmlElement("coordinates");
496 linestring->LinkEndChild(coordinates);
497
498 TiXmlText* text = new TiXmlText(lineStringCoords.str());
499 coordinates->LinkEndChild(text);
500
501 TiXmlPrinter printer;
502 printer.SetIndent(" ");
503 xmlDoc.Accept(&printer);
504
505 return wxString(printer.CStr(), wxConvUTF8);
506}
507
508wxString Kml::MakeKmlFromTrack(Track* track) {
509 TiXmlDocument xmlDoc;
510 wxString name = _("OpenCPN Track");
511 if (track->GetName().Length()) name = track->GetName();
512 TiXmlElement* document = StandardHead(xmlDoc, name);
513
514 TiXmlElement* pmTrack = new TiXmlElement("Placemark");
515 document->LinkEndChild(pmTrack);
516
517 TiXmlElement* pmName = new TiXmlElement("name");
518 pmTrack->LinkEndChild(pmName);
519 TiXmlText* pmNameVal = new TiXmlText(track->GetName().mb_str(wxConvUTF8));
520 pmName->LinkEndChild(pmNameVal);
521
522 TiXmlElement* gxTrack = new TiXmlElement("gx:Track");
523 pmTrack->LinkEndChild(gxTrack);
524
525 std::stringstream lineStringCoords;
526
527 for (int i = 0; i < track->GetnPoints(); i++) {
528 TrackPoint* trackpoint = track->GetPoint(i);
529
530 TiXmlElement* when = new TiXmlElement("when");
531 gxTrack->LinkEndChild(when);
532
533 wxDateTime whenTime(trackpoint->GetCreateTime());
534 TiXmlText* whenVal =
535 new TiXmlText(whenTime.Format("%Y-%m-%dT%H:%M:%SZ").mb_str(wxConvUTF8));
536 when->LinkEndChild(whenVal);
537 }
538
539 for (int i = 0; i < track->GetnPoints(); i++) {
540 TrackPoint* trackpoint = track->GetPoint(i);
541
542 TiXmlElement* coord = new TiXmlElement("gx:coord");
543 gxTrack->LinkEndChild(coord);
544 wxString coordStr =
545 wxString::Format("%f %f 0.0", trackpoint->m_lon, trackpoint->m_lat);
546 TiXmlText* coordVal = new TiXmlText(coordStr.mb_str(wxConvUTF8));
547 coord->LinkEndChild(coordVal);
548 }
549
550 TiXmlPrinter printer;
551 printer.SetIndent(" ");
552 xmlDoc.Accept(&printer);
553
554 return wxString(printer.CStr(), wxConvUTF8);
555}
556
557wxString Kml::MakeKmlFromWaypoint(RoutePoint* routepoint) {
558 TiXmlDocument xmlDoc;
559 wxString name = _("OpenCPN Waypoint");
560 if (routepoint->GetName().Length()) name = routepoint->GetName();
561 TiXmlElement* document = StandardHead(xmlDoc, name);
562
563 insertQtVlmExtendedData = false;
564 PointPlacemark(document, routepoint);
565
566 TiXmlPrinter printer;
567 printer.SetIndent(" ");
568 xmlDoc.Accept(&printer);
569
570 return wxString(printer.CStr(), wxConvUTF8);
571}
572
573void Kml::CopyRouteToClipboard(Route* route) {
574 KmlFormatDialog* formatDlg = new KmlFormatDialog(wxTheApp->GetTopWindow());
575 int format = formatDlg->ShowModal();
576
577 if (format != wxID_CANCEL) {
578 format = formatDlg->GetSelectedFormat();
579 bool extradata = (format == KML_COPY_EXTRADATA);
580
581 ::wxBeginBusyCursor();
582 if (wxTheClipboard->Open()) {
583 wxTextDataObject* data = new wxTextDataObject;
584 data->SetText(MakeKmlFromRoute(route, extradata));
585 wxTheClipboard->SetData(data);
586 }
587 ::wxEndBusyCursor();
588 }
589 delete formatDlg;
590}
591
592void Kml::CopyTrackToClipboard(Track* track) {
593 ::wxBeginBusyCursor();
594 if (wxTheClipboard->Open()) {
595 wxTextDataObject* data = new wxTextDataObject;
596 data->SetText(MakeKmlFromTrack(track));
597 wxTheClipboard->SetData(data);
598 }
599 ::wxEndBusyCursor();
600}
601
602void Kml::CopyWaypointToClipboard(RoutePoint* rp) {
603 if (wxTheClipboard->Open()) {
604 wxTextDataObject* data = new wxTextDataObject;
605 data->SetText(MakeKmlFromWaypoint(rp));
606 wxTheClipboard->SetData(data);
607 }
608}
609
610Kml::Kml() {
611 parsedRoute = NULL;
612 parsedTrack = NULL;
613 parsedRoutePoint = NULL;
614}
615
616Kml::~Kml() {
617 delete parsedTrack;
618 if (parsedRoute) {
619 for (int i = 1; i <= parsedRoute->GetnPoints(); i++) {
620 if (parsedRoute->GetPoint(i)) delete parsedRoute->GetPoint(i);
621 }
622 delete parsedRoute;
623 }
624 delete parsedRoutePoint;
625}
626
627//----------------------------------------------------------------------------------
628
629KmlFormatDialog::KmlFormatDialog(wxWindow* parent)
630 : wxDialog(parent, wxID_ANY, _("Choose Format for Copy"), wxDefaultPosition,
631 wxSize(250, 230)) {
632 wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);
633
634 wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
635 topSizer->Add(sizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5);
636
637 choices.push_back(new wxRadioButton(
638 this, KML_COPY_STANDARD, _("KML Standard (Google Earth and others)"),
639 wxDefaultPosition, wxDefaultSize, wxRB_GROUP));
640
641 choices.push_back(new wxRadioButton(
642 this, KML_COPY_EXTRADATA, _("KML with extended waypoint data (QtVlm)"),
643 wxDefaultPosition));
644
645 wxStdDialogButtonSizer* buttonSizer =
646 CreateStdDialogButtonSizer(wxOK | wxCANCEL);
647
648 sizer->Add(choices[0], 0, wxEXPAND | wxALL, 5);
649 sizer->Add(choices[1], 0, wxEXPAND | wxALL, 5);
650 sizer->Add(buttonSizer, 0, wxEXPAND | wxTOP, 5);
651
652 topSizer->SetSizeHints(this);
653 SetSizer(topSizer);
654}
655
656int KmlFormatDialog::GetSelectedFormat() {
657 for (unsigned int i = 0; i < choices.size(); i++) {
658 if (choices[i]->GetValue()) return choices[i]->GetId();
659 }
660 return 0;
661}
Represents a waypoint or mark within the navigation system.
Definition route_point.h:71
wxString m_MarkDescription
Description text for the waypoint.
bool m_bIsolatedMark
Flag indicating if the waypoint is a standalone mark.
bool m_bPtIsSelected
Flag indicating if this waypoint is currently selected.
Represents a navigational route in the navigation system.
Definition route.h:99
RoutePointList * pRoutePointList
Ordered list of waypoints (RoutePoints) that make up this route.
Definition route.h:336
wxString m_RouteNameString
User-assigned name for the route.
Definition route.h:247
Represents a single point in a track.
Definition track.h:59
wxDateTime GetCreateTime(void)
Retrieves the creation timestamp of a track point as a wxDateTime object.
Definition track.cpp:138
void SetCreateTime(wxDateTime dt)
Sets the creation timestamp for a track point.
Definition track.cpp:144
Represents a track, which is a series of connected track points.
Definition track.h:117
Definition kml.h:43
Read and write KML Format.
Utility functions.
OpenCPN top window.
Navigation data types.
double gLat
Vessel's current latitude in decimal degrees.
Definition own_ship.cpp:26
double gLon
Vessel's current longitude in decimal degrees.
Definition own_ship.cpp:27
Position, course, speed, etc.
Route abstraction.
Recorded track abstraction.