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