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