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