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("WaypointUseScaMinOverrule", &g_bOverruleScaMin))
1124 g_bOverruleScaMin = false;
1125 if (!Read("WaypointsShowName", &g_bShowWptName)) g_bShowWptName = true;
1126 if (!Read("UserIconsFirst", &g_bUserIconsFirst)) g_bUserIconsFirst = true;
1127
1128 // Support Version 3.0 and prior config setting for Radar Rings
1129 bool b300RadarRings = true;
1130 if (Read("ShowRadarRings", &b300RadarRings)) {
1131 if (!b300RadarRings) g_iNavAidRadarRingsNumberVisible = 0;
1132 }
1133
1134 Read("ConfirmObjectDeletion", &g_bConfirmObjectDelete);
1135
1136 // Waypoint dragging with mouse
1137 g_bWayPointPreventDragging = false;
1138 Read("WaypointPreventDragging", &g_bWayPointPreventDragging);
1139
1140 g_bEnableZoomToCursor = false;
1141 Read("EnableZoomToCursor", &g_bEnableZoomToCursor);
1142
1143 val.Clear();
1144 Read("TrackIntervalSeconds", &val);
1145 if (val.Length() > 0) {
1146 double tval = atof(val.mb_str());
1147 if (tval >= 2.) g_TrackIntervalSeconds = tval;
1148 }
1149
1150 val.Clear();
1151 Read("TrackDeltaDistance", &val);
1152 if (val.Length() > 0) {
1153 double tval = atof(val.mb_str());
1154 if (tval >= 0.05) g_TrackDeltaDistance = tval;
1155 }
1156
1157 Read("TrackPrecision", &g_nTrackPrecision);
1158
1159 Read("RouteLineWidth", &g_route_line_width);
1160 Read("TrackLineWidth", &g_track_line_width);
1161
1162 wxString l_wxsTrackLineColour;
1163 if (Read("TrackLineColour", &l_wxsTrackLineColour))
1164 g_colourTrackLineColour.Set(l_wxsTrackLineColour);
1165
1166 Read("TideCurrentWindowScale", &g_tcwin_scale);
1167 Read("DefaultWPIcon", &g_default_wp_icon);
1168 Read("DefaultRPIcon", &g_default_routepoint_icon);
1169
1170 SetPath("/MmsiProperties");
1171 int iPMax = GetNumberOfEntries();
1172 if (iPMax) {
1173 g_MMSI_Props_Array.Empty();
1174 wxString str, val;
1175 long dummy;
1176 bool bCont = pConfig->GetFirstEntry(str, dummy);
1177 while (bCont) {
1178 pConfig->Read(str, &val); // Get an entry
1179
1180 MmsiProperties *pProps = new MmsiProperties(val);
1181 g_MMSI_Props_Array.Add(pProps);
1182
1183 bCont = pConfig->GetNextEntry(str, dummy);
1184 }
1185 }
1186
1187 SetPath("/DataMonitor");
1188 g_dm_ok = ReadUnsigned("colors.ok", kUndefinedColor);
1189 g_dm_dropped = ReadUnsigned("colors.dropped", kUndefinedColor);
1190 g_dm_filtered = ReadUnsigned("colors.filtered", kUndefinedColor);
1191 g_dm_input = ReadUnsigned("colors.input", kUndefinedColor);
1192 g_dm_output = ReadUnsigned("colors.output", kUndefinedColor);
1193 g_dm_not_ok = ReadUnsigned("colors.not-ok", kUndefinedColor);
1194
1195 return 0;
1196}
1197
1198void MyConfig::LoadS57Config() {
1199 if (!ps52plib) return;
1200
1201 int read_int;
1202 double dval;
1203 SetPath("/Settings/GlobalState");
1204
1205 Read("bShowS57Text", &read_int, 1);
1206 ps52plib->SetShowS57Text(!(read_int == 0));
1207
1208 Read("bShowS57ImportantTextOnly", &read_int, 0);
1209 ps52plib->SetShowS57ImportantTextOnly(!(read_int == 0));
1210
1211 Read("bShowLightDescription", &read_int, 0);
1212 ps52plib->SetShowLdisText(!(read_int == 0));
1213
1214 Read("bExtendLightSectors", &read_int, 0);
1215 ps52plib->SetExtendLightSectors(!(read_int == 0));
1216
1217 Read("nDisplayCategory", &read_int, (enum _DisCat)STANDARD);
1218 ps52plib->SetDisplayCategory((enum _DisCat)read_int);
1219
1220 Read("nSymbolStyle", &read_int, (enum _LUPname)PAPER_CHART);
1221 ps52plib->m_nSymbolStyle = (LUPname)read_int;
1222
1223 Read("nBoundaryStyle", &read_int, PLAIN_BOUNDARIES);
1224 ps52plib->m_nBoundaryStyle = (LUPname)read_int;
1225
1226 Read("bShowSoundg", &read_int, 1);
1227 ps52plib->m_bShowSoundg = !(read_int == 0);
1228
1229 Read("bShowMeta", &read_int, 0);
1230 ps52plib->m_bShowMeta = !(read_int == 0);
1231
1232 Read("bUseSCAMIN", &read_int, 1);
1233 ps52plib->m_bUseSCAMIN = !(read_int == 0);
1234
1235 Read("bUseSUPER_SCAMIN", &read_int, 0);
1236 ps52plib->m_bUseSUPER_SCAMIN = !(read_int == 0);
1237
1238 Read("bShowAtonText", &read_int, 1);
1239 ps52plib->m_bShowAtonText = !(read_int == 0);
1240
1241 Read("bDeClutterText", &read_int, 0);
1242 ps52plib->m_bDeClutterText = !(read_int == 0);
1243
1244 Read("bShowNationalText", &read_int, 0);
1245 ps52plib->m_bShowNationalTexts = !(read_int == 0);
1246
1247 Read("ENCSoundingScaleFactor", &read_int, 0);
1248 ps52plib->m_nSoundingFactor = read_int;
1249
1250 Read("ENCTextScaleFactor", &read_int, 0);
1251 ps52plib->m_nTextFactor = read_int;
1252
1253 if (Read("S52_MAR_SAFETY_CONTOUR", &dval, 3.0)) {
1254 S52_setMarinerParam(S52_MAR_SAFETY_CONTOUR, dval);
1255 S52_setMarinerParam(S52_MAR_SAFETY_DEPTH,
1256 dval); // Set safety_contour and safety_depth the same
1257 }
1258
1259 if (Read("S52_MAR_SHALLOW_CONTOUR", &dval, 2.0))
1260 S52_setMarinerParam(S52_MAR_SHALLOW_CONTOUR, dval);
1261
1262 if (Read("S52_MAR_DEEP_CONTOUR", &dval, 6.0))
1263 S52_setMarinerParam(S52_MAR_DEEP_CONTOUR, dval);
1264
1265 if (Read("S52_MAR_TWO_SHADES", &dval, 0.0))
1266 S52_setMarinerParam(S52_MAR_TWO_SHADES, dval);
1267
1268 ps52plib->UpdateMarinerParams();
1269
1270 SetPath("/Settings/GlobalState");
1271 Read("S52_DEPTH_UNIT_SHOW", &read_int, 1); // default is metres
1272 read_int = wxMax(read_int, 0); // qualify value
1273 read_int = wxMin(read_int, 2);
1274 ps52plib->m_nDepthUnitDisplay = read_int;
1275 g_nDepthUnitDisplay = read_int;
1276
1277 // S57 Object Class Visibility
1278
1279 OBJLElement *pOLE;
1280
1281 SetPath("/Settings/ObjectFilter");
1282
1283 int iOBJMax = GetNumberOfEntries();
1284 if (iOBJMax) {
1285 wxString str;
1286 long val;
1287 long dummy;
1288
1289 wxString sObj;
1290
1291 bool bCont = pConfig->GetFirstEntry(str, dummy);
1292 while (bCont) {
1293 pConfig->Read(str, &val); // Get an Object Viz
1294
1295 bool bNeedNew = true;
1296
1297 if (str.StartsWith("viz", &sObj)) {
1298 for (unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount();
1299 iPtr++) {
1300 pOLE = (OBJLElement *)(ps52plib->pOBJLArray->Item(iPtr));
1301 if (!strncmp(pOLE->OBJLName, sObj.mb_str(), 6)) {
1302 pOLE->nViz = val;
1303 bNeedNew = false;
1304 break;
1305 }
1306 }
1307
1308 if (bNeedNew) {
1309 pOLE = (OBJLElement *)calloc(sizeof(OBJLElement), 1);
1310 memcpy(pOLE->OBJLName, sObj.mb_str(), OBJL_NAME_LEN);
1311 pOLE->nViz = 1;
1312
1313 ps52plib->pOBJLArray->Add((void *)pOLE);
1314 }
1315 }
1316 bCont = pConfig->GetNextEntry(str, dummy);
1317 }
1318 }
1319}
1320
1321bool MyConfig::LoadLayers(wxString &path) {
1322 wxArrayString file_array;
1323 wxDir dir;
1324 Layer *l;
1325 dir.Open(path);
1326 if (dir.IsOpened()) {
1327 wxString filename;
1328 bool cont = dir.GetFirst(&filename);
1329 while (cont) {
1330 file_array.Clear();
1331 filename.Prepend(wxFileName::GetPathSeparator());
1332 filename.Prepend(path);
1333 wxFileName f(filename);
1334 size_t nfiles = 0;
1335 if (f.GetExt().IsSameAs("gpx"))
1336 file_array.Add(filename); // single-gpx-file layer
1337 else {
1338 if (wxDir::Exists(filename)) {
1339 wxDir dir(filename);
1340 if (dir.IsOpened()) {
1341 nfiles = dir.GetAllFiles(filename, &file_array,
1342 "*.gpx"); // layers subdirectory set
1343 }
1344 }
1345 }
1346
1347 if (file_array.GetCount()) {
1348 l = new Layer();
1349 l->m_LayerID = ++g_LayerIdx;
1350 l->m_LayerFileName = file_array[0];
1351 if (file_array.GetCount() <= 1)
1352 wxFileName::SplitPath(file_array[0], NULL, NULL, &(l->m_LayerName),
1353 NULL, NULL);
1354 else
1355 wxFileName::SplitPath(filename, NULL, NULL, &(l->m_LayerName), NULL,
1356 NULL);
1357
1358 bool bLayerViz = g_bShowLayers;
1359
1360 if (g_VisibleLayers.Contains(l->m_LayerName)) bLayerViz = true;
1361 if (g_InvisibleLayers.Contains(l->m_LayerName)) bLayerViz = false;
1362
1363 l->m_bHasVisibleNames = wxCHK_UNDETERMINED;
1364 if (g_VisiNameinLayers.Contains(l->m_LayerName))
1365 l->m_bHasVisibleNames = wxCHK_CHECKED;
1366 if (g_InVisiNameinLayers.Contains(l->m_LayerName))
1367 l->m_bHasVisibleNames = wxCHK_UNCHECKED;
1368
1369 l->m_bIsVisibleOnChart = bLayerViz;
1370
1371 wxString laymsg;
1372 laymsg.Printf("New layer %d: %s", l->m_LayerID, l->m_LayerName.c_str());
1373 wxLogMessage(laymsg);
1374
1375 pLayerList->insert(pLayerList->begin(), l);
1376
1377 // Load the entire file array as a single layer
1378
1379 for (unsigned int i = 0; i < file_array.GetCount(); i++) {
1380 wxString file_path = file_array[i];
1381
1382 if (::wxFileExists(file_path)) {
1384 pugi::xml_parse_result result = pSet->load_file(file_path.fn_str());
1385 if (!result) {
1386 wxLogMessage("Error loading GPX file " + file_path);
1387 wxMessageBox(
1388 wxString::Format(
1389 _("Error loading GPX file %s, %s at character %d"),
1390 file_path, result.description(), result.offset),
1391 _("Import GPX File"));
1392 pSet->reset();
1393 }
1394 long nItems = pSet->LoadAllGPXObjectsAsLayer(
1395 l->m_LayerID, bLayerViz, l->m_bHasVisibleNames);
1396 l->m_NoOfItems += nItems;
1397 l->m_LayerType = _("Persistent");
1398
1399 wxString objmsg;
1400 objmsg.Printf("Loaded GPX file %s with %ld items.",
1401 file_path.c_str(), nItems);
1402 wxLogMessage(objmsg);
1403
1404 delete pSet;
1405 }
1406 }
1407 }
1408
1409 cont = dir.GetNext(&filename);
1410 }
1411 }
1412 g_bLayersLoaded = true;
1413
1414 return true;
1415}
1416
1417bool MyConfig::LoadChartDirArray(ArrayOfCDI &ChartDirArray) {
1418 // Chart Directories
1419 SetPath("/ChartDirectories");
1420 int iDirMax = GetNumberOfEntries();
1421 if (iDirMax) {
1422 ChartDirArray.Empty();
1423 wxString str, val;
1424 long dummy;
1425 int nAdjustChartDirs = 0;
1426 int iDir = 0;
1427 bool bCont = pConfig->GetFirstEntry(str, dummy);
1428 while (bCont) {
1429 pConfig->Read(str, &val); // Get a Directory name
1430
1431 wxString dirname(val);
1432 if (!dirname.IsEmpty()) {
1433 /* Special case for first time run after Windows install with sample
1434 chart data... We desire that the sample configuration file opencpn.ini
1435 should not contain any installation dependencies, so... Detect and
1436 update the sample [ChartDirectories] entries to point to the Shared
1437 Data directory For instance, if the (sample) opencpn.ini file should
1438 contain shortcut coded entries like:
1439
1440 [ChartDirectories]
1441 ChartDir1=SampleCharts\\MaptechRegion7
1442
1443 then this entry will be updated to be something like:
1444 ChartDir1=c:\Program Files\opencpn\SampleCharts\\MaptechRegion7
1445
1446 */
1447 if (dirname.Find("SampleCharts") ==
1448 0) // only update entries starting with "SampleCharts"
1449 {
1450 nAdjustChartDirs++;
1451
1452 pConfig->DeleteEntry(str);
1453 wxString new_dir = dirname.Mid(dirname.Find("SampleCharts"));
1454 new_dir.Prepend(g_Platform->GetSharedDataDir());
1455 dirname = new_dir;
1456 }
1457
1458 ChartDirInfo cdi;
1459 cdi.fullpath = dirname.BeforeFirst('^');
1460 cdi.magic_number = dirname.AfterFirst('^');
1461
1462 ChartDirArray.Add(cdi);
1463 iDir++;
1464 }
1465
1466 bCont = pConfig->GetNextEntry(str, dummy);
1467 }
1468
1469 if (nAdjustChartDirs) pConfig->UpdateChartDirs(ChartDirArray);
1470 }
1471
1472 return true;
1473}
1474
1475bool MyConfig::UpdateChartDirs(ArrayOfCDI &dir_array) {
1476 wxString key, dir;
1477 wxString str_buf;
1478
1479 SetPath("/ChartDirectories");
1480 int iDirMax = GetNumberOfEntries();
1481 if (iDirMax) {
1482 long dummy;
1483
1484 for (int i = 0; i < iDirMax; i++) {
1485 GetFirstEntry(key, dummy);
1486 DeleteEntry(key, false);
1487 }
1488 }
1489
1490 iDirMax = dir_array.GetCount();
1491
1492 for (int iDir = 0; iDir < iDirMax; iDir++) {
1493 ChartDirInfo cdi = dir_array[iDir];
1494
1495 wxString dirn = cdi.fullpath;
1496 dirn.Append("^");
1497 dirn.Append(cdi.magic_number);
1498
1499 str_buf.Printf("ChartDir%d", iDir + 1);
1500
1501 Write(str_buf, dirn);
1502 }
1503
1504// Avoid nonsense log errors...
1505#ifdef __ANDROID__
1506 wxLogNull logNo;
1507#endif
1508
1509 Flush();
1510 return true;
1511}
1512
1513void MyConfig::CreateConfigGroups(ChartGroupArray *pGroupArray) {
1514 if (!pGroupArray) return;
1515
1516 SetPath("/Groups");
1517 Write("GroupCount", (int)pGroupArray->GetCount());
1518
1519 for (unsigned int i = 0; i < pGroupArray->GetCount(); i++) {
1520 ChartGroup *pGroup = pGroupArray->Item(i);
1521 wxString s;
1522 s.Printf("Group%d", i + 1);
1523 s.Prepend("/Groups/");
1524 SetPath(s);
1525
1526 Write("GroupName", pGroup->m_group_name);
1527 Write("GroupItemCount", (int)pGroup->m_element_array.size());
1528
1529 for (unsigned int j = 0; j < pGroup->m_element_array.size(); j++) {
1530 wxString sg;
1531 sg.Printf("Group%d/Item%d", i + 1, j);
1532 sg.Prepend("/Groups/");
1533 SetPath(sg);
1534 Write("IncludeItem", pGroup->m_element_array[j].m_element_name);
1535
1536 wxString t;
1537 wxArrayString u = pGroup->m_element_array[j].m_missing_name_array;
1538 if (u.GetCount()) {
1539 for (unsigned int k = 0; k < u.GetCount(); k++) {
1540 t += u[k];
1541 t += ";";
1542 }
1543 Write("ExcludeItems", t);
1544 }
1545 }
1546 }
1547}
1548
1549void MyConfig::DestroyConfigGroups() {
1550 DeleteGroup("/Groups"); // zap
1551}
1552
1553void MyConfig::LoadConfigGroups(ChartGroupArray *pGroupArray) {
1554 SetPath("/Groups");
1555 unsigned int group_count;
1556 Read("GroupCount", (int *)&group_count, 0);
1557
1558 for (unsigned int i = 0; i < group_count; i++) {
1559 ChartGroup *pGroup = new ChartGroup;
1560 wxString s;
1561 s.Printf("Group%d", i + 1);
1562 s.Prepend("/Groups/");
1563 SetPath(s);
1564
1565 wxString t;
1566 Read("GroupName", &t);
1567 pGroup->m_group_name = t;
1568
1569 unsigned int item_count;
1570 Read("GroupItemCount", (int *)&item_count);
1571 for (unsigned int j = 0; j < item_count; j++) {
1572 wxString sg;
1573 sg.Printf("Group%d/Item%d", i + 1, j);
1574 sg.Prepend("/Groups/");
1575 SetPath(sg);
1576
1577 wxString v;
1578 Read("IncludeItem", &v);
1579
1580 ChartGroupElement pelement{v};
1581 wxString u;
1582 if (Read("ExcludeItems", &u)) {
1583 if (!u.IsEmpty()) {
1584 wxStringTokenizer tk(u, ";");
1585 while (tk.HasMoreTokens()) {
1586 wxString token = tk.GetNextToken();
1587 pelement.m_missing_name_array.Add(token);
1588 }
1589 }
1590 }
1591 pGroup->m_element_array.push_back(std::move(pelement));
1592 }
1593 pGroupArray->Add(pGroup);
1594 }
1595}
1596
1597void MyConfig::LoadCanvasConfigs(bool bApplyAsTemplate) {
1598 wxString s;
1599 canvasConfig *pcc;
1600 auto &config_array = ConfigMgr::Get().GetCanvasConfigArray();
1601
1602 SetPath("/Canvas");
1603
1604 // If the canvas config has never been set/persisted, use the global settings
1605 if (!HasEntry("CanvasConfig")) {
1606 pcc = new canvasConfig(0);
1607 pcc->LoadFromLegacyConfig(this);
1608 config_array.Add(pcc);
1609
1610 return;
1611 }
1612
1613 Read("CanvasConfig", (int *)&g_canvasConfig, 0);
1614
1615 // Do not recreate canvasConfigs when applying config dynamically
1616 if (config_array.GetCount() == 0) { // This is initial load from startup
1617 s.Printf("/Canvas/CanvasConfig%d", 1);
1618 SetPath(s);
1619 canvasConfig *pcca = new canvasConfig(0);
1620 LoadConfigCanvas(pcca, bApplyAsTemplate);
1621 config_array.Add(pcca);
1622
1623 s.Printf("/Canvas/CanvasConfig%d", 2);
1624 SetPath(s);
1625 pcca = new canvasConfig(1);
1626 LoadConfigCanvas(pcca, bApplyAsTemplate);
1627 config_array.Add(pcca);
1628 } else { // This is a dynamic (i.e. Template) load
1629 canvasConfig *pcca = config_array[0];
1630 s.Printf("/Canvas/CanvasConfig%d", 1);
1631 SetPath(s);
1632 LoadConfigCanvas(pcca, bApplyAsTemplate);
1633
1634 if (config_array.GetCount() > 1) {
1635 canvasConfig *pcca = config_array[1];
1636 s.Printf("/Canvas/CanvasConfig%d", 2);
1637 SetPath(s);
1638 LoadConfigCanvas(pcca, bApplyAsTemplate);
1639 } else {
1640 s.Printf("/Canvas/CanvasConfig%d", 2);
1641 SetPath(s);
1642 pcca = new canvasConfig(1);
1643 LoadConfigCanvas(pcca, bApplyAsTemplate);
1644 config_array.Add(pcca);
1645 }
1646 }
1647}
1648
1649void MyConfig::LoadConfigCanvas(canvasConfig *cConfig, bool bApplyAsTemplate) {
1650 wxString st;
1651 double st_lat, st_lon;
1652
1653 if (!bApplyAsTemplate) {
1654 // Reasonable starting point
1655 cConfig->iLat = START_LAT; // display viewpoint
1656 cConfig->iLon = START_LON;
1657
1658 if (Read("canvasVPLatLon", &st)) {
1659 sscanf(st.mb_str(wxConvUTF8), "%lf,%lf", &st_lat, &st_lon);
1660
1661 // Sanity check the lat/lon...both have to be reasonable.
1662 if (fabs(st_lon) < 360.) {
1663 while (st_lon < -180.) st_lon += 360.;
1664
1665 while (st_lon > 180.) st_lon -= 360.;
1666
1667 cConfig->iLon = st_lon;
1668 }
1669
1670 if (fabs(st_lat) < 90.0) cConfig->iLat = st_lat;
1671 }
1672
1673 cConfig->iScale = .0003; // decent initial value
1674 cConfig->iRotation = 0;
1675
1676 double st_view_scale;
1677 if (Read(wxString("canvasVPScale"), &st)) {
1678 sscanf(st.mb_str(wxConvUTF8), "%lf", &st_view_scale);
1679 // Sanity check the scale
1680 st_view_scale = fmax(st_view_scale, .001 / 32);
1681 st_view_scale = fmin(st_view_scale, 4);
1682 cConfig->iScale = st_view_scale;
1683 }
1684
1685 double st_rotation;
1686 if (Read(wxString("canvasVPRotation"), &st)) {
1687 sscanf(st.mb_str(wxConvUTF8), "%lf", &st_rotation);
1688 // Sanity check the rotation
1689 st_rotation = fmin(st_rotation, 360);
1690 st_rotation = fmax(st_rotation, 0);
1691 cConfig->iRotation = st_rotation * PI / 180.;
1692 }
1693
1694 Read("canvasInitialdBIndex", &cConfig->DBindex, 0);
1695 Read("canvasbFollow", &cConfig->bFollow, 0);
1696
1697 Read("canvasCourseUp", &cConfig->bCourseUp, 0);
1698 Read("canvasHeadUp", &cConfig->bHeadUp, 0);
1699 Read("canvasLookahead", &cConfig->bLookahead, 0);
1700 }
1701
1702 Read("ActiveChartGroup", &cConfig->GroupID, 0);
1703
1704 // Special check for group selection when applied as template
1705 if (cConfig->GroupID && bApplyAsTemplate) {
1706 if (cConfig->GroupID > (int)g_pGroupArray->GetCount()) cConfig->GroupID = 0;
1707 }
1708
1709 Read("canvasShowTides", &cConfig->bShowTides, 0);
1710 Read("canvasShowCurrents", &cConfig->bShowCurrents, 0);
1711
1712 Read("canvasQuilt", &cConfig->bQuilt, 1);
1713 Read("canvasShowGrid", &cConfig->bShowGrid, 0);
1714 Read("canvasShowOutlines", &cConfig->bShowOutlines, 0);
1715 Read("canvasShowDepthUnits", &cConfig->bShowDepthUnits, 0);
1716
1717 Read("canvasShowAIS", &cConfig->bShowAIS, 1);
1718 Read("canvasAttenAIS", &cConfig->bAttenAIS, 0);
1719
1720 // ENC options
1721 Read("canvasShowENCText", &cConfig->bShowENCText, 1);
1722 Read("canvasENCDisplayCategory", &cConfig->nENCDisplayCategory, STANDARD);
1723 Read("canvasENCShowDepths", &cConfig->bShowENCDepths, 1);
1724 Read("canvasENCShowBuoyLabels", &cConfig->bShowENCBuoyLabels, 1);
1725 Read("canvasENCShowLightDescriptions", &cConfig->bShowENCLightDescriptions,
1726 1);
1727 Read("canvasENCShowLights", &cConfig->bShowENCLights, 1);
1728 Read("canvasENCShowVisibleSectorLights",
1729 &cConfig->bShowENCVisibleSectorLights, 0);
1730 Read("canvasENCShowAnchorInfo", &cConfig->bShowENCAnchorInfo, 0);
1731 Read("canvasENCShowDataQuality", &cConfig->bShowENCDataQuality, 0);
1732
1733 int sx, sy;
1734 Read("canvasSizeX", &sx, 0);
1735 Read("canvasSizeY", &sy, 0);
1736 cConfig->canvasSize = wxSize(sx, sy);
1737}
1738
1739void MyConfig::SaveCanvasConfigs() {
1740 auto &config_array = ConfigMgr::Get().GetCanvasConfigArray();
1741
1742 SetPath("/Canvas");
1743 Write("CanvasConfig", (int)g_canvasConfig);
1744
1745 wxString s;
1746 canvasConfig *pcc;
1747
1748 switch (g_canvasConfig) {
1749 case 0:
1750 default:
1751
1752 s.Printf("/Canvas/CanvasConfig%d", 1);
1753 SetPath(s);
1754
1755 if (config_array.GetCount() > 0) {
1756 pcc = config_array.Item(0);
1757 if (pcc) {
1758 SaveConfigCanvas(pcc);
1759 }
1760 }
1761 break;
1762
1763 case 1:
1764
1765 if (config_array.GetCount() > 1) {
1766 s.Printf("/Canvas/CanvasConfig%d", 1);
1767 SetPath(s);
1768 pcc = config_array.Item(0);
1769 if (pcc) {
1770 SaveConfigCanvas(pcc);
1771 }
1772
1773 s.Printf("/Canvas/CanvasConfig%d", 2);
1774 SetPath(s);
1775 pcc = config_array.Item(1);
1776 if (pcc) {
1777 SaveConfigCanvas(pcc);
1778 }
1779 }
1780 break;
1781 }
1782}
1783
1784void MyConfig::SaveConfigCanvas(canvasConfig *cConfig) {
1785 wxString st1;
1786
1787 if (cConfig->canvas) {
1788 ViewPort vp = cConfig->canvas->GetVP();
1789
1790 if (vp.IsValid()) {
1791 st1.Printf("%10.4f,%10.4f", vp.clat, vp.clon);
1792 Write("canvasVPLatLon", st1);
1793 st1.Printf("%g", vp.view_scale_ppm);
1794 Write("canvasVPScale", st1);
1795 st1.Printf("%i", ((int)(vp.rotation * 180 / PI)) % 360);
1796 Write("canvasVPRotation", st1);
1797 }
1798
1799 int restore_dbindex = 0;
1800 ChartStack *pcs = cConfig->canvas->GetpCurrentStack();
1801 if (pcs) restore_dbindex = pcs->GetCurrentEntrydbIndex();
1802 if (cConfig->canvas->GetQuiltMode())
1803 restore_dbindex = cConfig->canvas->GetQuiltReferenceChartIndex();
1804 Write("canvasInitialdBIndex", restore_dbindex);
1805
1806 Write("canvasbFollow", cConfig->canvas->m_bFollow);
1807 Write("ActiveChartGroup", cConfig->canvas->m_groupIndex);
1808
1809 Write("canvasQuilt", cConfig->canvas->GetQuiltMode());
1810 Write("canvasShowGrid", cConfig->canvas->GetShowGrid());
1811 Write("canvasShowOutlines", cConfig->canvas->GetShowOutlines());
1812 Write("canvasShowDepthUnits", cConfig->canvas->GetShowDepthUnits());
1813
1814 Write("canvasShowAIS", cConfig->canvas->GetShowAIS());
1815 Write("canvasAttenAIS", cConfig->canvas->GetAttenAIS());
1816
1817 Write("canvasShowTides", cConfig->canvas->GetbShowTide());
1818 Write("canvasShowCurrents", cConfig->canvas->GetbShowCurrent());
1819
1820 // ENC options
1821 Write("canvasShowENCText", cConfig->canvas->GetShowENCText());
1822 Write("canvasENCDisplayCategory", cConfig->canvas->GetENCDisplayCategory());
1823 Write("canvasENCShowDepths", cConfig->canvas->GetShowENCDepth());
1824 Write("canvasENCShowBuoyLabels", cConfig->canvas->GetShowENCBuoyLabels());
1825 Write("canvasENCShowLightDescriptions",
1826 cConfig->canvas->GetShowENCLightDesc());
1827 Write("canvasENCShowLights", cConfig->canvas->GetShowENCLights());
1828 Write("canvasENCShowVisibleSectorLights",
1829 cConfig->canvas->GetShowVisibleSectors());
1830 Write("canvasENCShowAnchorInfo", cConfig->canvas->GetShowENCAnchor());
1831 Write("canvasENCShowDataQuality", cConfig->canvas->GetShowENCDataQual());
1832 Write("canvasCourseUp", cConfig->canvas->GetUpMode() == COURSE_UP_MODE);
1833 Write("canvasHeadUp", cConfig->canvas->GetUpMode() == HEAD_UP_MODE);
1834 Write("canvasLookahead", cConfig->canvas->GetLookahead());
1835
1836 int width = cConfig->canvas->GetSize().x;
1837 // if(cConfig->canvas->IsPrimaryCanvas()){
1838 // width = wxMax(width, gFrame->GetClientSize().x / 10);
1839 // }
1840 // else{
1841 // width = wxMin(width, gFrame->GetClientSize().x * 9 / 10);
1842 // }
1843
1844 Write("canvasSizeX", width);
1845 Write("canvasSizeY", cConfig->canvas->GetSize().y);
1846 }
1847}
1848
1849void MyConfig::UpdateSettings() {
1850 // Temporarily suppress logging of trivial non-fatal wxLogSysError() messages
1851 // provoked by Android security...
1852#ifdef __ANDROID__
1853 wxLogNull logNo;
1854#endif
1855
1856 // Global options and settings
1857 SetPath("/Settings");
1858
1859 Write("LastAppliedTemplate", g_lastAppliedTemplateGUID);
1860 Write("CompatOS", g_compatOS);
1861 Write("CompatOsVersion", g_compatOsVersion);
1862 Write("ConfigVersionString", g_config_version_string);
1863 if (wxIsEmpty(g_CmdSoundString)) g_CmdSoundString = wxString(OCPN_SOUND_CMD);
1864 Write("CmdSoundString", g_CmdSoundString);
1865 Write("NavMessageShown", n_NavMessageShown);
1866 Write("InlandEcdis", g_bInlandEcdis);
1867
1868 Write("AndroidVersionCode", g_AndroidVersionCode);
1869
1870 Write("UIexpert", g_bUIexpert);
1871 Write("SpaceDropMark", g_bSpaceDropMark);
1872 // Write( "UIStyle", g_StyleManager->GetStyleNextInvocation() );
1873 // //Not desired for O5 MUI
1874
1875 Write("ShowStatusBar", g_bShowStatusBar);
1876#ifndef __WXOSX__
1877 Write("ShowMenuBar", g_bShowMenuBar);
1878#endif
1879 Write("DefaultFontSize", g_default_font_size);
1880 Write("DefaultFontFacename", g_default_font_facename);
1881
1882 Write("Fullscreen", g_bFullscreen);
1883 Write("ShowCompassWindow", g_bShowCompassWin);
1884 Write("SetSystemTime", s_bSetSystemTime);
1885 Write("ShowGrid", g_bDisplayGrid);
1886 Write("PlayShipsBells", g_bPlayShipsBells);
1887 Write("SoundDeviceIndex", g_iSoundDeviceIndex);
1888 Write("FullscreenToolbar", g_bFullscreenToolbar);
1889 Write("TransparentToolbar", g_bTransparentToolbar);
1890 Write("PermanentMOBIcon", g_bPermanentMOBIcon);
1891 Write("ShowLayers", g_bShowLayers);
1892 Write("AutoAnchorDrop", g_bAutoAnchorMark);
1893 Write("ShowChartOutlines", g_bShowOutlines);
1894 Write("ShowActiveRouteTotal", g_bShowRouteTotal);
1895 Write("ShowActiveRouteHighway", g_bShowActiveRouteHighway);
1896 Write("SDMMFormat", g_iSDMMFormat);
1897 Write("MostRecentGPSUploadConnection", g_uploadConnection);
1898 Write("ShowChartBar", g_bShowChartBar);
1899
1900 Write("GUIScaleFactor", g_GUIScaleFactor);
1901 Write("ChartObjectScaleFactor", g_ChartScaleFactor);
1902 Write("ShipScaleFactor", g_ShipScaleFactor);
1903 Write("ENCSoundingScaleFactor", g_ENCSoundingScaleFactor);
1904 Write("ENCTextScaleFactor", g_ENCTextScaleFactor);
1905 Write("ObjQueryAppendFilesExt", g_ObjQFileExt);
1906
1907 // Plugin catalog persistent values.
1908 Write("CatalogCustomURL", g_catalog_custom_url);
1909 Write("CatalogChannel", g_catalog_channel);
1910
1911 Write("NetmaskBits", g_netmask_bits);
1912 Write("FilterNMEA_Avg", g_bfilter_cogsog);
1913 Write("FilterNMEA_Sec", g_COGFilterSec);
1914
1915 Write("TrackContinuous", g_btrackContinuous);
1916
1917 Write("ShowTrue", g_bShowTrue);
1918 Write("ShowMag", g_bShowMag);
1919 Write("UserMagVariation", wxString::Format("%.2f", g_UserVar));
1920
1921 Write("CM93DetailFactor", g_cm93_zoom_factor);
1922 Write("CM93DetailZoomPosX", g_detailslider_dialog_x);
1923 Write("CM93DetailZoomPosY", g_detailslider_dialog_y);
1924 Write("ShowCM93DetailSlider", g_bShowDetailSlider);
1925
1926 Write("SkewToNorthUp", g_bskew_comp);
1927 if (!g_bdisable_opengl) { // Only modify the saved value if OpenGL is not
1928 // force-disabled from the command line
1929 Write("OpenGL", g_bopengl);
1930 }
1931 Write("SoftwareGL", g_bSoftwareGL);
1932
1933 Write("ZoomDetailFactor", g_chart_zoom_modifier_raster);
1934 Write("ZoomDetailFactorVector", g_chart_zoom_modifier_vector);
1935
1936 Write("FogOnOverzoom", g_fog_overzoom);
1937 Write("OverzoomVectorScale", g_oz_vector_scale);
1938 Write("OverzoomEmphasisBase", g_overzoom_emphasis_base);
1939 Write("PlusMinusZoomFactor", g_plus_minus_zoom_factor);
1940 Write("MouseZoomSensitivity",
1941 MouseZoom::ui_to_config(g_mouse_zoom_sensitivity_ui));
1942 Write("ShowMUIZoomButtons", g_bShowMuiZoomButtons);
1943
1944#ifdef ocpnUSE_GL
1945 /* opengl options */
1946 Write("UseAcceleratedPanning", g_GLOptions.m_bUseAcceleratedPanning);
1947
1948 Write("GPUTextureCompression", g_GLOptions.m_bTextureCompression);
1949 Write("GPUTextureCompressionCaching",
1950 g_GLOptions.m_bTextureCompressionCaching);
1951 Write("GPUTextureDimension", g_GLOptions.m_iTextureDimension);
1952 Write("GPUTextureMemSize", g_GLOptions.m_iTextureMemorySize);
1953 Write("PolygonSmoothing", g_GLOptions.m_GLPolygonSmoothing);
1954 Write("LineSmoothing", g_GLOptions.m_GLLineSmoothing);
1955#endif
1956 Write("SmoothPanZoom", g_bsmoothpanzoom);
1957
1958 Write("CourseUpMode", g_bCourseUp);
1959 if (!g_bInlandEcdis) Write("LookAheadMode", g_bLookAhead);
1960 Write("TenHzUpdate", g_btenhertz);
1961
1962 Write("COGUPAvgSeconds", g_COGAvgSec);
1963 Write("UseMagAPB", g_bMagneticAPB);
1964
1965 Write("OwnshipCOGPredictorMinutes", g_ownship_predictor_minutes);
1966 Write("OwnshipCOGPredictorStyle", g_cog_predictor_style);
1967 Write("OwnshipCOGPredictorColor", g_cog_predictor_color);
1968 Write("OwnshipCOGPredictorEndmarker", g_cog_predictor_endmarker);
1969 Write("OwnshipCOGPredictorWidth", g_cog_predictor_width);
1970 Write("OwnshipHDTPredictorStyle", g_ownship_HDTpredictor_style);
1971 Write("OwnshipHDTPredictorColor", g_ownship_HDTpredictor_color);
1972 Write("OwnshipHDTPredictorEndmarker", g_ownship_HDTpredictor_endmarker);
1973 Write("OwnShipMMSINumber", g_OwnShipmmsi);
1974 Write("OwnshipHDTPredictorWidth", g_ownship_HDTpredictor_width);
1975 Write("OwnshipHDTPredictorMiles", g_ownship_HDTpredictor_miles);
1976
1977 Write("OwnShipIconType", g_OwnShipIconType);
1978 Write("OwnShipLength", g_n_ownship_length_meters);
1979 Write("OwnShipWidth", g_n_ownship_beam_meters);
1980 Write("OwnShipGPSOffsetX", g_n_gps_antenna_offset_x);
1981 Write("OwnShipGPSOffsetY", g_n_gps_antenna_offset_y);
1982 Write("OwnShipMinSize", g_n_ownship_min_mm);
1983 Write("OwnShipSogCogCalc", g_own_ship_sog_cog_calc);
1984 Write("OwnShipSogCogCalcDampSec", g_own_ship_sog_cog_calc_damp_sec);
1985 Write("ShowDirectRouteLine", g_bShowShipToActive);
1986 Write("DirectRouteLineStyle", g_shipToActiveStyle);
1987 Write("DirectRouteLineColor", g_shipToActiveColor);
1988
1989 wxString racr;
1990 // racr.Printf( "%g", g_n_arrival_circle_radius );
1991 // Write( "RouteArrivalCircleRadius", racr );
1992 Write("RouteArrivalCircleRadius",
1993 wxString::Format("%.2f", g_n_arrival_circle_radius));
1994
1995 Write("ChartQuilting", g_bQuiltEnable);
1996
1997 Write("PreserveScaleOnX", g_bPreserveScaleOnX);
1998
1999 Write("StartWithTrackActive", g_bTrackCarryOver);
2000 Write("AutomaticDailyTracks", g_bTrackDaily);
2001 Write("TrackRotateAt", g_track_rotate_time);
2002 Write("TrackRotateTimeType", g_track_rotate_time_type);
2003 Write("HighlightTracks", g_bHighliteTracks);
2004
2005 Write("DateTimeFormat", g_datetime_format);
2006 Write("InitialStackIndex", g_restore_stackindex);
2007 Write("InitialdBIndex", g_restore_dbindex);
2008
2009 Write("NMEAAPBPrecision", g_NMEAAPBPrecision);
2010
2011 Write("TalkerIdText", g_TalkerIdText);
2012 Write("ShowTrackPointTime", g_bShowTrackPointTime);
2013
2014 Write("AnchorWatch1GUID", g_AW1GUID);
2015 Write("AnchorWatch2GUID", g_AW2GUID);
2016
2017 Write("ToolbarX", g_maintoolbar_x);
2018 Write("ToolbarY", g_maintoolbar_y);
2019 // Write( "ToolbarOrient", g_maintoolbar_orient );
2020
2021 Write("iENCToolbarX", g_iENCToolbarPosX);
2022 Write("iENCToolbarY", g_iENCToolbarPosY);
2023
2024 if (!g_bInlandEcdis) {
2025 Write("GlobalToolbarConfig", g_toolbarConfig);
2026 Write("DistanceFormat", g_iDistanceFormat);
2027 Write("SpeedFormat", g_iSpeedFormat);
2028 Write("WindSpeedFormat", g_iWindSpeedFormat);
2029 Write("ShowDepthUnits", g_bShowDepthUnits);
2030 Write("TemperatureFormat", g_iTempFormat);
2031 Write("HeightFormat", g_iHeightFormat);
2032 }
2033 Write("GPSIdent", g_GPS_Ident);
2034 Write("ActiveRoute", g_active_route);
2035 Write("PersistActiveRoute", g_persist_active_route);
2036 Write("AlwaysSendRmbRmc", g_always_send_rmb_rmc);
2037
2038 Write("UseGarminHostUpload", g_bGarminHostUpload);
2039
2040 Write("MobileTouch", g_btouch);
2041 Write("ResponsiveGraphics", g_bresponsive);
2042 Write("EnableRolloverBlock", g_bRollover);
2043
2044 Write("AutoHideToolbar", g_bAutoHideToolbar);
2045 Write("AutoHideToolbarSecs", g_nAutoHideToolbar);
2046
2047 wxString st0;
2048 for (const auto &mm : g_config_display_size_mm) {
2049 st0.Append(wxString::Format("%zu,", mm));
2050 }
2051 st0.RemoveLast(); // Strip last comma
2052 Write("DisplaySizeMM", st0);
2053 Write("DisplaySizeManual", g_config_display_size_manual);
2054
2055 Write("SelectionRadiusMM", g_selection_radius_mm);
2056 Write("SelectionRadiusTouchMM", g_selection_radius_touch_mm);
2057
2058 st0.Printf("%g", g_PlanSpeed);
2059 Write("PlanSpeed", st0);
2060
2061 if (g_bLayersLoaded) {
2062 wxString vis, invis, visnames, invisnames;
2063 LayerList::iterator it;
2064 int index = 0;
2065 for (it = (*pLayerList).begin(); it != (*pLayerList).end(); ++it, ++index) {
2066 Layer *lay = (Layer *)(*it);
2067 if (lay->IsVisibleOnChart())
2068 vis += (lay->m_LayerName) + ";";
2069 else
2070 invis += (lay->m_LayerName) + ";";
2071
2072 if (lay->HasVisibleNames() == wxCHK_CHECKED) {
2073 visnames += (lay->m_LayerName) + ";";
2074 } else if (lay->HasVisibleNames() == wxCHK_UNCHECKED) {
2075 invisnames += (lay->m_LayerName) + ";";
2076 }
2077 }
2078 Write("VisibleLayers", vis);
2079 Write("InvisibleLayers", invis);
2080 Write("VisNameInLayers", visnames);
2081 Write("InvisNameInLayers", invisnames);
2082 }
2083 Write("Locale", g_locale);
2084 Write("LocaleOverride", g_localeOverride);
2085
2086 Write("KeepNavobjBackups", g_navobjbackups);
2087 Write("LegacyInputCOMPortFilterBehaviour", g_b_legacy_input_filter_behaviour);
2088 Write("AdvanceRouteWaypointOnArrivalOnly",
2089 g_bAdvanceRouteWaypointOnArrivalOnly);
2090 Write("EnableRootMenuDebug", g_enable_root_menu_debug);
2091
2092 // LIVE ETA OPTION
2093 Write("LiveETA", g_bShowLiveETA);
2094 Write("DefaultBoatSpeed", g_defaultBoatSpeed);
2095
2096 // S57 Object Filter Settings
2097
2098 SetPath("/Settings/ObjectFilter");
2099
2100 if (ps52plib) {
2101 for (unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount();
2102 iPtr++) {
2103 OBJLElement *pOLE = (OBJLElement *)(ps52plib->pOBJLArray->Item(iPtr));
2104
2105 wxString st1("viz");
2106 char name[7];
2107 strncpy(name, pOLE->OBJLName, 6);
2108 name[6] = 0;
2109 st1.Append(wxString(name, wxConvUTF8));
2110 Write(st1, pOLE->nViz);
2111 }
2112 }
2113
2114 // Global State
2115
2116 SetPath("/Settings/GlobalState");
2117
2118 wxString st1;
2119
2120 // if( cc1 ) {
2121 // ViewPort vp = cc1->GetVP();
2122 //
2123 // if( vp.IsValid() ) {
2124 // st1.Printf( "%10.4f,%10.4f", vp.clat, vp.clon );
2125 // Write( "VPLatLon", st1 );
2126 // st1.Printf( "%g", vp.view_scale_ppm );
2127 // Write( "VPScale", st1 );
2128 // st1.Printf( "%i", ((int)(vp.rotation * 180 / PI)) % 360
2129 // ); Write( "VPRotation", st1 );
2130 // }
2131 // }
2132
2133 st1.Printf("%10.4f, %10.4f", gLat, gLon);
2134 Write("OwnShipLatLon", st1);
2135
2136 // Various Options
2137 SetPath("/Settings/GlobalState");
2138 if (!g_bInlandEcdis) Write("nColorScheme", (int)gFrame->GetColorScheme());
2139
2140 Write("FrameWinX", g_nframewin_x);
2141 Write("FrameWinY", g_nframewin_y);
2142 Write("FrameWinPosX", g_nframewin_posx);
2143 Write("FrameWinPosY", g_nframewin_posy);
2144 Write("FrameMax", g_bframemax);
2145
2146 Write("ClientPosX", g_lastClientRectx);
2147 Write("ClientPosY", g_lastClientRecty);
2148 Write("ClientSzX", g_lastClientRectw);
2149 Write("ClientSzY", g_lastClientRecth);
2150
2151 Write("S52_DEPTH_UNIT_SHOW", g_nDepthUnitDisplay);
2152
2153 Write("RoutePropSizeX", g_route_prop_sx);
2154 Write("RoutePropSizeY", g_route_prop_sy);
2155 Write("RoutePropPosX", g_route_prop_x);
2156 Write("RoutePropPosY", g_route_prop_y);
2157
2158 // Sounds
2159 SetPath("/Settings/Audio");
2160 Write("AISAlertSoundFile", g_AIS_sound_file);
2161 Write("DSCAlertSoundFile", g_DSC_sound_file);
2162 Write("SARTAlertSoundFile", g_SART_sound_file);
2163 Write("AnchorAlarmSoundFile", g_anchorwatch_sound_file);
2164
2165 Write("bAIS_GCPA_AlertAudio", g_bAIS_GCPA_Alert_Audio);
2166 Write("bAIS_SART_AlertAudio", g_bAIS_SART_Alert_Audio);
2167 Write("bAIS_DSC_AlertAudio", g_bAIS_DSC_Alert_Audio);
2168 Write("bAnchorAlertAudio", g_bAnchor_Alert_Audio);
2169
2170 // AIS
2171 SetPath("/Settings/AIS");
2172
2173 Write("bNoCPAMax", g_bCPAMax);
2174 Write("NoCPAMaxNMi", g_CPAMax_NM);
2175 Write("bCPAWarn", g_bCPAWarn);
2176 Write("CPAWarnNMi", g_CPAWarn_NM);
2177 Write("bTCPAMax", g_bTCPA_Max);
2178 Write("TCPAMaxMinutes", g_TCPA_Max);
2179 Write("bMarkLostTargets", g_bMarkLost);
2180 Write("MarkLost_Minutes", g_MarkLost_Mins);
2181 Write("bRemoveLostTargets", g_bRemoveLost);
2182 Write("RemoveLost_Minutes", g_RemoveLost_Mins);
2183 Write("bShowCOGArrows", g_bShowCOG);
2184 Write("bSyncCogPredictors", g_bSyncCogPredictors);
2185 Write("CogArrowMinutes", g_ShowCOG_Mins);
2186 Write("bShowTargetTracks", g_bAISShowTracks);
2187 Write("TargetTracksMinutes", g_AISShowTracks_Mins);
2188
2189 Write("bHideMooredTargets", g_bHideMoored);
2190 Write("MooredTargetMaxSpeedKnots", g_ShowMoored_Kts);
2191
2192 Write("bAISAlertDialog", g_bAIS_CPA_Alert);
2193 Write("bAISAlertAudio", g_bAIS_CPA_Alert_Audio);
2194
2195 Write("AISAlertAudioFile", g_sAIS_Alert_Sound_File);
2196 Write("bAISAlertSuppressMoored", g_bAIS_CPA_Alert_Suppress_Moored);
2197 Write("bShowAreaNotices", g_bShowAreaNotices);
2198 Write("bDrawAISSize", g_bDrawAISSize);
2199 Write("bDrawAISRealtime", g_bDrawAISRealtime);
2200 Write("AISRealtimeMinSpeedKnots", g_AIS_RealtPred_Kts);
2201 Write("bShowAISName", g_bShowAISName);
2202 Write("ShowAISTargetNameScale", g_Show_Target_Name_Scale);
2203 Write("bWplIsAprsPositionReport", g_bWplUsePosition);
2204 Write("WplSelAction", g_WplAction);
2205 Write("AISCOGPredictorWidth", g_ais_cog_predictor_width);
2206 Write("bShowScaledTargets", g_bAllowShowScaled);
2207 Write("AISScaledNumber", g_ShowScaled_Num);
2208 Write("AISScaledNumberWeightSOG", g_ScaledNumWeightSOG);
2209 Write("AISScaledNumberWeightCPA", g_ScaledNumWeightCPA);
2210 Write("AISScaledNumberWeightTCPA", g_ScaledNumWeightTCPA);
2211 Write("AISScaledNumberWeightRange", g_ScaledNumWeightRange);
2212 Write("AISScaledNumberWeightSizeOfTarget", g_ScaledNumWeightSizeOfT);
2213 Write("AISScaledSizeMinimal", g_ScaledSizeMinimal);
2214 Write("AISShowScaled", g_bShowScaled);
2215
2216 Write("AlertDialogSizeX", g_ais_alert_dialog_sx);
2217 Write("AlertDialogSizeY", g_ais_alert_dialog_sy);
2218 Write("AlertDialogPosX", g_ais_alert_dialog_x);
2219 Write("AlertDialogPosY", g_ais_alert_dialog_y);
2220 Write("QueryDialogPosX", g_ais_query_dialog_x);
2221 Write("QueryDialogPosY", g_ais_query_dialog_y);
2222 Write("AISTargetListPerspective", g_AisTargetList_perspective);
2223 Write("AISTargetListRange", g_AisTargetList_range);
2224 Write("AISTargetListSortColumn", g_AisTargetList_sortColumn);
2225 Write("bAISTargetListSortReverse", g_bAisTargetList_sortReverse);
2226 Write("AISTargetListColumnSpec", g_AisTargetList_column_spec);
2227 Write("AISTargetListColumnOrder", g_AisTargetList_column_order);
2228
2229 Write("S57QueryDialogSizeX", g_S57_dialog_sx);
2230 Write("S57QueryDialogSizeY", g_S57_dialog_sy);
2231 Write("S57QueryExtraDialogSizeX", g_S57_extradialog_sx);
2232 Write("S57QueryExtraDialogSizeY", g_S57_extradialog_sy);
2233
2234 Write("bAISRolloverShowClass", g_bAISRolloverShowClass);
2235 Write("bAISRolloverShowCOG", g_bAISRolloverShowCOG);
2236 Write("bAISRolloverShowCPA", g_bAISRolloverShowCPA);
2237
2238 Write("bAISAlertAckTimeout", g_bAIS_ACK_Timeout);
2239 Write("AlertAckTimeoutMinutes", g_AckTimeout_Mins);
2240
2241 SetPath("/Settings/GlobalState");
2242 if (ps52plib) {
2243 Write("bShowS57Text", ps52plib->GetShowS57Text());
2244 Write("bShowS57ImportantTextOnly", ps52plib->GetShowS57ImportantTextOnly());
2245 if (!g_bInlandEcdis)
2246 Write("nDisplayCategory", (long)ps52plib->GetDisplayCategory());
2247 Write("nSymbolStyle", (int)ps52plib->m_nSymbolStyle);
2248 Write("nBoundaryStyle", (int)ps52plib->m_nBoundaryStyle);
2249
2250 Write("bShowSoundg", ps52plib->m_bShowSoundg);
2251 Write("bShowMeta", ps52plib->m_bShowMeta);
2252 Write("bUseSCAMIN", ps52plib->m_bUseSCAMIN);
2253 Write("bUseSUPER_SCAMIN", ps52plib->m_bUseSUPER_SCAMIN);
2254 Write("bShowAtonText", ps52plib->m_bShowAtonText);
2255 Write("bShowLightDescription", ps52plib->m_bShowLdisText);
2256 Write("bExtendLightSectors", ps52plib->m_bExtendLightSectors);
2257 Write("bDeClutterText", ps52plib->m_bDeClutterText);
2258 Write("bShowNationalText", ps52plib->m_bShowNationalTexts);
2259
2260 Write("S52_MAR_SAFETY_CONTOUR",
2261 S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR));
2262 Write("S52_MAR_SHALLOW_CONTOUR",
2263 S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR));
2264 Write("S52_MAR_DEEP_CONTOUR", S52_getMarinerParam(S52_MAR_DEEP_CONTOUR));
2265 Write("S52_MAR_TWO_SHADES", S52_getMarinerParam(S52_MAR_TWO_SHADES));
2266 Write("S52_DEPTH_UNIT_SHOW", ps52plib->m_nDepthUnitDisplay);
2267 Write("ENCSoundingScaleFactor", g_ENCSoundingScaleFactor);
2268 Write("ENCTextScaleFactor", g_ENCTextScaleFactor);
2269 }
2270 SetPath("/Directories");
2271 Write("S57DataLocation", "");
2272 // Write( "SENCFileLocation", "" );
2273
2274 SetPath("/Directories");
2275 Write("InitChartDir", *pInit_Chart_Dir);
2276 Write("GPXIODir", g_gpx_path);
2277 Write("TCDataDir", g_TCData_Dir);
2278 Write("BasemapDir", g_Platform->NormalizePath(gWorldMapLocation));
2279 Write("BaseShapefileDir", g_Platform->NormalizePath(gWorldShapefileLocation));
2280 Write("pluginInstallDir", g_Platform->NormalizePath(g_winPluginDir));
2281
2282 SetPath("/Settings/NMEADataSource");
2283 wxString connectionconfigs;
2284 for (size_t i = 0; i < TheConnectionParams().size(); i++) {
2285 if (i > 0) connectionconfigs.Append("|");
2286 connectionconfigs.Append(TheConnectionParams()[i]->Serialize());
2287 }
2288 Write("DataConnections", connectionconfigs);
2289
2290 // Fonts
2291
2292 // Store the persistent Auxiliary Font descriptor Keys
2293 SetPath("/Settings/AuxFontKeys");
2294
2295 wxArrayString keyArray = FontMgr::Get().GetAuxKeyArray();
2296 for (unsigned int i = 0; i < keyArray.GetCount(); i++) {
2297 wxString key;
2298 key.Printf("Key%i", i);
2299 wxString keyval = keyArray[i];
2300 Write(key, keyval);
2301 }
2302
2303 wxString font_path;
2304#ifdef __WXX11__
2305 font_path = ("/Settings/X11Fonts");
2306#endif
2307
2308#ifdef __WXGTK__
2309 font_path = ("/Settings/GTKFonts");
2310#endif
2311
2312#ifdef __WXMSW__
2313 font_path = ("/Settings/MSWFonts");
2314#endif
2315
2316#ifdef __WXMAC__
2317 font_path = ("/Settings/MacFonts");
2318#endif
2319
2320#ifdef __WXQT__
2321 font_path = ("/Settings/QTFonts");
2322#endif
2323
2324 if (HasEntry(font_path)) DeleteGroup(font_path);
2325
2326 SetPath(font_path);
2327
2328 int nFonts = FontMgr::Get().GetNumFonts();
2329
2330 for (int i = 0; i < nFonts; i++) {
2331 wxString cfstring(FontMgr::Get().GetConfigString(i));
2332 wxString valstring = FontMgr::Get().GetFullConfigDesc(i);
2333 Write(cfstring, valstring);
2334 }
2335
2336 // Tide/Current Data Sources
2337 if (HasGroup("/TideCurrentDataSources"))
2338 DeleteGroup("/TideCurrentDataSources");
2339 SetPath("/TideCurrentDataSources");
2340 unsigned int id = 0;
2341 for (auto val : TideCurrentDataSet) {
2342 wxString key;
2343 key.Printf("tcds%d", id);
2344 Write(key, wxString(val));
2345 ++id;
2346 }
2347
2348 SetPath("/Settings/Others");
2349
2350 // Radar rings
2351 Write("ShowRadarRings",
2352 (bool)(g_iNavAidRadarRingsNumberVisible > 0)); // 3.0.0 config support
2353 Write("RadarRingsNumberVisible", g_iNavAidRadarRingsNumberVisible);
2354 Write("RadarRingsStep", g_fNavAidRadarRingsStep);
2355 Write("RadarRingsStepUnits", g_pNavAidRadarRingsStepUnits);
2356 Write("RadarRingsColour",
2357 g_colourOwnshipRangeRingsColour.GetAsString(wxC2S_HTML_SYNTAX));
2358 Write("WaypointUseScaMin", g_bUseWptScaMin);
2359 Write("WaypointScaMinValue", g_iWpt_ScaMin);
2360 Write("WaypointUseScaMinOverrule", g_bOverruleScaMin);
2361 Write("WaypointsShowName", g_bShowWptName);
2362 Write("UserIconsFirst", g_bUserIconsFirst);
2363
2364 // Waypoint Radar rings
2365 Write("WaypointRangeRingsNumber", g_iWaypointRangeRingsNumber);
2366 Write("WaypointRangeRingsStep", g_fWaypointRangeRingsStep);
2367 Write("WaypointRangeRingsStepUnits", g_iWaypointRangeRingsStepUnits);
2368 Write("WaypointRangeRingsColour",
2369 g_colourWaypointRangeRingsColour.GetAsString(wxC2S_HTML_SYNTAX));
2370
2371 Write("ConfirmObjectDeletion", g_bConfirmObjectDelete);
2372
2373 // Waypoint dragging with mouse; toh, 2009.02.24
2374 Write("WaypointPreventDragging", g_bWayPointPreventDragging);
2375
2376 Write("EnableZoomToCursor", g_bEnableZoomToCursor);
2377
2378 Write("TrackIntervalSeconds", g_TrackIntervalSeconds);
2379 Write("TrackDeltaDistance", g_TrackDeltaDistance);
2380 Write("TrackPrecision", g_nTrackPrecision);
2381
2382 Write("RouteLineWidth", g_route_line_width);
2383 Write("TrackLineWidth", g_track_line_width);
2384 Write("TrackLineColour",
2385 g_colourTrackLineColour.GetAsString(wxC2S_HTML_SYNTAX));
2386 Write("DefaultWPIcon", g_default_wp_icon);
2387 Write("DefaultRPIcon", g_default_routepoint_icon);
2388
2389 DeleteGroup("/MmsiProperties");
2390 SetPath("/MmsiProperties");
2391 for (unsigned int i = 0; i < g_MMSI_Props_Array.GetCount(); i++) {
2392 wxString p;
2393 p.Printf("Props%d", i);
2394 Write(p, g_MMSI_Props_Array[i]->Serialize());
2395 }
2396 SetPath("/DataMonitor");
2397 Write("colors.ok", g_dm_ok);
2398 Write("colors.dropped", g_dm_dropped);
2399 Write("colors.filtered", g_dm_filtered);
2400 Write("colors.input", g_dm_input);
2401 Write("colors.output", g_dm_output);
2402 Write("colors.not-ok", g_dm_not_ok);
2403
2404 SaveCanvasConfigs();
2405
2406 Flush();
2407 SendMessageToAllPlugins("GLOBAL_SETTINGS_UPDATED", "{\"updated\":\"1\"}");
2408}
2409
2410static wxFileName exportFileName(wxWindow *parent,
2411 const wxString suggestedName) {
2412 wxFileName ret;
2413 wxString path;
2414 wxString valid_name = SanitizeFileName(suggestedName);
2415
2416#ifdef __ANDROID__
2417 if (!valid_name.EndsWith(".gpx")) {
2418 wxFileName fn(valid_name);
2419 fn.ClearExt();
2420 fn.SetExt("gpx");
2421 valid_name = fn.GetFullName();
2422 }
2423#endif
2424 int response = g_Platform->DoFileSelectorDialog(
2425 parent, &path, _("Export GPX file"), g_gpx_path, valid_name, "*.gpx");
2426
2427 if (response == wxID_OK) {
2428 wxFileName fn(path);
2429 g_gpx_path = fn.GetPath();
2430 if (!fn.GetExt().StartsWith("gpx")) fn.SetExt("gpx");
2431
2432#if defined(__WXMSW__) || defined(__WXGTK__)
2433 if (wxFileExists(fn.GetFullPath())) {
2434 int answer = OCPNMessageBox(NULL, _("Overwrite existing file?"),
2435 "Confirm", wxICON_QUESTION | wxYES_NO);
2436 if (answer != wxID_YES) return ret;
2437 }
2438#endif
2439 ret = fn;
2440 }
2441 return ret;
2442}
2443
2444int BackupDatabase(wxWindow *parent) {
2445 bool backupResult = false;
2446 wxDateTime tm = wxDateTime::Now();
2447 wxString proposedName = tm.Format("navobj-%Y-%m-%d_%H_%M");
2448 wxString acceptedName;
2449
2450 if (wxID_OK ==
2451 g_Platform->DoFileSelectorDialog(parent, &acceptedName, _("Backup"),
2452 wxStandardPaths::Get().GetDocumentsDir(),
2453 proposedName, "*.bkp")) {
2454 wxFileName fileName(acceptedName);
2455 if (fileName.IsOk()) {
2456#if defined(__WXMSW__) || defined(__WXGTK__)
2457 if (fileName.FileExists()) {
2458 if (wxID_YES != OCPNMessageBox(NULL, _("Overwrite existing file?"),
2459 "Confirm", wxICON_QUESTION | wxYES_NO)) {
2460 return wxID_ABORT; // We've decided not to overwrite a file, aborting
2461 }
2462 }
2463#endif
2464
2465#ifdef __ANDROID__
2466 wxString secureFileName = androidGetCacheDir() +
2467 wxFileName::GetPathSeparator() +
2468 fileName.GetFullName();
2469 backupResult = NavObj_dB::GetInstance().Backup(secureFileName);
2470 AndroidSecureCopyFile(secureFileName, fileName.GetFullPath());
2471#else
2472 backupResult = NavObj_dB::GetInstance().Backup(fileName.GetFullPath());
2473#endif
2474 }
2475 return backupResult ? wxID_YES : wxID_NO;
2476 }
2477 return wxID_ABORT; // Cancelled the file open dialog, aborting
2478}
2479
2480bool ExportGPXRoutes(wxWindow *parent, RouteList *pRoutes,
2481 const wxString suggestedName) {
2482#ifndef __ANDROID__
2483 wxFileName fn = exportFileName(parent, suggestedName);
2484 if (fn.IsOk()) {
2486 pgpx->AddGPXRoutesList(pRoutes);
2487 pgpx->SaveFile(fn.GetFullPath());
2488 delete pgpx;
2489 return true;
2490 }
2491#else
2492 // Create the .GPX file, saving it in the OCPN Android cache directory
2493 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
2494 suggestedName + ".gpx";
2496 pgpx->AddGPXRoutesList(pRoutes);
2497 pgpx->SaveFile(fns);
2498 delete pgpx;
2499
2500 // Kick off the Android file chooser activity
2501 wxString path;
2502 int response = g_Platform->DoFileSelectorDialog(
2503 parent, &path, _("Export GPX file"), g_gpx_path, suggestedName + ".gpx",
2504 "*.gpx");
2505
2506 if (path.IsEmpty()) // relocation handled by SAF logic in Java
2507 return true;
2508
2509 wxCopyFile(fns, path); // known to be safe paths, since SAF is not involved.
2510 return true;
2511
2512#endif
2513
2514 return false;
2515}
2516
2517bool ExportGPXTracks(wxWindow *parent, std::vector<Track *> *pTracks,
2518 const wxString suggestedName) {
2519#ifndef __ANDROID__
2520 wxFileName fn = exportFileName(parent, suggestedName);
2521 if (fn.IsOk()) {
2523 pgpx->AddGPXTracksList(pTracks);
2524 pgpx->SaveFile(fn.GetFullPath());
2525 delete pgpx;
2526 return true;
2527 }
2528#else
2529 // Create the .GPX file, saving it in the OCPN Android cache directory
2530 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
2531 suggestedName + ".gpx";
2533 pgpx->AddGPXTracksList(pTracks);
2534 pgpx->SaveFile(fns);
2535 delete pgpx;
2536
2537 // Kick off the Android file chooser activity
2538 wxString path;
2539 int response = g_Platform->DoFileSelectorDialog(
2540 parent, &path, _("Export GPX file"), g_gpx_path, suggestedName + ".gpx",
2541 "*.gpx");
2542
2543 if (path.IsEmpty()) // relocation handled by SAF logic in Java
2544 return true;
2545
2546 wxCopyFile(fns, path); // known to be safe paths, since SAF is not involved.
2547 return true;
2548#endif
2549
2550 return false;
2551}
2552
2553bool ExportGPXWaypoints(wxWindow *parent, RoutePointList *pRoutePoints,
2554 const wxString suggestedName) {
2555#ifndef __ANDROID__
2556 wxFileName fn = exportFileName(parent, suggestedName);
2557 if (fn.IsOk()) {
2559 pgpx->AddGPXPointsList(pRoutePoints);
2560 pgpx->SaveFile(fn.GetFullPath());
2561 delete pgpx;
2562 return true;
2563 }
2564#else
2565 // Create the .GPX file, saving it in the OCPN Android cache directory
2566 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
2567 suggestedName + ".gpx";
2569 pgpx->AddGPXPointsList(pRoutePoints);
2570 pgpx->SaveFile(fns);
2571 delete pgpx;
2572
2573 // Kick off the Android file chooser activity
2574 wxString path;
2575 int response = g_Platform->DoFileSelectorDialog(
2576 parent, &path, _("Export GPX file"), g_gpx_path, suggestedName + ".gpx",
2577 "*.gpx");
2578
2579 if (path.IsEmpty()) // relocation handled by SAF logic in Java
2580 return true;
2581
2582 wxCopyFile(fns, path); // known to be safe paths, since SAF is not involved.
2583 return true;
2584
2585#endif
2586
2587 return false;
2588}
2589
2590void ExportGPX(wxWindow *parent, bool bviz_only, bool blayer) {
2592 wxString fns;
2593
2594#ifndef __ANDROID__
2595 wxFileName fn = exportFileName(parent, "userobjects.gpx");
2596 if (!fn.IsOk()) return;
2597 fns = fn.GetFullPath();
2598#else
2599 // Create the .GPX file, saving it in the OCPN Android cache directory
2600 fns =
2601 androidGetCacheDir() + wxFileName::GetPathSeparator() + "userobjects.gpx";
2602
2603#endif
2604 ::wxBeginBusyCursor();
2605
2606 wxGenericProgressDialog *pprog = nullptr;
2607 int count = pWayPointMan->GetWaypointList()->size();
2608 int progStep = count / 32;
2609 if (count > 200) {
2610 pprog = new wxGenericProgressDialog(
2611 _("Export GPX file"), "0/0", count, NULL,
2612 wxPD_APP_MODAL | wxPD_SMOOTH | wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME |
2613 wxPD_REMAINING_TIME);
2614 pprog->SetSize(400, wxDefaultCoord);
2615 pprog->Centre();
2616 }
2617
2618 // WPTs
2619 int ic = 1;
2620
2621 for (RoutePoint *pr : *pWayPointMan->GetWaypointList()) {
2622 if (pprog && !(ic % progStep)) {
2623 wxString msg;
2624 msg.Printf("%d/%d", ic, count);
2625 pprog->Update(ic, msg);
2626 }
2627 ic++;
2628
2629 bool b_add = true;
2630 if (bviz_only && !pr->m_bIsVisible) b_add = false;
2631
2632 if (pr->m_bIsInLayer && !blayer) b_add = false;
2633 if (b_add) {
2634 if (pr->IsShared() || !WptIsInRouteList(pr)) pgpx->AddGPXWaypoint(pr);
2635 }
2636 }
2637 // RTEs and TRKs
2638 for (Route *pRoute : *pRouteList) {
2639 bool b_add = true;
2640 if (bviz_only && !pRoute->IsVisible()) b_add = false;
2641 if (pRoute->m_bIsInLayer && !blayer) b_add = false;
2642
2643 if (b_add) pgpx->AddGPXRoute(pRoute);
2644 }
2645
2646 for (Track *pTrack : g_TrackList) {
2647 bool b_add = true;
2648
2649 if (bviz_only && !pTrack->IsVisible()) b_add = false;
2650
2651 if (pTrack->m_bIsInLayer && !blayer) b_add = false;
2652
2653 if (b_add) pgpx->AddGPXTrack(pTrack);
2654 }
2655
2656 pgpx->SaveFile(fns);
2657
2658#ifdef __ANDROID__
2659 // Kick off the Android file chooser activity
2660 wxString path;
2661 int response =
2662 g_Platform->DoFileSelectorDialog(parent, &path, _("Export GPX file"),
2663 g_gpx_path, "userobjects.gpx", "*.gpx");
2664 if (path.IsEmpty()) // relocation handled by SAF logic in Java
2665 return;
2666
2667 wxCopyFile(fns, path); // known to be safe paths, since SAF is not involved.
2668 return;
2669#endif
2670 delete pgpx;
2671 ::wxEndBusyCursor();
2672 delete pprog;
2673}
2674
2675void UI_ImportGPX(wxWindow *parent, bool islayer, wxString dirpath,
2676 bool isdirectory, bool isPersistent) {
2677 int response = wxID_CANCEL;
2678 wxArrayString file_array;
2679
2680 if (!islayer || dirpath.IsSameAs("")) {
2681 // Platform DoFileSelectorDialog method does not properly handle multiple
2682 // selections So use native method if not Android, which means Android gets
2683 // single selection only.
2684#ifndef __ANDROID__
2685 wxFileDialog *popenDialog =
2686 new wxFileDialog(NULL, _("Import GPX file"), g_gpx_path, "",
2687 "GPX files (*.gpx)|*.gpx|All files (*.*)|*.*",
2688 wxFD_OPEN | wxFD_MULTIPLE);
2689
2690 if (g_bresponsive && parent)
2691 popenDialog = g_Platform->AdjustFileDialogFont(parent, popenDialog);
2692
2693 popenDialog->Centre();
2694
2695#ifdef __WXOSX__
2696 if (parent) parent->HideWithEffect(wxSHOW_EFFECT_BLEND);
2697#endif
2698
2699 response = popenDialog->ShowModal();
2700
2701#ifdef __WXOSX__
2702 if (parent) parent->ShowWithEffect(wxSHOW_EFFECT_BLEND);
2703#endif
2704
2705 if (response == wxID_OK) {
2706 popenDialog->GetPaths(file_array);
2707
2708 // Record the currently selected directory for later use
2709 if (file_array.GetCount()) {
2710 wxFileName fn(file_array[0]);
2711 g_gpx_path = fn.GetPath();
2712 }
2713 }
2714 delete popenDialog;
2715#else // Android
2716 wxString path;
2717 response = g_Platform->DoFileSelectorDialog(
2718 NULL, &path, _("Import GPX file"), g_gpx_path, "", "*.gpx");
2719
2720 wxFileName fn(path);
2721 g_gpx_path = fn.GetPath();
2722 if (path.IsEmpty()) { // Return from SAF processing, expecting callback
2723 PrepareImportAndroid(islayer, isPersistent);
2724 return;
2725 } else
2726 file_array.Add(path); // Return from safe app arena access
2727
2728#endif
2729 } else {
2730 if (isdirectory) {
2731 if (wxDir::GetAllFiles(dirpath, &file_array, "*.gpx")) response = wxID_OK;
2732 } else {
2733 file_array.Add(dirpath);
2734 response = wxID_OK;
2735 }
2736 }
2737
2738 if (response == wxID_OK) {
2739 ImportFileArray(file_array, islayer, isPersistent, dirpath);
2740 }
2741}
2742
2743void ImportFileArray(const wxArrayString &file_array, bool islayer,
2744 bool isPersistent, wxString dirpath) {
2745 Layer *l = NULL;
2746
2747 if (islayer) {
2748 l = new Layer();
2749 l->m_LayerID = ++g_LayerIdx;
2750 l->m_LayerFileName = file_array[0];
2751 if (file_array.GetCount() <= 1)
2752 wxFileName::SplitPath(file_array[0], NULL, NULL, &(l->m_LayerName), NULL,
2753 NULL);
2754 else {
2755 if (dirpath.IsSameAs(""))
2756 wxFileName::SplitPath(g_gpx_path, NULL, NULL, &(l->m_LayerName), NULL,
2757 NULL);
2758 else
2759 wxFileName::SplitPath(dirpath, NULL, NULL, &(l->m_LayerName), NULL,
2760 NULL);
2761 }
2762
2763 bool bLayerViz = g_bShowLayers;
2764 if (g_VisibleLayers.Contains(l->m_LayerName)) bLayerViz = true;
2765 if (g_InvisibleLayers.Contains(l->m_LayerName)) bLayerViz = false;
2766 l->m_bIsVisibleOnChart = bLayerViz;
2767
2768 // Default for new layers is "Names visible"
2769 l->m_bHasVisibleNames = wxCHK_CHECKED;
2770
2771 wxString laymsg;
2772 laymsg.Printf("New layer %d: %s", l->m_LayerID, l->m_LayerName.c_str());
2773 wxLogMessage(laymsg);
2774
2775 pLayerList->insert(pLayerList->begin(), l);
2776 }
2777
2778 for (unsigned int i = 0; i < file_array.GetCount(); i++) {
2779 wxString path = file_array[i];
2780
2781 if (::wxFileExists(path)) {
2783 pugi::xml_parse_result result = pSet->load_file(path.fn_str());
2784 if (!result) {
2785 wxLogMessage("Error loading GPX file " + path);
2786 wxMessageBox(
2787 wxString::Format(_("Error loading GPX file %s, %s at character %d"),
2788 path, result.description(), result.offset),
2789 _("Import GPX File"));
2790 pSet->reset();
2791 delete pSet;
2792 continue;
2793 }
2794
2795 if (islayer) {
2796 l->m_NoOfItems = pSet->LoadAllGPXObjectsAsLayer(
2797 l->m_LayerID, l->m_bIsVisibleOnChart, l->m_bHasVisibleNames);
2798 l->m_LayerType = isPersistent ? _("Persistent") : _("Temporary");
2799
2800 if (isPersistent) {
2801 // If this is a persistent layer also copy the file to config file
2802 // dir /layers
2803 wxString destf, f, name, ext;
2804 f = l->m_LayerFileName;
2805 wxFileName::SplitPath(f, NULL, NULL, &name, &ext);
2806 destf = g_Platform->GetPrivateDataDir();
2807 appendOSDirSlash(&destf);
2808 destf.Append("layers");
2809 appendOSDirSlash(&destf);
2810 if (!wxDirExists(destf)) {
2811 if (!wxMkdir(destf, wxS_DIR_DEFAULT))
2812 wxLogMessage("Error creating layer directory");
2813 }
2814
2815 destf << name << "." << ext;
2816 wxString msg;
2817 if (wxCopyFile(f, destf, true))
2818 msg.Printf("File: %s.%s also added to persistent layers", name,
2819 ext);
2820 else
2821 msg.Printf("Failed adding %s.%s to persistent layers", name, ext);
2822 wxLogMessage(msg);
2823 }
2824 } else {
2825 int wpt_dups;
2826 pSet->LoadAllGPXObjects(
2827 !pSet->IsOpenCPN(),
2828 wpt_dups); // Import with full visibility of names and objects
2829#ifndef __ANDROID__
2830 if (wpt_dups > 0) {
2831 OCPNMessageBox(
2832 NULL,
2833 wxString::Format("%d " + _("duplicate waypoints detected "
2834 "during import and ignored."),
2835 wpt_dups),
2836 _("OpenCPN Info"), wxICON_INFORMATION | wxOK, 10);
2837 }
2838#endif
2839 }
2840 delete pSet;
2841 }
2842 }
2843}
2844
2845//-------------------------------------------------------------------------
2846// Static Routine Switch to Inland Ecdis Mode
2847//-------------------------------------------------------------------------
2848void SwitchInlandEcdisMode(bool Switch) {
2849 if (Switch) {
2850 wxLogMessage("Switch InlandEcdis mode On");
2851 LoadS57();
2852 // Overrule some settings to comply with InlandEcdis
2853 // g_toolbarConfig = ".....XXXX.X...XX.XXXXXXXXXXXX";
2854 g_iDistanceFormat = 2; // 0 = "Nautical miles"), 1 = "Statute miles", 2 =
2855 // "Kilometers", 3 = "Meters"
2856 g_iSpeedFormat = 2; // 0 = "kts"), 1 = "mph", 2 = "km/h", 3 = "m/s"
2857 if (ps52plib) ps52plib->SetDisplayCategory(STANDARD);
2858 g_bDrawAISSize = false;
2859 if (gFrame) gFrame->RequestNewToolbars(true);
2860 } else {
2861 wxLogMessage("Switch InlandEcdis mode Off");
2862 // reread the settings overruled by inlandEcdis
2863 if (pConfig) {
2864 pConfig->SetPath("/Settings");
2865 pConfig->Read("GlobalToolbarConfig", &g_toolbarConfig);
2866 pConfig->Read("DistanceFormat", &g_iDistanceFormat);
2867 pConfig->Read("SpeedFormat", &g_iSpeedFormat);
2868 pConfig->Read("ShowDepthUnits", &g_bShowDepthUnits, 1);
2869 pConfig->Read("HeightFormat", &g_iHeightFormat);
2870 int read_int;
2871 pConfig->Read("nDisplayCategory", &read_int, (enum _DisCat)STANDARD);
2872 if (ps52plib) ps52plib->SetDisplayCategory((enum _DisCat)read_int);
2873 pConfig->SetPath("/Settings/AIS");
2874 pConfig->Read("bDrawAISSize", &g_bDrawAISSize);
2875 pConfig->Read("bDrawAISRealtime", &g_bDrawAISRealtime);
2876 }
2877 if (gFrame) gFrame->RequestNewToolbars(true);
2878 }
2879}
2880
2881//-------------------------------------------------------------------------
2882//
2883// Static GPX Support Routines
2884//
2885//-------------------------------------------------------------------------
2886// This function formats the input date/time into a valid GPX ISO 8601
2887// time string specified in the UTC time zone.
2888
2889wxString FormatGPXDateTime(wxDateTime dt) {
2890 // return dt.Format("%Y-%m-%dT%TZ", wxDateTime::GMT0);
2891 return dt.Format("%Y-%m-%dT%H:%M:%SZ");
2892}
2893
2894/**************************************************************************/
2895/* LogMessageOnce */
2896/**************************************************************************/
2897
2898bool LogMessageOnce(const wxString &msg) {
2899 // Search the array for a match
2900
2901 for (unsigned int i = 0; i < navutil::pMessageOnceArray->GetCount(); i++) {
2902 if (msg.IsSameAs(navutil::pMessageOnceArray->Item(i))) return false;
2903 }
2904
2905 // Not found, so add to the array
2906 navutil::pMessageOnceArray->Add(msg);
2907
2908 // And print it
2909 wxLogMessage(msg);
2910 return true;
2911}
2912
2913/**************************************************************************/
2914/* Some assorted utilities */
2915/**************************************************************************/
2916
2917wxDateTime toUsrDateTime(const wxDateTime ts, const int format,
2918 const double lon) {
2919 if (!ts.IsValid()) {
2920 return ts;
2921 }
2922 int effective_format = format;
2923 if (effective_format == GLOBAL_SETTINGS_INPUT) {
2924 if (::g_datetime_format == "UTC") {
2925 effective_format = UTCINPUT;
2926 } else if (::g_datetime_format == "LMT") {
2927 effective_format = LMTINPUT;
2928 } else if (::g_datetime_format == "Local Time") {
2929 effective_format = LTINPUT;
2930 } else {
2931 // Default to UTC
2932 effective_format = UTCINPUT;
2933 }
2934 }
2935 wxDateTime dt;
2936 switch (effective_format) {
2937 case LMTINPUT: // LMT@Location
2938 if (std::isnan(lon)) {
2939 dt = wxInvalidDateTime;
2940 } else {
2941 dt =
2942 ts.Add(wxTimeSpan(wxTimeSpan(0, 0, wxLongLong(lon * 3600. / 15.))));
2943 }
2944 break;
2945 case LTINPUT: // Local@PC
2946 // Convert date/time from UTC to local time.
2947 dt = ts.FromUTC();
2948 break;
2949 case UTCINPUT: // UTC
2950 // The date/time is already in UTC.
2951 dt = ts;
2952 break;
2953 }
2954 return dt;
2955}
2956
2957wxDateTime fromUsrDateTime(const wxDateTime ts, const int format,
2958 const double lon) {
2959 if (!ts.IsValid()) {
2960 return ts;
2961 }
2962 int effective_format = format;
2963 if (effective_format == GLOBAL_SETTINGS_INPUT) {
2964 if (::g_datetime_format == "UTC") {
2965 effective_format = UTCINPUT;
2966 } else if (::g_datetime_format == "LMT") {
2967 effective_format = LMTINPUT;
2968 } else if (::g_datetime_format == "Local Time") {
2969 effective_format = LTINPUT;
2970 } else {
2971 // Default to UTC
2972 effective_format = UTCINPUT;
2973 }
2974 }
2975 wxDateTime dt;
2976 switch (effective_format) {
2977 case LMTINPUT: // LMT@Location
2978 if (std::isnan(lon)) {
2979 dt = wxInvalidDateTime;
2980 } else {
2981 dt = ts.Subtract(wxTimeSpan(0, 0, wxLongLong(lon * 3600. / 15.)));
2982 }
2983 break;
2984 case LTINPUT: // Local@PC
2985 // The input date/time is in local time, so convert it to UTC.
2986 dt = ts.ToUTC();
2987 break;
2988 case UTCINPUT: // UTC
2989 dt = ts;
2990 break;
2991 }
2992 return dt;
2993}
2994
2995/**************************************************************************/
2996/* Converts the speed from the units selected by user to knots */
2997/**************************************************************************/
2998double fromUsrSpeed(double usr_speed, int unit) {
2999 double ret = NAN;
3000 if (unit == -1) unit = g_iSpeedFormat;
3001 switch (unit) {
3002 case SPEED_KTS: // kts
3003 ret = usr_speed;
3004 break;
3005 case SPEED_MPH: // mph
3006 ret = usr_speed / 1.15078;
3007 break;
3008 case SPEED_KMH: // km/h
3009 ret = usr_speed / 1.852;
3010 break;
3011 case SPEED_MS: // m/s
3012 ret = usr_speed / 0.514444444;
3013 break;
3014 }
3015 return ret;
3016}
3017/**************************************************************************/
3018/* Converts the wind speed from the units selected by user to knots */
3019/**************************************************************************/
3020double fromUsrWindSpeed(double usr_wspeed, int unit) {
3021 double ret = NAN;
3022 if (unit == -1) unit = g_iWindSpeedFormat;
3023 switch (unit) {
3024 case WSPEED_KTS: // kts
3025 ret = usr_wspeed;
3026 break;
3027 case WSPEED_MS: // m/s
3028 ret = usr_wspeed / 0.514444444;
3029 break;
3030 case WSPEED_MPH: // mph
3031 ret = usr_wspeed / 1.15078;
3032 break;
3033 case WSPEED_KMH: // km/h
3034 ret = usr_wspeed / 1.852;
3035 break;
3036 }
3037 return ret;
3038}
3039
3040/**************************************************************************/
3041/* Converts the temperature from the units selected by user to Celsius */
3042/**************************************************************************/
3043double fromUsrTemp(double usr_temp, int unit) {
3044 double ret = NAN;
3045 if (unit == -1) unit = g_iTempFormat;
3046 switch (unit) {
3047 case TEMPERATURE_C: // C
3048 ret = usr_temp;
3049 break;
3050 case TEMPERATURE_F: // F
3051 ret = (usr_temp - 32) * 5.0 / 9.0;
3052 break;
3053 case TEMPERATURE_K: // K
3054 ret = usr_temp - 273.15;
3055 break;
3056 }
3057 return ret;
3058}
3059
3060wxString formatAngle(double angle) {
3061 wxString out;
3062 if (g_bShowMag && g_bShowTrue) {
3063 out.Printf("%03.0f %cT (%.0f %cM)", angle, 0x00B0, toMagnetic(angle),
3064 0x00B0);
3065 } else if (g_bShowTrue) {
3066 out.Printf("%03.0f %cT", angle, 0x00B0);
3067 } else {
3068 out.Printf("%03.0f %cM", toMagnetic(angle), 0x00B0);
3069 }
3070 return out;
3071}
3072
3073/* render a rectangle at a given color and transparency */
3074void AlphaBlending(ocpnDC &dc, int x, int y, int size_x, int size_y,
3075 float radius, wxColour color, unsigned char transparency) {
3076 wxDC *pdc = dc.GetDC();
3077 if (pdc) {
3078 // Get wxImage of area of interest
3079 wxBitmap obm(size_x, size_y);
3080 wxMemoryDC mdc1;
3081 mdc1.SelectObject(obm);
3082 mdc1.Blit(0, 0, size_x, size_y, pdc, x, y);
3083 mdc1.SelectObject(wxNullBitmap);
3084 wxImage oim = obm.ConvertToImage();
3085
3086 // Create destination image
3087 wxBitmap olbm(size_x, size_y);
3088 wxMemoryDC oldc(olbm);
3089 if (!oldc.IsOk()) return;
3090
3091 oldc.SetBackground(*wxBLACK_BRUSH);
3092 oldc.SetBrush(*wxWHITE_BRUSH);
3093 oldc.Clear();
3094
3095 if (radius > 0.0) oldc.DrawRoundedRectangle(0, 0, size_x, size_y, radius);
3096
3097 wxImage dest = olbm.ConvertToImage();
3098 unsigned char *dest_data =
3099 (unsigned char *)malloc(size_x * size_y * 3 * sizeof(unsigned char));
3100 unsigned char *bg = oim.GetData();
3101 unsigned char *box = dest.GetData();
3102 unsigned char *d = dest_data;
3103
3104 // Sometimes, on Windows, the destination image is corrupt...
3105 if (NULL == box) {
3106 free(d);
3107 return;
3108 }
3109 float alpha = 1.0 - (float)transparency / 255.0;
3110 int sb = size_x * size_y;
3111 for (int i = 0; i < sb; i++) {
3112 float a = alpha;
3113 if (*box == 0 && radius > 0.0) a = 1.0;
3114 int r = ((*bg++) * a) + (1.0 - a) * color.Red();
3115 *d++ = r;
3116 box++;
3117 int g = ((*bg++) * a) + (1.0 - a) * color.Green();
3118 *d++ = g;
3119 box++;
3120 int b = ((*bg++) * a) + (1.0 - a) * color.Blue();
3121 *d++ = b;
3122 box++;
3123 }
3124
3125 dest.SetData(dest_data);
3126
3127 // Convert destination to bitmap and draw it
3128 wxBitmap dbm(dest);
3129 dc.DrawBitmap(dbm, x, y, false);
3130
3131 // on MSW, the dc Bounding box is not updated on DrawBitmap() method.
3132 // Do it explicitely here for all platforms.
3133 dc.CalcBoundingBox(x, y);
3134 dc.CalcBoundingBox(x + size_x, y + size_y);
3135 } else {
3136#ifdef ocpnUSE_GL
3137 glEnable(GL_BLEND);
3138
3139 float radMod = wxMax(radius, 2.0);
3140 wxColour c(color.Red(), color.Green(), color.Blue(), transparency);
3141 dc.SetBrush(wxBrush(c));
3142 dc.SetPen(wxPen(c, 1));
3143 dc.DrawRoundedRectangle(x, y, size_x, size_y, radMod);
3144
3145 glDisable(GL_BLEND);
3146
3147#endif
3148 }
3149}
3150
3151void DimeControl(wxWindow *ctrl) {
3152#ifdef __WXOSX__
3153 // On macOS 10.14+, we use the native colours in both light mode and dark
3154 // mode, and do not need to do anything else. Dark mode is toggled at the
3155 // application level in `SetAndApplyColorScheme`, and is also respected if it
3156 // is enabled system-wide.
3157 if (wxPlatformInfo::Get().CheckOSVersion(10, 14)) {
3158 return;
3159 }
3160#endif
3161#ifdef __WXQT__
3162 return; // this is seriously broken on wxqt
3163#endif
3164
3165 if (wxSystemSettings::GetColour(wxSystemColour::wxSYS_COLOUR_WINDOW).Red() <
3166 128) {
3167 // Dark system color themes usually do better job than we do on diming UI
3168 // controls, do not fight with them
3169 return;
3170 }
3171
3172 if (NULL == ctrl) return;
3173
3174 wxColour col, window_back_color, gridline, uitext, udkrd, ctrl_back_color,
3175 text_color;
3176 col = GetGlobalColor("DILG0"); // Dialog Background white
3177 window_back_color = GetGlobalColor("DILG1"); // Dialog Background
3178 ctrl_back_color = GetGlobalColor("DILG1"); // Control Background
3179 text_color = GetGlobalColor("DILG3"); // Text
3180 uitext = GetGlobalColor("UITX1"); // Menu Text, derived from UINFF
3181 udkrd = GetGlobalColor("UDKRD");
3182 gridline = GetGlobalColor("GREY2");
3183
3184 DimeControl(ctrl, col, window_back_color, ctrl_back_color, text_color, uitext,
3185 udkrd, gridline);
3186}
3187
3188void DimeControl(wxWindow *ctrl, wxColour col, wxColour window_back_color,
3189 wxColour ctrl_back_color, wxColour text_color, wxColour uitext,
3190 wxColour udkrd, wxColour gridline) {
3191#ifdef __WXOSX__
3192 // On macOS 10.14+, we use the native colours in both light mode and dark
3193 // mode, and do not need to do anything else. Dark mode is toggled at the
3194 // application level in `SetAndApplyColorScheme`, and is also respected if it
3195 // is enabled system-wide.
3196 if (wxPlatformInfo::Get().CheckOSVersion(10, 14)) {
3197 return;
3198 }
3199#endif
3200
3201 ColorScheme cs = global_color_scheme;
3202
3203 // Are we in dusk or night mode? (Used below in several places.)
3204 bool darkMode =
3205 (cs == GLOBAL_COLOR_SCHEME_DUSK || cs == GLOBAL_COLOR_SCHEME_NIGHT);
3206
3207 static int depth = 0; // recursion count
3208 if (depth == 0) { // only for the window root, not for every child
3209 // If the color scheme is DAY or RGB, use the default platform native colour
3210 // for backgrounds
3211 if (!darkMode) {
3212#ifdef _WIN32
3213 window_back_color = wxNullColour;
3214#else
3215 window_back_color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
3216#endif
3217 col = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX);
3218 uitext = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
3219 }
3220
3221 ctrl->SetBackgroundColour(window_back_color);
3222 if (darkMode) ctrl->SetForegroundColour(text_color);
3223 }
3224
3225 wxWindowList kids = ctrl->GetChildren();
3226 for (unsigned int i = 0; i < kids.GetCount(); i++) {
3227 wxWindowListNode *node = kids.Item(i);
3228 wxWindow *win = node->GetData();
3229
3230 if (dynamic_cast<wxListBox *>(win) || dynamic_cast<wxListCtrl *>(win) ||
3231 dynamic_cast<wxTextCtrl *>(win) ||
3232 dynamic_cast<wxTimePickerCtrl *>(win)) {
3233 win->SetBackgroundColour(col);
3234 } else if (dynamic_cast<wxStaticText *>(win) ||
3235 dynamic_cast<wxCheckBox *>(win) ||
3236 dynamic_cast<wxRadioButton *>(win)) {
3237 win->SetForegroundColour(uitext);
3238 }
3239#ifndef __WXOSX__
3240 // On macOS most controls can't be styled, and trying to do so only creates
3241 // weird coloured boxes around them. Fortunately, however, many of them
3242 // inherit a colour or tint from the background of their parent.
3243
3244 else if (dynamic_cast<wxBitmapComboBox *>(win) ||
3245 dynamic_cast<wxChoice *>(win) || dynamic_cast<wxComboBox *>(win) ||
3246 dynamic_cast<wxTreeCtrl *>(win)) {
3247 win->SetBackgroundColour(col);
3248 }
3249
3250 else if (dynamic_cast<wxScrolledWindow *>(win) ||
3251 dynamic_cast<wxGenericDirCtrl *>(win) ||
3252 dynamic_cast<wxListbook *>(win) || dynamic_cast<wxButton *>(win) ||
3253 dynamic_cast<wxToggleButton *>(win)) {
3254 win->SetBackgroundColour(window_back_color);
3255 }
3256
3257 else if (dynamic_cast<wxNotebook *>(win)) {
3258 win->SetBackgroundColour(window_back_color);
3259 win->SetForegroundColour(text_color);
3260 }
3261#endif
3262
3263 else if (dynamic_cast<wxHtmlWindow *>(win)) {
3264 if (cs != GLOBAL_COLOR_SCHEME_DAY && cs != GLOBAL_COLOR_SCHEME_RGB)
3265 win->SetBackgroundColour(ctrl_back_color);
3266 else
3267 win->SetBackgroundColour(wxNullColour);
3268 }
3269
3270 else if (dynamic_cast<wxGrid *>(win)) {
3271 dynamic_cast<wxGrid *>(win)->SetDefaultCellBackgroundColour(
3272 window_back_color);
3273 dynamic_cast<wxGrid *>(win)->SetDefaultCellTextColour(uitext);
3274 dynamic_cast<wxGrid *>(win)->SetLabelBackgroundColour(col);
3275 dynamic_cast<wxGrid *>(win)->SetLabelTextColour(uitext);
3276 dynamic_cast<wxGrid *>(win)->SetGridLineColour(gridline);
3277 }
3278
3279 if (win->GetChildren().GetCount() > 0) {
3280 depth++;
3281 wxWindow *w = win;
3282 DimeControl(w, col, window_back_color, ctrl_back_color, text_color,
3283 uitext, udkrd, gridline);
3284 depth--;
3285 }
3286 }
3287}
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:2917
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:2957
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.