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