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("canvasQuilt", &cConfig->bQuilt, 1);
1720 Read("canvasShowGrid", &cConfig->bShowGrid, 0);
1721 Read("canvasShowOutlines", &cConfig->bShowOutlines, 0);
1722 Read("canvasShowDepthUnits", &cConfig->bShowDepthUnits, 0);
1723
1724 Read("canvasShowAIS", &cConfig->bShowAIS, 1);
1725 Read("canvasAttenAIS", &cConfig->bAttenAIS, 0);
1726
1727 // ENC options
1728 Read("canvasShowENCText", &cConfig->bShowENCText, 1);
1729 Read("canvasENCDisplayCategory", &cConfig->nENCDisplayCategory, STANDARD);
1730 Read("canvasENCShowDepths", &cConfig->bShowENCDepths, 1);
1731 Read("canvasENCShowBuoyLabels", &cConfig->bShowENCBuoyLabels, 1);
1732 Read("canvasENCShowLightDescriptions", &cConfig->bShowENCLightDescriptions,
1733 1);
1734 Read("canvasENCShowLights", &cConfig->bShowENCLights, 1);
1735 Read("canvasENCShowVisibleSectorLights",
1736 &cConfig->bShowENCVisibleSectorLights, 0);
1737 Read("canvasENCShowAnchorInfo", &cConfig->bShowENCAnchorInfo, 0);
1738 Read("canvasENCShowDataQuality", &cConfig->bShowENCDataQuality, 0);
1739
1740 int sx, sy;
1741 Read("canvasSizeX", &sx, 0);
1742 Read("canvasSizeY", &sy, 0);
1743 cConfig->canvasSize = wxSize(sx, sy);
1744}
1745
1746void MyConfig::SaveCanvasConfigs() {
1747 auto &config_array = ConfigMgr::Get().GetCanvasConfigArray();
1748
1749 SetPath("/Canvas");
1750 Write("CanvasConfig", (int)g_canvasConfig);
1751
1752 wxString s;
1753 canvasConfig *pcc;
1754
1755 switch (g_canvasConfig) {
1756 case 0:
1757 default:
1758
1759 s.Printf("/Canvas/CanvasConfig%d", 1);
1760 SetPath(s);
1761
1762 if (config_array.GetCount() > 0) {
1763 pcc = config_array.Item(0);
1764 if (pcc) {
1765 SaveConfigCanvas(pcc);
1766 }
1767 }
1768 break;
1769
1770 case 1:
1771
1772 if (config_array.GetCount() > 1) {
1773 s.Printf("/Canvas/CanvasConfig%d", 1);
1774 SetPath(s);
1775 pcc = config_array.Item(0);
1776 if (pcc) {
1777 SaveConfigCanvas(pcc);
1778 }
1779
1780 s.Printf("/Canvas/CanvasConfig%d", 2);
1781 SetPath(s);
1782 pcc = config_array.Item(1);
1783 if (pcc) {
1784 SaveConfigCanvas(pcc);
1785 }
1786 }
1787 break;
1788 }
1789}
1790
1791void MyConfig::SaveConfigCanvas(canvasConfig *cConfig) {
1792 wxString st1;
1793
1794 if (cConfig->canvas) {
1795 ViewPort vp = cConfig->canvas->GetVP();
1796
1797 if (vp.IsValid()) {
1798 st1.Printf("%10.4f,%10.4f", vp.clat, vp.clon);
1799 Write("canvasVPLatLon", st1);
1800 st1.Printf("%g", vp.view_scale_ppm);
1801 Write("canvasVPScale", st1);
1802 st1.Printf("%i", ((int)(vp.rotation * 180 / PI)) % 360);
1803 Write("canvasVPRotation", st1);
1804 }
1805
1806 int restore_dbindex = 0;
1807 ChartStack *pcs = cConfig->canvas->GetpCurrentStack();
1808 if (pcs) restore_dbindex = pcs->GetCurrentEntrydbIndex();
1809 if (cConfig->canvas->GetQuiltMode())
1810 restore_dbindex = cConfig->canvas->GetQuiltReferenceChartIndex();
1811 Write("canvasInitialdBIndex", restore_dbindex);
1812
1813 Write("canvasbFollow", cConfig->canvas->m_bFollow);
1814 Write("ActiveChartGroup", cConfig->canvas->m_groupIndex);
1815
1816 Write("canvasQuilt", cConfig->canvas->GetQuiltMode());
1817 Write("canvasShowGrid", cConfig->canvas->GetShowGrid());
1818 Write("canvasShowOutlines", cConfig->canvas->GetShowOutlines());
1819 Write("canvasShowDepthUnits", cConfig->canvas->GetShowDepthUnits());
1820
1821 Write("canvasShowAIS", cConfig->canvas->GetShowAIS());
1822 Write("canvasAttenAIS", cConfig->canvas->GetAttenAIS());
1823
1824 Write("canvasShowTides", cConfig->canvas->GetbShowTide());
1825 Write("canvasShowCurrents", cConfig->canvas->GetbShowCurrent());
1826
1827 // ENC options
1828 Write("canvasShowENCText", cConfig->canvas->GetShowENCText());
1829 Write("canvasENCDisplayCategory", cConfig->canvas->GetENCDisplayCategory());
1830 Write("canvasENCShowDepths", cConfig->canvas->GetShowENCDepth());
1831 Write("canvasENCShowBuoyLabels", cConfig->canvas->GetShowENCBuoyLabels());
1832 Write("canvasENCShowLightDescriptions",
1833 cConfig->canvas->GetShowENCLightDesc());
1834 Write("canvasENCShowLights", cConfig->canvas->GetShowENCLights());
1835 Write("canvasENCShowVisibleSectorLights",
1836 cConfig->canvas->GetShowVisibleSectors());
1837 Write("canvasENCShowAnchorInfo", cConfig->canvas->GetShowENCAnchor());
1838 Write("canvasENCShowDataQuality", cConfig->canvas->GetShowENCDataQual());
1839 Write("canvasCourseUp", cConfig->canvas->GetUpMode() == COURSE_UP_MODE);
1840 Write("canvasHeadUp", cConfig->canvas->GetUpMode() == HEAD_UP_MODE);
1841 Write("canvasLookahead", cConfig->canvas->GetLookahead());
1842
1843 int width = cConfig->canvas->GetSize().x;
1844 // if(cConfig->canvas->IsPrimaryCanvas()){
1845 // width = wxMax(width, gFrame->GetClientSize().x / 10);
1846 // }
1847 // else{
1848 // width = wxMin(width, gFrame->GetClientSize().x * 9 / 10);
1849 // }
1850
1851 Write("canvasSizeX", width);
1852 Write("canvasSizeY", cConfig->canvas->GetSize().y);
1853 }
1854}
1855
1856void MyConfig::UpdateSettings() {
1857 // Temporarily suppress logging of trivial non-fatal wxLogSysError() messages
1858 // provoked by Android security...
1859#ifdef __ANDROID__
1860 wxLogNull logNo;
1861#endif
1862
1863 // Global options and settings
1864 SetPath("/Settings");
1865
1866 Write("LastAppliedTemplate", g_lastAppliedTemplateGUID);
1867 Write("CompatOS", g_compatOS);
1868 Write("CompatOsVersion", g_compatOsVersion);
1869 Write("ConfigVersionString", g_config_version_string);
1870 if (wxIsEmpty(g_CmdSoundString)) g_CmdSoundString = wxString(OCPN_SOUND_CMD);
1871 Write("CmdSoundString", g_CmdSoundString);
1872 Write("NavMessageShown", n_NavMessageShown);
1873 Write("InlandEcdis", g_bInlandEcdis);
1874
1875 Write("AndroidVersionCode", g_AndroidVersionCode);
1876
1877 Write("UIexpert", g_bUIexpert);
1878 Write("SpaceDropMark", g_bSpaceDropMark);
1879 // Write( "UIStyle", g_StyleManager->GetStyleNextInvocation() );
1880 // //Not desired for O5 MUI
1881
1882 Write("ShowStatusBar", g_bShowStatusBar);
1883#ifndef __WXOSX__
1884 Write("ShowMenuBar", g_bShowMenuBar);
1885#endif
1886 Write("DefaultFontSize", g_default_font_size);
1887 Write("DefaultFontFacename", g_default_font_facename);
1888
1889 Write("Fullscreen", g_bFullscreen);
1890 Write("ShowCompassWindow", g_bShowCompassWin);
1891 Write("SetSystemTime", s_bSetSystemTime);
1892 Write("ShowGrid", g_bDisplayGrid);
1893 Write("PlayShipsBells", g_bPlayShipsBells);
1894 Write("SoundDeviceIndex", g_iSoundDeviceIndex);
1895 Write("FullscreenToolbar", g_bFullscreenToolbar);
1896 Write("TransparentToolbar", g_bTransparentToolbar);
1897 Write("PermanentMOBIcon", g_bPermanentMOBIcon);
1898 Write("ShowLayers", g_bShowLayers);
1899 Write("AutoAnchorDrop", g_bAutoAnchorMark);
1900 Write("ShowChartOutlines", g_bShowOutlines);
1901 Write("ShowActiveRouteTotal", g_bShowRouteTotal);
1902 Write("ShowActiveRouteHighway", g_bShowActiveRouteHighway);
1903 Write("SDMMFormat", g_iSDMMFormat);
1904 Write("MostRecentGPSUploadConnection", g_uploadConnection);
1905 Write("ShowChartBar", g_bShowChartBar);
1906
1907 Write("GUIScaleFactor", g_GUIScaleFactor);
1908 Write("ChartObjectScaleFactor", g_ChartScaleFactor);
1909 Write("ShipScaleFactor", g_ShipScaleFactor);
1910 Write("ENCSoundingScaleFactor", g_ENCSoundingScaleFactor);
1911 Write("ENCTextScaleFactor", g_ENCTextScaleFactor);
1912 Write("ObjQueryAppendFilesExt", g_ObjQFileExt);
1913
1914 // Plugin catalog persistent values.
1915 Write("CatalogCustomURL", g_catalog_custom_url);
1916 Write("CatalogChannel", g_catalog_channel);
1917
1918 Write("NetmaskBits", g_netmask_bits);
1919 Write("FilterNMEA_Avg", g_bfilter_cogsog);
1920 Write("FilterNMEA_Sec", g_COGFilterSec);
1921
1922 Write("TrackContinuous", g_btrackContinuous);
1923
1924 Write("ShowTrue", g_bShowTrue);
1925 Write("ShowMag", g_bShowMag);
1926 Write("UserMagVariation", wxString::Format("%.2f", g_UserVar));
1927
1928 Write("CM93DetailFactor", g_cm93_zoom_factor);
1929 Write("CM93DetailZoomPosX", g_detailslider_dialog_x);
1930 Write("CM93DetailZoomPosY", g_detailslider_dialog_y);
1931 Write("ShowCM93DetailSlider", g_bShowDetailSlider);
1932
1933 Write("SkewToNorthUp", g_bskew_comp);
1934 if (!g_bdisable_opengl) { // Only modify the saved value if OpenGL is not
1935 // force-disabled from the command line
1936 Write("OpenGL", g_bopengl);
1937 }
1938 Write("SoftwareGL", g_bSoftwareGL);
1939
1940 Write("ZoomDetailFactor", g_chart_zoom_modifier_raster);
1941 Write("ZoomDetailFactorVector", g_chart_zoom_modifier_vector);
1942
1943 Write("FogOnOverzoom", g_fog_overzoom);
1944 Write("OverzoomVectorScale", g_oz_vector_scale);
1945 Write("OverzoomEmphasisBase", g_overzoom_emphasis_base);
1946 Write("PlusMinusZoomFactor", g_plus_minus_zoom_factor);
1947 Write("MouseZoomSensitivity",
1948 MouseZoom::ui_to_config(g_mouse_zoom_sensitivity_ui));
1949 Write("ShowMUIZoomButtons", g_bShowMuiZoomButtons);
1950
1951#ifdef ocpnUSE_GL
1952 /* opengl options */
1953 Write("UseAcceleratedPanning", g_GLOptions.m_bUseAcceleratedPanning);
1954
1955 Write("GPUTextureCompression", g_GLOptions.m_bTextureCompression);
1956 Write("GPUTextureCompressionCaching",
1957 g_GLOptions.m_bTextureCompressionCaching);
1958 Write("GPUTextureDimension", g_GLOptions.m_iTextureDimension);
1959 Write("GPUTextureMemSize", g_GLOptions.m_iTextureMemorySize);
1960 Write("PolygonSmoothing", g_GLOptions.m_GLPolygonSmoothing);
1961 Write("LineSmoothing", g_GLOptions.m_GLLineSmoothing);
1962#endif
1963 Write("SmoothPanZoom", g_bsmoothpanzoom);
1964
1965 Write("CourseUpMode", g_bCourseUp);
1966 if (!g_bInlandEcdis) Write("LookAheadMode", g_bLookAhead);
1967 Write("TenHzUpdate", g_btenhertz);
1968
1969 Write("COGUPAvgSeconds", g_COGAvgSec);
1970 Write("UseMagAPB", g_bMagneticAPB);
1971
1972 Write("OwnshipCOGPredictorMinutes", g_ownship_predictor_minutes);
1973 Write("OwnshipCOGPredictorStyle", g_cog_predictor_style);
1974 Write("OwnshipCOGPredictorColor", g_cog_predictor_color);
1975 Write("OwnshipCOGPredictorEndmarker", g_cog_predictor_endmarker);
1976 Write("OwnshipCOGPredictorWidth", g_cog_predictor_width);
1977 Write("OwnshipHDTPredictorStyle", g_ownship_HDTpredictor_style);
1978 Write("OwnshipHDTPredictorColor", g_ownship_HDTpredictor_color);
1979 Write("OwnshipHDTPredictorEndmarker", g_ownship_HDTpredictor_endmarker);
1980 Write("OwnShipMMSINumber", g_OwnShipmmsi);
1981 Write("OwnshipHDTPredictorWidth", g_ownship_HDTpredictor_width);
1982 Write("OwnshipHDTPredictorMiles", g_ownship_HDTpredictor_miles);
1983
1984 Write("OwnShipIconType", g_OwnShipIconType);
1985 Write("OwnShipLength", g_n_ownship_length_meters);
1986 Write("OwnShipWidth", g_n_ownship_beam_meters);
1987 Write("OwnShipGPSOffsetX", g_n_gps_antenna_offset_x);
1988 Write("OwnShipGPSOffsetY", g_n_gps_antenna_offset_y);
1989 Write("OwnShipMinSize", g_n_ownship_min_mm);
1990 Write("ShowDirectRouteLine", g_bShowShipToActive);
1991 Write("DirectRouteLineStyle", g_shipToActiveStyle);
1992 Write("DirectRouteLineColor", g_shipToActiveColor);
1993
1994 wxString racr;
1995 // racr.Printf( "%g", g_n_arrival_circle_radius );
1996 // Write( "RouteArrivalCircleRadius", racr );
1997 Write("RouteArrivalCircleRadius",
1998 wxString::Format("%.2f", g_n_arrival_circle_radius));
1999
2000 Write("ChartQuilting", g_bQuiltEnable);
2001
2002 Write("PreserveScaleOnX", g_bPreserveScaleOnX);
2003
2004 Write("StartWithTrackActive", g_bTrackCarryOver);
2005 Write("AutomaticDailyTracks", g_bTrackDaily);
2006 Write("TrackRotateAt", g_track_rotate_time);
2007 Write("TrackRotateTimeType", g_track_rotate_time_type);
2008 Write("HighlightTracks", g_bHighliteTracks);
2009
2010 Write("DateTimeFormat", g_datetime_format);
2011 Write("InitialStackIndex", g_restore_stackindex);
2012 Write("InitialdBIndex", g_restore_dbindex);
2013
2014 Write("NMEAAPBPrecision", g_NMEAAPBPrecision);
2015
2016 Write("TalkerIdText", g_TalkerIdText);
2017 Write("ShowTrackPointTime", g_bShowTrackPointTime);
2018
2019 Write("AnchorWatch1GUID", g_AW1GUID);
2020 Write("AnchorWatch2GUID", g_AW2GUID);
2021
2022 Write("ToolbarX", g_maintoolbar_x);
2023 Write("ToolbarY", g_maintoolbar_y);
2024 // Write( "ToolbarOrient", g_maintoolbar_orient );
2025
2026 Write("iENCToolbarX", g_iENCToolbarPosX);
2027 Write("iENCToolbarY", g_iENCToolbarPosY);
2028
2029 if (!g_bInlandEcdis) {
2030 Write("GlobalToolbarConfig", g_toolbarConfig);
2031 Write("DistanceFormat", g_iDistanceFormat);
2032 Write("SpeedFormat", g_iSpeedFormat);
2033 Write("WindSpeedFormat", g_iWindSpeedFormat);
2034 Write("ShowDepthUnits", g_bShowDepthUnits);
2035 Write("TemperatureFormat", g_iTempFormat);
2036 Write("HeightFormat", g_iHeightFormat);
2037 }
2038 Write("GPSIdent", g_GPS_Ident);
2039 Write("ActiveRoute", g_active_route);
2040 Write("PersistActiveRoute", g_persist_active_route);
2041 Write("AlwaysSendRmbRmc", g_always_send_rmb_rmc);
2042
2043 Write("UseGarminHostUpload", g_bGarminHostUpload);
2044
2045 Write("MobileTouch", g_btouch);
2046 Write("ResponsiveGraphics", g_bresponsive);
2047 Write("EnableRolloverBlock", g_bRollover);
2048
2049 Write("AutoHideToolbar", g_bAutoHideToolbar);
2050 Write("AutoHideToolbarSecs", g_nAutoHideToolbar);
2051
2052 wxString st0;
2053 for (const auto &mm : g_config_display_size_mm) {
2054 st0.Append(wxString::Format("%zu,", mm));
2055 }
2056 st0.RemoveLast(); // Strip last comma
2057 Write("DisplaySizeMM", st0);
2058 Write("DisplaySizeManual", g_config_display_size_manual);
2059
2060 Write("SelectionRadiusMM", g_selection_radius_mm);
2061 Write("SelectionRadiusTouchMM", g_selection_radius_touch_mm);
2062
2063 st0.Printf("%g", g_PlanSpeed);
2064 Write("PlanSpeed", st0);
2065
2066 if (g_bLayersLoaded) {
2067 wxString vis, invis, visnames, invisnames;
2068 LayerList::iterator it;
2069 int index = 0;
2070 for (it = (*pLayerList).begin(); it != (*pLayerList).end(); ++it, ++index) {
2071 Layer *lay = (Layer *)(*it);
2072 if (lay->IsVisibleOnChart())
2073 vis += (lay->m_LayerName) + ";";
2074 else
2075 invis += (lay->m_LayerName) + ";";
2076
2077 if (lay->HasVisibleNames() == wxCHK_CHECKED) {
2078 visnames += (lay->m_LayerName) + ";";
2079 } else if (lay->HasVisibleNames() == wxCHK_UNCHECKED) {
2080 invisnames += (lay->m_LayerName) + ";";
2081 }
2082 }
2083 Write("VisibleLayers", vis);
2084 Write("InvisibleLayers", invis);
2085 Write("VisNameInLayers", visnames);
2086 Write("InvisNameInLayers", invisnames);
2087 }
2088 Write("Locale", g_locale);
2089 Write("LocaleOverride", g_localeOverride);
2090
2091 Write("KeepNavobjBackups", g_navobjbackups);
2092 Write("LegacyInputCOMPortFilterBehaviour", g_b_legacy_input_filter_behaviour);
2093 Write("AdvanceRouteWaypointOnArrivalOnly",
2094 g_bAdvanceRouteWaypointOnArrivalOnly);
2095 Write("EnableRootMenuDebug", g_enable_root_menu_debug);
2096
2097 // LIVE ETA OPTION
2098 Write("LiveETA", g_bShowLiveETA);
2099 Write("DefaultBoatSpeed", g_defaultBoatSpeed);
2100
2101 // S57 Object Filter Settings
2102
2103 SetPath("/Settings/ObjectFilter");
2104
2105 if (ps52plib) {
2106 for (unsigned int iPtr = 0; iPtr < ps52plib->pOBJLArray->GetCount();
2107 iPtr++) {
2108 OBJLElement *pOLE = (OBJLElement *)(ps52plib->pOBJLArray->Item(iPtr));
2109
2110 wxString st1("viz");
2111 char name[7];
2112 strncpy(name, pOLE->OBJLName, 6);
2113 name[6] = 0;
2114 st1.Append(wxString(name, wxConvUTF8));
2115 Write(st1, pOLE->nViz);
2116 }
2117 }
2118
2119 // Global State
2120
2121 SetPath("/Settings/GlobalState");
2122
2123 wxString st1;
2124
2125 // if( cc1 ) {
2126 // ViewPort vp = cc1->GetVP();
2127 //
2128 // if( vp.IsValid() ) {
2129 // st1.Printf( "%10.4f,%10.4f", vp.clat, vp.clon );
2130 // Write( "VPLatLon", st1 );
2131 // st1.Printf( "%g", vp.view_scale_ppm );
2132 // Write( "VPScale", st1 );
2133 // st1.Printf( "%i", ((int)(vp.rotation * 180 / PI)) % 360
2134 // ); Write( "VPRotation", st1 );
2135 // }
2136 // }
2137
2138 st1.Printf("%10.4f, %10.4f", gLat, gLon);
2139 Write("OwnShipLatLon", st1);
2140
2141 // Various Options
2142 SetPath("/Settings/GlobalState");
2143 if (!g_bInlandEcdis)
2144 Write("nColorScheme", (int)user_colors::GetColorScheme());
2145
2146 Write("FrameWinX", g_nframewin_x);
2147 Write("FrameWinY", g_nframewin_y);
2148 Write("FrameWinPosX", g_nframewin_posx);
2149 Write("FrameWinPosY", g_nframewin_posy);
2150 Write("FrameMax", g_bframemax);
2151
2152 Write("ClientPosX", g_lastClientRectx);
2153 Write("ClientPosY", g_lastClientRecty);
2154 Write("ClientSzX", g_lastClientRectw);
2155 Write("ClientSzY", g_lastClientRecth);
2156
2157 Write("S52_DEPTH_UNIT_SHOW", g_nDepthUnitDisplay);
2158
2159 Write("RoutePropSizeX", g_route_prop_sx);
2160 Write("RoutePropSizeY", g_route_prop_sy);
2161 Write("RoutePropPosX", g_route_prop_x);
2162 Write("RoutePropPosY", g_route_prop_y);
2163
2164 // Sounds
2165 SetPath("/Settings/Audio");
2166 Write("AISAlertSoundFile", g_AIS_sound_file);
2167 Write("DSCAlertSoundFile", g_DSC_sound_file);
2168 Write("SARTAlertSoundFile", g_SART_sound_file);
2169 Write("AnchorAlarmSoundFile", g_anchorwatch_sound_file);
2170
2171 Write("bAIS_GCPA_AlertAudio", g_bAIS_GCPA_Alert_Audio);
2172 Write("bAIS_SART_AlertAudio", g_bAIS_SART_Alert_Audio);
2173 Write("bAIS_DSC_AlertAudio", g_bAIS_DSC_Alert_Audio);
2174 Write("bAnchorAlertAudio", g_bAnchor_Alert_Audio);
2175
2176 // AIS
2177 SetPath("/Settings/AIS");
2178
2179 Write("bNoCPAMax", g_bCPAMax);
2180 Write("NoCPAMaxNMi", g_CPAMax_NM);
2181 Write("bCPAWarn", g_bCPAWarn);
2182 Write("CPAWarnNMi", g_CPAWarn_NM);
2183 Write("bTCPAMax", g_bTCPA_Max);
2184 Write("TCPAMaxMinutes", g_TCPA_Max);
2185 Write("bMarkLostTargets", g_bMarkLost);
2186 Write("MarkLost_Minutes", g_MarkLost_Mins);
2187 Write("bRemoveLostTargets", g_bRemoveLost);
2188 Write("RemoveLost_Minutes", g_RemoveLost_Mins);
2189 Write("bShowCOGArrows", g_bShowCOG);
2190 Write("bSyncCogPredictors", g_bSyncCogPredictors);
2191 Write("CogArrowMinutes", g_ShowCOG_Mins);
2192 Write("bShowTargetTracks", g_bAISShowTracks);
2193 Write("TargetTracksMinutes", g_AISShowTracks_Mins);
2194
2195 Write("bHideMooredTargets", g_bHideMoored);
2196 Write("MooredTargetMaxSpeedKnots", g_ShowMoored_Kts);
2197
2198 Write("bAISAlertDialog", g_bAIS_CPA_Alert);
2199 Write("bAISAlertAudio", g_bAIS_CPA_Alert_Audio);
2200
2201 Write("AISAlertAudioFile", g_sAIS_Alert_Sound_File);
2202 Write("bAISAlertSuppressMoored", g_bAIS_CPA_Alert_Suppress_Moored);
2203 Write("bShowAreaNotices", g_bShowAreaNotices);
2204 Write("bDrawAISSize", g_bDrawAISSize);
2205 Write("bDrawAISRealtime", g_bDrawAISRealtime);
2206 Write("AISRealtimeMinSpeedKnots", g_AIS_RealtPred_Kts);
2207 Write("bShowAISName", g_bShowAISName);
2208 Write("ShowAISTargetNameScale", g_Show_Target_Name_Scale);
2209 Write("bWplIsAprsPositionReport", g_bWplUsePosition);
2210 Write("WplSelAction", g_WplAction);
2211 Write("AISCOGPredictorWidth", g_ais_cog_predictor_width);
2212 Write("bShowScaledTargets", g_bAllowShowScaled);
2213 Write("AISScaledNumber", g_ShowScaled_Num);
2214 Write("AISScaledNumberWeightSOG", g_ScaledNumWeightSOG);
2215 Write("AISScaledNumberWeightCPA", g_ScaledNumWeightCPA);
2216 Write("AISScaledNumberWeightTCPA", g_ScaledNumWeightTCPA);
2217 Write("AISScaledNumberWeightRange", g_ScaledNumWeightRange);
2218 Write("AISScaledNumberWeightSizeOfTarget", g_ScaledNumWeightSizeOfT);
2219 Write("AISScaledSizeMinimal", g_ScaledSizeMinimal);
2220 Write("AISShowScaled", g_bShowScaled);
2221
2222 Write("AlertDialogSizeX", g_ais_alert_dialog_sx);
2223 Write("AlertDialogSizeY", g_ais_alert_dialog_sy);
2224 Write("AlertDialogPosX", g_ais_alert_dialog_x);
2225 Write("AlertDialogPosY", g_ais_alert_dialog_y);
2226 Write("QueryDialogPosX", g_ais_query_dialog_x);
2227 Write("QueryDialogPosY", g_ais_query_dialog_y);
2228 Write("AISTargetListPerspective", g_AisTargetList_perspective);
2229 Write("AISTargetListRange", g_AisTargetList_range);
2230 Write("AISTargetListSortColumn", g_AisTargetList_sortColumn);
2231 Write("bAISTargetListSortReverse", g_bAisTargetList_sortReverse);
2232 Write("AISTargetListColumnSpec", g_AisTargetList_column_spec);
2233 Write("AISTargetListColumnOrder", g_AisTargetList_column_order);
2234
2235 Write("S57QueryDialogSizeX", g_S57_dialog_sx);
2236 Write("S57QueryDialogSizeY", g_S57_dialog_sy);
2237 Write("S57QueryExtraDialogSizeX", g_S57_extradialog_sx);
2238 Write("S57QueryExtraDialogSizeY", g_S57_extradialog_sy);
2239
2240 Write("bAISRolloverShowClass", g_bAISRolloverShowClass);
2241 Write("bAISRolloverShowCOG", g_bAISRolloverShowCOG);
2242 Write("bAISRolloverShowCPA", g_bAISRolloverShowCPA);
2243
2244 Write("bAISAlertAckTimeout", g_bAIS_ACK_Timeout);
2245 Write("AlertAckTimeoutMinutes", g_AckTimeout_Mins);
2246
2247 SetPath("/Settings/GlobalState");
2248 if (ps52plib) {
2249 Write("bShowS57Text", ps52plib->GetShowS57Text());
2250 Write("bShowS57ImportantTextOnly", ps52plib->GetShowS57ImportantTextOnly());
2251 if (!g_bInlandEcdis)
2252 Write("nDisplayCategory", (long)ps52plib->GetDisplayCategory());
2253 Write("nSymbolStyle", (int)ps52plib->m_nSymbolStyle);
2254 Write("nBoundaryStyle", (int)ps52plib->m_nBoundaryStyle);
2255
2256 Write("bShowSoundg", ps52plib->m_bShowSoundg);
2257 Write("bShowMeta", ps52plib->m_bShowMeta);
2258 Write("bUseSCAMIN", ps52plib->m_bUseSCAMIN);
2259 Write("bUseSUPER_SCAMIN", ps52plib->m_bUseSUPER_SCAMIN);
2260 Write("bShowAtonText", ps52plib->m_bShowAtonText);
2261 Write("bShowLightDescription", ps52plib->m_bShowLdisText);
2262 Write("bExtendLightSectors", ps52plib->m_bExtendLightSectors);
2263 Write("bDeClutterText", ps52plib->m_bDeClutterText);
2264 Write("bShowNationalText", ps52plib->m_bShowNationalTexts);
2265
2266 Write("S52_MAR_SAFETY_CONTOUR",
2267 S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR));
2268 Write("S52_MAR_SHALLOW_CONTOUR",
2269 S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR));
2270 Write("S52_MAR_DEEP_CONTOUR", S52_getMarinerParam(S52_MAR_DEEP_CONTOUR));
2271 Write("S52_MAR_TWO_SHADES", S52_getMarinerParam(S52_MAR_TWO_SHADES));
2272 Write("S52_DEPTH_UNIT_SHOW", ps52plib->m_nDepthUnitDisplay);
2273 Write("ENCSoundingScaleFactor", g_ENCSoundingScaleFactor);
2274 Write("ENCTextScaleFactor", g_ENCTextScaleFactor);
2275 }
2276 SetPath("/Directories");
2277 Write("S57DataLocation", "");
2278 // Write( "SENCFileLocation", "" );
2279
2280 SetPath("/Directories");
2281 Write("InitChartDir", *pInit_Chart_Dir);
2282 Write("GPXIODir", g_gpx_path);
2283 Write("TCDataDir", g_TCData_Dir);
2284 Write("BasemapDir", g_Platform->NormalizePath(gWorldMapLocation));
2285 if (gWorldShapefileLocation.Length())
2286 Write("BaseShapefileDir",
2287 g_Platform->NormalizePath(gWorldShapefileLocation));
2288 Write("pluginInstallDir", g_Platform->NormalizePath(g_winPluginDir));
2289
2290 SetPath("/Settings/NMEADataSource");
2291 wxString connectionconfigs;
2292 for (size_t i = 0; i < TheConnectionParams().size(); i++) {
2293 if (i > 0) connectionconfigs.Append("|");
2294 connectionconfigs.Append(TheConnectionParams()[i]->Serialize());
2295 }
2296 Write("DataConnections", connectionconfigs);
2297
2298 // Fonts
2299
2300 // Store the persistent Auxiliary Font descriptor Keys
2301 SetPath("/Settings/AuxFontKeys");
2302
2303 wxArrayString keyArray = FontMgr::Get().GetAuxKeyArray();
2304 for (unsigned int i = 0; i < keyArray.GetCount(); i++) {
2305 wxString key;
2306 key.Printf("Key%i", i);
2307 wxString keyval = keyArray[i];
2308 Write(key, keyval);
2309 }
2310
2311 wxString font_path;
2312#ifdef __WXX11__
2313 font_path = ("/Settings/X11Fonts");
2314#endif
2315
2316#ifdef __WXGTK__
2317 font_path = ("/Settings/GTKFonts");
2318#endif
2319
2320#ifdef __WXMSW__
2321 font_path = ("/Settings/MSWFonts");
2322#endif
2323
2324#ifdef __WXMAC__
2325 font_path = ("/Settings/MacFonts");
2326#endif
2327
2328#ifdef __WXQT__
2329 font_path = ("/Settings/QTFonts");
2330#endif
2331
2332 if (HasEntry(font_path)) DeleteGroup(font_path);
2333
2334 SetPath(font_path);
2335
2336 int nFonts = FontMgr::Get().GetNumFonts();
2337
2338 for (int i = 0; i < nFonts; i++) {
2339 wxString cfstring(FontMgr::Get().GetConfigString(i));
2340 wxString valstring = FontMgr::Get().GetFullConfigDesc(i);
2341 Write(cfstring, valstring);
2342 }
2343
2344 // Tide/Current Data Sources
2345 if (HasGroup("/TideCurrentDataSources"))
2346 DeleteGroup("/TideCurrentDataSources");
2347 SetPath("/TideCurrentDataSources");
2348 unsigned int id = 0;
2349 for (auto val : TideCurrentDataSet) {
2350 wxString key;
2351 key.Printf("tcds%d", id);
2352 Write(key, wxString(val));
2353 ++id;
2354 }
2355
2356 SetPath("/Settings/Others");
2357
2358 // Radar rings
2359 Write("ShowRadarRings",
2360 (bool)(g_iNavAidRadarRingsNumberVisible > 0)); // 3.0.0 config support
2361 Write("RadarRingsNumberVisible", g_iNavAidRadarRingsNumberVisible);
2362 Write("RadarRingsStep", g_fNavAidRadarRingsStep);
2363 Write("RadarRingsStepUnits", g_pNavAidRadarRingsStepUnits);
2364 Write("RadarRingsColour",
2365 g_colourOwnshipRangeRingsColour.GetAsString(wxC2S_HTML_SYNTAX));
2366 Write("WaypointUseScaMin", g_bUseWptScaMin);
2367 Write("WaypointScaMinValue", g_iWpt_ScaMin);
2368 Write("WaypointScaMaxValue", g_iWpt_ScaMax);
2369 Write("WaypointUseScaMinOverrule", g_bOverruleScaMin);
2370 Write("WaypointsShowName", g_bShowWptName);
2371 Write("UserIconsFirst", g_bUserIconsFirst);
2372
2373 // Waypoint Radar rings
2374 Write("WaypointRangeRingsNumber", g_iWaypointRangeRingsNumber);
2375 Write("WaypointRangeRingsStep", g_fWaypointRangeRingsStep);
2376 Write("WaypointRangeRingsStepUnits", g_iWaypointRangeRingsStepUnits);
2377 Write("WaypointRangeRingsColour",
2378 g_colourWaypointRangeRingsColour.GetAsString(wxC2S_HTML_SYNTAX));
2379
2380 Write("ConfirmObjectDeletion", g_bConfirmObjectDelete);
2381
2382 // Waypoint dragging with mouse; toh, 2009.02.24
2383 Write("WaypointPreventDragging", g_bWayPointPreventDragging);
2384
2385 Write("EnableZoomToCursor", g_bEnableZoomToCursor);
2386
2387 Write("TrackIntervalSeconds", g_TrackIntervalSeconds);
2388 Write("TrackDeltaDistance", g_TrackDeltaDistance);
2389 Write("TrackPrecision", g_nTrackPrecision);
2390
2391 Write("RouteLineWidth", g_route_line_width);
2392 Write("TrackLineWidth", g_track_line_width);
2393 Write("TrackLineColour",
2394 g_colourTrackLineColour.GetAsString(wxC2S_HTML_SYNTAX));
2395 Write("DefaultWPIcon", g_default_wp_icon);
2396 Write("DataMonitorLogfile", g_dm_logfile);
2397 Write("DefaultRPIcon", g_default_routepoint_icon);
2398
2399 DeleteGroup("/MmsiProperties");
2400 SetPath("/MmsiProperties");
2401 for (unsigned int i = 0; i < g_MMSI_Props_Array.GetCount(); i++) {
2402 wxString p;
2403 p.Printf("Props%d", i);
2404 Write(p, g_MMSI_Props_Array[i]->Serialize());
2405 }
2406 SetPath("/DataMonitor");
2407 Write("colors.ok", g_dm_ok);
2408 Write("colors.dropped", g_dm_dropped);
2409 Write("colors.filtered", g_dm_filtered);
2410 Write("colors.input", g_dm_input);
2411 Write("colors.output", g_dm_output);
2412 Write("colors.not-ok", g_dm_not_ok);
2413
2414 SaveCanvasConfigs();
2415
2416 Flush();
2417 SendMessageToAllPlugins("GLOBAL_SETTINGS_UPDATED", "{\"updated\":\"1\"}");
2418
2419#ifdef ocpnUSE_GL
2420 if (g_bopengl) {
2421 if (top_frame::Get()) top_frame::Get()->SendGlJsonConfigMsg();
2422 }
2423#endif
2424}
2425
2426static wxFileName exportFileName(wxWindow *parent,
2427 const wxString suggestedName) {
2428 wxFileName ret;
2429 wxString path;
2430 wxString valid_name = SanitizeFileName(suggestedName);
2431
2432#ifdef __ANDROID__
2433 if (!valid_name.EndsWith(".gpx")) {
2434 wxFileName fn(valid_name);
2435 fn.ClearExt();
2436 fn.SetExt("gpx");
2437 valid_name = fn.GetFullName();
2438 }
2439#endif
2440 int response = g_Platform->DoFileSelectorDialog(
2441 parent, &path, _("Export GPX file"), g_gpx_path, valid_name, "*.gpx");
2442
2443 if (response == wxID_OK) {
2444 wxFileName fn(path);
2445 g_gpx_path = fn.GetPath();
2446 if (!fn.GetExt().StartsWith("gpx")) fn.SetExt("gpx");
2447
2448#if defined(__WXMSW__) || defined(__WXGTK__)
2449 if (wxFileExists(fn.GetFullPath())) {
2450 int answer = OCPNMessageBox(NULL, _("Overwrite existing file?"),
2451 "Confirm", wxICON_QUESTION | wxYES_NO);
2452 if (answer != wxID_YES) return ret;
2453 }
2454#endif
2455 ret = fn;
2456 }
2457 return ret;
2458}
2459
2460int BackupDatabase(wxWindow *parent) {
2461 bool backupResult = false;
2462 wxDateTime tm = wxDateTime::Now();
2463 wxString proposedName = tm.Format("navobj-%Y-%m-%d_%H_%M");
2464 wxString acceptedName;
2465
2466 if (wxID_OK ==
2467 g_Platform->DoFileSelectorDialog(parent, &acceptedName, _("Backup"),
2468 wxStandardPaths::Get().GetDocumentsDir(),
2469 proposedName, "*.bkp")) {
2470 wxFileName fileName(acceptedName);
2471 if (fileName.IsOk()) {
2472#if defined(__WXMSW__) || defined(__WXGTK__)
2473 if (fileName.FileExists()) {
2474 if (wxID_YES != OCPNMessageBox(NULL, _("Overwrite existing file?"),
2475 "Confirm", wxICON_QUESTION | wxYES_NO)) {
2476 return wxID_ABORT; // We've decided not to overwrite a file, aborting
2477 }
2478 }
2479#endif
2480
2481#ifdef __ANDROID__
2482 wxString secureFileName = androidGetCacheDir() +
2483 wxFileName::GetPathSeparator() +
2484 fileName.GetFullName();
2485 backupResult = NavObj_dB::GetInstance().Backup(secureFileName);
2486 AndroidSecureCopyFile(secureFileName, fileName.GetFullPath());
2487#else
2488 backupResult = NavObj_dB::GetInstance().Backup(fileName.GetFullPath());
2489#endif
2490 }
2491 return backupResult ? wxID_YES : wxID_NO;
2492 }
2493 return wxID_ABORT; // Cancelled the file open dialog, aborting
2494}
2495
2496bool ExportGPXRoutes(wxWindow *parent, RouteList *pRoutes,
2497 const wxString suggestedName) {
2498#ifndef __ANDROID__
2499 wxFileName fn = exportFileName(parent, suggestedName);
2500 if (fn.IsOk()) {
2502 pgpx->AddGPXRoutesList(pRoutes);
2503 pgpx->SaveFile(fn.GetFullPath());
2504 delete pgpx;
2505 return true;
2506 }
2507#else
2508 // Create the .GPX file, saving it in the OCPN Android cache directory
2509 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
2510 suggestedName + ".gpx";
2512 pgpx->AddGPXRoutesList(pRoutes);
2513 pgpx->SaveFile(fns);
2514 delete pgpx;
2515
2516 // Kick off the Android file chooser activity
2517 wxString path;
2518 int response = g_Platform->DoFileSelectorDialog(
2519 parent, &path, _("Export GPX file"), g_gpx_path, suggestedName + ".gpx",
2520 "*.gpx");
2521
2522 if (path.IsEmpty()) // relocation handled by SAF logic in Java
2523 return true;
2524
2525 wxCopyFile(fns, path); // known to be safe paths, since SAF is not involved.
2526 return true;
2527
2528#endif
2529
2530 return false;
2531}
2532
2533bool ExportGPXTracks(wxWindow *parent, std::vector<Track *> *pTracks,
2534 const wxString suggestedName) {
2535#ifndef __ANDROID__
2536 wxFileName fn = exportFileName(parent, suggestedName);
2537 if (fn.IsOk()) {
2539 pgpx->AddGPXTracksList(pTracks);
2540 pgpx->SaveFile(fn.GetFullPath());
2541 delete pgpx;
2542 return true;
2543 }
2544#else
2545 // Create the .GPX file, saving it in the OCPN Android cache directory
2546 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
2547 suggestedName + ".gpx";
2549 pgpx->AddGPXTracksList(pTracks);
2550 pgpx->SaveFile(fns);
2551 delete pgpx;
2552
2553 // Kick off the Android file chooser activity
2554 wxString path;
2555 int response = g_Platform->DoFileSelectorDialog(
2556 parent, &path, _("Export GPX file"), g_gpx_path, suggestedName + ".gpx",
2557 "*.gpx");
2558
2559 if (path.IsEmpty()) // relocation handled by SAF logic in Java
2560 return true;
2561
2562 wxCopyFile(fns, path); // known to be safe paths, since SAF is not involved.
2563 return true;
2564#endif
2565
2566 return false;
2567}
2568
2569bool ExportGPXWaypoints(wxWindow *parent, RoutePointList *pRoutePoints,
2570 const wxString suggestedName) {
2571#ifndef __ANDROID__
2572 wxFileName fn = exportFileName(parent, suggestedName);
2573 if (fn.IsOk()) {
2575 pgpx->AddGPXPointsList(pRoutePoints);
2576 pgpx->SaveFile(fn.GetFullPath());
2577 delete pgpx;
2578 return true;
2579 }
2580#else
2581 // Create the .GPX file, saving it in the OCPN Android cache directory
2582 wxString fns = androidGetCacheDir() + wxFileName::GetPathSeparator() +
2583 suggestedName + ".gpx";
2585 pgpx->AddGPXPointsList(pRoutePoints);
2586 pgpx->SaveFile(fns);
2587 delete pgpx;
2588
2589 // Kick off the Android file chooser activity
2590 wxString path;
2591 int response = g_Platform->DoFileSelectorDialog(
2592 parent, &path, _("Export GPX file"), g_gpx_path, suggestedName + ".gpx",
2593 "*.gpx");
2594
2595 if (path.IsEmpty()) // relocation handled by SAF logic in Java
2596 return true;
2597
2598 wxCopyFile(fns, path); // known to be safe paths, since SAF is not involved.
2599 return true;
2600
2601#endif
2602
2603 return false;
2604}
2605
2606void ExportGPX(wxWindow *parent, bool bviz_only, bool blayer) {
2608 wxString fns;
2609
2610#ifndef __ANDROID__
2611 wxFileName fn = exportFileName(parent, "userobjects.gpx");
2612 if (!fn.IsOk()) return;
2613 fns = fn.GetFullPath();
2614#else
2615 // Create the .GPX file, saving it in the OCPN Android cache directory
2616 fns =
2617 androidGetCacheDir() + wxFileName::GetPathSeparator() + "userobjects.gpx";
2618
2619#endif
2620 ::wxBeginBusyCursor();
2621
2622 wxGenericProgressDialog *pprog = nullptr;
2623 int count = pWayPointMan->GetWaypointList()->size();
2624 int progStep = count / 32;
2625 if (count > 200) {
2626 pprog = new wxGenericProgressDialog(
2627 _("Export GPX file"), "0/0", count, NULL,
2628 wxPD_APP_MODAL | wxPD_SMOOTH | wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME |
2629 wxPD_REMAINING_TIME);
2630 pprog->SetSize(400, wxDefaultCoord);
2631 pprog->Centre();
2632 }
2633
2634 // WPTs
2635 int ic = 1;
2636
2637 for (RoutePoint *pr : *pWayPointMan->GetWaypointList()) {
2638 if (pprog && !(ic % progStep)) {
2639 wxString msg;
2640 msg.Printf("%d/%d", ic, count);
2641 pprog->Update(ic, msg);
2642 }
2643 ic++;
2644
2645 bool b_add = true;
2646 if (bviz_only && !pr->m_bIsVisible) b_add = false;
2647
2648 if (pr->m_bIsInLayer && !blayer) b_add = false;
2649 if (b_add) {
2650 if (pr->IsShared() || !WptIsInRouteList(pr)) pgpx->AddGPXWaypoint(pr);
2651 }
2652 }
2653 // RTEs and TRKs
2654 for (Route *pRoute : *pRouteList) {
2655 bool b_add = true;
2656 if (bviz_only && !pRoute->IsVisible()) b_add = false;
2657 if (pRoute->m_bIsInLayer && !blayer) b_add = false;
2658
2659 if (b_add) pgpx->AddGPXRoute(pRoute);
2660 }
2661
2662 for (Track *pTrack : g_TrackList) {
2663 bool b_add = true;
2664
2665 if (bviz_only && !pTrack->IsVisible()) b_add = false;
2666
2667 if (pTrack->m_bIsInLayer && !blayer) b_add = false;
2668
2669 if (b_add) pgpx->AddGPXTrack(pTrack);
2670 }
2671
2672 pgpx->SaveFile(fns);
2673
2674#ifdef __ANDROID__
2675 // Kick off the Android file chooser activity
2676 wxString path;
2677 int response =
2678 g_Platform->DoFileSelectorDialog(parent, &path, _("Export GPX file"),
2679 g_gpx_path, "userobjects.gpx", "*.gpx");
2680 if (path.IsEmpty()) // relocation handled by SAF logic in Java
2681 return;
2682
2683 wxCopyFile(fns, path); // known to be safe paths, since SAF is not involved.
2684 return;
2685#endif
2686 delete pgpx;
2687 ::wxEndBusyCursor();
2688 delete pprog;
2689}
2690
2691void UI_ImportGPX(wxWindow *parent, bool islayer, wxString dirpath,
2692 bool isdirectory, bool isPersistent) {
2693 int response = wxID_CANCEL;
2694 wxArrayString file_array;
2695
2696 if (!islayer || dirpath.IsSameAs("")) {
2697 // Platform DoFileSelectorDialog method does not properly handle multiple
2698 // selections So use native method if not Android, which means Android gets
2699 // single selection only.
2700#ifndef __ANDROID__
2701 wxFileDialog *popenDialog =
2702 new wxFileDialog(NULL, _("Import GPX file"), g_gpx_path, "",
2703 "GPX files (*.gpx)|*.gpx|All files (*.*)|*.*",
2704 wxFD_OPEN | wxFD_MULTIPLE);
2705
2706 if (g_bresponsive && parent)
2707 popenDialog = g_Platform->AdjustFileDialogFont(parent, popenDialog);
2708
2709 popenDialog->Centre();
2710
2711#ifdef __WXOSX__
2712 if (parent) parent->HideWithEffect(wxSHOW_EFFECT_BLEND);
2713#endif
2714
2715 response = popenDialog->ShowModal();
2716
2717#ifdef __WXOSX__
2718 if (parent) parent->ShowWithEffect(wxSHOW_EFFECT_BLEND);
2719#endif
2720
2721 if (response == wxID_OK) {
2722 popenDialog->GetPaths(file_array);
2723
2724 // Record the currently selected directory for later use
2725 if (file_array.GetCount()) {
2726 wxFileName fn(file_array[0]);
2727 g_gpx_path = fn.GetPath();
2728 }
2729 }
2730 delete popenDialog;
2731#else // Android
2732 wxString path;
2733 response = g_Platform->DoFileSelectorDialog(
2734 NULL, &path, _("Import GPX file"), g_gpx_path, "", "*.gpx");
2735
2736 wxFileName fn(path);
2737 g_gpx_path = fn.GetPath();
2738 if (path.IsEmpty()) { // Return from SAF processing, expecting callback
2739 PrepareImportAndroid(islayer, isPersistent);
2740 return;
2741 } else
2742 file_array.Add(path); // Return from safe app arena access
2743
2744#endif
2745 } else {
2746 if (isdirectory) {
2747 if (wxDir::GetAllFiles(dirpath, &file_array, "*.gpx")) response = wxID_OK;
2748 } else {
2749 file_array.Add(dirpath);
2750 response = wxID_OK;
2751 }
2752 }
2753
2754 if (response == wxID_OK) {
2755 ImportFileArray(file_array, islayer, isPersistent, dirpath);
2756 }
2757}
2758
2759void ImportFileArray(const wxArrayString &file_array, bool islayer,
2760 bool isPersistent, wxString dirpath) {
2761 Layer *l = NULL;
2762
2763 if (islayer) {
2764 l = new Layer();
2765 l->m_LayerID = ++g_LayerIdx;
2766 l->m_LayerFileName = file_array[0];
2767 if (file_array.GetCount() <= 1)
2768 wxFileName::SplitPath(file_array[0], NULL, NULL, &(l->m_LayerName), NULL,
2769 NULL);
2770 else {
2771 if (dirpath.IsSameAs(""))
2772 wxFileName::SplitPath(g_gpx_path, NULL, NULL, &(l->m_LayerName), NULL,
2773 NULL);
2774 else
2775 wxFileName::SplitPath(dirpath, NULL, NULL, &(l->m_LayerName), NULL,
2776 NULL);
2777 }
2778
2779 bool bLayerViz = g_bShowLayers;
2780 if (g_VisibleLayers.Contains(l->m_LayerName)) bLayerViz = true;
2781 if (g_InvisibleLayers.Contains(l->m_LayerName)) bLayerViz = false;
2782 l->m_bIsVisibleOnChart = bLayerViz;
2783
2784 // Default for new layers is "Names visible"
2785 l->m_bHasVisibleNames = wxCHK_CHECKED;
2786
2787 wxString laymsg;
2788 laymsg.Printf("New layer %d: %s", l->m_LayerID, l->m_LayerName.c_str());
2789 wxLogMessage(laymsg);
2790
2791 pLayerList->insert(pLayerList->begin(), l);
2792 }
2793
2794 for (unsigned int i = 0; i < file_array.GetCount(); i++) {
2795 wxString path = file_array[i];
2796
2797 if (::wxFileExists(path)) {
2799 pugi::xml_parse_result result = pSet->load_file(path.fn_str());
2800 if (!result) {
2801 wxLogMessage("Error loading GPX file " + path);
2802 wxMessageBox(
2803 wxString::Format(_("Error loading GPX file %s, %s at character %d"),
2804 path, result.description(), result.offset),
2805 _("Import GPX File"));
2806 pSet->reset();
2807 delete pSet;
2808 continue;
2809 }
2810
2811 if (islayer) {
2812 l->m_NoOfItems = pSet->LoadAllGPXObjectsAsLayer(
2813 l->m_LayerID, l->m_bIsVisibleOnChart, l->m_bHasVisibleNames);
2814 l->m_LayerType = isPersistent ? _("Persistent") : _("Temporary");
2815
2816 if (isPersistent) {
2817 // If this is a persistent layer also copy the file to config file
2818 // dir /layers
2819 wxString destf, f, name, ext;
2820 f = l->m_LayerFileName;
2821 wxFileName::SplitPath(f, NULL, NULL, &name, &ext);
2822 destf = g_Platform->GetPrivateDataDir();
2823 appendOSDirSlash(&destf);
2824 destf.Append("layers");
2825 appendOSDirSlash(&destf);
2826 if (!wxDirExists(destf)) {
2827 if (!wxMkdir(destf, wxS_DIR_DEFAULT))
2828 wxLogMessage("Error creating layer directory");
2829 }
2830
2831 destf << name << "." << ext;
2832 wxString msg;
2833 if (wxCopyFile(f, destf, true))
2834 msg.Printf("File: %s.%s also added to persistent layers", name,
2835 ext);
2836 else
2837 msg.Printf("Failed adding %s.%s to persistent layers", name, ext);
2838 wxLogMessage(msg);
2839 }
2840 } else {
2841 int wpt_dups;
2842 pSet->LoadAllGPXObjects(
2843 !pSet->IsOpenCPN(),
2844 wpt_dups); // Import with full visibility of names and objects
2845#ifndef __ANDROID__
2846 if (wpt_dups > 0) {
2847 OCPNMessageBox(
2848 NULL,
2849 wxString::Format("%d " + _("duplicate waypoints detected "
2850 "during import and ignored."),
2851 wpt_dups),
2852 _("OpenCPN Info"), wxICON_INFORMATION | wxOK, 10);
2853 }
2854#endif
2855 }
2856 delete pSet;
2857 }
2858 }
2859}
2860
2861//-------------------------------------------------------------------------
2862// Static Routine Switch to Inland Ecdis Mode
2863//-------------------------------------------------------------------------
2864void SwitchInlandEcdisMode(bool Switch) {
2865 if (Switch) {
2866 wxLogMessage("Switch InlandEcdis mode On");
2867 LoadS57();
2868 // Overrule some settings to comply with InlandEcdis
2869 // g_toolbarConfig = ".....XXXX.X...XX.XXXXXXXXXXXX";
2870 g_iDistanceFormat = 2; // 0 = "Nautical miles"), 1 = "Statute miles", 2 =
2871 // "Kilometers", 3 = "Meters"
2872 g_iSpeedFormat = 2; // 0 = "kts"), 1 = "mph", 2 = "km/h", 3 = "m/s"
2873 if (ps52plib) ps52plib->SetDisplayCategory(STANDARD);
2874 g_bDrawAISSize = false;
2875 if (top_frame::Get()) top_frame::Get()->RequestNewToolbars(true);
2876 } else {
2877 wxLogMessage("Switch InlandEcdis mode Off");
2878 // reread the settings overruled by inlandEcdis
2879 if (pConfig) {
2880 pConfig->SetPath("/Settings");
2881 pConfig->Read("GlobalToolbarConfig", &g_toolbarConfig);
2882 pConfig->Read("DistanceFormat", &g_iDistanceFormat);
2883 pConfig->Read("SpeedFormat", &g_iSpeedFormat);
2884 pConfig->Read("ShowDepthUnits", &g_bShowDepthUnits, 1);
2885 pConfig->Read("HeightFormat", &g_iHeightFormat);
2886 int read_int;
2887 pConfig->Read("nDisplayCategory", &read_int, (enum _DisCat)STANDARD);
2888 if (ps52plib) ps52plib->SetDisplayCategory((enum _DisCat)read_int);
2889 pConfig->SetPath("/Settings/AIS");
2890 pConfig->Read("bDrawAISSize", &g_bDrawAISSize);
2891 pConfig->Read("bDrawAISRealtime", &g_bDrawAISRealtime);
2892 }
2893 if (top_frame::Get()) top_frame::Get()->RequestNewToolbars(true);
2894 }
2895}
2896
2897//-------------------------------------------------------------------------
2898//
2899// Static GPX Support Routines
2900//
2901//-------------------------------------------------------------------------
2902// This function formats the input date/time into a valid GPX ISO 8601
2903// time string specified in the UTC time zone.
2904
2905wxString FormatGPXDateTime(wxDateTime dt) {
2906 // return dt.Format("%Y-%m-%dT%TZ", wxDateTime::GMT0);
2907 return dt.Format("%Y-%m-%dT%H:%M:%SZ");
2908}
2909
2910/**************************************************************************/
2911/* LogMessageOnce */
2912/**************************************************************************/
2913
2914bool LogMessageOnce(const wxString &msg) {
2915 // Search the array for a match
2916
2917 for (unsigned int i = 0; i < navutil::pMessageOnceArray->GetCount(); i++) {
2918 if (msg.IsSameAs(navutil::pMessageOnceArray->Item(i))) return false;
2919 }
2920
2921 // Not found, so add to the array
2922 navutil::pMessageOnceArray->Add(msg);
2923
2924 // And print it
2925 wxLogMessage(msg);
2926 return true;
2927}
2928
2929/**************************************************************************/
2930/* Some assorted utilities */
2931/**************************************************************************/
2932
2933wxDateTime toUsrDateTime(const wxDateTime ts, const int format,
2934 const double lon) {
2935 if (!ts.IsValid()) {
2936 return ts;
2937 }
2938 int effective_format = format;
2939 if (effective_format == GLOBAL_SETTINGS_INPUT) {
2940 if (::g_datetime_format == "UTC") {
2941 effective_format = UTCINPUT;
2942 } else if (::g_datetime_format == "LMT") {
2943 effective_format = LMTINPUT;
2944 } else if (::g_datetime_format == "Local Time") {
2945 effective_format = LTINPUT;
2946 } else {
2947 // Default to UTC
2948 effective_format = UTCINPUT;
2949 }
2950 }
2951 wxDateTime dt;
2952 switch (effective_format) {
2953 case LMTINPUT: // LMT@Location
2954 if (std::isnan(lon)) {
2955 dt = wxInvalidDateTime;
2956 } else {
2957 dt =
2958 ts.Add(wxTimeSpan(wxTimeSpan(0, 0, wxLongLong(lon * 3600. / 15.))));
2959 }
2960 break;
2961 case LTINPUT: // Local@PC
2962 // Convert date/time from UTC to local time.
2963 dt = ts.FromUTC();
2964 break;
2965 case UTCINPUT: // UTC
2966 // The date/time is already in UTC.
2967 dt = ts;
2968 break;
2969 }
2970 return dt;
2971}
2972
2973wxDateTime fromUsrDateTime(const wxDateTime ts, const int format,
2974 const double lon) {
2975 if (!ts.IsValid()) {
2976 return ts;
2977 }
2978 int effective_format = format;
2979 if (effective_format == GLOBAL_SETTINGS_INPUT) {
2980 if (::g_datetime_format == "UTC") {
2981 effective_format = UTCINPUT;
2982 } else if (::g_datetime_format == "LMT") {
2983 effective_format = LMTINPUT;
2984 } else if (::g_datetime_format == "Local Time") {
2985 effective_format = LTINPUT;
2986 } else {
2987 // Default to UTC
2988 effective_format = UTCINPUT;
2989 }
2990 }
2991 wxDateTime dt;
2992 switch (effective_format) {
2993 case LMTINPUT: // LMT@Location
2994 if (std::isnan(lon)) {
2995 dt = wxInvalidDateTime;
2996 } else {
2997 dt = ts.Subtract(wxTimeSpan(0, 0, wxLongLong(lon * 3600. / 15.)));
2998 }
2999 break;
3000 case LTINPUT: // Local@PC
3001 // The input date/time is in local time, so convert it to UTC.
3002 dt = ts.ToUTC();
3003 break;
3004 case UTCINPUT: // UTC
3005 dt = ts;
3006 break;
3007 }
3008 return dt;
3009}
3010
3011/**************************************************************************/
3012/* Converts the speed from the units selected by user to knots */
3013/**************************************************************************/
3014double fromUsrSpeed(double usr_speed, int unit) {
3015 double ret = NAN;
3016 if (unit == -1) unit = g_iSpeedFormat;
3017 switch (unit) {
3018 case SPEED_KTS: // kts
3019 ret = usr_speed;
3020 break;
3021 case SPEED_MPH: // mph
3022 ret = usr_speed / 1.15078;
3023 break;
3024 case SPEED_KMH: // km/h
3025 ret = usr_speed / 1.852;
3026 break;
3027 case SPEED_MS: // m/s
3028 ret = usr_speed / 0.514444444;
3029 break;
3030 }
3031 return ret;
3032}
3033/**************************************************************************/
3034/* Converts the wind speed from the units selected by user to knots */
3035/**************************************************************************/
3036double fromUsrWindSpeed(double usr_wspeed, int unit) {
3037 double ret = NAN;
3038 if (unit == -1) unit = g_iWindSpeedFormat;
3039 switch (unit) {
3040 case WSPEED_KTS: // kts
3041 ret = usr_wspeed;
3042 break;
3043 case WSPEED_MS: // m/s
3044 ret = usr_wspeed / 0.514444444;
3045 break;
3046 case WSPEED_MPH: // mph
3047 ret = usr_wspeed / 1.15078;
3048 break;
3049 case WSPEED_KMH: // km/h
3050 ret = usr_wspeed / 1.852;
3051 break;
3052 }
3053 return ret;
3054}
3055
3056/**************************************************************************/
3057/* Converts the temperature from the units selected by user to Celsius */
3058/**************************************************************************/
3059double fromUsrTemp(double usr_temp, int unit) {
3060 double ret = NAN;
3061 if (unit == -1) unit = g_iTempFormat;
3062 switch (unit) {
3063 case TEMPERATURE_C: // C
3064 ret = usr_temp;
3065 break;
3066 case TEMPERATURE_F: // F
3067 ret = (usr_temp - 32) * 5.0 / 9.0;
3068 break;
3069 case TEMPERATURE_K: // K
3070 ret = usr_temp - 273.15;
3071 break;
3072 }
3073 return ret;
3074}
3075
3076wxString formatAngle(double angle) {
3077 wxString out;
3078 if (g_bShowMag && g_bShowTrue) {
3079 out.Printf("%03.0f %cT (%.0f %cM)", angle, 0x00B0, toMagnetic(angle),
3080 0x00B0);
3081 } else if (g_bShowTrue) {
3082 out.Printf("%03.0f %cT", angle, 0x00B0);
3083 } else {
3084 out.Printf("%03.0f %cM", toMagnetic(angle), 0x00B0);
3085 }
3086 return out;
3087}
3088
3089/* render a rectangle at a given color and transparency */
3090void AlphaBlending(ocpnDC &dc, int x, int y, int size_x, int size_y,
3091 float radius, wxColour color, unsigned char transparency) {
3092 wxDC *pdc = dc.GetDC();
3093 if (pdc) {
3094 // Get wxImage of area of interest
3095 wxBitmap obm(size_x, size_y);
3096 wxMemoryDC mdc1;
3097 mdc1.SelectObject(obm);
3098 mdc1.Blit(0, 0, size_x, size_y, pdc, x, y);
3099 mdc1.SelectObject(wxNullBitmap);
3100 wxImage oim = obm.ConvertToImage();
3101
3102 // Create destination image
3103 wxBitmap olbm(size_x, size_y);
3104 wxMemoryDC oldc(olbm);
3105 if (!oldc.IsOk()) return;
3106
3107 oldc.SetBackground(*wxBLACK_BRUSH);
3108 oldc.SetBrush(*wxWHITE_BRUSH);
3109 oldc.Clear();
3110
3111 if (radius > 0.0) oldc.DrawRoundedRectangle(0, 0, size_x, size_y, radius);
3112
3113 wxImage dest = olbm.ConvertToImage();
3114 unsigned char *dest_data =
3115 (unsigned char *)malloc(size_x * size_y * 3 * sizeof(unsigned char));
3116 unsigned char *bg = oim.GetData();
3117 unsigned char *box = dest.GetData();
3118 unsigned char *d = dest_data;
3119
3120 // Sometimes, on Windows, the destination image is corrupt...
3121 if (NULL == box) {
3122 free(d);
3123 return;
3124 }
3125 float alpha = 1.0 - (float)transparency / 255.0;
3126 int sb = size_x * size_y;
3127 for (int i = 0; i < sb; i++) {
3128 float a = alpha;
3129 if (*box == 0 && radius > 0.0) a = 1.0;
3130 int r = ((*bg++) * a) + (1.0 - a) * color.Red();
3131 *d++ = r;
3132 box++;
3133 int g = ((*bg++) * a) + (1.0 - a) * color.Green();
3134 *d++ = g;
3135 box++;
3136 int b = ((*bg++) * a) + (1.0 - a) * color.Blue();
3137 *d++ = b;
3138 box++;
3139 }
3140
3141 dest.SetData(dest_data);
3142
3143 // Convert destination to bitmap and draw it
3144 wxBitmap dbm(dest);
3145 dc.DrawBitmap(dbm, x, y, false);
3146
3147 // on MSW, the dc Bounding box is not updated on DrawBitmap() method.
3148 // Do it explicitely here for all platforms.
3149 dc.CalcBoundingBox(x, y);
3150 dc.CalcBoundingBox(x + size_x, y + size_y);
3151 } else {
3152#ifdef ocpnUSE_GL
3153 glEnable(GL_BLEND);
3154
3155 float radMod = wxMax(radius, 2.0);
3156 wxColour c(color.Red(), color.Green(), color.Blue(), transparency);
3157 dc.SetBrush(wxBrush(c));
3158 dc.SetPen(wxPen(c, 1));
3159 dc.DrawRoundedRectangle(x, y, size_x, size_y, radMod);
3160
3161 glDisable(GL_BLEND);
3162
3163#endif
3164 }
3165}
3166
3167void DimeControl(wxWindow *ctrl) {
3168#ifdef __WXOSX__
3169 // On macOS 10.14+, we use the native colours in both light mode and dark
3170 // mode, and do not need to do anything else. Dark mode is toggled at the
3171 // application level in `SetAndApplyColorScheme`, and is also respected if it
3172 // is enabled system-wide.
3173 if (wxPlatformInfo::Get().CheckOSVersion(10, 14)) {
3174 return;
3175 }
3176#endif
3177#ifdef __WXQT__
3178 return; // this is seriously broken on wxqt
3179#endif
3180
3181 if (wxSystemSettings::GetColour(wxSystemColour::wxSYS_COLOUR_WINDOW).Red() <
3182 128) {
3183 // Dark system color themes usually do better job than we do on diming UI
3184 // controls, do not fight with them
3185 return;
3186 }
3187
3188 if (NULL == ctrl) return;
3189
3190 wxColour col, window_back_color, gridline, uitext, udkrd, ctrl_back_color,
3191 text_color;
3192 col = GetGlobalColor("DILG0"); // Dialog Background white
3193 window_back_color = GetGlobalColor("DILG1"); // Dialog Background
3194 ctrl_back_color = GetGlobalColor("DILG1"); // Control Background
3195 text_color = GetGlobalColor("DILG3"); // Text
3196 uitext = GetGlobalColor("UITX1"); // Menu Text, derived from UINFF
3197 udkrd = GetGlobalColor("UDKRD");
3198 gridline = GetGlobalColor("GREY2");
3199
3200 DimeControl(ctrl, col, window_back_color, ctrl_back_color, text_color, uitext,
3201 udkrd, gridline);
3202}
3203
3204void DimeControl(wxWindow *ctrl, wxColour col, wxColour window_back_color,
3205 wxColour ctrl_back_color, wxColour text_color, wxColour uitext,
3206 wxColour udkrd, wxColour gridline) {
3207#ifdef __WXOSX__
3208 // On macOS 10.14+, we use the native colours in both light mode and dark
3209 // mode, and do not need to do anything else. Dark mode is toggled at the
3210 // application level in `SetAndApplyColorScheme`, and is also respected if it
3211 // is enabled system-wide.
3212 if (wxPlatformInfo::Get().CheckOSVersion(10, 14)) {
3213 return;
3214 }
3215#endif
3216
3217 ColorScheme cs = global_color_scheme;
3218
3219 // Are we in dusk or night mode? (Used below in several places.)
3220 bool darkMode =
3221 (cs == GLOBAL_COLOR_SCHEME_DUSK || cs == GLOBAL_COLOR_SCHEME_NIGHT);
3222
3223 static int depth = 0; // recursion count
3224 if (depth == 0) { // only for the window root, not for every child
3225 // If the color scheme is DAY or RGB, use the default platform native colour
3226 // for backgrounds
3227 if (!darkMode) {
3228#ifdef _WIN32
3229 window_back_color = wxNullColour;
3230#else
3231 window_back_color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
3232#endif
3233 col = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX);
3234 uitext = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
3235 }
3236
3237 ctrl->SetBackgroundColour(window_back_color);
3238 if (darkMode) ctrl->SetForegroundColour(text_color);
3239 }
3240
3241 wxWindowList kids = ctrl->GetChildren();
3242 for (unsigned int i = 0; i < kids.GetCount(); i++) {
3243 wxWindowListNode *node = kids.Item(i);
3244 wxWindow *win = node->GetData();
3245
3246 if (dynamic_cast<wxListBox *>(win) || dynamic_cast<wxListCtrl *>(win) ||
3247 dynamic_cast<wxTextCtrl *>(win) ||
3248 dynamic_cast<wxTimePickerCtrl *>(win)) {
3249 win->SetBackgroundColour(col);
3250 } else if (dynamic_cast<wxStaticText *>(win) ||
3251 dynamic_cast<wxCheckBox *>(win) ||
3252 dynamic_cast<wxRadioButton *>(win)) {
3253 win->SetForegroundColour(uitext);
3254 }
3255#ifndef __WXOSX__
3256 // On macOS most controls can't be styled, and trying to do so only creates
3257 // weird coloured boxes around them. Fortunately, however, many of them
3258 // inherit a colour or tint from the background of their parent.
3259
3260 else if (dynamic_cast<wxBitmapComboBox *>(win) ||
3261 dynamic_cast<wxChoice *>(win) || dynamic_cast<wxComboBox *>(win) ||
3262 dynamic_cast<wxTreeCtrl *>(win)) {
3263 win->SetBackgroundColour(col);
3264 }
3265
3266 else if (dynamic_cast<wxScrolledWindow *>(win) ||
3267 dynamic_cast<wxGenericDirCtrl *>(win) ||
3268 dynamic_cast<wxListbook *>(win) || dynamic_cast<wxButton *>(win) ||
3269 dynamic_cast<wxToggleButton *>(win)) {
3270 win->SetBackgroundColour(window_back_color);
3271 }
3272
3273 else if (dynamic_cast<wxNotebook *>(win)) {
3274 win->SetBackgroundColour(window_back_color);
3275 win->SetForegroundColour(text_color);
3276 }
3277#endif
3278
3279 else if (dynamic_cast<wxHtmlWindow *>(win)) {
3280 if (cs != GLOBAL_COLOR_SCHEME_DAY && cs != GLOBAL_COLOR_SCHEME_RGB)
3281 win->SetBackgroundColour(ctrl_back_color);
3282 else
3283 win->SetBackgroundColour(wxNullColour);
3284 }
3285
3286 else if (dynamic_cast<wxGrid *>(win)) {
3287 dynamic_cast<wxGrid *>(win)->SetDefaultCellBackgroundColour(
3288 window_back_color);
3289 dynamic_cast<wxGrid *>(win)->SetDefaultCellTextColour(uitext);
3290 dynamic_cast<wxGrid *>(win)->SetLabelBackgroundColour(col);
3291 dynamic_cast<wxGrid *>(win)->SetLabelTextColour(uitext);
3292 dynamic_cast<wxGrid *>(win)->SetGridLineColour(gridline);
3293 }
3294
3295 if (win->GetChildren().GetCount() > 0) {
3296 depth++;
3297 wxWindow *w = win;
3298 DimeControl(w, col, window_back_color, ctrl_back_color, text_color,
3299 uitext, udkrd, gridline);
3300 depth--;
3301 }
3302 }
3303}
ArrayOfMmsiProperties g_MMSI_Props_Array
Global instance.
unsigned g_OwnShipmmsi
Global instance.
Class AisDecoder and helpers.
Global state for AIS decoder.
Chart canvas configuration state
General chart base definitions.
Charts database management
ChartGroupArray * g_pGroupArray
Global instance.
Definition chartdbs.cpp:61
Generic Chart canvas base.
wxString & GetPrivateDataDir()
Return dir path for opencpn.log, etc., respecting -c cli option.
Represents an individual component within a ChartGroup.
Definition chartdbs.h:466
Represents a user-defined collection of logically related charts.
Definition chartdbs.h:486
wxString GetFullConfigDesc(int i) const
Gets description of font at index i.
Definition font_mgr.cpp:360
bool AddAuxKey(wxString key)
Adds new plugin-defined font configuration key.
Definition font_mgr.cpp:653
void LoadFontNative(wxString *pConfigString, wxString *pNativeDesc)
Loads font settings from a string descriptor.
Definition font_mgr.cpp:387
static wxString GetFontConfigKey(const wxString &description)
Creates configuration key from UI element name by combining locale with hash.
Definition font_mgr.cpp:125
int GetNumFonts(void) const
Gets the total number of font configurations currently loaded.
Definition font_mgr.cpp:322
wxArrayString & GetAuxKeyArray()
Gets array of plugin-defined font configuration keys.
Definition font_mgr.h:200
Represents a layer of chart objects in OpenCPN.
Definition layer.h:44
Process incoming AIS messages.
Definition ais_decoder.h:74
static int config_to_ui(double value)
Convert configuration 1.02..3.0 value to slider scale 1..100.
Definition navutil.h:161
static double ui_to_config(int slider_pos)
Convert a slider scale 1-100 value to configuration value 1.02..3.0.
Definition navutil.h:156
Represents a waypoint or mark within the navigation system.
Definition route_point.h:71
Represents a navigational route in the navigation system.
Definition route.h:99
Represents a track, which is a series of connected track points.
Definition track.h:117
ViewPort - Core geographic projection and coordinate transformation engine.
Definition viewport.h:56
double view_scale_ppm
Requested view scale in physical pixels per meter (ppm), before applying projections.
Definition viewport.h:204
double rotation
Rotation angle of the viewport in radians.
Definition viewport.h:214
double clon
Center longitude of the viewport in degrees.
Definition viewport.h:199
double clat
Center latitude of the viewport in degrees.
Definition viewport.h:197
Encapsulates persistent canvas configuration.
double iLat
Latitude of the center of the chart, in degrees.
bool bShowOutlines
Display chart outlines.
wxSize canvasSize
Canvas dimensions.
bool bShowDepthUnits
Display depth unit indicators.
double iLon
Longitude of the center of the chart, in degrees.
double iRotation
Initial rotation angle in radians.
bool bCourseUp
Orient display to course up.
bool bQuilt
Enable chart quilting.
bool bFollow
Enable vessel following mode.
double iScale
Initial chart scale factor.
bool bShowENCText
Display ENC text elements.
bool bShowAIS
Display AIS targets.
bool bShowGrid
Display coordinate grid.
ChartCanvas * canvas
Pointer to associated chart canvas.
bool bShowCurrents
Display current information.
bool bShowTides
Display tide information.
bool bLookahead
Enable lookahead mode.
bool bHeadUp
Orient display to heading up.
bool bAttenAIS
Enable AIS target attenuation.
Device context class that can use either wxDC or OpenGL for drawing.
Definition ocpndc.h:60
Class cm93chart and helpers – CM93 chart state.
Global variables reflecting command line options and arguments.
Config file user configuration interface.
wxString g_datetime_format
Date/time format to use when formatting date/time strings.
bool g_always_send_rmb_rmc
Always send RMB and RMC n0183 messages even if there is no active route.
bool g_bsmoothpanzoom
Controls how the chart panning and zooming smoothing is done during user interactions.
int g_iTempFormat
User-selected temperature unit format for display and input.
int g_nDepthUnitDisplay
User-selected depth (below surface) unit format for display and input.
wxString g_default_font_facename
Default font size for user interface elements such as menus, dialogs, etc.
wxString g_winPluginDir
Base plugin directory on Windows.
wxString g_dm_logfile
Last Data Monitor log file.
bool g_bRollover
enable/disable mouse rollover GUI effects
bool g_bShowTide
not used
int g_COGAvgSec
COG average period for Course Up Mode (sec)
int g_iSpeedFormat
User-selected speed unit format for display and input.
int g_iHeightFormat
User-selected height (vertical, above reference datum) unit format for display and input.
std::vector< size_t > g_config_display_size_mm
Size of pysical screen in millimeters.
int g_iDistanceFormat
User-selected distance (horizontal) unit format for display and input.
bool g_bDisplayGrid
Should lat/lon grid be displayed ?
Global variables stored in configuration file.
Connection parameters.
Extern C linked utilities.
std::vector< OCPN_MonitorInfo > g_monitor_info
Information about the monitors connected to the system.
Definition displays.cpp:45
Display utilities.
NavmsgFilter Read(const std::string &name)
Read filter with given name from disk.
bool Write(const NavmsgFilter &filter, const std::string &name)
Write contents for given filter to disk.
Font list manager.
OpenCPN Georef utility.
OpenGL chart rendering canvas.
Platform independent GL includes.
size_t g_current_monitor
Current monitor displaying main application frame.
Definition gui_vars.cpp:75
double vLat
Virtual lat from chcanv popup.
Definition gui_vars.cpp:72
double vLon
Virtual lon from chcanv popup.
Definition gui_vars.cpp:73
Miscellaneous globals primarely used by gui layer, not persisted in configuration file.
GUI constant definitions.
Chart object layer.
Multiplexer class and helpers.
MySQL based storage for routes, tracks, etc.
MyConfig * pConfig
Global instance.
Definition navutil.cpp:118
wxDateTime toUsrDateTime(const wxDateTime ts, const int format, const double lon)
Converts a timestamp from UTC to the user's preferred time format.
Definition navutil.cpp:2933
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:2973
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.