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