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