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