OpenCPN Partial API docs
Loading...
Searching...
No Matches
navutil.cpp
Go to the documentation of this file.
1/**************************************************************************
2 * Copyright (C) 2010 by David S. Register *
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 *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 **************************************************************************/
19
26#include "gl_headers.h" // Must be included before anything using GL stuff
27
28#include <wx/wxprec.h>
29
30#ifdef __MINGW32__
31#undef IPV6STRICT // mingw FTBS fix: missing struct ip_mreq
32#include <windows.h>
33#endif
34
35#include <algorithm>
36#include <stdlib.h>
37#include <time.h>
38#include <locale>
39#include <list>
40
41#ifndef WX_PRECOMP
42#include <wx/wx.h>
43#endif // precompiled headers
44
45#include <wx/bmpcbox.h>
46#include <wx/dir.h>
47#include "wx/dirctrl.h"
48#include <wx/filename.h>
49#include <wx/graphics.h>
50#include <wx/image.h>
51#include <wx/listbook.h>
52#include <wx/listimpl.cpp>
53#include <wx/progdlg.h>
54#include <wx/sstream.h>
55#include <wx/tglbtn.h>
56#include <wx/timectrl.h>
57#include <wx/tokenzr.h>
58
59#include "o_sound/o_sound.h"
60
61#include "model/ais_decoder.h"
63#include "model/cmdline.h"
64#include "model/config_vars.h"
65#include "model/conn_params.h"
66#include "model/cutil.h"
67#include "model/geodesic.h"
68#include "model/georef.h"
69#include "model/gui_vars.h"
70#include "model/idents.h"
71#include "model/multiplexer.h"
72#include "model/nav_object_database.h"
73#include "model/navutil_base.h"
74#include "model/navobj_db.h"
75#include "model/own_ship.h"
76#include "model/plugin_comm.h"
77#include "model/route.h"
78#include "model/routeman.h"
79#include "model/select.h"
80#include "model/track.h"
81
82#include "ais.h"
83#include "canvas_config.h"
84#include "chartbase.h"
85#include "chartdb.h"
86#include "chcanv.h"
87#include "cm93.h"
88#include "config.h"
89#include "config_mgr.h"
90#include "dychart.h"
91#include "font_mgr.h"
92#include "layer.h"
93#include "navutil.h"
94#include "nmea0183.h"
95#include "observable_globvar.h"
96#include "ocpndc.h"
97#include "ocpn_frame.h"
98#include "ocpn_plugin.h"
99#include "ocpn_platform.h"
100#include "s52plib.h"
101#include "s52utils.h"
102#include "snd_config.h"
103#include "styles.h"
104
105#ifdef ocpnUSE_GL
106#include "gl_chart_canvas.h"
107#endif
108
109#ifdef __ANDROID__
110#include "androidUTIL.h"
111#endif
112
114static bool g_bLayersLoaded;
115
116#ifdef ocpnUSE_GL
117extern ocpnGLOptions g_GLOptions;
118#endif
119
120#if !defined(NAN)
121static const long long lNaN = 0xfff8000000000000;
122#define NAN (*(double *)&lNaN)
123#endif
124
125namespace navutil {
126
127wxArrayString *pMessageOnceArray;
128
129void InitGlobals() { pMessageOnceArray = new wxArrayString(); }
130
131void DeinitGlobals() {
132 delete pMessageOnceArray;
133 pMessageOnceArray = nullptr;
134}
135
136} // namespace navutil
137
138// Layer helper function
139
140wxString GetLayerName(int id) {
141 wxString name("unknown layer");
142 if (id <= 0) return (name);
143 LayerList::iterator it;
144 int index = 0;
145 for (it = (*pLayerList).begin(); it != (*pLayerList).end(); ++it, ++index) {
146 Layer *lay = (Layer *)(*it);
147 if (lay->m_LayerID == id) return (lay->m_LayerName);
148 }
149 return (name);
150}
151
152// Helper conditional file name dir slash
153void appendOSDirSlash(wxString *pString);
154
155//-----------------------------------------------------------------------------
156// MyConfig Implementation
157//-----------------------------------------------------------------------------
158//
159
160MyConfig::MyConfig(const wxString &LocalFileName)
161 : wxFileConfig("", "", LocalFileName, "", wxCONFIG_USE_LOCAL_FILE) {}
162
163MyConfig::~MyConfig() {}
164
165int MyConfig::LoadMyConfig() {
166 int display_width, display_height;
167 display_width = g_monitor_info[g_current_monitor].width;
168 display_height = g_monitor_info[g_current_monitor].height;
169
170 // Set up any defaults not set elsewhere
171 g_useMUI = true;
172 g_TalkerIdText = "EC";
173 g_maxWPNameLength = 6;
174 g_NMEAAPBPrecision = 3;
175
176#ifdef ocpnUSE_GL
177 g_GLOptions.m_bUseAcceleratedPanning = true;
178 g_GLOptions.m_GLPolygonSmoothing = true;
179 g_GLOptions.m_GLLineSmoothing = true;
180 g_GLOptions.m_iTextureDimension = 512;
181 g_GLOptions.m_iTextureMemorySize = 128;
182 if (!g_bGLexpert) {
183 g_GLOptions.m_iTextureMemorySize =
184 wxMax(128, g_GLOptions.m_iTextureMemorySize);
185 g_GLOptions.m_bTextureCompressionCaching =
186 g_GLOptions.m_bTextureCompression;
187 }
188#endif
189
190 g_maintoolbar_orient = wxTB_HORIZONTAL;
191 g_iENCToolbarPosX = -1;
192 g_iENCToolbarPosY = -1;
193 g_restore_dbindex = -1;
194 g_ChartNotRenderScaleFactor = 1.5;
195 g_detailslider_dialog_x = 200L;
196 g_detailslider_dialog_y = 200L;
197 g_SENC_LOD_pixels = 2;
198 g_SkewCompUpdatePeriod = 10;
199
200 g_bShowStatusBar = 1;
201 g_bShowCompassWin = 1;
202 g_iSoundDeviceIndex = -1;
203 g_bFullscreenToolbar = 1;
204 g_bTransparentToolbar = 0;
205 g_bShowLayers = 1;
206 g_bShowDepthUnits = 1;
207 g_bShowActiveRouteHighway = 1;
208 g_bShowChartBar = 1;
209 g_defaultBoatSpeed = 6.0;
210 g_ownship_predictor_minutes = 5;
211 g_cog_predictor_style = 105;
212 g_cog_predictor_color = "rgb(255,0,0)";
213 g_cog_predictor_endmarker = 1;
214 g_ownship_HDTpredictor_style = 105;
215 g_ownship_HDTpredictor_color = "rgb(255,0,0)";
216 g_ownship_HDTpredictor_endmarker = 1;
217 g_ownship_HDTpredictor_width = 0;
218 g_cog_predictor_width = 3;
219 g_ownship_HDTpredictor_miles = 1;
220 g_n_ownship_min_mm = 2;
221 g_own_ship_sog_cog_calc_damp_sec = 1;
222 g_bFullScreenQuilt = 1;
223 g_track_rotate_time_type = TIME_TYPE_COMPUTER;
224 g_bHighliteTracks = 1;
225 g_bPreserveScaleOnX = 1;
226 g_navobjbackups = 5;
227 g_benableAISNameCache = true;
228 g_n_arrival_circle_radius = 0.05;
229 g_plus_minus_zoom_factor = 2.0;
230 g_mouse_zoom_sensitivity = 1.5;
231 g_datetime_format = "UTC";
232
233 g_AISShowTracks_Mins = 20;
234 g_AISShowTracks_Limit = 300.0;
235 g_ShowScaled_Num = 10;
236 g_ScaledNumWeightSOG = 50;
237 g_ScaledNumWeightCPA = 60;
238 g_ScaledNumWeightTCPA = 25;
239 g_ScaledSizeMinimal = 50;
240 g_ScaledNumWeightRange = 75;
241 g_ScaledNumWeightSizeOfT = 25;
242 g_Show_Target_Name_Scale = 250000;
243 g_bWplUsePosition = 0;
244 g_WplAction = 0;
245 g_ais_cog_predictor_width = 3;
246 g_ais_alert_dialog_sx = 200;
247 g_ais_alert_dialog_sy = 200;
248 g_ais_alert_dialog_x = 200;
249 g_ais_alert_dialog_y = 200;
250 g_ais_query_dialog_x = 200;
251 g_ais_query_dialog_y = 200;
252 g_AisTargetList_range = 40;
253 g_AisTargetList_sortColumn = 2; // Column #2 is MMSI
254 g_S57_dialog_sx = 400;
255 g_S57_dialog_sy = 400;
256 g_S57_extradialog_sx = 400;
257 g_S57_extradialog_sy = 400;
258
259 // Reasonable starting point
260 vLat = START_LAT; // display viewpoint
261 vLon = START_LON;
262 gLat = START_LAT; // GPS position, as default
263 gLon = START_LON;
264 g_maxzoomin = 800;
265
266 g_iNavAidRadarRingsNumberVisible = 0;
267 g_bNavAidRadarRingsShown = false;
268 g_fNavAidRadarRingsStep = 1.0;
269 g_pNavAidRadarRingsStepUnits = 0;
270 g_colourOwnshipRangeRingsColour = *wxRED;
271 g_iWaypointRangeRingsNumber = 0;
272 g_fWaypointRangeRingsStep = 1.0;
273 g_iWaypointRangeRingsStepUnits = 0;
274 g_colourWaypointRangeRingsColour = wxColour(*wxRED);
275 g_bConfirmObjectDelete = true;
276
277 g_TrackIntervalSeconds = 60.0;
278 g_TrackDeltaDistance = 0.10;
279 g_route_line_width = 2;
280 g_track_line_width = 2;
281 g_colourTrackLineColour = wxColour(243, 229, 47); // Yellow
282
283 g_tcwin_scale = 100;
284 g_default_wp_icon = "triangle";
285 g_default_routepoint_icon = "diamond";
286
287 g_nAWDefault = 50;
288 g_nAWMax = 1852;
289 g_ObjQFileExt = "txt,rtf,png,html,gif,tif,jpg";
290
291 // Load the raw value, with no defaults, and no processing
292 int ret_Val = LoadMyConfigRaw();
293
294 // Perform any required post processing and validation
295 if (!ret_Val) {
297 g_Platform->GetChartScaleFactorExp(g_ChartScaleFactor);
298 g_ShipScaleFactorExp =
299 g_Platform->GetChartScaleFactorExp(g_ShipScaleFactor);
300 g_MarkScaleFactorExp =
301 g_Platform->GetMarkScaleFactorExp(g_ChartScaleFactor);
302
303 g_COGFilterSec = wxMin(g_COGFilterSec, MAX_COGSOG_FILTER_SECONDS);
304 g_COGFilterSec = wxMax(g_COGFilterSec, 1);
305 g_SOGFilterSec = g_COGFilterSec;
306
307 if (!g_bShowTrue && !g_bShowMag) g_bShowTrue = true;
309 wxMin(g_COGAvgSec, MAX_COG_AVERAGE_SECONDS); // Bound the array size
310
311 if (g_bInlandEcdis) g_bLookAhead = 1;
312
313 if (g_bdisable_opengl) g_bopengl = false;
314
315#ifdef ocpnUSE_GL
316 if (!g_bGLexpert) {
317 g_GLOptions.m_iTextureMemorySize =
318 wxMax(128, g_GLOptions.m_iTextureMemorySize);
319 g_GLOptions.m_bTextureCompressionCaching =
320 g_GLOptions.m_bTextureCompression;
321 }
322#endif
323
324 g_chart_zoom_modifier_raster = wxMin(g_chart_zoom_modifier_raster, 5);
325 g_chart_zoom_modifier_raster = wxMax(g_chart_zoom_modifier_raster, -5);
326 g_chart_zoom_modifier_vector = wxMin(g_chart_zoom_modifier_vector, 5);
327 g_chart_zoom_modifier_vector = wxMax(g_chart_zoom_modifier_vector, -5);
328 g_cm93_zoom_factor = wxMin(g_cm93_zoom_factor, CM93_ZOOM_FACTOR_MAX_RANGE);
329 g_cm93_zoom_factor =
330 wxMax(g_cm93_zoom_factor, (-CM93_ZOOM_FACTOR_MAX_RANGE));
331
332 if ((g_detailslider_dialog_x < 0) ||
333 (g_detailslider_dialog_x > display_width))
334 g_detailslider_dialog_x = 5;
335 if ((g_detailslider_dialog_y < 0) ||
336 (g_detailslider_dialog_y > display_height))
337 g_detailslider_dialog_y = 5;
338
339 g_defaultBoatSpeedUserUnit = toUsrSpeed(g_defaultBoatSpeed, -1);
340 g_n_ownship_min_mm = wxMax(g_n_ownship_min_mm, 2);
341
342 if (g_navobjbackups > 99) g_navobjbackups = 99;
343 if (g_navobjbackups < 0) g_navobjbackups = 0;
344 g_n_arrival_circle_radius = wxClip(g_n_arrival_circle_radius, 0.001, 0.6);
345
346 g_selection_radius_mm = wxMax(g_selection_radius_mm, 0.5);
347 g_selection_radius_touch_mm = wxMax(g_selection_radius_touch_mm, 1.0);
348
349 g_Show_Target_Name_Scale = wxMax(5000, g_Show_Target_Name_Scale);
350
351 if ((g_ais_alert_dialog_x < 0) || (g_ais_alert_dialog_x > display_width))
352 g_ais_alert_dialog_x = 5;
353 if ((g_ais_alert_dialog_y < 0) || (g_ais_alert_dialog_y > display_height))
354 g_ais_alert_dialog_y = 5;
355 if ((g_ais_query_dialog_x < 0) || (g_ais_query_dialog_x > display_width))
356 g_ais_query_dialog_x = 5;
357 if ((g_ais_query_dialog_y < 0) || (g_ais_query_dialog_y > display_height))
358 g_ais_query_dialog_y = 5;
359
360 SwitchInlandEcdisMode(g_bInlandEcdis);
361 if (g_bInlandEcdis)
362 global_color_scheme =
363 GLOBAL_COLOR_SCHEME_DUSK; // startup in duskmode if inlandEcdis
364
365 // Multicanvas Settings
366 LoadCanvasConfigs();
367 }
368
369 return ret_Val;
370}
371
372int MyConfig::LoadMyConfigRaw(bool bAsTemplate) {
373 int read_int;
374 wxString val;
375
376 int display_width, display_height;
377 display_width = g_monitor_info[g_current_monitor].width;
378 display_height = g_monitor_info[g_current_monitor].height;
379
380 // Global options and settings
381 SetPath("/Settings");
382 Read("ActiveRoute", &g_active_route);
383 Read("PersistActiveRoute", &g_persist_active_route);
384 Read("AlwaysSendRmbRmc", &g_always_send_rmb_rmc);
385 Read("LastAppliedTemplate", &g_lastAppliedTemplateGUID);
386 Read("CompatOS", &g_compatOS);
387 Read("CompatOsVersion", &g_compatOsVersion);
388
389 // Some undocumented values
390 Read("ConfigVersionString", &g_config_version_string);
391 Read("CmdSoundString", &g_CmdSoundString, wxString(OCPN_SOUND_CMD));
392 if (wxIsEmpty(g_CmdSoundString)) g_CmdSoundString = wxString(OCPN_SOUND_CMD);
393 Read("NavMessageShown", &n_NavMessageShown);
394
395 Read("AndroidVersionCode", &g_AndroidVersionCode);
396
397 Read("UIexpert", &g_bUIexpert);
398
399 Read("UIStyle", &g_uiStyle);
400
401 Read("NCacheLimit", &g_nCacheLimit);
402
403 Read("InlandEcdis",
404 &g_bInlandEcdis); // First read if in iENC mode as this will override
405 // some config settings
406
407 Read("SpaceDropMark", &g_bSpaceDropMark);
408
409 int mem_limit = 0;
410 Read("MEMCacheLimit", &mem_limit);
411 if (mem_limit > 0)
412 g_memCacheLimit = mem_limit * 1024; // convert from MBytes to kBytes
413
414 Read("UseModernUI5", &g_useMUI);
415
416 Read("NCPUCount", &g_nCPUCount);
417
418 Read("DebugGDAL", &g_bGDAL_Debug);
419 Read("DebugNMEA", &g_nNMEADebug);
420 Read("AnchorWatchDefault", &g_nAWDefault);
421 Read("AnchorWatchMax", &g_nAWMax);
422 Read("GPSDogTimeout", &gps_watchdog_timeout_ticks);
423 Read("DebugCM93", &g_bDebugCM93);
424 Read("DebugS57",
425 &g_bDebugS57); // Show LUP and Feature info in object query
426 Read("DebugBSBImg", &g_BSBImgDebug);
427 Read("DebugGPSD", &g_bDebugGPSD);
428 Read("MaxZoomScale", &g_maxzoomin);
429 g_maxzoomin = wxMax(g_maxzoomin, 50);
430
431 Read("DefaultFontSize", &g_default_font_size);
432 Read("DefaultFontFacename", &g_default_font_facename);
433
434 Read("UseGreenShipIcon", &g_bUseGreenShip);
435
436 Read("AutoHideToolbar", &g_bAutoHideToolbar);
437 Read("AutoHideToolbarSecs", &g_nAutoHideToolbar);
438
439 Read("UseSimplifiedScalebar", &g_bsimplifiedScalebar);
440 Read("ShowTide", &g_bShowTide);
441 Read("ShowCurrent", &g_bShowCurrent);
442
443 wxString size_mm;
444 Read("DisplaySizeMM", &size_mm);
445
446 Read("SelectionRadiusMM", &g_selection_radius_mm);
447 Read("SelectionRadiusTouchMM", &g_selection_radius_touch_mm);
448
449 if (!bAsTemplate) {
451 wxStringTokenizer tokenizer(size_mm, ",");
452 while (tokenizer.HasMoreTokens()) {
453 wxString token = tokenizer.GetNextToken();
454 int size;
455 try {
456 size = std::stoi(token.ToStdString());
457 } catch (std::invalid_argument &e) {
458 size = 0;
459 }
460 if (size > 100 && size < 2000) {
461 g_config_display_size_mm.push_back(size);
462 } else {
463 g_config_display_size_mm.push_back(0);
464 }
465 }
466 Read("DisplaySizeManual", &g_config_display_size_manual);
467 }
468
469 Read("GUIScaleFactor", &g_GUIScaleFactor);
470
471 Read("ChartObjectScaleFactor", &g_ChartScaleFactor);
472 Read("ShipScaleFactor", &g_ShipScaleFactor);
473 Read("ENCSoundingScaleFactor", &g_ENCSoundingScaleFactor);
474 Read("ENCTextScaleFactor", &g_ENCTextScaleFactor);
475 Read("ObjQueryAppendFilesExt", &g_ObjQFileExt);
476
477 // Plugin catalog handler persistent variables.
478 Read("CatalogCustomURL", &g_catalog_custom_url);
479 Read("CatalogChannel", &g_catalog_channel);
480
481 Read("NetmaskBits", &g_netmask_bits);
482
483 // NMEA connection options.
484 if (!bAsTemplate) {
485 Read("FilterNMEA_Avg", &g_bfilter_cogsog);
486 Read("FilterNMEA_Sec", &g_COGFilterSec);
487 Read("GPSIdent", &g_GPS_Ident);
488 Read("UseGarminHostUpload", &g_bGarminHostUpload);
489 Read("UseNMEA_GLL", &g_bUseGLL);
490 Read("UseMagAPB", &g_bMagneticAPB);
491 Read("TrackContinuous", &g_btrackContinuous, false);
492 Read("FilterTrackDropLargeJump", &g_trackFilterMax, 1000);
493 }
494
495 Read("ShowTrue", &g_bShowTrue);
496 Read("ShowMag", &g_bShowMag);
497
498 wxString umv;
499 Read("UserMagVariation", &umv);
500 if (umv.Len()) umv.ToDouble(&g_UserVar);
501
502 Read("ScreenBrightness", &g_nbrightness);
503
504 Read("MemFootprintTargetMB", &g_MemFootMB);
505
506 Read("WindowsComPortMax", &g_nCOMPortCheck);
507
508 Read("ChartQuilting", &g_bQuiltEnable);
509 Read("ChartQuiltingInitial", &g_bQuiltStart);
510
511 Read("CourseUpMode", &g_bCourseUp);
512 Read("COGUPAvgSeconds", &g_COGAvgSec);
513 Read("LookAheadMode", &g_bLookAhead);
514 Read("SkewToNorthUp", &g_bskew_comp);
515 Read("TenHzUpdate", &g_btenhertz, 0);
516 Read("DeclutterAnchorage", &g_declutter_anchorage, 0);
517
518 Read("NMEAAPBPrecision", &g_NMEAAPBPrecision);
519
520 Read("TalkerIdText", &g_TalkerIdText);
521 Read("MaxWaypointNameLength", &g_maxWPNameLength);
522 Read("MbtilesMaxLayers", &g_mbtilesMaxLayers);
523
524 Read("ShowTrackPointTime", &g_bShowTrackPointTime, true);
525 /* opengl options */
526#ifdef ocpnUSE_GL
527 if (!bAsTemplate) {
528 Read("OpenGLExpert", &g_bGLexpert, false);
529 Read("UseAcceleratedPanning", &g_GLOptions.m_bUseAcceleratedPanning, true);
530 Read("GPUTextureCompression", &g_GLOptions.m_bTextureCompression);
531 Read("GPUTextureCompressionCaching",
532 &g_GLOptions.m_bTextureCompressionCaching);
533 Read("PolygonSmoothing", &g_GLOptions.m_GLPolygonSmoothing);
534 Read("LineSmoothing", &g_GLOptions.m_GLLineSmoothing);
535 Read("GPUTextureDimension", &g_GLOptions.m_iTextureDimension);
536 Read("GPUTextureMemSize", &g_GLOptions.m_iTextureMemorySize);
537 Read("DebugOpenGL", &g_bDebugOGL);
538 Read("OpenGL", &g_bopengl);
539 Read("SoftwareGL", &g_bSoftwareGL);
540 }
541#endif
542
543 Read("SmoothPanZoom", &g_bsmoothpanzoom);
544
545 Read("ToolbarX", &g_maintoolbar_x);
546 Read("ToolbarY", &g_maintoolbar_y);
547 Read("ToolbarOrient", &g_maintoolbar_orient);
548 Read("GlobalToolbarConfig", &g_toolbarConfig);
549
550 Read("iENCToolbarX", &g_iENCToolbarPosX);
551 Read("iENCToolbarY", &g_iENCToolbarPosY);
552
553 Read("AnchorWatch1GUID", &g_AW1GUID);
554 Read("AnchorWatch2GUID", &g_AW2GUID);
555
556 Read("InitialStackIndex", &g_restore_stackindex);
557 Read("InitialdBIndex", &g_restore_dbindex);
558
559 Read("ChartNotRenderScaleFactor", &g_ChartNotRenderScaleFactor);
560
561 Read("MobileTouch", &g_btouch);
562
563// "Responsive graphics" option deprecated in O58+
564// Read("ResponsiveGraphics", &g_bresponsive);
565#ifdef __ANDROID__
566 g_bresponsive = true;
567#else
568 g_bresponsive = false;
569#endif
570
571 Read("EnableRolloverBlock", &g_bRollover);
572
573 Read("ZoomDetailFactor", &g_chart_zoom_modifier_raster);
574 Read("ZoomDetailFactorVector", &g_chart_zoom_modifier_vector);
575 Read("PlusMinusZoomFactor", &g_plus_minus_zoom_factor, 2.0);
576 Read("MouseZoomSensitivity", &g_mouse_zoom_sensitivity, 1.3);
577 g_mouse_zoom_sensitivity_ui =
578 MouseZoom::config_to_ui(g_mouse_zoom_sensitivity);
579 Read("CM93DetailFactor", &g_cm93_zoom_factor);
580
581 Read("CM93DetailZoomPosX", &g_detailslider_dialog_x);
582 Read("CM93DetailZoomPosY", &g_detailslider_dialog_y);
583 Read("ShowCM93DetailSlider", &g_bShowDetailSlider);
584
585 Read("SENC_LOD_Pixels", &g_SENC_LOD_pixels);
586
587 Read("SkewCompUpdatePeriod", &g_SkewCompUpdatePeriod);
588
589 Read("SetSystemTime", &s_bSetSystemTime);
590 Read("EnableKioskStartup", &g_kiosk_startup);
591 Read("ShowStatusBar", &g_bShowStatusBar);
592#ifndef __WXOSX__
593 Read("ShowMenuBar", &g_bShowMenuBar);
594#endif
595 Read("Fullscreen", &g_bFullscreen);
596 Read("ShowCompassWindow", &g_bShowCompassWin);
597 Read("ShowGrid", &g_bDisplayGrid);
598 Read("PlayShipsBells", &g_bPlayShipsBells);
599 Read("SoundDeviceIndex", &g_iSoundDeviceIndex);
600 Read("FullscreenToolbar", &g_bFullscreenToolbar);
601 Read("PermanentMOBIcon", &g_bPermanentMOBIcon);
602 Read("ShowLayers", &g_bShowLayers);
603 Read("ShowDepthUnits", &g_bShowDepthUnits);
604 Read("AutoAnchorDrop", &g_bAutoAnchorMark);
605 Read("ShowChartOutlines", &g_bShowOutlines);
606 Read("ShowActiveRouteHighway", &g_bShowActiveRouteHighway);
607 Read("ShowActiveRouteTotal", &g_bShowRouteTotal);
608 Read("MostRecentGPSUploadConnection", &g_uploadConnection);
609 Read("ShowChartBar", &g_bShowChartBar);
610 Read("SDMMFormat",
611 &g_iSDMMFormat); // 0 = "Degrees, Decimal minutes"), 1 = "Decimal
612 // degrees", 2 = "Degrees,Minutes, Seconds"
613
614 Read("DistanceFormat",
615 &g_iDistanceFormat); // 0 = "Nautical miles"), 1 = "Statute miles", 2 =
616 // "Kilometers", 3 = "Meters"
617 Read("SpeedFormat",
618 &g_iSpeedFormat); // 0 = "kts"), 1 = "mph", 2 = "km/h", 3 = "m/s"
619 Read("WindSpeedFormat",
620 &g_iWindSpeedFormat); // 0 = "knots"), 1 = "m/s", 2 = "Mph", 3 = "km/h"
621 Read("TemperatureFormat", &g_iTempFormat); // 0 = C, 1 = F, 2 = K
622 Read("HeightFormat", &g_iHeightFormat); // 0 = M, 1 = FT
623
624 // LIVE ETA OPTION
625 Read("LiveETA", &g_bShowLiveETA);
626 Read("DefaultBoatSpeed", &g_defaultBoatSpeed);
627
628 Read("OwnshipCOGPredictorMinutes", &g_ownship_predictor_minutes);
629 Read("OwnshipCOGPredictorStyle", &g_cog_predictor_style);
630 Read("OwnshipCOGPredictorColor", &g_cog_predictor_color);
631 Read("OwnshipCOGPredictorEndmarker", &g_cog_predictor_endmarker);
632 Read("OwnshipCOGPredictorWidth", &g_cog_predictor_width);
633 Read("OwnshipHDTPredictorStyle", &g_ownship_HDTpredictor_style);
634 Read("OwnshipHDTPredictorColor", &g_ownship_HDTpredictor_color);
635 Read("OwnshipHDTPredictorEndmarker", &g_ownship_HDTpredictor_endmarker);
636 Read("OwnshipHDTPredictorWidth", &g_ownship_HDTpredictor_width);
637 Read("OwnshipHDTPredictorMiles", &g_ownship_HDTpredictor_miles);
638 int mmsi;
639 Read("OwnShipMMSINumber", &mmsi);
640 g_OwnShipmmsi = mmsi >= 0 ? static_cast<unsigned>(mmsi) : 0;
641 Read("OwnShipIconType", &g_OwnShipIconType);
642 Read("OwnShipLength", &g_n_ownship_length_meters);
643 Read("OwnShipWidth", &g_n_ownship_beam_meters);
644 Read("OwnShipGPSOffsetX", &g_n_gps_antenna_offset_x);
645 Read("OwnShipGPSOffsetY", &g_n_gps_antenna_offset_y);
646 Read("OwnShipMinSize", &g_n_ownship_min_mm);
647 Read("OwnShipSogCogCalc", &g_own_ship_sog_cog_calc);
648 Read("OwnShipSogCogCalcDampSec", &g_own_ship_sog_cog_calc_damp_sec);
649 Read("ShowDirectRouteLine", &g_bShowShipToActive);
650 Read("DirectRouteLineStyle", &g_shipToActiveStyle);
651 Read("DirectRouteLineColor", &g_shipToActiveColor);
652
653 wxString racr;
654 Read("RouteArrivalCircleRadius", &racr);
655 if (racr.Len()) racr.ToDouble(&g_n_arrival_circle_radius);
656
657 Read("FullScreenQuilt", &g_bFullScreenQuilt);
658
659 Read("StartWithTrackActive", &g_bTrackCarryOver);
660 Read("AutomaticDailyTracks", &g_bTrackDaily);
661 Read("TrackRotateAt", &g_track_rotate_time);
662 Read("TrackRotateTimeType", &g_track_rotate_time_type);
663 Read("HighlightTracks", &g_bHighliteTracks);
664
665 Read("DateTimeFormat", &g_datetime_format);
666
667 wxString stps;
668 Read("PlanSpeed", &stps);
669 if (!stps.IsEmpty()) stps.ToDouble(&g_PlanSpeed);
670
671 Read("VisibleLayers", &g_VisibleLayers);
672 Read("InvisibleLayers", &g_InvisibleLayers);
673 Read("VisNameInLayers", &g_VisiNameinLayers);
674 Read("InvisNameInLayers", &g_InVisiNameinLayers);
675
676 Read("PreserveScaleOnX", &g_bPreserveScaleOnX);
677
678 Read("ShowMUIZoomButtons", &g_bShowMuiZoomButtons);
679
680 Read("Locale", &g_locale);
681 Read("LocaleOverride", &g_localeOverride);
682
683 // We allow 0-99 backups ov navobj.xml
684 Read("KeepNavobjBackups", &g_navobjbackups);
685
686 // Boolean to cater for legacy Input COM Port filer behaviour, i.e. show msg
687 // filtered but put msg on bus.
688 Read("LegacyInputCOMPortFilterBehaviour", &g_b_legacy_input_filter_behaviour);
689
690 // Boolean to cater for sailing when not approaching waypoint
691 Read("AdvanceRouteWaypointOnArrivalOnly",
692 &g_bAdvanceRouteWaypointOnArrivalOnly);
693 Read("EnableRootMenuDebug", &g_enable_root_menu_debug);
694
695 Read("EnableRotateKeys", &g_benable_rotate);
696 Read("EmailCrashReport", &g_bEmailCrashReport);
697
698 g_benableAISNameCache = true;
699 Read("EnableAISNameCache", &g_benableAISNameCache);
700
701 Read("EnableUDPNullHeader", &g_benableUDPNullHeader);
702
703 SetPath("/Settings/GlobalState");
704
705 Read("FrameWinX", &g_nframewin_x);
706 Read("FrameWinY", &g_nframewin_y);
707 Read("FrameWinPosX", &g_nframewin_posx);
708 Read("FrameWinPosY", &g_nframewin_posy);
709 Read("FrameMax", &g_bframemax);
710
711 Read("ClientPosX", &g_lastClientRectx);
712 Read("ClientPosY", &g_lastClientRecty);
713 Read("ClientSzX", &g_lastClientRectw);
714 Read("ClientSzY", &g_lastClientRecth);
715
716 Read("RoutePropSizeX", &g_route_prop_sx);
717 Read("RoutePropSizeY", &g_route_prop_sy);
718 Read("RoutePropPosX", &g_route_prop_x);
719 Read("RoutePropPosY", &g_route_prop_y);
720
721 Read("AllowArbitrarySystemPlugins", &g_allow_arb_system_plugin);
722
723 read_int = -1;
724 Read("S52_DEPTH_UNIT_SHOW", &read_int); // default is metres
725 if (read_int >= 0) {
726 read_int = wxMax(read_int, 0); // qualify value
727 read_int = wxMin(read_int, 2);
728 g_nDepthUnitDisplay = read_int;
729 }
730
731 // Sounds
732 SetPath("/Settings/Audio");
733
734 // Set reasonable defaults
735 wxString sound_dir = g_Platform->GetSharedDataDir();
736 sound_dir.Append("sounds");
737 sound_dir.Append(wxFileName::GetPathSeparator());
738
739 g_AIS_sound_file = sound_dir + "beep_ssl.wav";
740 g_DSC_sound_file = sound_dir + "phonering1.wav";
741 g_SART_sound_file = sound_dir + "beep3.wav";
742 g_anchorwatch_sound_file = sound_dir + "beep1.wav";
743
744 Read("AISAlertSoundFile", &g_AIS_sound_file);
745 Read("DSCAlertSoundFile", &g_DSC_sound_file);
746 Read("SARTAlertSoundFile", &g_SART_sound_file);
747 Read("AnchorAlarmSoundFile", &g_anchorwatch_sound_file);
748
749 Read("bAIS_GCPA_AlertAudio", &g_bAIS_GCPA_Alert_Audio);
750 Read("bAIS_SART_AlertAudio", &g_bAIS_SART_Alert_Audio);
751 Read("bAIS_DSC_AlertAudio", &g_bAIS_DSC_Alert_Audio);
752 Read("bAnchorAlertAudio", &g_bAnchor_Alert_Audio);
753
754 // AIS
755 wxString s;
756 SetPath("/Settings/AIS");
757
758 g_bUseOnlyConfirmedAISName = false;
759 Read("UseOnlyConfirmedAISName", &g_bUseOnlyConfirmedAISName);
760
761 Read("bNoCPAMax", &g_bCPAMax);
762
763 Read("NoCPAMaxNMi", &s);
764 s.ToDouble(&g_CPAMax_NM);
765
766 Read("bCPAWarn", &g_bCPAWarn);
767
768 Read("CPAWarnNMi", &s);
769 s.ToDouble(&g_CPAWarn_NM);
770
771 Read("bTCPAMax", &g_bTCPA_Max);
772
773 Read("TCPAMaxMinutes", &s);
774 s.ToDouble(&g_TCPA_Max);
775
776 Read("bMarkLostTargets", &g_bMarkLost);
777
778 Read("MarkLost_Minutes", &s);
779 s.ToDouble(&g_MarkLost_Mins);
780
781 Read("bRemoveLostTargets", &g_bRemoveLost);
782
783 Read("RemoveLost_Minutes", &s);
784 s.ToDouble(&g_RemoveLost_Mins);
785
786 Read("bShowCOGArrows", &g_bShowCOG);
787
788 Read("bSyncCogPredictors", &g_bSyncCogPredictors);
789
790 Read("CogArrowMinutes", &s);
791 s.ToDouble(&g_ShowCOG_Mins);
792
793 Read("bShowTargetTracks", &g_bAISShowTracks);
794
795 if (Read("TargetTracksLimit", &s)) {
796 s.ToDouble(&g_AISShowTracks_Limit);
797 g_AISShowTracks_Limit = wxMax(300.0, g_AISShowTracks_Limit);
798 }
799 if (Read("TargetTracksMinutes", &s)) {
800 s.ToDouble(&g_AISShowTracks_Mins);
801 g_AISShowTracks_Mins = wxMax(1.0, g_AISShowTracks_Mins);
802 g_AISShowTracks_Mins = wxMin(g_AISShowTracks_Limit, g_AISShowTracks_Mins);
803 }
804
805 Read("bHideMooredTargets", &g_bHideMoored);
806 if (Read("MooredTargetMaxSpeedKnots", &s)) s.ToDouble(&g_ShowMoored_Kts);
807
808 g_SOGminCOG_kts = 0.2;
809 if (Read("SOGMinimumForCOGDisplay", &s)) s.ToDouble(&g_SOGminCOG_kts);
810
811 Read("bShowScaledTargets", &g_bAllowShowScaled);
812 Read("AISScaledNumber", &g_ShowScaled_Num);
813 Read("AISScaledNumberWeightSOG", &g_ScaledNumWeightSOG);
814 Read("AISScaledNumberWeightCPA", &g_ScaledNumWeightCPA);
815 Read("AISScaledNumberWeightTCPA", &g_ScaledNumWeightTCPA);
816 Read("AISScaledNumberWeightRange", &g_ScaledNumWeightRange);
817 Read("AISScaledNumberWeightSizeOfTarget", &g_ScaledNumWeightSizeOfT);
818 Read("AISScaledSizeMinimal", &g_ScaledSizeMinimal);
819 Read("AISShowScaled", &g_bShowScaled);
820
821 Read("bShowAreaNotices", &g_bShowAreaNotices);
822 Read("bDrawAISSize", &g_bDrawAISSize);
823 Read("bDrawAISRealtime", &g_bDrawAISRealtime);
824 Read("bShowAISName", &g_bShowAISName);
825 Read("AISRealtimeMinSpeedKnots", &g_AIS_RealtPred_Kts, 0.7);
826 Read("bAISAlertDialog", &g_bAIS_CPA_Alert);
827 Read("ShowAISTargetNameScale", &g_Show_Target_Name_Scale);
828 Read("bWplIsAprsPositionReport", &g_bWplUsePosition);
829 Read("WplSelAction", &g_WplAction);
830 Read("AISCOGPredictorWidth", &g_ais_cog_predictor_width);
831
832 Read("bAISAlertAudio", &g_bAIS_CPA_Alert_Audio);
833 Read("AISAlertAudioFile", &g_sAIS_Alert_Sound_File);
834 Read("bAISAlertSuppressMoored", &g_bAIS_CPA_Alert_Suppress_Moored);
835
836 Read("bAISAlertAckTimeout", &g_bAIS_ACK_Timeout);
837 if (Read("AlertAckTimeoutMinutes", &s)) s.ToDouble(&g_AckTimeout_Mins);
838
839 Read("AlertDialogSizeX", &g_ais_alert_dialog_sx);
840 Read("AlertDialogSizeY", &g_ais_alert_dialog_sy);
841 Read("AlertDialogPosX", &g_ais_alert_dialog_x);
842 Read("AlertDialogPosY", &g_ais_alert_dialog_y);
843 Read("QueryDialogPosX", &g_ais_query_dialog_x);
844 Read("QueryDialogPosY", &g_ais_query_dialog_y);
845
846 Read("AISTargetListPerspective", &g_AisTargetList_perspective);
847 Read("AISTargetListRange", &g_AisTargetList_range);
848 Read("AISTargetListSortColumn", &g_AisTargetList_sortColumn);
849 Read("bAISTargetListSortReverse", &g_bAisTargetList_sortReverse);
850 Read("AISTargetListColumnSpec", &g_AisTargetList_column_spec);
851 Read("AISTargetListColumnOrder", &g_AisTargetList_column_order);
852
853 Read("bAISRolloverShowClass", &g_bAISRolloverShowClass);
854 Read("bAISRolloverShowCOG", &g_bAISRolloverShowCOG);
855 Read("bAISRolloverShowCPA", &g_bAISRolloverShowCPA);
856
857 Read("S57QueryDialogSizeX", &g_S57_dialog_sx);
858 Read("S57QueryDialogSizeY", &g_S57_dialog_sy);
859 Read("S57QueryExtraDialogSizeX", &g_S57_extradialog_sx);
860 Read("S57QueryExtraDialogSizeY", &g_S57_extradialog_sy);
861
862 wxString strpres("PresentationLibraryData");
863 wxString valpres;
864 SetPath("/Directories");
865 Read(strpres, &valpres); // Get the File name
866 if (!valpres.IsEmpty()) g_UserPresLibData = valpres;
867
868 wxString strs("SENCFileLocation");
869 SetPath("/Directories");
870 wxString vals;
871 Read(strs, &vals); // Get the Directory name
872 if (!vals.IsEmpty()) g_SENCPrefix = vals;
873
874 SetPath("/Directories");
875 wxString vald;
876 Read("InitChartDir", &vald); // Get the Directory name
877
878 wxString dirnamed(vald);
879 if (!dirnamed.IsEmpty()) {
880 if (pInit_Chart_Dir->IsEmpty()) // on second pass, don't overwrite
881 {
882 pInit_Chart_Dir->Clear();
883 pInit_Chart_Dir->Append(vald);
884 }
885 }
886
887 Read("GPXIODir", &g_gpx_path); // Get the Directory name
888 Read("TCDataDir", &g_TCData_Dir); // Get the Directory name
889 Read("BasemapDir", &gWorldMapLocation);
890 Read("BaseShapefileDir", &gWorldShapefileLocation);
891 Read("pluginInstallDir", &g_winPluginDir);
892 wxLogMessage("winPluginDir, read from ini file: %s",
893 g_winPluginDir.mb_str().data());
894
895 SetPath("/Settings/GlobalState");
896
897 if (Read("nColorScheme", &read_int))
898 global_color_scheme = (ColorScheme)read_int;
899
900 if (!bAsTemplate) {
901 SetPath("/Settings/NMEADataSource");
902
903 TheConnectionParams().clear();
904 wxString connectionconfigs;
905 Read("DataConnections", &connectionconfigs);
906 if (!connectionconfigs.IsEmpty()) {
907 wxArrayString confs = wxStringTokenize(connectionconfigs, "|");
908 for (size_t i = 0; i < confs.Count(); i++) {
909 ConnectionParams *prm = new ConnectionParams(confs[i]);
910 if (!prm->Valid) {
911 wxLogMessage("Skipped invalid DataStream config");
912 delete prm;
913 continue;
914 }
915 TheConnectionParams().push_back(prm);
916 }
917 }
918 }
919
920 SetPath("/Settings/GlobalState");
921 wxString st;
922
923 double st_lat, st_lon;
924 if (Read("VPLatLon", &st)) {
925 sscanf(st.mb_str(wxConvUTF8), "%lf,%lf", &st_lat, &st_lon);
926
927 // Sanity check the lat/lon...both have to be reasonable.
928 if (fabs(st_lon) < 360.) {
929 while (st_lon < -180.) st_lon += 360.;
930
931 while (st_lon > 180.) st_lon -= 360.;
932
933 vLon = st_lon;
934 }
935
936 if (fabs(st_lat) < 90.0) vLat = st_lat;
937
938 s.Printf("Setting Viewpoint Lat/Lon %g, %g", vLat, vLon);
939 wxLogMessage(s);
940 }
941
942 double st_view_scale, st_rotation;
943 if (Read(wxString("VPScale"), &st)) {
944 sscanf(st.mb_str(wxConvUTF8), "%lf", &st_view_scale);
945 // Sanity check the scale
946 st_view_scale = fmax(st_view_scale, .001 / 32);
947 st_view_scale = fmin(st_view_scale, 4);
948 }
949
950 if (Read(wxString("VPRotation"), &st)) {
951 sscanf(st.mb_str(wxConvUTF8), "%lf", &st_rotation);
952 // Sanity check the rotation
953 st_rotation = fmin(st_rotation, 360);
954 st_rotation = fmax(st_rotation, 0);
955 }
956
957 wxString sll;
958 double lat, lon;
959 if (Read("OwnShipLatLon", &sll)) {
960 sscanf(sll.mb_str(wxConvUTF8), "%lf,%lf", &lat, &lon);
961
962 // Sanity check the lat/lon...both have to be reasonable.
963 if (fabs(lon) < 360.) {
964 while (lon < -180.) lon += 360.;
965
966 while (lon > 180.) lon -= 360.;
967
968 gLon = lon;
969 }
970
971 if (fabs(lat) < 90.0) gLat = lat;
972
973 s.Printf("Setting Ownship Lat/Lon %g, %g", gLat, gLon);
974 wxLogMessage(s);
975 }
976
977 // Fonts
978
979 // Load the persistent Auxiliary Font descriptor Keys
980 SetPath("/Settings/AuxFontKeys");
981
982 wxString strk;
983 long dummyk;
984 wxString kval;
985 bool bContk = GetFirstEntry(strk, dummyk);
986 bool bNewKey = false;
987 while (bContk) {
988 Read(strk, &kval);
989 bNewKey = FontMgr::Get().AddAuxKey(kval);
990 if (!bAsTemplate && !bNewKey) {
991 DeleteEntry(strk);
992 dummyk--;
993 }
994 bContk = GetNextEntry(strk, dummyk);
995 }
996
997#ifdef __WXX11__
998 SetPath("/Settings/X11Fonts");
999#endif
1000
1001#ifdef __WXGTK__
1002 SetPath("/Settings/GTKFonts");
1003#endif
1004
1005#ifdef __WXMSW__
1006 SetPath("/Settings/MSWFonts");
1007#endif
1008
1009#ifdef __WXMAC__
1010 SetPath("/Settings/MacFonts");
1011#endif
1012
1013#ifdef __WXQT__
1014 SetPath("/Settings/QTFonts");
1015#endif
1016
1017 wxString str;
1018 long dummy;
1019 wxString pval;
1020 wxArrayString deleteList;
1021
1022 bool bCont = GetFirstEntry(str, dummy);
1023 while (bCont) {
1024 pval = Read(str);
1025
1026 if (str.StartsWith("Font")) {
1027 // Convert pre 3.1 setting. Can't delete old entries from inside the
1028 // GetNextEntry() loop, so we need to save those and delete outside.
1029 deleteList.Add(str);
1030 wxString oldKey = pval.BeforeFirst(_T(':'));
1031 str = FontMgr::GetFontConfigKey(oldKey);
1032 }
1033
1034 if (pval.IsEmpty() || pval.StartsWith(":")) {
1035 deleteList.Add(str);
1036 } else
1037 FontMgr::Get().LoadFontNative(&str, &pval);
1038
1039 bCont = GetNextEntry(str, dummy);
1040 }
1041
1042 for (unsigned int i = 0; i < deleteList.Count(); i++) {
1043 DeleteEntry(deleteList[i]);
1044 }
1045 deleteList.Clear();
1046
1047 // Tide/Current Data Sources
1048 SetPath("/TideCurrentDataSources");
1049 if (GetNumberOfEntries()) {
1050 TideCurrentDataSet.clear();
1051 wxString str, val;
1052 long dummy;
1053 bool bCont = GetFirstEntry(str, dummy);
1054 while (bCont) {
1055 Read(str, &val); // Get a file name and add it to the list just in case
1056 // it is not repeated
1057 // We have seen duplication of dataset entries in
1058 // https://github.com/OpenCPN/OpenCPN/issues/3042, this effectively gets
1059 // rid of them.
1060 if (std::find(TideCurrentDataSet.begin(), TideCurrentDataSet.end(),
1061 val.ToStdString()) == TideCurrentDataSet.end()) {
1062 TideCurrentDataSet.push_back(val.ToStdString());
1063 }
1064 bCont = GetNextEntry(str, dummy);
1065 }
1066 }
1067
1068 // Groups
1069 LoadConfigGroups(g_pGroupArray);
1070
1071 // // Multicanvas Settings
1072 // LoadCanvasConfigs();
1073
1074 SetPath("/Settings/Others");
1075
1076 // Radar rings
1077 Read("RadarRingsNumberVisible", &val);
1078 if (val.Length() > 0) g_iNavAidRadarRingsNumberVisible = atoi(val.mb_str());
1079 g_bNavAidRadarRingsShown = g_iNavAidRadarRingsNumberVisible > 0;
1080
1081 Read("RadarRingsStep", &val);
1082 if (val.Length() > 0) g_fNavAidRadarRingsStep = atof(val.mb_str());
1083
1084 Read("RadarRingsStepUnits", &g_pNavAidRadarRingsStepUnits);
1085
1086 wxString l_wxsOwnshipRangeRingsColour;
1087 Read("RadarRingsColour", &l_wxsOwnshipRangeRingsColour);
1088 if (l_wxsOwnshipRangeRingsColour.Length())
1089 g_colourOwnshipRangeRingsColour.Set(l_wxsOwnshipRangeRingsColour);
1090
1091 // Waypoint Radar rings
1092 Read("WaypointRangeRingsNumber", &val);
1093 if (val.Length() > 0) g_iWaypointRangeRingsNumber = atoi(val.mb_str());
1094
1095 Read("WaypointRangeRingsStep", &val);
1096 if (val.Length() > 0) g_fWaypointRangeRingsStep = atof(val.mb_str());
1097
1098 Read("WaypointRangeRingsStepUnits", &g_iWaypointRangeRingsStepUnits);
1099
1100 wxString l_wxsWaypointRangeRingsColour;
1101 Read("WaypointRangeRingsColour", &l_wxsWaypointRangeRingsColour);
1102 g_colourWaypointRangeRingsColour.Set(l_wxsWaypointRangeRingsColour);
1103
1104 if (!Read("WaypointUseScaMin", &g_bUseWptScaMin)) g_bUseWptScaMin = false;
1105 if (!Read("WaypointScaMinValue", &g_iWpt_ScaMin)) g_iWpt_ScaMin = 2147483646;
1106 if (!Read("WaypointUseScaMinOverrule", &g_bOverruleScaMin))
1107 g_bOverruleScaMin = false;
1108 if (!Read("WaypointsShowName", &g_bShowWptName)) g_bShowWptName = true;
1109 if (!Read("UserIconsFirst", &g_bUserIconsFirst)) g_bUserIconsFirst = true;
1110
1111 // Support Version 3.0 and prior config setting for Radar Rings
1112 bool b300RadarRings = true;
1113 if (Read("ShowRadarRings", &b300RadarRings)) {
1114 if (!b300RadarRings) g_iNavAidRadarRingsNumberVisible = 0;
1115 }
1116
1117 Read("ConfirmObjectDeletion", &g_bConfirmObjectDelete);
1118
1119 // Waypoint dragging with mouse
1120 g_bWayPointPreventDragging = false;
1121 Read("WaypointPreventDragging", &g_bWayPointPreventDragging);
1122
1123 g_bEnableZoomToCursor = false;
1124 Read("EnableZoomToCursor", &g_bEnableZoomToCursor);
1125
1126 val.Clear();
1127 Read("TrackIntervalSeconds", &val);
1128 if (val.Length() > 0) {
1129 double tval = atof(val.mb_str());
1130 if (tval >= 2.) g_TrackIntervalSeconds = tval;
1131 }
1132
1133 val.Clear();
1134 Read("TrackDeltaDistance", &val);
1135 if (val.Length() > 0) {
1136 double tval = atof(val.mb_str());
1137 if (tval >= 0.05) g_TrackDeltaDistance = tval;
1138 }
1139
1140 Read("TrackPrecision", &g_nTrackPrecision);
1141
1142 Read("RouteLineWidth", &g_route_line_width);
1143 Read("TrackLineWidth", &g_track_line_width);
1144
1145 wxString l_wxsTrackLineColour;
1146 if (Read("TrackLineColour", &l_wxsTrackLineColour))
1147 g_colourTrackLineColour.Set(l_wxsTrackLineColour);
1148
1149 Read("TideCurrentWindowScale", &g_tcwin_scale);
1150 Read("DefaultWPIcon", &g_default_wp_icon);
1151 Read("DefaultRPIcon", &g_default_routepoint_icon);
1152
1153 SetPath("/MmsiProperties");
1154 int iPMax = GetNumberOfEntries();
1155 if (iPMax) {
1156 g_MMSI_Props_Array.Empty();
1157 wxString str, val;
1158 long dummy;
1159 bool bCont = pConfig->GetFirstEntry(str, dummy);
1160 while (bCont) {
1161 pConfig->Read(str, &val); // Get an entry
1162
1163 MmsiProperties *pProps = new MmsiProperties(val);
1164 g_MMSI_Props_Array.Add(pProps);
1165
1166 bCont = pConfig->GetNextEntry(str, dummy);
1167 }
1168 }
1169
1170 return (0);
1171}
1172
1173void MyConfig::LoadS57Config() {
1174 if (!ps52plib) return;
1175
1176 int read_int;
1177 double dval;
1178 SetPath("/Settings/GlobalState");
1179
1180 Read("bShowS57Text", &read_int, 1);
1181 ps52plib->SetShowS57Text(!(read_int == 0));
1182
1183 Read("bShowS57ImportantTextOnly", &read_int, 0);
1184 ps52plib->SetShowS57ImportantTextOnly(!(read_int == 0));
1185
1186 Read("bShowLightDescription", &read_int, 0);
1187 ps52plib->SetShowLdisText(!(read_int == 0));
1188
1189 Read("bExtendLightSectors", &read_int, 0);
1190 ps52plib->SetExtendLightSectors(!(read_int == 0));
1191
1192 Read("nDisplayCategory", &read_int, (enum _DisCat)STANDARD);
1193 ps52plib->SetDisplayCategory((enum _DisCat)read_int);
1194
1195 Read("nSymbolStyle", &read_int, (enum _LUPname)PAPER_CHART);
1196 ps52plib->m_nSymbolStyle = (LUPname)read_int;
1197
1198 Read("nBoundaryStyle", &read_int, PLAIN_BOUNDARIES);
1199 ps52plib->m_nBoundaryStyle = (LUPname)read_int;
1200
1201 Read("bShowSoundg", &read_int, 1);
1202 ps52plib->m_bShowSoundg = !(read_int == 0);
1203
1204 Read("bShowMeta", &read_int, 0);
1205 ps52plib->m_bShowMeta = !(read_int == 0);
1206
1207 Read("bUseSCAMIN", &read_int, 1);
1208 ps52plib->m_bUseSCAMIN = !(read_int == 0);
1209
1210 Read("bUseSUPER_SCAMIN", &read_int, 0);
1211 ps52plib->m_bUseSUPER_SCAMIN = !(read_int == 0);
1212
1213 Read("bShowAtonText", &read_int, 1);
1214 ps52plib->m_bShowAtonText = !(read_int == 0);
1215
1216 Read("bDeClutterText", &read_int, 0);
1217 ps52plib->m_bDeClutterText = !(read_int == 0);
1218
1219 Read("bShowNationalText", &read_int, 0);
1220 ps52plib->m_bShowNationalTexts = !(read_int == 0);
1221
1222 Read("ENCSoundingScaleFactor", &read_int, 0);
1223 ps52plib->m_nSoundingFactor = read_int;
1224
1225 Read("ENCTextScaleFactor", &read_int, 0);
1226 ps52plib->m_nTextFactor = read_int;
1227
1228 if (Read("S52_MAR_SAFETY_CONTOUR", &dval, 3.0)) {
1229 S52_setMarinerParam(S52_MAR_SAFETY_CONTOUR, dval);
1230 S52_setMarinerParam(S52_MAR_SAFETY_DEPTH,
1231 dval); // Set safety_contour and safety_depth the same
1232 }
1233
1234 if (Read("S52_MAR_SHALLOW_CONTOUR", &dval, 2.0))
1235 S52_setMarinerParam(S52_MAR_SHALLOW_CONTOUR, dval);
1236
1237 if (Read("S52_MAR_DEEP_CONTOUR", &dval, 6.0))
1238 S52_setMarinerParam(S52_MAR_DEEP_CONTOUR, dval);
1239
1240 if (Read("S52_MAR_TWO_SHADES", &dval, 0.0))
1241 S52_setMarinerParam(S52_MAR_TWO_SHADES, dval);
1242
1243 ps52plib->UpdateMarinerParams();
1244
1245 SetPath("/Settings/GlobalState");
1246 Read("S52_DEPTH_UNIT_SHOW", &read_int, 1); // default is metres
1247 read_int = wxMax(read_int, 0); // qualify value
1248 read_int = wxMin(read_int, 2);
1249 ps52plib->m_nDepthUnitDisplay = read_int;
1250 g_nDepthUnitDisplay = read_int;
1251
1252 // S57 Object Class Visibility
1253
1254 OBJLElement *pOLE;
1255
1256 SetPath("/Settings/ObjectFilter");
1257
1258 int iOBJMax = GetNumberOfEntries();
1259 if (iOBJMax) {
1260 wxString str;
1261 long val;
1262 long dummy;
1263
1264 wxString sObj;
1265
1266 bool bCont = pConfig->GetFirstEntry(str, dummy);
1267 while (bCont) {
1268 pConfig->Read(str, &val); // Get an Object Viz
1269
1270 bool bNeedNew = true;
1271
1272 if (str.StartsWith("viz", &sObj)) {
1273 for (unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount();
1274 iPtr++) {
1275 pOLE = (OBJLElement *)(ps52plib->pOBJLArray->Item(iPtr));
1276 if (!strncmp(pOLE->OBJLName, sObj.mb_str(), 6)) {
1277 pOLE->nViz = val;
1278 bNeedNew = false;
1279 break;
1280 }
1281 }
1282
1283 if (bNeedNew) {
1284 pOLE = (OBJLElement *)calloc(sizeof(OBJLElement), 1);
1285 memcpy(pOLE->OBJLName, sObj.mb_str(), OBJL_NAME_LEN);
1286 pOLE->nViz = 1;
1287
1288 ps52plib->pOBJLArray->Add((void *)pOLE);
1289 }
1290 }
1291 bCont = pConfig->GetNextEntry(str, dummy);
1292 }
1293 }
1294}
1295
1296bool MyConfig::LoadLayers(wxString &path) {
1297 wxArrayString file_array;
1298 wxDir dir;
1299 Layer *l;
1300 dir.Open(path);
1301 if (dir.IsOpened()) {
1302 wxString filename;
1303 bool cont = dir.GetFirst(&filename);
1304 while (cont) {
1305 file_array.Clear();
1306 filename.Prepend(wxFileName::GetPathSeparator());
1307 filename.Prepend(path);
1308 wxFileName f(filename);
1309 size_t nfiles = 0;
1310 if (f.GetExt().IsSameAs("gpx"))
1311 file_array.Add(filename); // single-gpx-file layer
1312 else {
1313 if (wxDir::Exists(filename)) {
1314 wxDir dir(filename);
1315 if (dir.IsOpened()) {
1316 nfiles = dir.GetAllFiles(filename, &file_array,
1317 "*.gpx"); // layers subdirectory set
1318 }
1319 }
1320 }
1321
1322 if (file_array.GetCount()) {
1323 l = new Layer();
1324 l->m_LayerID = ++g_LayerIdx;
1325 l->m_LayerFileName = file_array[0];
1326 if (file_array.GetCount() <= 1)
1327 wxFileName::SplitPath(file_array[0], NULL, NULL, &(l->m_LayerName),
1328 NULL, NULL);
1329 else
1330 wxFileName::SplitPath(filename, NULL, NULL, &(l->m_LayerName), NULL,
1331 NULL);
1332
1333 bool bLayerViz = g_bShowLayers;
1334
1335 if (g_VisibleLayers.Contains(l->m_LayerName)) bLayerViz = true;
1336 if (g_InvisibleLayers.Contains(l->m_LayerName)) bLayerViz = false;
1337
1338 l->m_bHasVisibleNames = wxCHK_UNDETERMINED;
1339 if (g_VisiNameinLayers.Contains(l->m_LayerName))
1340 l->m_bHasVisibleNames = wxCHK_CHECKED;
1341 if (g_InVisiNameinLayers.Contains(l->m_LayerName))
1342 l->m_bHasVisibleNames = wxCHK_UNCHECKED;
1343
1344 l->m_bIsVisibleOnChart = bLayerViz;
1345
1346 wxString laymsg;
1347 laymsg.Printf("New layer %d: %s", l->m_LayerID, l->m_LayerName.c_str());
1348 wxLogMessage(laymsg);
1349
1350 pLayerList->insert(pLayerList->begin(), l);
1351
1352 // Load the entire file array as a single layer
1353
1354 for (unsigned int i = 0; i < file_array.GetCount(); i++) {
1355 wxString file_path = file_array[i];
1356
1357 if (::wxFileExists(file_path)) {
1359 if (pSet->load_file(file_path.fn_str()).status !=
1360 pugi::xml_parse_status::status_ok) {
1361 wxLogMessage("Error loading GPX file " + file_path);
1362 pSet->reset();
1363 }
1364 long nItems = pSet->LoadAllGPXObjectsAsLayer(
1365 l->m_LayerID, bLayerViz, l->m_bHasVisibleNames);
1366 l->m_NoOfItems += nItems;
1367 l->m_LayerType = _("Persistent");
1368
1369 wxString objmsg;
1370 objmsg.Printf("Loaded GPX file %s with %ld items.",
1371 file_path.c_str(), nItems);
1372 wxLogMessage(objmsg);
1373
1374 delete pSet;
1375 }
1376 }
1377 }
1378
1379 cont = dir.GetNext(&filename);
1380 }
1381 }
1382 g_bLayersLoaded = true;
1383
1384 return true;
1385}
1386
1387bool MyConfig::LoadChartDirArray(ArrayOfCDI &ChartDirArray) {
1388 // Chart Directories
1389 SetPath("/ChartDirectories");
1390 int iDirMax = GetNumberOfEntries();
1391 if (iDirMax) {
1392 ChartDirArray.Empty();
1393 wxString str, val;
1394 long dummy;
1395 int nAdjustChartDirs = 0;
1396 int iDir = 0;
1397 bool bCont = pConfig->GetFirstEntry(str, dummy);
1398 while (bCont) {
1399 pConfig->Read(str, &val); // Get a Directory name
1400
1401 wxString dirname(val);
1402 if (!dirname.IsEmpty()) {
1403 /* Special case for first time run after Windows install with sample
1404 chart data... We desire that the sample configuration file opencpn.ini
1405 should not contain any installation dependencies, so... Detect and
1406 update the sample [ChartDirectories] entries to point to the Shared
1407 Data directory For instance, if the (sample) opencpn.ini file should
1408 contain shortcut coded entries like:
1409
1410 [ChartDirectories]
1411 ChartDir1=SampleCharts\\MaptechRegion7
1412
1413 then this entry will be updated to be something like:
1414 ChartDir1=c:\Program Files\opencpn\SampleCharts\\MaptechRegion7
1415
1416 */
1417 if (dirname.Find("SampleCharts") ==
1418 0) // only update entries starting with "SampleCharts"
1419 {
1420 nAdjustChartDirs++;
1421
1422 pConfig->DeleteEntry(str);
1423 wxString new_dir = dirname.Mid(dirname.Find("SampleCharts"));
1424 new_dir.Prepend(g_Platform->GetSharedDataDir());
1425 dirname = new_dir;
1426 }
1427
1428 ChartDirInfo cdi;
1429 cdi.fullpath = dirname.BeforeFirst('^');
1430 cdi.magic_number = dirname.AfterFirst('^');
1431
1432 ChartDirArray.Add(cdi);
1433 iDir++;
1434 }
1435
1436 bCont = pConfig->GetNextEntry(str, dummy);
1437 }
1438
1439 if (nAdjustChartDirs) pConfig->UpdateChartDirs(ChartDirArray);
1440 }
1441
1442 return true;
1443}
1444
1445bool MyConfig::UpdateChartDirs(ArrayOfCDI &dir_array) {
1446 wxString key, dir;
1447 wxString str_buf;
1448
1449 SetPath("/ChartDirectories");
1450 int iDirMax = GetNumberOfEntries();
1451 if (iDirMax) {
1452 long dummy;
1453
1454 for (int i = 0; i < iDirMax; i++) {
1455 GetFirstEntry(key, dummy);
1456 DeleteEntry(key, false);
1457 }
1458 }
1459
1460 iDirMax = dir_array.GetCount();
1461
1462 for (int iDir = 0; iDir < iDirMax; iDir++) {
1463 ChartDirInfo cdi = dir_array[iDir];
1464
1465 wxString dirn = cdi.fullpath;
1466 dirn.Append("^");
1467 dirn.Append(cdi.magic_number);
1468
1469 str_buf.Printf("ChartDir%d", iDir + 1);
1470
1471 Write(str_buf, dirn);
1472 }
1473
1474// Avoid nonsense log errors...
1475#ifdef __ANDROID__
1476 wxLogNull logNo;
1477#endif
1478
1479 Flush();
1480 return true;
1481}
1482
1483void MyConfig::CreateConfigGroups(ChartGroupArray *pGroupArray) {
1484 if (!pGroupArray) return;
1485
1486 SetPath("/Groups");
1487 Write("GroupCount", (int)pGroupArray->GetCount());
1488
1489 for (unsigned int i = 0; i < pGroupArray->GetCount(); i++) {
1490 ChartGroup *pGroup = pGroupArray->Item(i);
1491 wxString s;
1492 s.Printf("Group%d", i + 1);
1493 s.Prepend("/Groups/");
1494 SetPath(s);
1495
1496 Write("GroupName", pGroup->m_group_name);
1497 Write("GroupItemCount", (int)pGroup->m_element_array.size());
1498
1499 for (unsigned int j = 0; j < pGroup->m_element_array.size(); j++) {
1500 wxString sg;
1501 sg.Printf("Group%d/Item%d", i + 1, j);
1502 sg.Prepend("/Groups/");
1503 SetPath(sg);
1504 Write("IncludeItem", pGroup->m_element_array[j].m_element_name);
1505
1506 wxString t;
1507 wxArrayString u = pGroup->m_element_array[j].m_missing_name_array;
1508 if (u.GetCount()) {
1509 for (unsigned int k = 0; k < u.GetCount(); k++) {
1510 t += u[k];
1511 t += ";";
1512 }
1513 Write("ExcludeItems", t);
1514 }
1515 }
1516 }
1517}
1518
1519void MyConfig::DestroyConfigGroups() {
1520 DeleteGroup("/Groups"); // zap
1521}
1522
1523void MyConfig::LoadConfigGroups(ChartGroupArray *pGroupArray) {
1524 SetPath("/Groups");
1525 unsigned int group_count;
1526 Read("GroupCount", (int *)&group_count, 0);
1527
1528 for (unsigned int i = 0; i < group_count; i++) {
1529 ChartGroup *pGroup = new ChartGroup;
1530 wxString s;
1531 s.Printf("Group%d", i + 1);
1532 s.Prepend("/Groups/");
1533 SetPath(s);
1534
1535 wxString t;
1536 Read("GroupName", &t);
1537 pGroup->m_group_name = t;
1538
1539 unsigned int item_count;
1540 Read("GroupItemCount", (int *)&item_count);
1541 for (unsigned int j = 0; j < item_count; j++) {
1542 wxString sg;
1543 sg.Printf("Group%d/Item%d", i + 1, j);
1544 sg.Prepend("/Groups/");
1545 SetPath(sg);
1546
1547 wxString v;
1548 Read("IncludeItem", &v);
1549
1550 ChartGroupElement pelement{v};
1551 wxString u;
1552 if (Read("ExcludeItems", &u)) {
1553 if (!u.IsEmpty()) {
1554 wxStringTokenizer tk(u, ";");
1555 while (tk.HasMoreTokens()) {
1556 wxString token = tk.GetNextToken();
1557 pelement.m_missing_name_array.Add(token);
1558 }
1559 }
1560 }
1561 pGroup->m_element_array.push_back(std::move(pelement));
1562 }
1563 pGroupArray->Add(pGroup);
1564 }
1565}
1566
1567void MyConfig::LoadCanvasConfigs(bool bApplyAsTemplate) {
1568 wxString s;
1569 canvasConfig *pcc;
1570 auto &config_array = ConfigMgr::Get().GetCanvasConfigArray();
1571
1572 SetPath("/Canvas");
1573
1574 // If the canvas config has never been set/persisted, use the global settings
1575 if (!HasEntry("CanvasConfig")) {
1576 pcc = new canvasConfig(0);
1577 pcc->LoadFromLegacyConfig(this);
1578 config_array.Add(pcc);
1579
1580 return;
1581 }
1582
1583 Read("CanvasConfig", (int *)&g_canvasConfig, 0);
1584
1585 // Do not recreate canvasConfigs when applying config dynamically
1586 if (config_array.GetCount() == 0) { // This is initial load from startup
1587 s.Printf("/Canvas/CanvasConfig%d", 1);
1588 SetPath(s);
1589 canvasConfig *pcca = new canvasConfig(0);
1590 LoadConfigCanvas(pcca, bApplyAsTemplate);
1591 config_array.Add(pcca);
1592
1593 s.Printf("/Canvas/CanvasConfig%d", 2);
1594 SetPath(s);
1595 pcca = new canvasConfig(1);
1596 LoadConfigCanvas(pcca, bApplyAsTemplate);
1597 config_array.Add(pcca);
1598 } else { // This is a dynamic (i.e. Template) load
1599 canvasConfig *pcca = config_array[0];
1600 s.Printf("/Canvas/CanvasConfig%d", 1);
1601 SetPath(s);
1602 LoadConfigCanvas(pcca, bApplyAsTemplate);
1603
1604 if (config_array.GetCount() > 1) {
1605 canvasConfig *pcca = config_array[1];
1606 s.Printf("/Canvas/CanvasConfig%d", 2);
1607 SetPath(s);
1608 LoadConfigCanvas(pcca, bApplyAsTemplate);
1609 } else {
1610 s.Printf("/Canvas/CanvasConfig%d", 2);
1611 SetPath(s);
1612 pcca = new canvasConfig(1);
1613 LoadConfigCanvas(pcca, bApplyAsTemplate);
1614 config_array.Add(pcca);
1615 }
1616 }
1617}
1618
1619void MyConfig::LoadConfigCanvas(canvasConfig *cConfig, bool bApplyAsTemplate) {
1620 wxString st;
1621 double st_lat, st_lon;
1622
1623 if (!bApplyAsTemplate) {
1624 // Reasonable starting point
1625 cConfig->iLat = START_LAT; // display viewpoint
1626 cConfig->iLon = START_LON;
1627
1628 if (Read("canvasVPLatLon", &st)) {
1629 sscanf(st.mb_str(wxConvUTF8), "%lf,%lf", &st_lat, &st_lon);
1630
1631 // Sanity check the lat/lon...both have to be reasonable.
1632 if (fabs(st_lon) < 360.) {
1633 while (st_lon < -180.) st_lon += 360.;
1634
1635 while (st_lon > 180.) st_lon -= 360.;
1636
1637 cConfig->iLon = st_lon;
1638 }
1639
1640 if (fabs(st_lat) < 90.0) cConfig->iLat = st_lat;
1641 }
1642
1643 cConfig->iScale = .0003; // decent initial value
1644 cConfig->iRotation = 0;
1645
1646 double st_view_scale;
1647 if (Read(wxString("canvasVPScale"), &st)) {
1648 sscanf(st.mb_str(wxConvUTF8), "%lf", &st_view_scale);
1649 // Sanity check the scale
1650 st_view_scale = fmax(st_view_scale, .001 / 32);
1651 st_view_scale = fmin(st_view_scale, 4);
1652 cConfig->iScale = st_view_scale;
1653 }
1654
1655 double st_rotation;
1656 if (Read(wxString("canvasVPRotation"), &st)) {
1657 sscanf(st.mb_str(wxConvUTF8), "%lf", &st_rotation);
1658 // Sanity check the rotation
1659 st_rotation = fmin(st_rotation, 360);
1660 st_rotation = fmax(st_rotation, 0);
1661 cConfig->iRotation = st_rotation * PI / 180.;
1662 }
1663
1664 Read("canvasInitialdBIndex", &cConfig->DBindex, 0);
1665 Read("canvasbFollow", &cConfig->bFollow, 0);
1666
1667 Read("canvasCourseUp", &cConfig->bCourseUp, 0);
1668 Read("canvasHeadUp", &cConfig->bHeadUp, 0);
1669 Read("canvasLookahead", &cConfig->bLookahead, 0);
1670 }
1671
1672 Read("ActiveChartGroup", &cConfig->GroupID, 0);
1673
1674 // Special check for group selection when applied as template
1675 if (cConfig->GroupID && bApplyAsTemplate) {
1676 if (cConfig->GroupID > (int)g_pGroupArray->GetCount()) cConfig->GroupID = 0;
1677 }
1678
1679 Read("canvasShowTides", &cConfig->bShowTides, 0);
1680 Read("canvasShowCurrents", &cConfig->bShowCurrents, 0);
1681
1682 Read("canvasQuilt", &cConfig->bQuilt, 1);
1683 Read("canvasShowGrid", &cConfig->bShowGrid, 0);
1684 Read("canvasShowOutlines", &cConfig->bShowOutlines, 0);
1685 Read("canvasShowDepthUnits", &cConfig->bShowDepthUnits, 0);
1686
1687 Read("canvasShowAIS", &cConfig->bShowAIS, 1);
1688 Read("canvasAttenAIS", &cConfig->bAttenAIS, 0);
1689
1690 // ENC options
1691 Read("canvasShowENCText", &cConfig->bShowENCText, 1);
1692 Read("canvasENCDisplayCategory", &cConfig->nENCDisplayCategory, STANDARD);
1693 Read("canvasENCShowDepths", &cConfig->bShowENCDepths, 1);
1694 Read("canvasENCShowBuoyLabels", &cConfig->bShowENCBuoyLabels, 1);
1695 Read("canvasENCShowLightDescriptions", &cConfig->bShowENCLightDescriptions,
1696 1);
1697 Read("canvasENCShowLights", &cConfig->bShowENCLights, 1);
1698 Read("canvasENCShowVisibleSectorLights",
1699 &cConfig->bShowENCVisibleSectorLights, 0);
1700 Read("canvasENCShowAnchorInfo", &cConfig->bShowENCAnchorInfo, 0);
1701 Read("canvasENCShowDataQuality", &cConfig->bShowENCDataQuality, 0);
1702
1703 int sx, sy;
1704 Read("canvasSizeX", &sx, 0);
1705 Read("canvasSizeY", &sy, 0);
1706 cConfig->canvasSize = wxSize(sx, sy);
1707}
1708
1709void MyConfig::SaveCanvasConfigs() {
1710 auto &config_array = ConfigMgr::Get().GetCanvasConfigArray();
1711
1712 SetPath("/Canvas");
1713 Write("CanvasConfig", (int)g_canvasConfig);
1714
1715 wxString s;
1716 canvasConfig *pcc;
1717
1718 switch (g_canvasConfig) {
1719 case 0:
1720 default:
1721
1722 s.Printf("/Canvas/CanvasConfig%d", 1);
1723 SetPath(s);
1724
1725 if (config_array.GetCount() > 0) {
1726 pcc = config_array.Item(0);
1727 if (pcc) {
1728 SaveConfigCanvas(pcc);
1729 }
1730 }
1731 break;
1732
1733 case 1:
1734
1735 if (config_array.GetCount() > 1) {
1736 s.Printf("/Canvas/CanvasConfig%d", 1);
1737 SetPath(s);
1738 pcc = config_array.Item(0);
1739 if (pcc) {
1740 SaveConfigCanvas(pcc);
1741 }
1742
1743 s.Printf("/Canvas/CanvasConfig%d", 2);
1744 SetPath(s);
1745 pcc = config_array.Item(1);
1746 if (pcc) {
1747 SaveConfigCanvas(pcc);
1748 }
1749 }
1750 break;
1751 }
1752}
1753
1754void MyConfig::SaveConfigCanvas(canvasConfig *cConfig) {
1755 wxString st1;
1756
1757 if (cConfig->canvas) {
1758 ViewPort vp = cConfig->canvas->GetVP();
1759
1760 if (vp.IsValid()) {
1761 st1.Printf("%10.4f,%10.4f", vp.clat, vp.clon);
1762 Write("canvasVPLatLon", st1);
1763 st1.Printf("%g", vp.view_scale_ppm);
1764 Write("canvasVPScale", st1);
1765 st1.Printf("%i", ((int)(vp.rotation * 180 / PI)) % 360);
1766 Write("canvasVPRotation", st1);
1767 }
1768
1769 int restore_dbindex = 0;
1770 ChartStack *pcs = cConfig->canvas->GetpCurrentStack();
1771 if (pcs) restore_dbindex = pcs->GetCurrentEntrydbIndex();
1772 if (cConfig->canvas->GetQuiltMode())
1773 restore_dbindex = cConfig->canvas->GetQuiltReferenceChartIndex();
1774 Write("canvasInitialdBIndex", restore_dbindex);
1775
1776 Write("canvasbFollow", cConfig->canvas->m_bFollow);
1777 Write("ActiveChartGroup", cConfig->canvas->m_groupIndex);
1778
1779 Write("canvasQuilt", cConfig->canvas->GetQuiltMode());
1780 Write("canvasShowGrid", cConfig->canvas->GetShowGrid());
1781 Write("canvasShowOutlines", cConfig->canvas->GetShowOutlines());
1782 Write("canvasShowDepthUnits", cConfig->canvas->GetShowDepthUnits());
1783
1784 Write("canvasShowAIS", cConfig->canvas->GetShowAIS());
1785 Write("canvasAttenAIS", cConfig->canvas->GetAttenAIS());
1786
1787 Write("canvasShowTides", cConfig->canvas->GetbShowTide());
1788 Write("canvasShowCurrents", cConfig->canvas->GetbShowCurrent());
1789
1790 // ENC options
1791 Write("canvasShowENCText", cConfig->canvas->GetShowENCText());
1792 Write("canvasENCDisplayCategory", cConfig->canvas->GetENCDisplayCategory());
1793 Write("canvasENCShowDepths", cConfig->canvas->GetShowENCDepth());
1794 Write("canvasENCShowBuoyLabels", cConfig->canvas->GetShowENCBuoyLabels());
1795 Write("canvasENCShowLightDescriptions",
1796 cConfig->canvas->GetShowENCLightDesc());
1797 Write("canvasENCShowLights", cConfig->canvas->GetShowENCLights());
1798 Write("canvasENCShowVisibleSectorLights",
1799 cConfig->canvas->GetShowVisibleSectors());
1800 Write("canvasENCShowAnchorInfo", cConfig->canvas->GetShowENCAnchor());
1801 Write("canvasENCShowDataQuality", cConfig->canvas->GetShowENCDataQual());
1802 Write("canvasCourseUp", cConfig->canvas->GetUpMode() == COURSE_UP_MODE);
1803 Write("canvasHeadUp", cConfig->canvas->GetUpMode() == HEAD_UP_MODE);
1804 Write("canvasLookahead", cConfig->canvas->GetLookahead());
1805
1806 int width = cConfig->canvas->GetSize().x;
1807 // if(cConfig->canvas->IsPrimaryCanvas()){
1808 // width = wxMax(width, gFrame->GetClientSize().x / 10);
1809 // }
1810 // else{
1811 // width = wxMin(width, gFrame->GetClientSize().x * 9 / 10);
1812 // }
1813
1814 Write("canvasSizeX", width);
1815 Write("canvasSizeY", cConfig->canvas->GetSize().y);
1816 }
1817}
1818
1819void MyConfig::UpdateSettings() {
1820 // Temporarily suppress logging of trivial non-fatal wxLogSysError() messages
1821 // provoked by Android security...
1822#ifdef __ANDROID__
1823 wxLogNull logNo;
1824#endif
1825
1826 // Global options and settings
1827 SetPath("/Settings");
1828
1829 Write("LastAppliedTemplate", g_lastAppliedTemplateGUID);
1830 Write("CompatOS", g_compatOS);
1831 Write("CompatOsVersion", g_compatOsVersion);
1832 Write("ConfigVersionString", g_config_version_string);
1833 if (wxIsEmpty(g_CmdSoundString)) g_CmdSoundString = wxString(OCPN_SOUND_CMD);
1834 Write("CmdSoundString", g_CmdSoundString);
1835 Write("NavMessageShown", n_NavMessageShown);
1836 Write("InlandEcdis", g_bInlandEcdis);
1837
1838 Write("AndroidVersionCode", g_AndroidVersionCode);
1839
1840 Write("UIexpert", g_bUIexpert);
1841 Write("SpaceDropMark", g_bSpaceDropMark);
1842 // Write( "UIStyle", g_StyleManager->GetStyleNextInvocation() );
1843 // //Not desired for O5 MUI
1844
1845 Write("ShowStatusBar", g_bShowStatusBar);
1846#ifndef __WXOSX__
1847 Write("ShowMenuBar", g_bShowMenuBar);
1848#endif
1849 Write("DefaultFontSize", g_default_font_size);
1850 Write("DefaultFontFacename", g_default_font_facename);
1851
1852 Write("Fullscreen", g_bFullscreen);
1853 Write("ShowCompassWindow", g_bShowCompassWin);
1854 Write("SetSystemTime", s_bSetSystemTime);
1855 Write("ShowGrid", g_bDisplayGrid);
1856 Write("PlayShipsBells", g_bPlayShipsBells);
1857 Write("SoundDeviceIndex", g_iSoundDeviceIndex);
1858 Write("FullscreenToolbar", g_bFullscreenToolbar);
1859 Write("TransparentToolbar", g_bTransparentToolbar);
1860 Write("PermanentMOBIcon", g_bPermanentMOBIcon);
1861 Write("ShowLayers", g_bShowLayers);
1862 Write("AutoAnchorDrop", g_bAutoAnchorMark);
1863 Write("ShowChartOutlines", g_bShowOutlines);
1864 Write("ShowActiveRouteTotal", g_bShowRouteTotal);
1865 Write("ShowActiveRouteHighway", g_bShowActiveRouteHighway);
1866 Write("SDMMFormat", g_iSDMMFormat);
1867 Write("MostRecentGPSUploadConnection", g_uploadConnection);
1868 Write("ShowChartBar", g_bShowChartBar);
1869
1870 Write("GUIScaleFactor", g_GUIScaleFactor);
1871 Write("ChartObjectScaleFactor", g_ChartScaleFactor);
1872 Write("ShipScaleFactor", g_ShipScaleFactor);
1873 Write("ENCSoundingScaleFactor", g_ENCSoundingScaleFactor);
1874 Write("ENCTextScaleFactor", g_ENCTextScaleFactor);
1875 Write("ObjQueryAppendFilesExt", g_ObjQFileExt);
1876
1877 // Plugin catalog persistent values.
1878 Write("CatalogCustomURL", g_catalog_custom_url);
1879 Write("CatalogChannel", g_catalog_channel);
1880
1881 Write("NetmaskBits", g_netmask_bits);
1882 Write("FilterNMEA_Avg", g_bfilter_cogsog);
1883 Write("FilterNMEA_Sec", g_COGFilterSec);
1884
1885 Write("TrackContinuous", g_btrackContinuous);
1886
1887 Write("ShowTrue", g_bShowTrue);
1888 Write("ShowMag", g_bShowMag);
1889 Write("UserMagVariation", wxString::Format("%.2f", g_UserVar));
1890
1891 Write("CM93DetailFactor", g_cm93_zoom_factor);
1892 Write("CM93DetailZoomPosX", g_detailslider_dialog_x);
1893 Write("CM93DetailZoomPosY", g_detailslider_dialog_y);
1894 Write("ShowCM93DetailSlider", g_bShowDetailSlider);
1895
1896 Write("SkewToNorthUp", g_bskew_comp);
1897 if (!g_bdisable_opengl) { // Only modify the saved value if OpenGL is not
1898 // force-disabled from the command line
1899 Write("OpenGL", g_bopengl);
1900 }
1901 Write("SoftwareGL", g_bSoftwareGL);
1902
1903 Write("ZoomDetailFactor", g_chart_zoom_modifier_raster);
1904 Write("ZoomDetailFactorVector", g_chart_zoom_modifier_vector);
1905
1906 Write("FogOnOverzoom", g_fog_overzoom);
1907 Write("OverzoomVectorScale", g_oz_vector_scale);
1908 Write("OverzoomEmphasisBase", g_overzoom_emphasis_base);
1909 Write("PlusMinusZoomFactor", g_plus_minus_zoom_factor);
1910 Write("MouseZoomSensitivity",
1911 MouseZoom::ui_to_config(g_mouse_zoom_sensitivity_ui));
1912 Write("ShowMUIZoomButtons", g_bShowMuiZoomButtons);
1913
1914#ifdef ocpnUSE_GL
1915 /* opengl options */
1916 Write("UseAcceleratedPanning", g_GLOptions.m_bUseAcceleratedPanning);
1917
1918 Write("GPUTextureCompression", g_GLOptions.m_bTextureCompression);
1919 Write("GPUTextureCompressionCaching",
1920 g_GLOptions.m_bTextureCompressionCaching);
1921 Write("GPUTextureDimension", g_GLOptions.m_iTextureDimension);
1922 Write("GPUTextureMemSize", g_GLOptions.m_iTextureMemorySize);
1923 Write("PolygonSmoothing", g_GLOptions.m_GLPolygonSmoothing);
1924 Write("LineSmoothing", g_GLOptions.m_GLLineSmoothing);
1925#endif
1926 Write("SmoothPanZoom", g_bsmoothpanzoom);
1927
1928 Write("CourseUpMode", g_bCourseUp);
1929 if (!g_bInlandEcdis) Write("LookAheadMode", g_bLookAhead);
1930 Write("TenHzUpdate", g_btenhertz);
1931
1932 Write("COGUPAvgSeconds", g_COGAvgSec);
1933 Write("UseMagAPB", g_bMagneticAPB);
1934
1935 Write("OwnshipCOGPredictorMinutes", g_ownship_predictor_minutes);
1936 Write("OwnshipCOGPredictorStyle", g_cog_predictor_style);
1937 Write("OwnshipCOGPredictorColor", g_cog_predictor_color);
1938 Write("OwnshipCOGPredictorEndmarker", g_cog_predictor_endmarker);
1939 Write("OwnshipCOGPredictorWidth", g_cog_predictor_width);
1940 Write("OwnshipHDTPredictorStyle", g_ownship_HDTpredictor_style);
1941 Write("OwnshipHDTPredictorColor", g_ownship_HDTpredictor_color);
1942 Write("OwnshipHDTPredictorEndmarker", g_ownship_HDTpredictor_endmarker);
1943 Write("OwnShipMMSINumber", g_OwnShipmmsi);
1944 Write("OwnshipHDTPredictorWidth", g_ownship_HDTpredictor_width);
1945 Write("OwnshipHDTPredictorMiles", g_ownship_HDTpredictor_miles);
1946
1947 Write("OwnShipIconType", g_OwnShipIconType);
1948 Write("OwnShipLength", g_n_ownship_length_meters);
1949 Write("OwnShipWidth", g_n_ownship_beam_meters);
1950 Write("OwnShipGPSOffsetX", g_n_gps_antenna_offset_x);
1951 Write("OwnShipGPSOffsetY", g_n_gps_antenna_offset_y);
1952 Write("OwnShipMinSize", g_n_ownship_min_mm);
1953 Write("OwnShipSogCogCalc", g_own_ship_sog_cog_calc);
1954 Write("OwnShipSogCogCalcDampSec", g_own_ship_sog_cog_calc_damp_sec);
1955 Write("ShowDirectRouteLine", g_bShowShipToActive);
1956 Write("DirectRouteLineStyle", g_shipToActiveStyle);
1957 Write("DirectRouteLineColor", g_shipToActiveColor);
1958
1959 wxString racr;
1960 // racr.Printf( "%g", g_n_arrival_circle_radius );
1961 // Write( "RouteArrivalCircleRadius", racr );
1962 Write("RouteArrivalCircleRadius",
1963 wxString::Format("%.2f", g_n_arrival_circle_radius));
1964
1965 Write("ChartQuilting", g_bQuiltEnable);
1966
1967 Write("PreserveScaleOnX", g_bPreserveScaleOnX);
1968
1969 Write("StartWithTrackActive", g_bTrackCarryOver);
1970 Write("AutomaticDailyTracks", g_bTrackDaily);
1971 Write("TrackRotateAt", g_track_rotate_time);
1972 Write("TrackRotateTimeType", g_track_rotate_time_type);
1973 Write("HighlightTracks", g_bHighliteTracks);
1974
1975 Write("DateTimeFormat", g_datetime_format);
1976 Write("InitialStackIndex", g_restore_stackindex);
1977 Write("InitialdBIndex", g_restore_dbindex);
1978
1979 Write("NMEAAPBPrecision", g_NMEAAPBPrecision);
1980
1981 Write("TalkerIdText", g_TalkerIdText);
1982 Write("ShowTrackPointTime", g_bShowTrackPointTime);
1983
1984 Write("AnchorWatch1GUID", g_AW1GUID);
1985 Write("AnchorWatch2GUID", g_AW2GUID);
1986
1987 Write("ToolbarX", g_maintoolbar_x);
1988 Write("ToolbarY", g_maintoolbar_y);
1989 // Write( "ToolbarOrient", g_maintoolbar_orient );
1990
1991 Write("iENCToolbarX", g_iENCToolbarPosX);
1992 Write("iENCToolbarY", g_iENCToolbarPosY);
1993
1994 if (!g_bInlandEcdis) {
1995 Write("GlobalToolbarConfig", g_toolbarConfig);
1996 Write("DistanceFormat", g_iDistanceFormat);
1997 Write("SpeedFormat", g_iSpeedFormat);
1998 Write("WindSpeedFormat", g_iWindSpeedFormat);
1999 Write("ShowDepthUnits", g_bShowDepthUnits);
2000 Write("TemperatureFormat", g_iTempFormat);
2001 Write("HeightFormat", g_iHeightFormat);
2002 }
2003 Write("GPSIdent", g_GPS_Ident);
2004 Write("ActiveRoute", g_active_route);
2005 Write("PersistActiveRoute", g_persist_active_route);
2006 Write("AlwaysSendRmbRmc", g_always_send_rmb_rmc);
2007
2008 Write("UseGarminHostUpload", g_bGarminHostUpload);
2009
2010 Write("MobileTouch", g_btouch);
2011 Write("ResponsiveGraphics", g_bresponsive);
2012 Write("EnableRolloverBlock", g_bRollover);
2013
2014 Write("AutoHideToolbar", g_bAutoHideToolbar);
2015 Write("AutoHideToolbarSecs", g_nAutoHideToolbar);
2016
2017 wxString st0;
2018 for (const auto &mm : g_config_display_size_mm) {
2019 st0.Append(wxString::Format("%zu,", mm));
2020 }
2021 st0.RemoveLast(); // Strip last comma
2022 Write("DisplaySizeMM", st0);
2023 Write("DisplaySizeManual", g_config_display_size_manual);
2024
2025 Write("SelectionRadiusMM", g_selection_radius_mm);
2026 Write("SelectionRadiusTouchMM", g_selection_radius_touch_mm);
2027
2028 st0.Printf("%g", g_PlanSpeed);
2029 Write("PlanSpeed", st0);
2030
2031 if (g_bLayersLoaded) {
2032 wxString vis, invis, visnames, invisnames;
2033 LayerList::iterator it;
2034 int index = 0;
2035 for (it = (*pLayerList).begin(); it != (*pLayerList).end(); ++it, ++index) {
2036 Layer *lay = (Layer *)(*it);
2037 if (lay->IsVisibleOnChart())
2038 vis += (lay->m_LayerName) + ";";
2039 else
2040 invis += (lay->m_LayerName) + ";";
2041
2042 if (lay->HasVisibleNames() == wxCHK_CHECKED) {
2043 visnames += (lay->m_LayerName) + ";";
2044 } else if (lay->HasVisibleNames() == wxCHK_UNCHECKED) {
2045 invisnames += (lay->m_LayerName) + ";";
2046 }
2047 }
2048 Write("VisibleLayers", vis);
2049 Write("InvisibleLayers", invis);
2050 Write("VisNameInLayers", visnames);
2051 Write("InvisNameInLayers", invisnames);
2052 }
2053 Write("Locale", g_locale);
2054 Write("LocaleOverride", g_localeOverride);
2055
2056 Write("KeepNavobjBackups", g_navobjbackups);
2057 Write("LegacyInputCOMPortFilterBehaviour", g_b_legacy_input_filter_behaviour);
2058 Write("AdvanceRouteWaypointOnArrivalOnly",
2059 g_bAdvanceRouteWaypointOnArrivalOnly);
2060 Write("EnableRootMenuDebug", g_enable_root_menu_debug);
2061
2062 // LIVE ETA OPTION
2063 Write("LiveETA", g_bShowLiveETA);
2064 Write("DefaultBoatSpeed", g_defaultBoatSpeed);
2065
2066 // S57 Object Filter Settings
2067
2068 SetPath("/Settings/ObjectFilter");
2069
2070 if (ps52plib) {
2071 for (unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount();
2072 iPtr++) {
2073 OBJLElement *pOLE = (OBJLElement *)(ps52plib->pOBJLArray->Item(iPtr));
2074
2075 wxString st1("viz");
2076 char name[7];
2077 strncpy(name, pOLE->OBJLName, 6);
2078 name[6] = 0;
2079 st1.Append(wxString(name, wxConvUTF8));
2080 Write(st1, pOLE->nViz);
2081 }
2082 }
2083
2084 // Global State
2085
2086 SetPath("/Settings/GlobalState");
2087
2088 wxString st1;
2089
2090 // if( cc1 ) {
2091 // ViewPort vp = cc1->GetVP();
2092 //
2093 // if( vp.IsValid() ) {
2094 // st1.Printf( "%10.4f,%10.4f", vp.clat, vp.clon );
2095 // Write( "VPLatLon", st1 );
2096 // st1.Printf( "%g", vp.view_scale_ppm );
2097 // Write( "VPScale", st1 );
2098 // st1.Printf( "%i", ((int)(vp.rotation * 180 / PI)) % 360
2099 // ); Write( "VPRotation", st1 );
2100 // }
2101 // }
2102
2103 st1.Printf("%10.4f, %10.4f", gLat, gLon);
2104 Write("OwnShipLatLon", st1);
2105
2106 // Various Options
2107 SetPath("/Settings/GlobalState");
2108 if (!g_bInlandEcdis) Write("nColorScheme", (int)gFrame->GetColorScheme());
2109
2110 Write("FrameWinX", g_nframewin_x);
2111 Write("FrameWinY", g_nframewin_y);
2112 Write("FrameWinPosX", g_nframewin_posx);
2113 Write("FrameWinPosY", g_nframewin_posy);
2114 Write("FrameMax", g_bframemax);
2115
2116 Write("ClientPosX", g_lastClientRectx);
2117 Write("ClientPosY", g_lastClientRecty);
2118 Write("ClientSzX", g_lastClientRectw);
2119 Write("ClientSzY", g_lastClientRecth);
2120
2121 Write("S52_DEPTH_UNIT_SHOW", g_nDepthUnitDisplay);
2122
2123 Write("RoutePropSizeX", g_route_prop_sx);
2124 Write("RoutePropSizeY", g_route_prop_sy);
2125 Write("RoutePropPosX", g_route_prop_x);
2126 Write("RoutePropPosY", g_route_prop_y);
2127
2128 // Sounds
2129 SetPath("/Settings/Audio");
2130 Write("AISAlertSoundFile", g_AIS_sound_file);
2131 Write("DSCAlertSoundFile", g_DSC_sound_file);
2132 Write("SARTAlertSoundFile", g_SART_sound_file);
2133 Write("AnchorAlarmSoundFile", g_anchorwatch_sound_file);
2134
2135 Write("bAIS_GCPA_AlertAudio", g_bAIS_GCPA_Alert_Audio);
2136 Write("bAIS_SART_AlertAudio", g_bAIS_SART_Alert_Audio);
2137 Write("bAIS_DSC_AlertAudio", g_bAIS_DSC_Alert_Audio);
2138 Write("bAnchorAlertAudio", g_bAnchor_Alert_Audio);
2139
2140 // AIS
2141 SetPath("/Settings/AIS");
2142
2143 Write("bNoCPAMax", g_bCPAMax);
2144 Write("NoCPAMaxNMi", g_CPAMax_NM);
2145 Write("bCPAWarn", g_bCPAWarn);
2146 Write("CPAWarnNMi", g_CPAWarn_NM);
2147 Write("bTCPAMax", g_bTCPA_Max);
2148 Write("TCPAMaxMinutes", g_TCPA_Max);
2149 Write("bMarkLostTargets", g_bMarkLost);
2150 Write("MarkLost_Minutes", g_MarkLost_Mins);
2151 Write("bRemoveLostTargets", g_bRemoveLost);
2152 Write("RemoveLost_Minutes", g_RemoveLost_Mins);
2153 Write("bShowCOGArrows", g_bShowCOG);
2154 Write("bSyncCogPredictors", g_bSyncCogPredictors);
2155 Write("CogArrowMinutes", g_ShowCOG_Mins);
2156 Write("bShowTargetTracks", g_bAISShowTracks);
2157 Write("TargetTracksMinutes", g_AISShowTracks_Mins);
2158
2159 Write("bHideMooredTargets", g_bHideMoored);
2160 Write("MooredTargetMaxSpeedKnots", g_ShowMoored_Kts);
2161
2162 Write("bAISAlertDialog", g_bAIS_CPA_Alert);
2163 Write("bAISAlertAudio", g_bAIS_CPA_Alert_Audio);
2164
2165 Write("AISAlertAudioFile", g_sAIS_Alert_Sound_File);
2166 Write("bAISAlertSuppressMoored", g_bAIS_CPA_Alert_Suppress_Moored);
2167 Write("bShowAreaNotices", g_bShowAreaNotices);
2168 Write("bDrawAISSize", g_bDrawAISSize);
2169 Write("bDrawAISRealtime", g_bDrawAISRealtime);
2170 Write("AISRealtimeMinSpeedKnots", g_AIS_RealtPred_Kts);
2171 Write("bShowAISName", g_bShowAISName);
2172 Write("ShowAISTargetNameScale", g_Show_Target_Name_Scale);
2173 Write("bWplIsAprsPositionReport", g_bWplUsePosition);
2174 Write("WplSelAction", g_WplAction);
2175 Write("AISCOGPredictorWidth", g_ais_cog_predictor_width);
2176 Write("bShowScaledTargets", g_bAllowShowScaled);
2177 Write("AISScaledNumber", g_ShowScaled_Num);
2178 Write("AISScaledNumberWeightSOG", g_ScaledNumWeightSOG);
2179 Write("AISScaledNumberWeightCPA", g_ScaledNumWeightCPA);
2180 Write("AISScaledNumberWeightTCPA", g_ScaledNumWeightTCPA);
2181 Write("AISScaledNumberWeightRange", g_ScaledNumWeightRange);
2182 Write("AISScaledNumberWeightSizeOfTarget", g_ScaledNumWeightSizeOfT);
2183 Write("AISScaledSizeMinimal", g_ScaledSizeMinimal);
2184 Write("AISShowScaled", g_bShowScaled);
2185
2186 Write("AlertDialogSizeX", g_ais_alert_dialog_sx);
2187 Write("AlertDialogSizeY", g_ais_alert_dialog_sy);
2188 Write("AlertDialogPosX", g_ais_alert_dialog_x);
2189 Write("AlertDialogPosY", g_ais_alert_dialog_y);
2190 Write("QueryDialogPosX", g_ais_query_dialog_x);
2191 Write("QueryDialogPosY", g_ais_query_dialog_y);
2192 Write("AISTargetListPerspective", g_AisTargetList_perspective);
2193 Write("AISTargetListRange", g_AisTargetList_range);
2194 Write("AISTargetListSortColumn", g_AisTargetList_sortColumn);
2195 Write("bAISTargetListSortReverse", g_bAisTargetList_sortReverse);
2196 Write("AISTargetListColumnSpec", g_AisTargetList_column_spec);
2197 Write("AISTargetListColumnOrder", g_AisTargetList_column_order);
2198
2199 Write("S57QueryDialogSizeX", g_S57_dialog_sx);
2200 Write("S57QueryDialogSizeY", g_S57_dialog_sy);
2201 Write("S57QueryExtraDialogSizeX", g_S57_extradialog_sx);
2202 Write("S57QueryExtraDialogSizeY", g_S57_extradialog_sy);
2203
2204 Write("bAISRolloverShowClass", g_bAISRolloverShowClass);
2205 Write("bAISRolloverShowCOG", g_bAISRolloverShowCOG);
2206 Write("bAISRolloverShowCPA", g_bAISRolloverShowCPA);
2207
2208 Write("bAISAlertAckTimeout", g_bAIS_ACK_Timeout);
2209 Write("AlertAckTimeoutMinutes", g_AckTimeout_Mins);
2210
2211 SetPath("/Settings/GlobalState");
2212 if (ps52plib) {
2213 Write("bShowS57Text", ps52plib->GetShowS57Text());
2214 Write("bShowS57ImportantTextOnly", ps52plib->GetShowS57ImportantTextOnly());
2215 if (!g_bInlandEcdis)
2216 Write("nDisplayCategory", (long)ps52plib->GetDisplayCategory());
2217 Write("nSymbolStyle", (int)ps52plib->m_nSymbolStyle);
2218 Write("nBoundaryStyle", (int)ps52plib->m_nBoundaryStyle);
2219
2220 Write("bShowSoundg", ps52plib->m_bShowSoundg);
2221 Write("bShowMeta", ps52plib->m_bShowMeta);
2222 Write("bUseSCAMIN", ps52plib->m_bUseSCAMIN);
2223 Write("bUseSUPER_SCAMIN", ps52plib->m_bUseSUPER_SCAMIN);
2224 Write("bShowAtonText", ps52plib->m_bShowAtonText);
2225 Write("bShowLightDescription", ps52plib->m_bShowLdisText);
2226 Write("bExtendLightSectors", ps52plib->m_bExtendLightSectors);
2227 Write("bDeClutterText", ps52plib->m_bDeClutterText);
2228 Write("bShowNationalText", ps52plib->m_bShowNationalTexts);
2229
2230 Write("S52_MAR_SAFETY_CONTOUR",
2231 S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR));
2232 Write("S52_MAR_SHALLOW_CONTOUR",
2233 S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR));
2234 Write("S52_MAR_DEEP_CONTOUR", S52_getMarinerParam(S52_MAR_DEEP_CONTOUR));
2235 Write("S52_MAR_TWO_SHADES", S52_getMarinerParam(S52_MAR_TWO_SHADES));
2236 Write("S52_DEPTH_UNIT_SHOW", ps52plib->m_nDepthUnitDisplay);
2237 Write("ENCSoundingScaleFactor", g_ENCSoundingScaleFactor);
2238 Write("ENCTextScaleFactor", g_ENCTextScaleFactor);
2239 }
2240 SetPath("/Directories");
2241 Write("S57DataLocation", "");
2242 // Write( "SENCFileLocation", "" );
2243
2244 SetPath("/Directories");
2245 Write("InitChartDir", *pInit_Chart_Dir);
2246 Write("GPXIODir", g_gpx_path);
2247 Write("TCDataDir", g_TCData_Dir);
2248 Write("BasemapDir", g_Platform->NormalizePath(gWorldMapLocation));
2249 Write("BaseShapefileDir", g_Platform->NormalizePath(gWorldShapefileLocation));
2250 Write("pluginInstallDir", g_Platform->NormalizePath(g_winPluginDir));
2251
2252 SetPath("/Settings/NMEADataSource");
2253 wxString connectionconfigs;
2254 for (size_t i = 0; i < TheConnectionParams().size(); i++) {
2255 if (i > 0) connectionconfigs.Append("|");
2256 connectionconfigs.Append(TheConnectionParams()[i]->Serialize());
2257 }
2258 Write("DataConnections", connectionconfigs);
2259
2260 // Fonts
2261
2262 // Store the persistent Auxiliary Font descriptor Keys
2263 SetPath("/Settings/AuxFontKeys");
2264
2265 wxArrayString keyArray = FontMgr::Get().GetAuxKeyArray();
2266 for (unsigned int i = 0; i < keyArray.GetCount(); i++) {
2267 wxString key;
2268 key.Printf("Key%i", i);
2269 wxString keyval = keyArray[i];
2270 Write(key, keyval);
2271 }
2272
2273 wxString font_path;
2274#ifdef __WXX11__
2275 font_path = ("/Settings/X11Fonts");
2276#endif
2277
2278#ifdef __WXGTK__
2279 font_path = ("/Settings/GTKFonts");
2280#endif
2281
2282#ifdef __WXMSW__
2283 font_path = ("/Settings/MSWFonts");
2284#endif
2285
2286#ifdef __WXMAC__
2287 font_path = ("/Settings/MacFonts");
2288#endif
2289
2290#ifdef __WXQT__
2291 font_path = ("/Settings/QTFonts");
2292#endif
2293
2294 if (HasEntry(font_path)) DeleteGroup(font_path);
2295
2296 SetPath(font_path);
2297
2298 int nFonts = FontMgr::Get().GetNumFonts();
2299
2300 for (int i = 0; i < nFonts; i++) {
2301 wxString cfstring(FontMgr::Get().GetConfigString(i));
2302 wxString valstring = FontMgr::Get().GetFullConfigDesc(i);
2303 Write(cfstring, valstring);
2304 }
2305
2306 // Tide/Current Data Sources
2307 if (HasEntry("/TideCurrentDataSources"))
2308 DeleteGroup("/TideCurrentDataSources");
2309 SetPath("/TideCurrentDataSources");
2310 unsigned int id = 0;
2311 for (auto val : TideCurrentDataSet) {
2312 wxString key;
2313 key.Printf("tcds%d", id);
2314 Write(key, wxString(val));
2315 ++id;
2316 }
2317
2318 SetPath("/Settings/Others");
2319
2320 // Radar rings
2321 Write("ShowRadarRings",
2322 (bool)(g_iNavAidRadarRingsNumberVisible > 0)); // 3.0.0 config support
2323 Write("RadarRingsNumberVisible", g_iNavAidRadarRingsNumberVisible);
2324 Write("RadarRingsStep", g_fNavAidRadarRingsStep);
2325 Write("RadarRingsStepUnits", g_pNavAidRadarRingsStepUnits);
2326 Write("RadarRingsColour",
2327 g_colourOwnshipRangeRingsColour.GetAsString(wxC2S_HTML_SYNTAX));
2328 Write("WaypointUseScaMin", g_bUseWptScaMin);
2329 Write("WaypointScaMinValue", g_iWpt_ScaMin);
2330 Write("WaypointUseScaMinOverrule", g_bOverruleScaMin);
2331 Write("WaypointsShowName", g_bShowWptName);
2332 Write("UserIconsFirst", g_bUserIconsFirst);
2333
2334 // Waypoint Radar rings
2335 Write("WaypointRangeRingsNumber", g_iWaypointRangeRingsNumber);
2336 Write("WaypointRangeRingsStep", g_fWaypointRangeRingsStep);
2337 Write("WaypointRangeRingsStepUnits", g_iWaypointRangeRingsStepUnits);
2338 Write("WaypointRangeRingsColour",
2339 g_colourWaypointRangeRingsColour.GetAsString(wxC2S_HTML_SYNTAX));
2340
2341 Write("ConfirmObjectDeletion", g_bConfirmObjectDelete);
2342
2343 // Waypoint dragging with mouse; toh, 2009.02.24
2344 Write("WaypointPreventDragging", g_bWayPointPreventDragging);
2345
2346 Write("EnableZoomToCursor", g_bEnableZoomToCursor);
2347
2348 Write("TrackIntervalSeconds", g_TrackIntervalSeconds);
2349 Write("TrackDeltaDistance", g_TrackDeltaDistance);
2350 Write("TrackPrecision", g_nTrackPrecision);
2351
2352 Write("RouteLineWidth", g_route_line_width);
2353 Write("TrackLineWidth", g_track_line_width);
2354 Write("TrackLineColour",
2355 g_colourTrackLineColour.GetAsString(wxC2S_HTML_SYNTAX));
2356 Write("DefaultWPIcon", g_default_wp_icon);
2357 Write("DefaultRPIcon", g_default_routepoint_icon);
2358
2359 DeleteGroup("/MmsiProperties");
2360 SetPath("/MmsiProperties");
2361 for (unsigned int i = 0; i < g_MMSI_Props_Array.GetCount(); i++) {
2362 wxString p;
2363 p.Printf("Props%d", i);
2364 Write(p, g_MMSI_Props_Array[i]->Serialize());
2365 }
2366
2367 SaveCanvasConfigs();
2368
2369 Flush();
2370 SendMessageToAllPlugins("GLOBAL_SETTINGS_UPDATED", "{\"updated\":\"1\"}");
2371}
2372
2373static wxFileName exportFileName(wxWindow *parent,
2374 const wxString suggestedName) {
2375 wxFileName ret;
2376 wxString path;
2377 wxString valid_name = SanitizeFileName(suggestedName);
2378
2379#ifdef __ANDROID__
2380 if (!valid_name.EndsWith(".gpx")) {
2381 wxFileName fn(valid_name);
2382 fn.ClearExt();
2383 fn.SetExt("gpx");
2384 valid_name = fn.GetFullName();
2385 }
2386#endif
2387 int response = g_Platform->DoFileSelectorDialog(
2388 parent, &path, _("Export GPX file"), g_gpx_path, valid_name, "*.gpx");
2389
2390 if (response == wxID_OK) {
2391 wxFileName fn(path);
2392 g_gpx_path = fn.GetPath();
2393 if (!fn.GetExt().StartsWith("gpx")) fn.SetExt("gpx");
2394
2395#if defined(__WXMSW__) || defined(__WXGTK__)
2396 if (wxFileExists(fn.GetFullPath())) {
2397 int answer = OCPNMessageBox(NULL, _("Overwrite existing file?"),
2398 "Confirm", wxICON_QUESTION | wxYES_NO);
2399 if (answer != wxID_YES) return ret;
2400 }
2401#endif
2402 ret = fn;
2403 }
2404 return ret;
2405}
2406
2407int BackupDatabase(wxWindow *parent) {
2408 bool backupResult = false;
2409 wxDateTime tm = wxDateTime::Now();
2410 wxString proposedName = tm.Format("navobj-%Y-%m-%d_%H_%M");
2411 wxString acceptedName;
2412
2413 if (wxID_OK ==
2414 g_Platform->DoFileSelectorDialog(parent, &acceptedName, _("Backup"),
2415 wxStandardPaths::Get().GetDocumentsDir(),
2416 proposedName, "*.bkp")) {
2417 wxFileName fileName(acceptedName);
2418 if (fileName.IsOk()) {
2419#if defined(__WXMSW__) || defined(__WXGTK__)
2420 if (fileName.FileExists()) {
2421 if (wxID_YES != OCPNMessageBox(NULL, _("Overwrite existing file?"),
2422 "Confirm", wxICON_QUESTION | wxYES_NO)) {
2423 return wxID_ABORT; // We've decided not to overwrite a file, aborting
2424 }
2425 }
2426#endif
2427
2428#ifdef __ANDROID__
2429 wxString secureFileName = androidGetCacheDir() +
2430 wxFileName::GetPathSeparator() +
2431 fileName.GetFullName();
2432 backupResult = NavObj_dB::GetInstance().Backup(secureFileName);
2433 AndroidSecureCopyFile(secureFileName, fileName.GetFullPath());
2434#else
2435 backupResult = NavObj_dB::GetInstance().Backup(fileName.GetFullPath());
2436#endif
2437 }
2438 return backupResult ? wxID_YES : wxID_NO;
2439 }
2440 return wxID_ABORT; // Cancelled the file open dialog, aborting
2441}
2442
2443bool ExportGPXRoutes(wxWindow *parent, RouteList *pRoutes,
2444 const wxString suggestedName) {
2445#ifndef __ANDROID__
2446 wxFileName fn = exportFileName(parent, suggestedName);
2447 if (fn.IsOk()) {
2449 pgpx->AddGPXRoutesList(pRoutes);
2450 pgpx->SaveFile(fn.GetFullPath());
2451 delete pgpx;
2452 return true;
2453 }
2454#else
2455 // Create the .GPX file, saving it in the OCPN Android cache directory
2456 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
2457 suggestedName + ".gpx";
2459 pgpx->AddGPXRoutesList(pRoutes);
2460 pgpx->SaveFile(fns);
2461 delete pgpx;
2462
2463 // Kick off the Android file chooser activity
2464 wxString path;
2465 int response = g_Platform->DoFileSelectorDialog(
2466 parent, &path, _("Export GPX file"), g_gpx_path, suggestedName + ".gpx",
2467 "*.gpx");
2468
2469 if (path.IsEmpty()) // relocation handled by SAF logic in Java
2470 return true;
2471
2472 wxCopyFile(fns, path); // known to be safe paths, since SAF is not involved.
2473 return true;
2474
2475#endif
2476
2477 return false;
2478}
2479
2480bool ExportGPXTracks(wxWindow *parent, std::vector<Track *> *pTracks,
2481 const wxString suggestedName) {
2482#ifndef __ANDROID__
2483 wxFileName fn = exportFileName(parent, suggestedName);
2484 if (fn.IsOk()) {
2486 pgpx->AddGPXTracksList(pTracks);
2487 pgpx->SaveFile(fn.GetFullPath());
2488 delete pgpx;
2489 return true;
2490 }
2491#else
2492 // Create the .GPX file, saving it in the OCPN Android cache directory
2493 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
2494 suggestedName + ".gpx";
2496 pgpx->AddGPXTracksList(pTracks);
2497 pgpx->SaveFile(fns);
2498 delete pgpx;
2499
2500 // Kick off the Android file chooser activity
2501 wxString path;
2502 int response = g_Platform->DoFileSelectorDialog(
2503 parent, &path, _("Export GPX file"), g_gpx_path, suggestedName + ".gpx",
2504 "*.gpx");
2505
2506 if (path.IsEmpty()) // relocation handled by SAF logic in Java
2507 return true;
2508
2509 wxCopyFile(fns, path); // known to be safe paths, since SAF is not involved.
2510 return true;
2511#endif
2512
2513 return false;
2514}
2515
2516bool ExportGPXWaypoints(wxWindow *parent, RoutePointList *pRoutePoints,
2517 const wxString suggestedName) {
2518#ifndef __ANDROID__
2519 wxFileName fn = exportFileName(parent, suggestedName);
2520 if (fn.IsOk()) {
2522 pgpx->AddGPXPointsList(pRoutePoints);
2523 pgpx->SaveFile(fn.GetFullPath());
2524 delete pgpx;
2525 return true;
2526 }
2527#else
2528 // Create the .GPX file, saving it in the OCPN Android cache directory
2529 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
2530 suggestedName + ".gpx";
2532 pgpx->AddGPXPointsList(pRoutePoints);
2533 pgpx->SaveFile(fns);
2534 delete pgpx;
2535
2536 // Kick off the Android file chooser activity
2537 wxString path;
2538 int response = g_Platform->DoFileSelectorDialog(
2539 parent, &path, _("Export GPX file"), g_gpx_path, suggestedName + ".gpx",
2540 "*.gpx");
2541
2542 if (path.IsEmpty()) // relocation handled by SAF logic in Java
2543 return true;
2544
2545 wxCopyFile(fns, path); // known to be safe paths, since SAF is not involved.
2546 return true;
2547
2548#endif
2549
2550 return false;
2551}
2552
2553void ExportGPX(wxWindow *parent, bool bviz_only, bool blayer) {
2555 wxString fns;
2556
2557#ifndef __ANDROID__
2558 wxFileName fn = exportFileName(parent, "userobjects.gpx");
2559 if (!fn.IsOk()) return;
2560 fns = fn.GetFullPath();
2561#else
2562 // Create the .GPX file, saving it in the OCPN Android cache directory
2563 fns =
2564 androidGetCacheDir() + wxFileName::GetPathSeparator() + "userobjects.gpx";
2565
2566#endif
2567 ::wxBeginBusyCursor();
2568
2569 wxGenericProgressDialog *pprog = nullptr;
2570 int count = pWayPointMan->GetWaypointList()->size();
2571 int progStep = count / 32;
2572 if (count > 200) {
2573 pprog = new wxGenericProgressDialog(
2574 _("Export GPX file"), "0/0", count, NULL,
2575 wxPD_APP_MODAL | wxPD_SMOOTH | wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME |
2576 wxPD_REMAINING_TIME);
2577 pprog->SetSize(400, wxDefaultCoord);
2578 pprog->Centre();
2579 }
2580
2581 // WPTs
2582 int ic = 1;
2583
2584 for (RoutePoint *pr : *pWayPointMan->GetWaypointList()) {
2585 if (pprog && !(ic % progStep)) {
2586 wxString msg;
2587 msg.Printf("%d/%d", ic, count);
2588 pprog->Update(ic, msg);
2589 }
2590 ic++;
2591
2592 bool b_add = true;
2593 if (bviz_only && !pr->m_bIsVisible) b_add = false;
2594
2595 if (pr->m_bIsInLayer && !blayer) b_add = false;
2596 if (b_add) {
2597 if (pr->IsShared() || !WptIsInRouteList(pr)) pgpx->AddGPXWaypoint(pr);
2598 }
2599 }
2600 // RTEs and TRKs
2601 for (Route *pRoute : *pRouteList) {
2602 bool b_add = true;
2603 if (bviz_only && !pRoute->IsVisible()) b_add = false;
2604 if (pRoute->m_bIsInLayer && !blayer) b_add = false;
2605
2606 if (b_add) pgpx->AddGPXRoute(pRoute);
2607 }
2608
2609 for (Track *pTrack : g_TrackList) {
2610 bool b_add = true;
2611
2612 if (bviz_only && !pTrack->IsVisible()) b_add = false;
2613
2614 if (pTrack->m_bIsInLayer && !blayer) b_add = false;
2615
2616 if (b_add) pgpx->AddGPXTrack(pTrack);
2617 }
2618
2619 pgpx->SaveFile(fns);
2620
2621#ifdef __ANDROID__
2622 // Kick off the Android file chooser activity
2623 wxString path;
2624 int response =
2625 g_Platform->DoFileSelectorDialog(parent, &path, _("Export GPX file"),
2626 g_gpx_path, "userobjects.gpx", "*.gpx");
2627 if (path.IsEmpty()) // relocation handled by SAF logic in Java
2628 return;
2629
2630 wxCopyFile(fns, path); // known to be safe paths, since SAF is not involved.
2631 return;
2632#endif
2633 delete pgpx;
2634 ::wxEndBusyCursor();
2635 delete pprog;
2636}
2637
2638void UI_ImportGPX(wxWindow *parent, bool islayer, wxString dirpath,
2639 bool isdirectory, bool isPersistent) {
2640 int response = wxID_CANCEL;
2641 wxArrayString file_array;
2642
2643 if (!islayer || dirpath.IsSameAs("")) {
2644 // Platform DoFileSelectorDialog method does not properly handle multiple
2645 // selections So use native method if not Android, which means Android gets
2646 // single selection only.
2647#ifndef __ANDROID__
2648 wxFileDialog *popenDialog =
2649 new wxFileDialog(NULL, _("Import GPX file"), g_gpx_path, "",
2650 "GPX files (*.gpx)|*.gpx|All files (*.*)|*.*",
2651 wxFD_OPEN | wxFD_MULTIPLE);
2652
2653 if (g_bresponsive && parent)
2654 popenDialog = g_Platform->AdjustFileDialogFont(parent, popenDialog);
2655
2656 popenDialog->Centre();
2657
2658#ifdef __WXOSX__
2659 if (parent) parent->HideWithEffect(wxSHOW_EFFECT_BLEND);
2660#endif
2661
2662 response = popenDialog->ShowModal();
2663
2664#ifdef __WXOSX__
2665 if (parent) parent->ShowWithEffect(wxSHOW_EFFECT_BLEND);
2666#endif
2667
2668 if (response == wxID_OK) {
2669 popenDialog->GetPaths(file_array);
2670
2671 // Record the currently selected directory for later use
2672 if (file_array.GetCount()) {
2673 wxFileName fn(file_array[0]);
2674 g_gpx_path = fn.GetPath();
2675 }
2676 }
2677 delete popenDialog;
2678#else // Android
2679 wxString path;
2680 response = g_Platform->DoFileSelectorDialog(
2681 NULL, &path, _("Import GPX file"), g_gpx_path, "", "*.gpx");
2682
2683 wxFileName fn(path);
2684 g_gpx_path = fn.GetPath();
2685 if (path.IsEmpty()) { // Return from SAF processing, expecting callback
2686 PrepareImportAndroid(islayer, isPersistent);
2687 return;
2688 } else
2689 file_array.Add(path); // Return from safe app arena access
2690
2691#endif
2692 } else {
2693 if (isdirectory) {
2694 if (wxDir::GetAllFiles(dirpath, &file_array, "*.gpx")) response = wxID_OK;
2695 } else {
2696 file_array.Add(dirpath);
2697 response = wxID_OK;
2698 }
2699 }
2700
2701 if (response == wxID_OK) {
2702 ImportFileArray(file_array, islayer, isPersistent, dirpath);
2703 }
2704}
2705
2706void ImportFileArray(const wxArrayString &file_array, bool islayer,
2707 bool isPersistent, wxString dirpath) {
2708 Layer *l = NULL;
2709
2710 if (islayer) {
2711 l = new Layer();
2712 l->m_LayerID = ++g_LayerIdx;
2713 l->m_LayerFileName = file_array[0];
2714 if (file_array.GetCount() <= 1)
2715 wxFileName::SplitPath(file_array[0], NULL, NULL, &(l->m_LayerName), NULL,
2716 NULL);
2717 else {
2718 if (dirpath.IsSameAs(""))
2719 wxFileName::SplitPath(g_gpx_path, NULL, NULL, &(l->m_LayerName), NULL,
2720 NULL);
2721 else
2722 wxFileName::SplitPath(dirpath, NULL, NULL, &(l->m_LayerName), NULL,
2723 NULL);
2724 }
2725
2726 bool bLayerViz = g_bShowLayers;
2727 if (g_VisibleLayers.Contains(l->m_LayerName)) bLayerViz = true;
2728 if (g_InvisibleLayers.Contains(l->m_LayerName)) bLayerViz = false;
2729 l->m_bIsVisibleOnChart = bLayerViz;
2730
2731 // Default for new layers is "Names visible"
2732 l->m_bHasVisibleNames = wxCHK_CHECKED;
2733
2734 wxString laymsg;
2735 laymsg.Printf("New layer %d: %s", l->m_LayerID, l->m_LayerName.c_str());
2736 wxLogMessage(laymsg);
2737
2738 pLayerList->insert(pLayerList->begin(), l);
2739 }
2740
2741 for (unsigned int i = 0; i < file_array.GetCount(); i++) {
2742 wxString path = file_array[i];
2743
2744 if (::wxFileExists(path)) {
2746 if (pSet->load_file(path.fn_str()).status !=
2747 pugi::xml_parse_status::status_ok) {
2748 wxLogMessage("Error loading GPX file " + path);
2749 pSet->reset();
2750 delete pSet;
2751 continue;
2752 }
2753
2754 if (islayer) {
2755 l->m_NoOfItems = pSet->LoadAllGPXObjectsAsLayer(
2756 l->m_LayerID, l->m_bIsVisibleOnChart, l->m_bHasVisibleNames);
2757 l->m_LayerType = isPersistent ? _("Persistent") : _("Temporary");
2758
2759 if (isPersistent) {
2760 // If this is a persistent layer also copy the file to config file
2761 // dir /layers
2762 wxString destf, f, name, ext;
2763 f = l->m_LayerFileName;
2764 wxFileName::SplitPath(f, NULL, NULL, &name, &ext);
2765 destf = g_Platform->GetPrivateDataDir();
2766 appendOSDirSlash(&destf);
2767 destf.Append("layers");
2768 appendOSDirSlash(&destf);
2769 if (!wxDirExists(destf)) {
2770 if (!wxMkdir(destf, wxS_DIR_DEFAULT))
2771 wxLogMessage("Error creating layer directory");
2772 }
2773
2774 destf << name << "." << ext;
2775 wxString msg;
2776 if (wxCopyFile(f, destf, true))
2777 msg.Printf("File: %s.%s also added to persistent layers", name,
2778 ext);
2779 else
2780 msg.Printf("Failed adding %s.%s to persistent layers", name, ext);
2781 wxLogMessage(msg);
2782 }
2783 } else {
2784 int wpt_dups;
2785 pSet->LoadAllGPXObjects(
2786 !pSet->IsOpenCPN(),
2787 wpt_dups); // Import with full visibility of names and objects
2788#ifndef __ANDROID__
2789 if (wpt_dups > 0) {
2790 OCPNMessageBox(
2791 NULL,
2792 wxString::Format("%d " + _("duplicate waypoints detected "
2793 "during import and ignored."),
2794 wpt_dups),
2795 _("OpenCPN Info"), wxICON_INFORMATION | wxOK, 10);
2796 }
2797#endif
2798 }
2799 delete pSet;
2800 }
2801 }
2802}
2803
2804//-------------------------------------------------------------------------
2805// Static Routine Switch to Inland Ecdis Mode
2806//-------------------------------------------------------------------------
2807void SwitchInlandEcdisMode(bool Switch) {
2808 if (Switch) {
2809 wxLogMessage("Switch InlandEcdis mode On");
2810 LoadS57();
2811 // Overrule some settings to comply with InlandEcdis
2812 // g_toolbarConfig = ".....XXXX.X...XX.XXXXXXXXXXXX";
2813 g_iDistanceFormat = 2; // 0 = "Nautical miles"), 1 = "Statute miles", 2 =
2814 // "Kilometers", 3 = "Meters"
2815 g_iSpeedFormat = 2; // 0 = "kts"), 1 = "mph", 2 = "km/h", 3 = "m/s"
2816 if (ps52plib) ps52plib->SetDisplayCategory(STANDARD);
2817 g_bDrawAISSize = false;
2818 if (gFrame) gFrame->RequestNewToolbars(true);
2819 } else {
2820 wxLogMessage("Switch InlandEcdis mode Off");
2821 // reread the settings overruled by inlandEcdis
2822 if (pConfig) {
2823 pConfig->SetPath("/Settings");
2824 pConfig->Read("GlobalToolbarConfig", &g_toolbarConfig);
2825 pConfig->Read("DistanceFormat", &g_iDistanceFormat);
2826 pConfig->Read("SpeedFormat", &g_iSpeedFormat);
2827 pConfig->Read("ShowDepthUnits", &g_bShowDepthUnits, 1);
2828 pConfig->Read("HeightFormat", &g_iHeightFormat);
2829 int read_int;
2830 pConfig->Read("nDisplayCategory", &read_int, (enum _DisCat)STANDARD);
2831 if (ps52plib) ps52plib->SetDisplayCategory((enum _DisCat)read_int);
2832 pConfig->SetPath("/Settings/AIS");
2833 pConfig->Read("bDrawAISSize", &g_bDrawAISSize);
2834 pConfig->Read("bDrawAISRealtime", &g_bDrawAISRealtime);
2835 }
2836 if (gFrame) gFrame->RequestNewToolbars(true);
2837 }
2838}
2839
2840//-------------------------------------------------------------------------
2841//
2842// Static GPX Support Routines
2843//
2844//-------------------------------------------------------------------------
2845// This function formats the input date/time into a valid GPX ISO 8601
2846// time string specified in the UTC time zone.
2847
2848wxString FormatGPXDateTime(wxDateTime dt) {
2849 // return dt.Format("%Y-%m-%dT%TZ", wxDateTime::GMT0);
2850 return dt.Format("%Y-%m-%dT%H:%M:%SZ");
2851}
2852
2853/**************************************************************************/
2854/* LogMessageOnce */
2855/**************************************************************************/
2856
2857bool LogMessageOnce(const wxString &msg) {
2858 // Search the array for a match
2859
2860 for (unsigned int i = 0; i < navutil::pMessageOnceArray->GetCount(); i++) {
2861 if (msg.IsSameAs(navutil::pMessageOnceArray->Item(i))) return false;
2862 }
2863
2864 // Not found, so add to the array
2865 navutil::pMessageOnceArray->Add(msg);
2866
2867 // And print it
2868 wxLogMessage(msg);
2869 return true;
2870}
2871
2872/**************************************************************************/
2873/* Some assorted utilities */
2874/**************************************************************************/
2875
2876wxDateTime toUsrDateTime(const wxDateTime ts, const int format,
2877 const double lon) {
2878 if (!ts.IsValid()) {
2879 return ts;
2880 }
2881 int effective_format = format;
2882 if (effective_format == GLOBAL_SETTINGS_INPUT) {
2883 if (::g_datetime_format == "UTC") {
2884 effective_format = UTCINPUT;
2885 } else if (::g_datetime_format == "LMT") {
2886 effective_format = LMTINPUT;
2887 } else if (::g_datetime_format == "Local Time") {
2888 effective_format = LTINPUT;
2889 } else {
2890 // Default to UTC
2891 effective_format = UTCINPUT;
2892 }
2893 }
2894 wxDateTime dt;
2895 switch (effective_format) {
2896 case LMTINPUT: // LMT@Location
2897 if (std::isnan(lon)) {
2898 dt = wxInvalidDateTime;
2899 } else {
2900 dt =
2901 ts.Add(wxTimeSpan(wxTimeSpan(0, 0, wxLongLong(lon * 3600. / 15.))));
2902 }
2903 break;
2904 case LTINPUT: // Local@PC
2905 // Convert date/time from UTC to local time.
2906 dt = ts.FromUTC();
2907 break;
2908 case UTCINPUT: // UTC
2909 // The date/time is already in UTC.
2910 dt = ts;
2911 break;
2912 }
2913 return dt;
2914}
2915
2916wxDateTime fromUsrDateTime(const wxDateTime ts, const int format,
2917 const double lon) {
2918 if (!ts.IsValid()) {
2919 return ts;
2920 }
2921 int effective_format = format;
2922 if (effective_format == GLOBAL_SETTINGS_INPUT) {
2923 if (::g_datetime_format == "UTC") {
2924 effective_format = UTCINPUT;
2925 } else if (::g_datetime_format == "LMT") {
2926 effective_format = LMTINPUT;
2927 } else if (::g_datetime_format == "Local Time") {
2928 effective_format = LTINPUT;
2929 } else {
2930 // Default to UTC
2931 effective_format = UTCINPUT;
2932 }
2933 }
2934 wxDateTime dt;
2935 switch (effective_format) {
2936 case LMTINPUT: // LMT@Location
2937 if (std::isnan(lon)) {
2938 dt = wxInvalidDateTime;
2939 } else {
2940 dt = ts.Subtract(wxTimeSpan(0, 0, wxLongLong(lon * 3600. / 15.)));
2941 }
2942 break;
2943 case LTINPUT: // Local@PC
2944 // The input date/time is in local time, so convert it to UTC.
2945 dt = ts.ToUTC();
2946 break;
2947 case UTCINPUT: // UTC
2948 dt = ts;
2949 break;
2950 }
2951 return dt;
2952}
2953
2954/**************************************************************************/
2955/* Converts the speed from the units selected by user to knots */
2956/**************************************************************************/
2957double fromUsrSpeed(double usr_speed, int unit) {
2958 double ret = NAN;
2959 if (unit == -1) unit = g_iSpeedFormat;
2960 switch (unit) {
2961 case SPEED_KTS: // kts
2962 ret = usr_speed;
2963 break;
2964 case SPEED_MPH: // mph
2965 ret = usr_speed / 1.15078;
2966 break;
2967 case SPEED_KMH: // km/h
2968 ret = usr_speed / 1.852;
2969 break;
2970 case SPEED_MS: // m/s
2971 ret = usr_speed / 0.514444444;
2972 break;
2973 }
2974 return ret;
2975}
2976/**************************************************************************/
2977/* Converts the wind speed from the units selected by user to knots */
2978/**************************************************************************/
2979double fromUsrWindSpeed(double usr_wspeed, int unit) {
2980 double ret = NAN;
2981 if (unit == -1) unit = g_iWindSpeedFormat;
2982 switch (unit) {
2983 case WSPEED_KTS: // kts
2984 ret = usr_wspeed;
2985 break;
2986 case WSPEED_MS: // m/s
2987 ret = usr_wspeed / 0.514444444;
2988 break;
2989 case WSPEED_MPH: // mph
2990 ret = usr_wspeed / 1.15078;
2991 break;
2992 case WSPEED_KMH: // km/h
2993 ret = usr_wspeed / 1.852;
2994 break;
2995 }
2996 return ret;
2997}
2998
2999/**************************************************************************/
3000/* Converts the temperature from the units selected by user to Celsius */
3001/**************************************************************************/
3002double fromUsrTemp(double usr_temp, int unit) {
3003 double ret = NAN;
3004 if (unit == -1) unit = g_iTempFormat;
3005 switch (unit) {
3006 case TEMPERATURE_C: // C
3007 ret = usr_temp;
3008 break;
3009 case TEMPERATURE_F: // F
3010 ret = (usr_temp - 32) * 5.0 / 9.0;
3011 break;
3012 case TEMPERATURE_K: // K
3013 ret = usr_temp - 273.15;
3014 break;
3015 }
3016 return ret;
3017}
3018
3019wxString formatAngle(double angle) {
3020 wxString out;
3021 if (g_bShowMag && g_bShowTrue) {
3022 out.Printf("%03.0f %cT (%.0f %cM)", angle, 0x00B0, toMagnetic(angle),
3023 0x00B0);
3024 } else if (g_bShowTrue) {
3025 out.Printf("%03.0f %cT", angle, 0x00B0);
3026 } else {
3027 out.Printf("%03.0f %cM", toMagnetic(angle), 0x00B0);
3028 }
3029 return out;
3030}
3031
3032/* render a rectangle at a given color and transparency */
3033void AlphaBlending(ocpnDC &dc, int x, int y, int size_x, int size_y,
3034 float radius, wxColour color, unsigned char transparency) {
3035 wxDC *pdc = dc.GetDC();
3036 if (pdc) {
3037 // Get wxImage of area of interest
3038 wxBitmap obm(size_x, size_y);
3039 wxMemoryDC mdc1;
3040 mdc1.SelectObject(obm);
3041 mdc1.Blit(0, 0, size_x, size_y, pdc, x, y);
3042 mdc1.SelectObject(wxNullBitmap);
3043 wxImage oim = obm.ConvertToImage();
3044
3045 // Create destination image
3046 wxBitmap olbm(size_x, size_y);
3047 wxMemoryDC oldc(olbm);
3048 if (!oldc.IsOk()) return;
3049
3050 oldc.SetBackground(*wxBLACK_BRUSH);
3051 oldc.SetBrush(*wxWHITE_BRUSH);
3052 oldc.Clear();
3053
3054 if (radius > 0.0) oldc.DrawRoundedRectangle(0, 0, size_x, size_y, radius);
3055
3056 wxImage dest = olbm.ConvertToImage();
3057 unsigned char *dest_data =
3058 (unsigned char *)malloc(size_x * size_y * 3 * sizeof(unsigned char));
3059 unsigned char *bg = oim.GetData();
3060 unsigned char *box = dest.GetData();
3061 unsigned char *d = dest_data;
3062
3063 // Sometimes, on Windows, the destination image is corrupt...
3064 if (NULL == box) {
3065 free(d);
3066 return;
3067 }
3068 float alpha = 1.0 - (float)transparency / 255.0;
3069 int sb = size_x * size_y;
3070 for (int i = 0; i < sb; i++) {
3071 float a = alpha;
3072 if (*box == 0 && radius > 0.0) a = 1.0;
3073 int r = ((*bg++) * a) + (1.0 - a) * color.Red();
3074 *d++ = r;
3075 box++;
3076 int g = ((*bg++) * a) + (1.0 - a) * color.Green();
3077 *d++ = g;
3078 box++;
3079 int b = ((*bg++) * a) + (1.0 - a) * color.Blue();
3080 *d++ = b;
3081 box++;
3082 }
3083
3084 dest.SetData(dest_data);
3085
3086 // Convert destination to bitmap and draw it
3087 wxBitmap dbm(dest);
3088 dc.DrawBitmap(dbm, x, y, false);
3089
3090 // on MSW, the dc Bounding box is not updated on DrawBitmap() method.
3091 // Do it explicitely here for all platforms.
3092 dc.CalcBoundingBox(x, y);
3093 dc.CalcBoundingBox(x + size_x, y + size_y);
3094 } else {
3095#ifdef ocpnUSE_GL
3096 glEnable(GL_BLEND);
3097
3098 float radMod = wxMax(radius, 2.0);
3099 wxColour c(color.Red(), color.Green(), color.Blue(), transparency);
3100 dc.SetBrush(wxBrush(c));
3101 dc.SetPen(wxPen(c, 1));
3102 dc.DrawRoundedRectangle(x, y, size_x, size_y, radMod);
3103
3104 glDisable(GL_BLEND);
3105
3106#endif
3107 }
3108}
3109
3110void DimeControl(wxWindow *ctrl) {
3111#ifdef __WXOSX__
3112 // On macOS 10.14+, we use the native colours in both light mode and dark
3113 // mode, and do not need to do anything else. Dark mode is toggled at the
3114 // application level in `SetAndApplyColorScheme`, and is also respected if it
3115 // is enabled system-wide.
3116 if (wxPlatformInfo::Get().CheckOSVersion(10, 14)) {
3117 return;
3118 }
3119#endif
3120#ifdef __WXQT__
3121 return; // this is seriously broken on wxqt
3122#endif
3123
3124 if (wxSystemSettings::GetColour(wxSystemColour::wxSYS_COLOUR_WINDOW).Red() <
3125 128) {
3126 // Dark system color themes usually do better job than we do on diming UI
3127 // controls, do not fight with them
3128 return;
3129 }
3130
3131 if (NULL == ctrl) return;
3132
3133 wxColour col, window_back_color, gridline, uitext, udkrd, ctrl_back_color,
3134 text_color;
3135 col = GetGlobalColor("DILG0"); // Dialog Background white
3136 window_back_color = GetGlobalColor("DILG1"); // Dialog Background
3137 ctrl_back_color = GetGlobalColor("DILG1"); // Control Background
3138 text_color = GetGlobalColor("DILG3"); // Text
3139 uitext = GetGlobalColor("UITX1"); // Menu Text, derived from UINFF
3140 udkrd = GetGlobalColor("UDKRD");
3141 gridline = GetGlobalColor("GREY2");
3142
3143 DimeControl(ctrl, col, window_back_color, ctrl_back_color, text_color, uitext,
3144 udkrd, gridline);
3145}
3146
3147void DimeControl(wxWindow *ctrl, wxColour col, wxColour window_back_color,
3148 wxColour ctrl_back_color, wxColour text_color, wxColour uitext,
3149 wxColour udkrd, wxColour gridline) {
3150#ifdef __WXOSX__
3151 // On macOS 10.14+, we use the native colours in both light mode and dark
3152 // mode, and do not need to do anything else. Dark mode is toggled at the
3153 // application level in `SetAndApplyColorScheme`, and is also respected if it
3154 // is enabled system-wide.
3155 if (wxPlatformInfo::Get().CheckOSVersion(10, 14)) {
3156 return;
3157 }
3158#endif
3159
3160 ColorScheme cs = global_color_scheme;
3161
3162 // Are we in dusk or night mode? (Used below in several places.)
3163 bool darkMode =
3164 (cs == GLOBAL_COLOR_SCHEME_DUSK || cs == GLOBAL_COLOR_SCHEME_NIGHT);
3165
3166 static int depth = 0; // recursion count
3167 if (depth == 0) { // only for the window root, not for every child
3168 // If the color scheme is DAY or RGB, use the default platform native colour
3169 // for backgrounds
3170 if (!darkMode) {
3171#ifdef _WIN32
3172 window_back_color = wxNullColour;
3173#else
3174 window_back_color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
3175#endif
3176 col = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX);
3177 uitext = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
3178 }
3179
3180 ctrl->SetBackgroundColour(window_back_color);
3181 if (darkMode) ctrl->SetForegroundColour(text_color);
3182 }
3183
3184 wxWindowList kids = ctrl->GetChildren();
3185 for (unsigned int i = 0; i < kids.GetCount(); i++) {
3186 wxWindowListNode *node = kids.Item(i);
3187 wxWindow *win = node->GetData();
3188
3189 if (dynamic_cast<wxListBox *>(win) || dynamic_cast<wxListCtrl *>(win) ||
3190 dynamic_cast<wxTextCtrl *>(win) ||
3191 dynamic_cast<wxTimePickerCtrl *>(win)) {
3192 win->SetBackgroundColour(col);
3193 } else if (dynamic_cast<wxStaticText *>(win) ||
3194 dynamic_cast<wxCheckBox *>(win) ||
3195 dynamic_cast<wxRadioButton *>(win)) {
3196 win->SetForegroundColour(uitext);
3197 }
3198#ifndef __WXOSX__
3199 // On macOS most controls can't be styled, and trying to do so only creates
3200 // weird coloured boxes around them. Fortunately, however, many of them
3201 // inherit a colour or tint from the background of their parent.
3202
3203 else if (dynamic_cast<wxBitmapComboBox *>(win) ||
3204 dynamic_cast<wxChoice *>(win) || dynamic_cast<wxComboBox *>(win) ||
3205 dynamic_cast<wxTreeCtrl *>(win)) {
3206 win->SetBackgroundColour(col);
3207 }
3208
3209 else if (dynamic_cast<wxScrolledWindow *>(win) ||
3210 dynamic_cast<wxGenericDirCtrl *>(win) ||
3211 dynamic_cast<wxListbook *>(win) || dynamic_cast<wxButton *>(win) ||
3212 dynamic_cast<wxToggleButton *>(win)) {
3213 win->SetBackgroundColour(window_back_color);
3214 }
3215
3216 else if (dynamic_cast<wxNotebook *>(win)) {
3217 win->SetBackgroundColour(window_back_color);
3218 win->SetForegroundColour(text_color);
3219 }
3220#endif
3221
3222 else if (dynamic_cast<wxHtmlWindow *>(win)) {
3223 if (cs != GLOBAL_COLOR_SCHEME_DAY && cs != GLOBAL_COLOR_SCHEME_RGB)
3224 win->SetBackgroundColour(ctrl_back_color);
3225 else
3226 win->SetBackgroundColour(wxNullColour);
3227 }
3228
3229 else if (dynamic_cast<wxGrid *>(win)) {
3230 dynamic_cast<wxGrid *>(win)->SetDefaultCellBackgroundColour(
3231 window_back_color);
3232 dynamic_cast<wxGrid *>(win)->SetDefaultCellTextColour(uitext);
3233 dynamic_cast<wxGrid *>(win)->SetLabelBackgroundColour(col);
3234 dynamic_cast<wxGrid *>(win)->SetLabelTextColour(uitext);
3235 dynamic_cast<wxGrid *>(win)->SetGridLineColour(gridline);
3236 }
3237
3238 if (win->GetChildren().GetCount() > 0) {
3239 depth++;
3240 wxWindow *w = win;
3241 DimeControl(w, col, window_back_color, ctrl_back_color, text_color,
3242 uitext, udkrd, gridline);
3243 depth--;
3244 }
3245 }
3246}
ArrayOfMmsiProperties g_MMSI_Props_Array
Global instance.
unsigned g_OwnShipmmsi
Global instance.
Class AisDecoder and helpers.
Global state for AIS decoder.
Chart canvas configuration state
General chart base definitions.
Charts database management
ChartGroupArray * g_pGroupArray
Global instance.
Definition chartdbs.cpp:56
Generic Chart canvas base.
wxString & GetPrivateDataDir()
Return dir path for opencpn.log, etc., respecting -c cli option.
Represents an individual component within a ChartGroup.
Definition chartdbs.h:448
Represents a user-defined collection of logically related charts.
Definition chartdbs.h:468
wxString GetFullConfigDesc(int i) const
Gets description of font at index i.
Definition font_mgr.cpp:360
bool AddAuxKey(wxString key)
Adds new plugin-defined font configuration key.
Definition font_mgr.cpp:653
void LoadFontNative(wxString *pConfigString, wxString *pNativeDesc)
Loads font settings from a string descriptor.
Definition font_mgr.cpp:387
static wxString GetFontConfigKey(const wxString &description)
Creates configuration key from UI element name by combining locale with hash.
Definition font_mgr.cpp:125
int GetNumFonts(void) const
Gets the total number of font configurations currently loaded.
Definition font_mgr.cpp:322
wxArrayString & GetAuxKeyArray()
Gets array of plugin-defined font configuration keys.
Definition font_mgr.h:200
Represents a layer of chart objects in OpenCPN.
Definition layer.h:44
Process incoming AIS messages.
Definition ais_decoder.h:74
static int config_to_ui(double value)
Convert configuration 1.02..3.0 value to slider scale 1..100.
Definition navutil.h:158
static double ui_to_config(int slider_pos)
Convert a slider scale 1-100 value to configuration value 1.02..3.0.
Definition navutil.h:153
Represents a waypoint or mark within the navigation system.
Definition route_point.h:71
Represents a navigational route in the navigation system.
Definition route.h:99
Represents a track, which is a series of connected track points.
Definition track.h:117
ViewPort - Core geographic projection and coordinate transformation engine.
Definition viewport.h:56
double view_scale_ppm
Requested view scale in physical pixels per meter (ppm), before applying projections.
Definition viewport.h:204
double rotation
Rotation angle of the viewport in radians.
Definition viewport.h:214
double clon
Center longitude of the viewport in degrees.
Definition viewport.h:199
double clat
Center latitude of the viewport in degrees.
Definition viewport.h:197
Encapsulates persistent canvas configuration.
double iLat
Latitude of the center of the chart, in degrees.
bool bShowOutlines
Display chart outlines.
wxSize canvasSize
Canvas dimensions.
bool bShowDepthUnits
Display depth unit indicators.
double iLon
Longitude of the center of the chart, in degrees.
double iRotation
Initial rotation angle in radians.
bool bCourseUp
Orient display to course up.
bool bQuilt
Enable chart quilting.
bool bFollow
Enable vessel following mode.
double iScale
Initial chart scale factor.
bool bShowENCText
Display ENC text elements.
bool bShowAIS
Display AIS targets.
bool bShowGrid
Display coordinate grid.
ChartCanvas * canvas
Pointer to associated chart canvas.
bool bShowCurrents
Display current information.
bool bShowTides
Display tide information.
bool bLookahead
Enable lookahead mode.
bool bHeadUp
Orient display to heading up.
bool bAttenAIS
Enable AIS target attenuation.
Device context class that can use either wxDC or OpenGL for drawing.
Definition ocpndc.h:60
Class cm93chart and helpers – CM93 chart state.
Global variables reflecting command line options and arguments.
Config file user configuration interface.
wxString g_datetime_format
Date/time format to use when formatting date/time strings.
bool g_always_send_rmb_rmc
Always send RMB and RMC n0183 messages even if there is no active route.
bool g_bsmoothpanzoom
Controls how the chart panning and zooming smoothing is done during user interactions.
int g_iTempFormat
User-selected temperature unit format for display and input.
int g_nDepthUnitDisplay
User-selected depth (below surface) unit format for display and input.
wxString g_default_font_facename
Default font size for user interface elements such as menus, dialogs, etc.
wxString g_winPluginDir
Base plugin directory on Windows.
bool g_bRollover
enable/disable mouse rollover GUI effects
bool g_bShowTide
not used
int g_COGAvgSec
COG average period for Course Up Mode (sec)
int g_iSpeedFormat
User-selected speed unit format for display and input.
int g_iHeightFormat
User-selected height (vertical, above reference datum) unit format for display and input.
std::vector< size_t > g_config_display_size_mm
Size of pysical screen in millimeters.
int g_iDistanceFormat
User-selected distance (horizontal) unit format for display and input.
bool g_bDisplayGrid
Should lat/lon grid be displayed ?
Global variables stored in configuration file.
Connection parameters.
Extern C linked utilities.
std::vector< OCPN_MonitorInfo > g_monitor_info
Information about the monitors connected to the system.
Definition displays.cpp:45
NavmsgFilter Read(const std::string &name)
Read filter with given name from disk.
bool Write(const NavmsgFilter &filter, const std::string &name)
Write contents for given filter to disk.
Font list manager.
OpenCPN Georef utility.
OpenGL chart rendering canvas.
Platform independent GL includes.
size_t g_current_monitor
Current monitor displaying main application frame.
Definition gui_vars.cpp:75
double vLat
Virtual lat from chcanv popup.
Definition gui_vars.cpp:72
double vLon
Virtual lon from chcanv popup.
Definition gui_vars.cpp:73
Miscellaneous globals primarely used by gui layer, not persisted in configuration file.
GUI constant definitions.
Chart object layer.
Multiplexer class and helpers.
MySQL based storage for routes, tracks, etc.
MyConfig * pConfig
Global instance.
Definition navutil.cpp:113
wxDateTime toUsrDateTime(const wxDateTime ts, const int format, const double lon)
Converts a timestamp from UTC to the user's preferred time format.
Definition navutil.cpp:2876
wxDateTime fromUsrDateTime(const wxDateTime ts, const int format, const double lon)
Converts a timestamp from a user's preferred time format to UTC.
Definition navutil.cpp:2916
Utility functions.
MyConfig * pConfig
Global instance.
Definition navutil.cpp:113
Navigation Utility Functions without GUI dependencies.
Global variables Listen()/Notify() wrapper.
OpenCPN top window.
OpenCPN Platform specific support utilities.
PlugIn Object Definition/API.
Layer to use wxDC or opengl.
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.
Tools to send data to plugins.
Route abstraction.
wxColour g_colourWaypointRangeRingsColour
Global instance.
int g_LayerIdx
Global instance.
#define LMTINPUT
Format date/time using the remote location LMT time.
#define GLOBAL_SETTINGS_INPUT
Format date/time according to global OpenCPN settings.
#define UTCINPUT
Format date/time in UTC.
#define LTINPUT
Format date/time using timezone configured in the operating system./*#end#*‍/.
RouteList * pRouteList
Global instance.
Definition routeman.cpp:66
float g_ChartScaleFactorExp
Global instance.
Definition routeman.cpp:68
Route Manager.
Selected route, segment, waypoint, etc.
Chart Symbols.
std::vector< Track * > g_TrackList
Global instance.
Definition track.cpp:96
Recorded track abstraction.