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