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