OpenCPN Partial API docs
Loading...
Searching...
No Matches
about.cpp
Go to the documentation of this file.
1/**************************************************************************
2 * Copyright (C) 2010-2023 by David S. Register *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 **************************************************************************/
19
25#include <fstream>
26#include <sstream>
27
28#include <wx/wxprec.h>
29
30#ifndef WX_PRECOMP
31#include <wx/wx.h>
32#endif
33
34#include <wx/textfile.h>
35#include <wx/ffile.h>
36#include <wx/clipbrd.h>
37#include <wx/html/htmlwin.h>
38#include <wx/tokenzr.h>
39#include <config.h>
40
41#include "about.h"
42#include "gui_lib.h"
43#include "chcanv.h"
44#include "styles.h"
45#include "OCPNPlatform.h"
46#include "FontMgr.h"
47#include "navutil.h"
48#include "std_filesystem.h"
49#ifdef __ANDROID__
50#include "androidUTIL.h"
51#endif
52#include "ocpn_frame.h"
53
54extern OCPNPlatform* g_Platform;
55extern ocpnStyle::StyleManager* g_StyleManager;
56extern About* g_pAboutDlgLegacy;
57extern bool g_bresponsive;
58
59wxString OpenCPNVersion("\n Version ");
60
61#define xID_OK 10009
62
63// clang-format off
64
65const wxString AboutText =
66 "<br>OpenCPN<br>"
67 "(c) 2000-2024 The OpenCPN Authors<br><br>";
68
69const wxString OpenCPNInfo =
70 "<br><br>"
71 "OpenCPN is a Free Software project, built by sailors. "
72 "It is freely available to download and distribute "
73 "without charge at opencpn.org.<br><br>"
74 "If you use OpenCPN, please consider contributing "
75 "or donating funds to the project.<br><br>"
76 "For more information, visit http://opencpn.org<br><br>";
77
78const wxString OpenCPNInfoAlt =
79 "<br><br>"
80 "OpenCPN is a Free Software project, built by sailors."
81 "The complete source code and many other resources "
82 "are freely available for your download and use, "
83 "subject to applicable License agreements."
84 "<br><br>"
85 "For more information, visit http://opencpn.org<br><br>";
86
87// clang-format on
88
89BEGIN_EVENT_TABLE(About, wxDialog)
90EVT_BUTTON(xID_OK, About::OnXidOkClick)
91EVT_BUTTON(ID_DONATE, About::OnDonateClick)
92EVT_BUTTON(ID_COPYINI, About::OnCopyClick)
93EVT_BUTTON(ID_COPYLOG, About::OnCopyClick)
94EVT_CLOSE(About::OnClose)
95END_EVENT_TABLE()
96
97About::About(void)
98 : m_DataLocn(wxEmptyString), m_parent(NULL), m_btips_loaded(FALSE) {
99 pAboutHTMLCtl = NULL;
100 pLicenseHTMLCtl = NULL;
101 pAuthorHTMLCtl = NULL;
102 m_blicensePageSet = false;
103}
104
105About::About(wxWindow* parent, wxString Data_Locn,
106 std::function<void()> launch_local_help, wxWindowID id,
107 const wxString& caption, const wxPoint& pos, const wxSize& size,
108 long style)
109 : m_DataLocn(Data_Locn),
110 m_parent(parent),
111 m_launch_local_help(launch_local_help),
112 m_btips_loaded(FALSE) {
113 pAboutHTMLCtl = NULL;
114 pLicenseHTMLCtl = NULL;
115 pAuthorHTMLCtl = NULL;
116 m_blicensePageSet = false;
117
118 if (strlen(DEBIAN_PPA_VERSION))
119 OpenCPNVersion += wxString(DEBIAN_PPA_VERSION);
120 else
121 OpenCPNVersion += wxString(PACKAGE_VERSION);
122
123 Create(parent, id, caption, pos, size, style);
124}
125
126bool About::Create(wxWindow* parent, wxWindowID id, const wxString& caption,
127 const wxPoint& pos, const wxSize& size, long style) {
128 m_parent = parent;
129#ifdef __WXOSX__
130 style |= wxSTAY_ON_TOP;
131#endif
132
133 SetExtraStyle(GetExtraStyle() | wxWS_EX_BLOCK_EVENTS);
134 wxDialog::Create(parent, id, caption, pos, size, style);
135 wxFont* qFont = GetOCPNScaledFont(_("Dialog"));
136 SetFont(*qFont);
137
138 m_displaySize = g_Platform->getDisplaySize();
139 CreateControls();
140 Populate();
141
142 RecalculateSize();
143
144 return TRUE;
145}
146
147void About::SetColorScheme(void) {
148 DimeControl(this);
149 wxColor bg = GetBackgroundColour();
150 if (pAboutHTMLCtl) pAboutHTMLCtl->SetBackgroundColour(bg);
151 if (pLicenseHTMLCtl) pLicenseHTMLCtl->SetBackgroundColour(bg);
152 if (pAuthorHTMLCtl) pAuthorHTMLCtl->SetBackgroundColour(bg);
153
154 // This looks like non-sense, but is needed for __WXGTK__
155 // to get colours to propagate down the control's family tree.
156 SetBackgroundColour(bg);
157
158#ifdef __WXQT__
159 // wxQT has some trouble clearing the background of HTML window...
160 wxBitmap tbm(GetSize().x, GetSize().y, -1);
161 wxMemoryDC tdc(tbm);
162 tdc.SetBackground(bg);
163 tdc.Clear();
164 if (pAboutHTMLCtl) pAboutHTMLCtl->SetBackgroundImage(tbm);
165 if (pLicenseHTMLCtl) pLicenseHTMLCtl->SetBackgroundImage(tbm);
166 if (pAuthorHTMLCtl) pAuthorHTMLCtl->SetBackgroundImage(tbm);
167#endif
168}
169
170void About::Populate(void) {
171 wxColor bg = GetBackgroundColour();
172 wxColor fg = wxColour(0, 0, 0);
173
174 // The HTML Header
175 wxString aboutText = wxString::Format(
176 "<html><body bgcolor=#%02x%02x%02x><font color=#%02x%02x%02x>", bg.Red(),
177 bg.Blue(), bg.Green(), fg.Red(), fg.Blue(), fg.Green());
178
179 wxFont* dFont = FontMgr::Get().GetFont(_("Dialog"));
180
181 // Do weird font size calculation
182 int points = dFont->GetPointSize();
183#ifndef __WXOSX__
184 ++points;
185#endif
186 int sizes[7];
187 for (int i = -2; i < 5; i++) {
188 sizes[i + 2] = points + i + (i > 0 ? i : 0);
189 }
190 wxString face = dFont->GetFaceName();
191 pAboutHTMLCtl->SetFonts(face, face, sizes);
192
193 if (wxFONTSTYLE_ITALIC == dFont->GetStyle()) aboutText.Append("<i>");
194
195#ifdef __OCPN__ANDROID__
196 wxString msg;
197 msg.Printf(" [%d]", androidGetVersionCode());
198 wxString OpenCPNVersionAndroid =
199 "OpenCPN for Android Version " + androidGetVersionName() + msg;
200
201 aboutText.Append(AboutText + OpenCPNVersionAndroid + OpenCPNInfoAlt);
202#else
203 aboutText.Append(AboutText + OpenCPNVersion + OpenCPNInfo);
204#endif
205
206 // Show where the log file is going to be placed
207 wxString log_string = "Logfile location: " + g_Platform->GetLogFileName();
208 log_string.Replace("/", "/ "); // allow line breaks, in a cheap way...
209
210 aboutText.Append(log_string);
211
212 // Show where the config file is going to be placed
213 wxString config_string =
214 "<br><br>Config file location: " + g_Platform->GetConfigFileName();
215 config_string.Replace("/", "/ "); // allow line breaks, in a cheap way...
216 aboutText.Append(config_string);
217
218 if (wxFONTSTYLE_ITALIC == dFont->GetStyle()) aboutText.Append("</i>");
219
220 // The HTML Footer
221 aboutText.Append("</font></body></html>");
222
223 pAboutHTMLCtl->SetPage(aboutText);
224
226 // The HTML Header
227 //
228 fs::path data_path(g_Platform->GetSharedDataDir().ToStdString());
229 std::ifstream istream(data_path / "Authors.html");
230 std::stringstream ss;
231 ss << istream.rdbuf();
232 pAuthorHTMLCtl->SetPage(ss.str());
233
235 // Deferred....
236#if 0
237 // The HTML Header
238 wxString licenseText =
239 wxString::Format(
240 _T( "<html><body bgcolor=#%02x%02x%02x><font color=#%02x%02x%02x>" ),
241 bg.Red(), bg.Blue(), bg.Green(), fg.Red(), fg.Blue(), fg.Green() );
242
243 pLicenseHTMLCtl->SetFonts( face, face, sizes );
244
245 wxTextFile license_filea( m_DataLocn + _T("license.txt") );
246 if ( license_filea.Open() ) {
247 for ( wxString str = license_filea.GetFirstLine(); !license_filea.Eof() ; str = license_filea.GetNextLine() )
248 licenseText.Append( str + _T("<br>") );
249 license_filea.Close();
250 } else {
251 wxLogMessage( _T("Could not open License file: ") + m_DataLocn );
252 }
253
254 wxString suppLicense = g_Platform->GetSupplementalLicenseString();
255
256 wxStringTokenizer st(suppLicense, _T("\n"), wxTOKEN_DEFAULT);
257 while( st.HasMoreTokens() )
258 {
259 wxString s1 = st.GetNextToken();
260 licenseText.Append( s1 + _T("<br>") );
261 }
262
263 // The HTML Footer
264 licenseText.Append( _T("</font></body></html>") );
265
266 pLicenseHTMLCtl->SetPage( licenseText );
267#endif
268
269 SetColorScheme();
270}
271
272void About::RecalculateSize(void) {
273 // Make an estimate of the dialog size, without scrollbars showing
274
275 wxSize esize;
276 esize.x = GetCharWidth() * 110;
277 esize.y = GetCharHeight() * 44;
278
279 wxSize dsize = GetParent()->GetSize();
280 esize.y = wxMin(esize.y, dsize.y - (0 * GetCharHeight()));
281 esize.x = wxMin(esize.x, dsize.x - (0 * GetCharHeight()));
282 SetClientSize(esize);
283
284 wxSize fsize = GetSize();
285 fsize.y = wxMin(fsize.y, dsize.y - (0 * GetCharHeight()));
286 fsize.x = wxMin(fsize.x, dsize.x - (0 * GetCharHeight()));
287
288 SetSize(fsize);
289
290 Centre();
291}
292
293void About::CreateControls(void) {
294 // Set the nominal vertical size of the embedded controls
295
296 wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
297 SetSizer(mainSizer);
298 wxStaticText* pST1 =
299 new wxStaticText(this, -1, _("The Open Source Chart Plotter/Navigator"),
300 wxDefaultPosition, wxSize(-1, 50 /* 500, 30 */),
301 wxALIGN_CENTRE /* | wxALIGN_CENTER_VERTICAL */);
302
303 wxFont* qFont = GetOCPNScaledFont(_("Dialog"));
304
305 wxFont* headerFont = FontMgr::Get().FindOrCreateFont(
306 14, wxFONTFAMILY_DEFAULT, qFont->GetStyle(), wxFONTWEIGHT_BOLD, false,
307 qFont->GetFaceName());
308 pST1->SetFont(*headerFont);
309 mainSizer->Add(pST1, 0, wxALL | wxEXPAND, 8);
310
311 bool orient = m_displaySize.x < m_displaySize.y;
312#ifndef __OCPN__ANDROID__
313 wxBoxSizer* buttonSizer = new wxBoxSizer(orient ? wxVERTICAL : wxHORIZONTAL);
314 mainSizer->Add(buttonSizer, 0, wxALL, 0);
315
316 wxButton* donateButton = new wxBitmapButton(
317 this, ID_DONATE, g_StyleManager->GetCurrentStyle()->GetIcon("donate"),
318 wxDefaultPosition, wxDefaultSize, 0);
319
320 buttonSizer->Add(
321 new wxButton(this, ID_COPYLOG, _("Copy Log File to Clipboard")), 1,
322 wxALL | wxEXPAND, 3);
323 buttonSizer->Add(
324 new wxButton(this, ID_COPYINI, _("Copy Settings File to Clipboard")), 1,
325 wxALL | wxEXPAND, 3);
326 buttonSizer->Add(
327 donateButton, 1,
328 wxALL |
329 (buttonSizer->GetOrientation() == wxHORIZONTAL ? wxALIGN_RIGHT : 0),
330 3);
331#endif
332
333 // Main Notebook
334 pNotebook = new wxNotebook(this, ID_NOTEBOOK_HELP, wxDefaultPosition,
335 wxSize(-1, -1), wxNB_TOP);
336
337 pNotebook->Connect(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
338 wxNotebookEventHandler(About::OnNBPageChange), NULL, this);
339
340 pNotebook->InheritAttributes();
341 mainSizer->Add(pNotebook, 1,
342 (orient ? wxALIGN_CENTER_VERTICAL : 0) | wxEXPAND | wxALL, 5);
343
344 // About Panel
345 itemPanelAbout = new wxPanel(pNotebook, -1, wxDefaultPosition, wxDefaultSize,
346 wxSUNKEN_BORDER | wxTAB_TRAVERSAL);
347 itemPanelAbout->InheritAttributes();
348 pNotebook->AddPage(itemPanelAbout, _("About"), TRUE /* Default page */);
349
350 pAboutHTMLCtl =
351 new wxHtmlWindow(itemPanelAbout, wxID_ANY, wxDefaultPosition,
352 wxDefaultSize, wxHW_SCROLLBAR_AUTO | wxHW_NO_SELECTION);
353 pAboutHTMLCtl->SetBorders(5);
354 wxBoxSizer* aboutSizer = new wxBoxSizer(wxVERTICAL);
355 aboutSizer->Add(pAboutHTMLCtl, 1,
356 wxALIGN_CENTER_HORIZONTAL | wxEXPAND | wxALL, 5);
357 itemPanelAbout->SetSizer(aboutSizer);
358
359 // Authors Panel
360
361 itemPanelAuthors =
362 new wxPanel(pNotebook, -1, wxDefaultPosition, wxDefaultSize,
363 wxSUNKEN_BORDER | wxTAB_TRAVERSAL);
364 itemPanelAuthors->InheritAttributes();
365 pNotebook->AddPage(itemPanelAuthors, _("Authors"));
366
367 pAuthorHTMLCtl =
368 new wxHtmlWindow(itemPanelAuthors, wxID_ANY, wxDefaultPosition,
369 wxDefaultSize, wxHW_SCROLLBAR_AUTO | wxHW_NO_SELECTION);
370 pAuthorHTMLCtl->SetBorders(5);
371 wxBoxSizer* authorSizer = new wxBoxSizer(wxVERTICAL);
372 authorSizer->Add(pAuthorHTMLCtl, 1,
373 wxALIGN_CENTER_HORIZONTAL | wxEXPAND | wxALL, 5);
374 itemPanelAuthors->SetSizer(authorSizer);
375
376 // License Panel
377 itemPanelLicense =
378 new wxPanel(pNotebook, -1, wxDefaultPosition, wxDefaultSize,
379 wxSUNKEN_BORDER | wxTAB_TRAVERSAL);
380 itemPanelLicense->InheritAttributes();
381 pNotebook->AddPage(itemPanelLicense, _("License"));
382
383 pLicenseHTMLCtl =
384 new wxHtmlWindow(itemPanelLicense, wxID_ANY, wxDefaultPosition,
385 wxDefaultSize, wxHW_SCROLLBAR_AUTO | wxHW_NO_SELECTION);
386 pLicenseHTMLCtl->SetBorders(5);
387 wxBoxSizer* licenseSizer = new wxBoxSizer(wxVERTICAL);
388 licenseSizer->Add(pLicenseHTMLCtl, 1,
389 wxALIGN_CENTER_HORIZONTAL | wxEXPAND | wxALL, 5);
390 itemPanelLicense->SetSizer(licenseSizer);
391
392 // Help Panel
393 itemPanelTips = new wxPanel(pNotebook, -1, wxDefaultPosition, wxDefaultSize,
394 wxSUNKEN_BORDER | wxTAB_TRAVERSAL);
395 itemPanelTips->InheritAttributes();
396 pNotebook->AddPage(itemPanelTips, _("Help"));
397
398 wxBoxSizer* helpSizer = new wxBoxSizer(wxVERTICAL);
399 itemPanelTips->SetSizer(helpSizer);
400
401 // Close Button
402 wxButton* closeButton = new wxButton(this, xID_OK, _("Close"),
403 wxDefaultPosition, wxDefaultSize, 0);
404 closeButton->SetDefault();
405 closeButton->InheritAttributes();
406 mainSizer->Add(closeButton, 0, wxALIGN_RIGHT | wxALL, 5);
407}
408
409void About::OnNBPageChange(wxNotebookEvent& event) {
410 unsigned int i = event.GetSelection();
411
412 if (i == 3) {
413 m_launch_local_help();
414 pNotebook->ChangeSelection(0);
415 }
416
417 else if ((i == 2) && !m_blicensePageSet) { // license
418
419 wxColor bg = GetBackgroundColour();
420 wxColor fg = wxColour(0, 0, 0);
421 wxFont* dFont = FontMgr::Get().GetFont(_("Dialog"));
422
423 // Do weird font size calculation
424 int points = dFont->GetPointSize();
425#ifndef __WXOSX__
426 ++points;
427#endif
428 int sizes[7];
429 for (int i = -2; i < 5; i++) {
430 sizes[i + 2] = points + i + (i > 0 ? i : 0);
431 }
432 wxString face = dFont->GetFaceName();
433
435 g_Platform->ShowBusySpinner();
436
437 // The HTML Header
438 wxString licenseText = wxString::Format(
439 "<html><body bgcolor=#%02x%02x%02x><font color=#%02x%02x%02x>",
440 bg.Red(), bg.Blue(), bg.Green(), fg.Red(), fg.Blue(), fg.Green());
441
442 pLicenseHTMLCtl->SetFonts(face, face, sizes);
443
444 wxTextFile license_filea(m_DataLocn + "license.txt");
445 if (license_filea.Open()) {
446 for (wxString str = license_filea.GetFirstLine(); !license_filea.Eof();
447 str = license_filea.GetNextLine())
448 licenseText.Append(str + "<br>");
449 license_filea.Close();
450 } else {
451 wxLogMessage("Could not open License file: " + m_DataLocn);
452 }
453
454 wxString suppLicense = g_Platform->GetSupplementalLicenseString();
455
456 wxStringTokenizer st(suppLicense, "\n", wxTOKEN_DEFAULT);
457 while (st.HasMoreTokens()) {
458 wxString s1 = st.GetNextToken();
459 licenseText.Append(s1 + "<br>");
460 }
461
462 // The HTML Footer
463 licenseText.Append("</font></body></html>");
464
465 pLicenseHTMLCtl->SetPage(licenseText);
466
467 g_Platform->HideBusySpinner();
468
469 SetColorScheme();
470 m_blicensePageSet = true;
471 }
472}
473
474void About::OnXidOkClick(wxCommandEvent& event) { Close(); }
475
476void About::OnClose(wxCloseEvent& event) {
477#ifdef __WXGTK__
478 wxTheApp->GetTopWindow()->Raise();
479#endif
480 Destroy();
481 g_pAboutDlgLegacy = NULL;
482}
483
484void About::OnDonateClick(wxCommandEvent& event) {
485 wxLaunchDefaultBrowser(
486 "https://sourceforge.net/donate/index.php?group_id=180842");
487}
488
489void About::OnCopyClick(wxCommandEvent& event) {
490 wxString filename = event.GetId() == ID_COPYLOG
491 ? g_Platform->GetLogFileName()
492 : g_Platform->GetConfigFileName();
493
494 wxFFile file(filename);
495
496 if (!file.IsOpened()) {
497 wxLogMessage("Failed to open file for Copy to Clipboard.");
498 return;
499 }
500
501 wxString fileContent;
502 char buf[1024];
503 while (!file.Eof()) {
504 int c = file.Read(&buf, 1024);
505 if (c) fileContent += wxString(buf, wxConvUTF8, c);
506 }
507
508 file.Close();
509 int length = fileContent.Length();
510
511 if (event.GetId() == ID_COPYLOG) {
512 wxString lastLogs = fileContent;
513 int pos = lastLogs.Find("________");
514 while (pos != wxNOT_FOUND && lastLogs.Length() > 65000) {
515 lastLogs = lastLogs.Right(lastLogs.Length() - pos - 8);
516 pos = lastLogs.Find("________");
517 }
518 fileContent = lastLogs;
519 }
520
521 ::wxBeginBusyCursor();
522 if (wxTheClipboard->Open()) {
523 if (!wxTheClipboard->SetData(new wxTextDataObject(fileContent)))
524 wxLogMessage("wxTheClipboard->Open() failed.");
525 wxTheClipboard->Close();
526 } else {
527 wxLogMessage("wxTheClipboard->Open() failed.");
528 }
529 ::wxEndBusyCursor();
530}
bool g_bresponsive
Flag to control adaptive UI scaling.
Definition ocpn_app.cpp:662
class About
The OpenCPN About dialog displaying information including version, authors, license,...
Definition about.h:52
wxFont * FindOrCreateFont(int point_size, wxFontFamily family, wxFontStyle style, wxFontWeight weight, bool underline=false, const wxString &facename=wxEmptyString, wxFontEncoding encoding=wxFONTENCODING_DEFAULT)
Creates or finds a matching font in the font cache.
Definition FontMgr.cpp:450
wxFont * GetFont(const wxString &TextElement, int requested_font_size=0)
Gets a font object for a UI element.
Definition FontMgr.cpp:186
Provides platform-specific support utilities for OpenCPN.
wxSize getDisplaySize()
Get the display size in logical pixels.
wxFont * GetOCPNScaledFont(wxString item, int default_size)
Retrieves a font from FontMgr, optionally scaled for physical readability.
Definition gui_lib.cpp:54
General purpose GUI support.