KiCad PCB EDA Suite
dialog_about.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2010 Rafael Sokolowski <[email protected]>
5 * Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.TXT for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25
26#include <config.h>
27#include <string>
28
29#include <kicad_build_version.h>
30
31#include <wx/clipbrd.h>
32#include <wx/msgdlg.h>
33#include <wx/hyperlink.h>
34
35/* All KiCad icons are linked into shared library 'libbitmaps.a'.
36 * Icons:
37 * preference_xpm; // Icon for 'Developers' tab
38 * editor_xpm; // Icon for 'Doc Writers' tab
39 * color_materials_xpm; // Icon for 'Artists' tab
40 * language_xpm; // Icon for 'Translators' tab
41 * right_xpm; // Right arrow icon for list items
42 * info_xpm; // Bulb for description tab
43 * tools_xpm; // Sheet of paper icon for license info tab
44 */
45#include <bitmaps.h>
46#include <build_version.h>
48#include <tool/tool_manager.h>
49
50#include "dialog_about.h"
51
52
54 : DIALOG_ABOUT_BASE( aParent ), m_info( aAppInfo )
55{
56 wxASSERT( aParent != nullptr );
57
58 // TODO: Change these to 16x16 versions when available
59 m_images = new wxImageList( 24, 24, false, 9 );
60
61 m_images->Add( KiBitmap( BITMAPS::info ) ); // INFORMATION
62 m_images->Add( KiBitmap( BITMAPS::recent ) ); // VERSION
63 m_images->Add( KiBitmap( BITMAPS::preference ) ); // DEVELOPERS
64 m_images->Add( KiBitmap( BITMAPS::editor ) ); // DOCWRITERS
65 m_images->Add( KiBitmap( BITMAPS::library ) ); // LIBRARIANS
66 m_images->Add( KiBitmap( BITMAPS::color_materials ) ); // ARTISTS
67 m_images->Add( KiBitmap( BITMAPS::language ) ); // TRANSLATORS
68 m_images->Add( KiBitmap( BITMAPS::zip ) ); // PACKAGERS
69 m_images->Add( KiBitmap( BITMAPS::tools ) ); // LICENSE
70
71 m_notebook->SetImageList( m_images );
72
73 if( m_info.GetAppIcon().IsOk() )
74 {
75 SetIcon( m_info.GetAppIcon() );
76 m_bitmapApp->SetBitmap( m_info.GetAppIcon() );
77 }
78 else
79 {
80 wxIcon icon;
81#if KICAD_IS_NIGHTLY
82 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly ) );
83#else
84 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad ) );
85#endif
86 SetIcon( icon );
87 m_bitmapApp->SetBitmap( icon );
88 }
89
90 m_titleName = aParent->GetAboutTitle();
93 m_staticTextBuildVersion->SetLabel( "Version: " + m_info.GetBuildVersion() );
95
96 SetTitle( wxString::Format( _( "About %s" ), m_titleName ) );
98
99 GetSizer()->SetSizeHints( this );
100 SetFocus();
101 Centre();
102}
103
104
106{
107 delete m_images;
108}
109
110
112{
113 // three columns with vertical and horizontal extra space of two pixels
114 wxFlexGridSizer* fgSizer = new wxFlexGridSizer( 3, 2, 2 );
115 fgSizer->SetFlexibleDirection( wxHORIZONTAL );
116 fgSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
117
118 return fgSizer;
119}
120
121
123{
126
127 wxString version = GetVersionInfoData( m_titleName, true );
128
129 createNotebookHtmlPage( m_notebook, _( "Version" ), IMAGES::VERSION, version, true );
130
135
138
140 m_info.GetArtists() );
145
147}
148
149void DIALOG_ABOUT::createNotebookPage( wxNotebook* aParent, const wxString& aCaption,
150 IMAGES aIconIndex, const CONTRIBUTORS& aContributors )
151{
152 wxPanel* outerPanel = new wxPanel( aParent );
153 wxBoxSizer* outerSizer = new wxBoxSizer( wxVERTICAL );
154
155 wxBoxSizer* bSizer = new wxBoxSizer( wxHORIZONTAL );
156
157 wxScrolledWindow* m_scrolledWindow1 = new wxScrolledWindow( outerPanel, wxID_ANY,
158 wxDefaultPosition,
159 wxDefaultSize,
160 wxHSCROLL|wxVSCROLL );
161 m_scrolledWindow1->SetScrollRate( 5, 5 );
162
163 /* Panel for additional space at the left,
164 * but can also be used to show an additional bitmap.
165 */
166 wxPanel* panel1 = new wxPanel( m_scrolledWindow1 );
167
168 wxFlexGridSizer* fgSizer1 = createFlexGridSizer();
169
170 for( size_t i=0; i<aContributors.GetCount(); ++i )
171 {
172 CONTRIBUTOR* contributor = &aContributors.Item( i );
173
174 // Icon at first column
175 wxStaticBitmap* m_bitmap1 = createStaticBitmap( m_scrolledWindow1, contributor->GetIcon() );
176 fgSizer1->Add( m_bitmap1, 0, wxALIGN_CENTER|wxLEFT|wxRIGHT, 5 );
177
178 // Name of contributor at second column
179 if ( contributor->GetName() != wxEmptyString )
180 {
181 wxStaticText* m_staticText1 = new wxStaticText( m_scrolledWindow1, wxID_ANY,
182 contributor->GetName(),
183 wxDefaultPosition, wxDefaultSize, 0 );
184 m_staticText1->Wrap( -1 );
185 fgSizer1->Add( m_staticText1, 0, wxALIGN_LEFT|wxBOTTOM, 2 );
186 }
187 else
188 {
189 fgSizer1->AddSpacer( 5 );
190 }
191
192 // Email address of contributor at third column
193 if ( contributor->GetExtra() != wxEmptyString )
194 {
195 wxStaticText* hyperlink = wxStaticTextRef( m_scrolledWindow1,
196 contributor->GetExtra() );
197 fgSizer1->Add( hyperlink, 0, wxALIGN_LEFT|wxBOTTOM, 2 );
198 }
199 else
200 {
201 fgSizer1->AddSpacer( 5 );
202 }
203 }
204
205 bSizer->Add( panel1, 1, wxEXPAND|wxALL, 10 );
206 bSizer->Add( fgSizer1, 7, wxEXPAND|wxALL, 10 ); // adjust width of panel with first int value
207 m_scrolledWindow1->SetSizer( bSizer );
208 m_scrolledWindow1->Layout();
209 bSizer->Fit( m_scrolledWindow1 );
210
211 outerSizer->Add( m_scrolledWindow1, 1, wxEXPAND, 0 );
212 outerPanel->SetSizer( outerSizer );
213
214 aParent->AddPage( outerPanel, aCaption, false, static_cast<int>( aIconIndex ) );
215}
216
217
218void DIALOG_ABOUT::createNotebookPageByCategory( wxNotebook* aParent, const wxString& aCaption,
219 IMAGES aIconIndex,
220 const CONTRIBUTORS& aContributors )
221{
222 // The left justification between wxStaticText and wxHyperlinkCtrl is different so
223 // we must pad to make the alignment look decent.
224 //
225 // @todo Just make all of the contributor lists HTML so the alignment is consistent.
226 wxString padding;
227
228 // Of course the padding is different depending on the platform so we adjust the
229 // padding accordingly.
230#if defined( __WXGTK__ )
231 padding += " ";
232#endif
233 wxPanel* outerPanel = new wxPanel( aParent );
234 wxBoxSizer* outerSizer = new wxBoxSizer( wxVERTICAL );
235
236 wxBoxSizer* bSizer = new wxBoxSizer( wxHORIZONTAL );
237
238 wxScrolledWindow* m_scrolledWindow1 = new wxScrolledWindow( outerPanel, wxID_ANY,
239 wxDefaultPosition,
240 wxDefaultSize,
241 wxHSCROLL|wxVSCROLL );
242 m_scrolledWindow1->SetScrollRate( 5, 5 );
243
244 /* Panel for additional space at the left,
245 * but can also be used to show an additional bitmap.
246 */
247 wxPanel* panel1 = new wxPanel( m_scrolledWindow1 );
248
249 wxFlexGridSizer* fgSizer1 = createFlexGridSizer();
250
251 for( size_t i=0; i < aContributors.GetCount(); ++i )
252 {
253 CONTRIBUTOR* contributor = &aContributors.Item( i );
254
255 wxBitmap* icon = contributor->GetIcon();
256 wxString category = contributor->GetCategory();
257
258 /* to construct the next row we expect to have
259 * a category and a contributor that was not considered up to now
260 */
261 if( ( category != wxEmptyString ) && !( contributor->IsChecked() ) )
262 {
263 // Icon at first column
264 wxStaticBitmap* m_bitmap1 = createStaticBitmap( m_scrolledWindow1, icon );
265 fgSizer1->Add( m_bitmap1, 0, wxALIGN_CENTER|wxLEFT|wxRIGHT, 5 );
266
267 // Category name at second column
268 wxStaticText* m_staticText1 = new wxStaticText( m_scrolledWindow1, wxID_ANY,
269 contributor->GetCategory() + wxT( ":" ),
270 wxDefaultPosition, wxDefaultSize, 0 );
271 m_staticText1->SetFont( m_staticText1->GetFont().Bold() );
272 m_staticText1->Wrap( -1 );
273 fgSizer1->Add( m_staticText1, 0, wxALIGN_LEFT|wxBOTTOM|wxEXPAND, 2 );
274
275 // Nothing at third column
276 fgSizer1->AddSpacer( 5 );
277
278 // Now, all contributors of the same category will follow
279 for( size_t j=0; j < aContributors.GetCount(); ++j )
280 {
281 CONTRIBUTOR* sub_contributor = &aContributors.Item( j );
282
283 if ( sub_contributor->GetCategory() == category )
284 {
285 // First column is empty
286 fgSizer1->AddSpacer( 5 );
287
288 wxControl* ctrl;
289
290 // No URL supplied, display normal text control
291 if( sub_contributor->GetUrl().IsEmpty() )
292 {
293 ctrl = new wxStaticText( m_scrolledWindow1, wxID_ANY,
294 padding + wxT( "• " ) + sub_contributor->GetName(),
295 wxDefaultPosition,
296 wxDefaultSize, 0 );
297 }
298 else
299 {
300 // Display a hyperlink control instead
301 ctrl = new wxHyperlinkCtrl( m_scrolledWindow1, wxID_ANY,
302 wxT( "• " ) + sub_contributor->GetName(),
303 sub_contributor->GetUrl(),
304 wxDefaultPosition,
305 wxDefaultSize,
306 wxBORDER_NONE | wxHL_CONTEXTMENU | wxHL_ALIGN_LEFT );
307 }
308
309 m_staticText1->Wrap( -1 );
310
311 fgSizer1->Add( ctrl, 0, wxALIGN_LEFT|wxBOTTOM, 2 );
312
313 // Email address of contributor at third column
314 if( sub_contributor->GetExtra() != wxEmptyString )
315 {
316 wxStaticText* mail = wxStaticTextRef( m_scrolledWindow1,
317 sub_contributor->GetExtra() );
318 fgSizer1->Add( mail, 0, wxALIGN_LEFT|wxBOTTOM, 2 );
319 }
320 else
321 {
322 fgSizer1->AddSpacer( 5 );
323 }
324
325 /* this contributor was added to the GUI,
326 * thus can be ignored next time
327 */
328 sub_contributor->SetChecked( true );
329 }
330 }
331 }
332 else
333 {
334 continue;
335 }
336 }
337
338 /* Now, lets list the remaining contributors that have not been considered
339 * because they were not assigned to any category.
340 */
341 for ( size_t k=0; k < aContributors.GetCount(); ++k )
342 {
343 CONTRIBUTOR* contributor = &aContributors.Item( k );
344
345 if ( contributor->IsChecked() )
346 continue;
347
348 // Icon at first column
349 wxStaticBitmap* m_bitmap1 = createStaticBitmap( m_scrolledWindow1, contributor->GetIcon() );
350 fgSizer1->Add( m_bitmap1, 0, wxALIGN_CENTER|wxLEFT|wxRIGHT, 5 );
351
352 // Name of contributor at second column
353 if( contributor->GetName() != wxEmptyString )
354 {
355 wxStaticText* m_staticText1 = new wxStaticText( m_scrolledWindow1, wxID_ANY,
356 contributor->GetName(),
357 wxDefaultPosition, wxDefaultSize, 0 );
358 m_staticText1->Wrap( -1 );
359 fgSizer1->Add( m_staticText1, 0, wxALIGN_LEFT|wxBOTTOM, 2 );
360 }
361 else
362 {
363 fgSizer1->AddSpacer( 5 );
364 }
365
366 // Email address of contributor at third column
367 if ( contributor->GetExtra() != wxEmptyString )
368 {
369 wxStaticText* mail = wxStaticTextRef( m_scrolledWindow1, contributor->GetExtra() );
370 fgSizer1->Add( mail, 0, wxALIGN_LEFT|wxBOTTOM, 2 );
371 }
372 else
373 {
374 fgSizer1->AddSpacer( 5 );
375 }
376 }
377
378 bSizer->Add( panel1, 1, wxEXPAND|wxALL, 10 );
379 bSizer->Add( fgSizer1, 7, wxEXPAND|wxALL, 10 ); // adjust width of panel with first int value
380 m_scrolledWindow1->SetSizer( bSizer );
381 m_scrolledWindow1->Layout();
382 bSizer->Fit( m_scrolledWindow1 );
383
384 outerSizer->Add( m_scrolledWindow1, 1, wxEXPAND, 0 );
385 outerPanel->SetSizer( outerSizer );
386
387 aParent->AddPage( outerPanel, aCaption, false, static_cast<int>( aIconIndex ) );
388}
389
390
391void DIALOG_ABOUT::createNotebookHtmlPage( wxNotebook* aParent, const wxString& aCaption,
392 IMAGES aIconIndex, const wxString& html,
393 bool aSelection )
394{
395 wxPanel* panel = new wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
396 wxTAB_TRAVERSAL );
397
398 wxBoxSizer* bSizer = new wxBoxSizer( wxVERTICAL );
399
400 int flags = aSelection ? wxHW_SCROLLBAR_AUTO : ( wxHW_SCROLLBAR_AUTO | wxHW_NO_SELECTION );
401
402 // the HTML page is going to be created with previously created HTML content
403 HTML_WINDOW* htmlWindow = new HTML_WINDOW( panel, wxID_ANY, wxDefaultPosition, wxDefaultSize,
404 flags );
405
406 // HTML font set to font properties as they are used for widgets to have an unique look
407 // under different platforms with HTML
408 wxFont font = GetFont();
409 htmlWindow->SetStandardFonts( font.GetPointSize(), font.GetFaceName(), font.GetFaceName() );
410 htmlWindow->SetPage( html );
411
412 // the HTML window shall not be used to open external links, thus this task is delegated
413 // to users default browser
414 htmlWindow->Connect( wxEVT_COMMAND_HTML_LINK_CLICKED,
415 wxHtmlLinkEventHandler( DIALOG_ABOUT::onHtmlLinkClicked ), NULL, this );
416
417 // no additional space around the HTML window as it is also the case by the other notebook pages
418 bSizer->Add( htmlWindow, 1, wxEXPAND, 0 );
419 panel->SetSizer( bSizer );
420
421 aParent->AddPage( panel, aCaption, false, static_cast<int>( aIconIndex ) );
422}
423
424
425wxStaticText* DIALOG_ABOUT::wxStaticTextRef( wxScrolledWindow* aParent, const wxString& aReference )
426{
427 wxStaticText* text = new wxStaticText( aParent, wxID_ANY,
428 wxT( "(" ) + aReference + wxT( ")" ) );
429
430 return text;
431}
432
433
434wxStaticBitmap* DIALOG_ABOUT::createStaticBitmap( wxScrolledWindow* aParent, wxBitmap* aIcon )
435{
436 wxStaticBitmap* bitmap = new wxStaticBitmap( aParent, wxID_ANY, wxNullBitmap,
437 wxDefaultPosition, wxDefaultSize, 0 );
438
439 if( aIcon )
440 bitmap->SetBitmap( *aIcon );
441 else
442 bitmap->SetBitmap( KiBitmap( BITMAPS::right ) );
443
444 return bitmap;
445}
446
447
448void DIALOG_ABOUT::onHtmlLinkClicked( wxHtmlLinkEvent& event )
449{
450 ::wxLaunchDefaultBrowser( event.GetLinkInfo().GetHref() );
451}
452
453
454void DIALOG_ABOUT::onCopyVersionInfo( wxCommandEvent& event )
455{
456 wxLogNull doNotLog; // disable logging of failed clipboard actions
457
458 if( !wxTheClipboard->Open() )
459 {
460 wxMessageBox( _( "Could not open clipboard to write version information." ),
461 _( "Clipboard Error" ), wxOK | wxICON_EXCLAMATION, this );
462 return;
463 }
464
465 wxString msg_version = GetVersionInfoData( m_titleName );
466
467 wxTheClipboard->SetData( new wxTextDataObject( msg_version ) );
468 wxTheClipboard->Flush(); // Allow clipboard data to be available after KiCad closes
469 wxTheClipboard->Close();
470 m_btCopyVersionInfo->SetLabel( _( "Copied..." ) );
471}
472
473
474void DIALOG_ABOUT::onDonateClick( wxCommandEvent& event )
475{
476 if( TOOL_MANAGER* mgr = static_cast<EDA_BASE_FRAME*>( GetParent() )->GetToolManager() )
477 mgr->RunAction( "common.SuiteControl.donate", true );
478}
479
480
481void DIALOG_ABOUT::onReportBug( wxCommandEvent& event )
482{
483 if( TOOL_MANAGER* mgr = static_cast<EDA_BASE_FRAME*>( GetParent() )->GetToolManager() )
484 mgr->RunAction( "common.SuiteControl.reportBug", true );
485}
486
487
488void DIALOG_ABOUT::OnNotebookPageChanged( wxNotebookEvent& aEvent )
489{
490 // Work around wxMac issue where the notebook pages are blank
491#ifdef __WXMAC__
492 int page = aEvent.GetSelection();
493
494 if( page >= 0 )
495 m_notebook->ChangeSelection( static_cast<unsigned>( page ) );
496#endif
497}
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
@ icon_kicad_nightly
@ color_materials
wxString GetVersionInfoData(const wxString &aTitle, bool aHtml, bool aBrief)
Create a version info string for bug reports and the about dialog.
An object of this class is meant to be used to store application specific information like who has co...
Definition: aboutinfo.h:45
CONTRIBUTORS GetPackagers()
Definition: aboutinfo.h:91
CONTRIBUTORS GetLibrarians()
Definition: aboutinfo.h:88
wxString GetCopyright()
Definition: aboutinfo.h:100
wxString & GetLibVersion()
Definition: aboutinfo.h:112
CONTRIBUTORS GetDevelopers()
Definition: aboutinfo.h:86
CONTRIBUTORS GetDocWriters()
Definition: aboutinfo.h:87
wxString & GetBuildVersion()
Definition: aboutinfo.h:106
wxString & GetDescription()
Definition: aboutinfo.h:94
CONTRIBUTORS GetTranslators()
Definition: aboutinfo.h:90
CONTRIBUTORS GetArtists()
Definition: aboutinfo.h:89
wxIcon & GetAppIcon()
Wrapper to manage memory allocation for bitmaps.
Definition: aboutinfo.h:115
wxString & GetLicense()
Definition: aboutinfo.h:97
A contributor, a person which was involved in the development of the application or which has contrib...
Definition: aboutinfo.h:161
wxString & GetName()
Definition: aboutinfo.h:191
wxString & GetUrl()
Definition: aboutinfo.h:193
wxString & GetExtra()
Definition: aboutinfo.h:192
wxString & GetCategory()
Definition: aboutinfo.h:194
wxBitmap * GetIcon()
Definition: aboutinfo.h:195
bool IsChecked()
Definition: aboutinfo.h:197
void SetChecked(bool status)
Definition: aboutinfo.h:196
Class DIALOG_ABOUT_BASE.
wxStaticText * m_staticTextBuildVersion
wxStaticBitmap * m_bitmapApp
wxStaticText * m_staticTextCopyright
wxStaticText * m_staticTextLibVersion
wxButton * m_btCopyVersionInfo
wxNotebook * m_notebook
wxStaticText * m_staticTextAppTitle
void OnNotebookPageChanged(wxNotebookEvent &aEvent) override
wxString m_titleName
Definition: dialog_about.h:57
wxImageList * m_images
Definition: dialog_about.h:56
void createNotebookPage(wxNotebook *aParent, const wxString &aCaption, IMAGES aIconIndex, const CONTRIBUTORS &aContributors)
void createNotebooks()
ABOUT_APP_INFO & m_info
Definition: dialog_about.h:59
void createNotebookPageByCategory(wxNotebook *aParent, const wxString &aCaption, IMAGES aIconIndex, const CONTRIBUTORS &aContributors)
DIALOG_ABOUT(EDA_BASE_FRAME *aParent, ABOUT_APP_INFO &aAppInfo)
wxStaticBitmap * createStaticBitmap(wxScrolledWindow *aParent, wxBitmap *icon)
void onCopyVersionInfo(wxCommandEvent &event) override
void onHtmlLinkClicked(wxHtmlLinkEvent &event)
wxFlexGridSizer * createFlexGridSizer()
void onReportBug(wxCommandEvent &event) override
wxStaticText * wxStaticTextRef(wxScrolledWindow *aParent, const wxString &aReference)
void onDonateClick(wxCommandEvent &event) override
void createNotebookHtmlPage(wxNotebook *aParent, const wxString &aCaption, IMAGES aIconIndex, const wxString &aHtmlMessage, bool aSelection=false)
The base frame for deriving all KiCad main window classes.
const wxString & GetAboutTitle() const
Add dark theme support to wxHtmlWindow.
Definition: html_window.h:34
bool SetPage(const wxString &aSource) override
Definition: html_window.cpp:38
Master controller class:
Definition: tool_manager.h:55
IMAGES
Definition: dialog_about.h:37
@ TRANSLATORS
@ DOCWRITERS
@ LIBRARIANS
@ DEVELOPERS
@ INFORMATION
#define _(s)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200