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