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