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_platform.h"
49#include "std_filesystem.h"
50#include "styles.h"
51
52#ifdef __ANDROID__
53#include "androidUTIL.h"
54#endif
55
56#define xID_OK 10009
57
60
61static wxString OpenCPNVersion("\n Version ");
62
63// clang-format off
64
65static const wxString AboutText =
66 "<br>OpenCPN<br>"
67 "(c) 2000-2024 The OpenCPN Authors<br><br>";
68
69static const 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
78static const 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()
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_BasePlatform->getDisplaySize();
139 CreateControls();
140 Populate();
141
142 RecalculateSize();
143
144 return TRUE;
145}
146
147void About::SetColorScheme() {
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() {
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 __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_BasePlatform->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_BasePlatform->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_BasePlatform->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 "<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 + "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 + "<br>" );
249 license_filea.Close();
250 } else {
251 wxLogMessage( "Could not open License file: " + m_DataLocn );
252 }
253
254 wxString suppLicense = g_Platform->GetSupplementalLicenseString();
255
256 wxStringTokenizer st(suppLicense, "\n", wxTOKEN_DEFAULT);
257 while( st.HasMoreTokens() )
258 {
259 wxString s1 = st.GetNextToken();
260 licenseText.Append( s1 + "<br>" );
261 }
262
263 // The HTML Footer
264 licenseText.Append( "</font></body></html>" );
265
266 pLicenseHTMLCtl->SetPage( licenseText );
267#endif
268
269 SetColorScheme();
270}
271
272void About::RecalculateSize() {
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() {
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 __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 j = -2; j < 5; j++) {
430 sizes[j + 2] = points + j + (j > 0 ? j : 0);
431 }
432 wxString face = dFont->GetFaceName();
433
435 g_BasePlatform->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_BasePlatform->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_BasePlatform->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_BasePlatform->GetLogFileName()
492 : g_BasePlatform->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}
AboutFrameImpl * g_pAboutDlg
Global instance.
Definition about.cpp:59
About * g_pAboutDlgLegacy
Global instance.
Definition about.cpp:58
class About
About * g_pAboutDlgLegacy
Global instance.
Definition about.cpp:58
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:442
wxFont * GetFont(const wxString &TextElement, int requested_font_size=0)
Get a font object for a UI element.
Definition font_mgr.cpp:193
Font list manager.
wxFont * GetOCPNScaledFont(wxString item, int default_size)
Retrieves a font from FontMgr, optionally scaled for physical readability.
Definition gui_lib.cpp:61
General purpose GUI support.
Utility functions.
OpenCPN Platform specific support utilities.
Chart Symbols.