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