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