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