KiCad PCB EDA Suite
wx_html_report_panel.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) 2015 CERN
5 * Copyright (C) 2015-2021 KiCad Developers, see AUTHORS.txt for contributors.
6 * Author: Tomasz Wlostowski <[email protected]>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <algorithm>
23
25
27#include <gal/color4d.h>
28#include <wx/clipbrd.h>
29#include <string_utils.h>
30#include <wx/ffile.h>
31#include <wx/log.h>
32#include <wx/filedlg.h>
33#include <wx/msgdlg.h>
34#include <wx/menu.h>
35#include <wx/textctrl.h>
36#include <kiplatform/ui.h>
37#include <kiway_holder.h>
38#include <project.h>
39
40WX_HTML_REPORT_PANEL::WX_HTML_REPORT_PANEL( wxWindow* parent, wxWindowID id, const wxPoint& pos,
41 const wxSize& size, long style ) :
42 WX_HTML_REPORT_PANEL_BASE( parent, id, pos, size, style ),
43 m_reporter( this ),
44 m_severities( -1 ),
45 m_lazyUpdate( false )
46{
49 Flush();
50
51 Connect( wxEVT_COMMAND_MENU_SELECTED,
52 wxMenuEventHandler( WX_HTML_REPORT_PANEL::onMenuEvent ), nullptr, this );
53
54 m_htmlView->Bind( wxEVT_SYS_COLOUR_CHANGED,
55 wxSysColourChangedEventHandler( WX_HTML_REPORT_PANEL::onThemeChanged ),
56 this );
57}
58
59
61{
62}
63
64
65void WX_HTML_REPORT_PANEL::onThemeChanged( wxSysColourChangedEvent &aEvent )
66{
67 Flush();
68
69 aEvent.Skip();
70}
71
72
73void WX_HTML_REPORT_PANEL::MsgPanelSetMinSize( const wxSize& aMinSize )
74{
75 m_fgSizer->SetMinSize( aMinSize );
76 GetSizer()->SetSizeHints( this );
77}
78
79
81{
82 return m_reporter;
83}
84
85
86void WX_HTML_REPORT_PANEL::Report( const wxString& aText, SEVERITY aSeverity,
87 REPORTER::LOCATION aLocation )
88{
89 REPORT_LINE line;
90 line.message = aText;
91 line.severity = aSeverity;
92
93 if( aLocation == REPORTER::LOC_HEAD )
94 m_reportHead.push_back( line );
95 else if( aLocation == REPORTER::LOC_TAIL )
96 m_reportTail.push_back( line );
97 else
98 m_report.push_back( line );
99
100 if( !m_lazyUpdate )
101 {
104 }
105}
106
107
109{
110 m_lazyUpdate = aLazyUpdate;
111}
112
113
115{
116 wxString html;
117
118 if( aSort )
119 {
120 std::sort( m_report.begin(), m_report.end(),
121 []( const REPORT_LINE& a, const REPORT_LINE& b)
122 {
123 return a.severity < b.severity;
124 });
125 }
126
127 for( const auto& line : m_reportHead )
128 html += generateHtml( line );
129
130 for( const auto& line : m_report )
131 html += generateHtml( line );
132
133 for( const auto& line : m_reportTail )
134 html += generateHtml( line );
135
136 m_htmlView->SetPage( html );
138}
139
140
142{
143 int x, y, xUnit, yUnit;
144
145 m_htmlView->GetVirtualSize( &x, &y );
146 m_htmlView->GetScrollPixelsPerUnit( &xUnit, &yUnit );
147 m_htmlView->Scroll( 0, y / yUnit );
148
149 updateBadges();
150}
151
152
154{
155 int count = Count(RPT_SEVERITY_ERROR );
157
158 count = Count(RPT_SEVERITY_WARNING );
160}
161
162
163int WX_HTML_REPORT_PANEL::Count( int severityMask )
164{
165 int count = 0;
166
167 for( const auto& reportLineArray : { m_report, m_reportHead, m_reportTail } )
168 {
169 for( const REPORT_LINE& reportLine : reportLineArray )
170 {
171 if( severityMask & reportLine.severity )
172 count++;
173 }
174 }
175
176 return count;
177}
178
179
181{
182 wxString retv;
183
184 if( !( m_severities & aLine.severity ) )
185 return retv;
186
188 {
189 switch( aLine.severity )
190 {
192 retv = "<font color=#F04040 size=3>" + _( "Error:" ) + " </font>"
193 "<font size=3>" + aLine.message + "</font><br>";
194 break;
196 retv = "<font size=3>" + _( "Warning:" ) + wxS( " " ) + aLine.message + "</font><br>";
197 break;
199 retv = "<font color=#909090 size=3>" + aLine.message + "</font><br>";
200 break;
202 retv = "<font color=#60D060 size=3>" + aLine.message + "</font><br>";
203 break;
204 default:
205 retv = "<font size=3>" + aLine.message + "</font><br>";
206 }
207 }
208 else
209 {
210 switch( aLine.severity )
211 {
213 retv = "<font color=#D00000 size=3>" + _( "Error:" ) + " </font>"
214 "<font size=3>" + aLine.message + "</font><br>";
215 break;
217 retv = "<font size=3>" + _( "Warning:" ) + wxS( " " ) + aLine.message + "</font><br>";
218 break;
220 retv = "<font color=#808080 size=3>" + aLine.message + "</font><br>";
221 break;
223 retv = "<font color=#008000 size=3>" + aLine.message + "</font><br>";
224 break;
225 default:
226 retv = "<font size=3>" + aLine.message + "</font><br>";
227 }
228 }
229
230 // wxHtmlWindow fails to do correct baseline alignment between Japanese/Chinese cells and
231 // Roman cells. This keeps the line in a single cell.
232 retv.Replace( " ", "&nbsp;" );
233
234 return retv;
235}
236
237
239{
240 switch( aLine.severity )
241 {
242 case RPT_SEVERITY_ERROR: return _( "Error:" ) + wxS( " " ) + aLine.message + wxT( "\n" );
243 case RPT_SEVERITY_WARNING: return _( "Warning:" ) + wxS( " " ) + aLine.message + wxT( "\n" );
244 case RPT_SEVERITY_INFO: return _( "Info:" ) + wxS( " " ) + aLine.message + wxT( "\n" );
245 default: return aLine.message + wxT( "\n" );
246 }
247}
248
249
250void WX_HTML_REPORT_PANEL::onRightClick( wxMouseEvent& event )
251{
252 wxMenu popup;
253 popup.Append( wxID_COPY, "Copy" );
254 PopupMenu( &popup );
255}
256
257
258void WX_HTML_REPORT_PANEL::onMenuEvent( wxMenuEvent& event )
259{
260 if( event.GetId() == wxID_COPY )
261 {
262 wxLogNull doNotLog; // disable logging of failed clipboard actions
263
264 if( wxTheClipboard->Open() )
265 {
266 bool primarySelection = wxTheClipboard->IsUsingPrimarySelection();
267 wxTheClipboard->UsePrimarySelection( false ); // required to use the main clipboard
268 wxTheClipboard->SetData( new wxTextDataObject( m_htmlView->SelectionToText() ) );
269 wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
270 wxTheClipboard->Close();
271 wxTheClipboard->UsePrimarySelection( primarySelection );
272 }
273 }
274}
275
276
277// Don't globally define this; different facilities use different definitions of "ALL"
280
281
282void WX_HTML_REPORT_PANEL::onCheckBoxShowAll( wxCommandEvent& event )
283{
284 if( event.IsChecked() )
286 else
288
290 Flush( true );
291}
292
293
295{
301}
302
303
305{
306 if( event.IsChecked() )
308 else
309 m_severities &= ~RPT_SEVERITY_WARNING;
310
312 Flush( true );
313}
314
315
317{
318 if( event.IsChecked() )
320 else
321 m_severities &= ~RPT_SEVERITY_ERROR;
322
324 Flush( true );
325}
326
327
328void WX_HTML_REPORT_PANEL::onCheckBoxShowInfos( wxCommandEvent& event )
329{
330 if( event.IsChecked() )
332 else
333 m_severities &= ~RPT_SEVERITY_INFO;
334
336 Flush( true );
337}
338
339
341{
342 if( event.IsChecked() )
344 else
345 m_severities &= ~RPT_SEVERITY_ACTION;
346
348 Flush( true );
349}
350
351
352void WX_HTML_REPORT_PANEL::onBtnSaveToFile( wxCommandEvent& event )
353{
354 wxFileName fn;
355
356 if( m_reportFileName.empty() )
357 {
358 fn = wxT( "report.txt" );
359
360 KIWAY_HOLDER* parent = dynamic_cast<KIWAY_HOLDER*>( m_parent );
361
362 if( parent )
363 fn.SetPath( parent->Prj().GetProjectPath() );
364 }
365 else
366 fn = m_reportFileName;
367
368 wxFileDialog dlg( this, _( "Save Report to File" ), fn.GetPath(), fn.GetFullName(),
369 TextFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
370
371 if( dlg.ShowModal() != wxID_OK )
372 return;
373
374 fn = dlg.GetPath();
375
376 if( fn.GetExt().IsEmpty() )
377 fn.SetExt( "txt" );
378
379 wxFFile f( fn.GetFullPath(), "wb" );
380
381 if( !f.IsOpened() )
382 {
383 wxString msg;
384
385 msg.Printf( _( "Cannot write report to file '%s'." ),
386 fn.GetFullPath().GetData() );
387 wxMessageBox( msg, _( "File save error" ), wxOK | wxICON_ERROR, this );
388 return;
389 }
390
391 for( REPORT_LINES section : { m_reportHead, m_report, m_reportTail } )
392 {
393 for( const REPORT_LINE& l : section )
394 {
395 wxString s = generatePlainText( l );
396
398 f.Write( s );
399 }
400 }
401
402 m_reportFileName = fn.GetFullPath();
403 f.Close();
404}
405
406
408{
409 m_report.clear();
410 m_reportHead.clear();
411 m_reportTail.clear();
412}
413
414
415void WX_HTML_REPORT_PANEL::SetLabel( const wxString& aLabel )
416{
417 m_box->GetStaticBox()->SetLabel( aLabel );
418}
419
420
422{
423 if( aSeverities < 0 )
425 else
426 m_severities = aSeverities;
427
429}
430
431
433{
434 return m_severities;
435}
436
437
438void WX_HTML_REPORT_PANEL::SetFileName( const wxString& aReportFileName )
439{
440 m_reportFileName = aReportFileName;
441}
442
443
445{
446 return ( m_reportFileName );
447}
448
449
451{
452 switch( aSeverity )
453 {
454 case RPT_SEVERITY_INFO: m_checkBoxShowInfos->SetValue( aValue ); break;
455 case RPT_SEVERITY_ACTION: m_checkBoxShowActions->SetValue( aValue ); break;
456 case RPT_SEVERITY_WARNING: m_checkBoxShowWarnings->SetValue( aValue ); break;
457 default: m_checkBoxShowErrors->SetValue( aValue ); break;
458 }
459}
bool SetPage(const wxString &aSource) override
Definition: html_window.cpp:38
bool AppendToPage(const wxString &aSource)
Definition: html_window.cpp:57
A mix in class which holds the location of a wxWindow's KIWAY.
Definition: kiway_holder.h:37
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
void UpdateNumber(int aNumber, SEVERITY aSeverity)
Update the number displayed on the badge.
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:126
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:71
LOCATION
Location where the message is to be reported.
Definition: reporter.h:79
@ LOC_TAIL
Definition: reporter.h:82
@ LOC_HEAD
Definition: reporter.h:80
Class WX_HTML_REPORT_PANEL_BASE.
void Clear()
return the number of messages matching the given severity mask.
void onCheckBoxShowErrors(wxCommandEvent &event) override
wxString m_reportFileName
defaults to the not very useful /bin/report.txt
void onThemeChanged(wxSysColourChangedEvent &aEvent)
void onCheckBoxShowActions(wxCommandEvent &event) override
REPORT_LINES m_report
copy of the report, stored for filtering
void onRightClick(wxMouseEvent &event) override
int m_severities
message severities to display (mask)
int Count(int severityMask)
sets the frame label
void SetLazyUpdate(bool aLazyUpdate)
Forces updating the HTML page, after the report is built in lazy mode If aSort = true,...
WX_HTML_PANEL_REPORTER m_reporter
void SetLabel(const wxString &aLabel) override
Sets the lazy update.
std::vector< REPORT_LINE > REPORT_LINES
void MsgPanelSetMinSize(const wxSize &aMinSize)
returns the reporter object that reports to this panel
void SetFileName(const wxString &aReportFileName)
wxString generateHtml(const REPORT_LINE &aLine)
void Report(const wxString &aText, SEVERITY aSeverity, REPORTER::LOCATION aLocation=REPORTER::LOC_BODY)
Reports the string.
void onCheckBoxShowAll(wxCommandEvent &event) override
void SetShowSeverity(SEVERITY aSeverity, bool aValue)
Set the report full file name to the string.
void SetVisibleSeverities(int aSeverities)
void Flush(bool aSort=false)
Set the visible severity filter.
void onCheckBoxShowWarnings(wxCommandEvent &event) override
void onMenuEvent(wxMenuEvent &event)
wxString generatePlainText(const REPORT_LINE &aLine)
void onBtnSaveToFile(wxCommandEvent &event) override
REPORT_LINES m_reportHead
... and at the beginning, regardless of sorting
~WX_HTML_REPORT_PANEL()
Set the min size of the area which displays html messages:
void onCheckBoxShowInfos(wxCommandEvent &event) override
REPORT_LINES m_reportTail
Lines to print at the end, regardless of sorting.
WX_HTML_REPORT_PANEL(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(500, 300), long style=wxTAB_TRAVERSAL)
#define _(s)
wxString TextFileWildcard()
bool IsDarkTheme()
Determine if the desktop interface is currently using a dark theme or a light theme.
Definition: gtk/ui.cpp:31
wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:144
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
@ RPT_SEVERITY_ACTION
bool ConvertSmartQuotesAndDashes(wxString *aString)
Convert curly quotes and em/en dashes to straight quotes and dashes.
Definition of file extensions used in Kicad.
static int RPT_SEVERITY_ALL