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-2017 KiCad Developers, see change_log.txt for contributors.
6  * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
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 "wx_html_report_panel.h"
23 
25 #include <gal/color4d.h>
26 #include <wx/clipbrd.h>
27 
29  wxWindowID id,
30  const wxPoint& pos,
31  const wxSize& size,
32  long style ) :
33  WX_HTML_REPORT_PANEL_BASE( parent, id, pos, size, style ),
34  m_reporter( this ),
35  m_severities( -1 ),
36  m_showAll( true ),
37  m_lazyUpdate( false )
38 {
40  m_htmlView->SetPage( addHeader( "" ) );
41 
42  Connect( wxEVT_COMMAND_MENU_SELECTED,
43  wxMenuEventHandler( WX_HTML_REPORT_PANEL::onMenuEvent ), NULL, this );
44 }
45 
46 
48 {
49 }
50 
51 
52 void WX_HTML_REPORT_PANEL::MsgPanelSetMinSize( const wxSize& aMinSize )
53 {
54  m_fgSizer->SetMinSize( aMinSize );
55  GetSizer()->SetSizeHints( this );
56 }
57 
58 
60 {
61  return m_reporter;
62 }
63 
64 
65 void WX_HTML_REPORT_PANEL::Report( const wxString& aText, REPORTER::SEVERITY aSeverity )
66 {
67  REPORT_LINE line;
68  line.message = aText;
69  line.severity = aSeverity;
70 
71  m_report.push_back( line );
72 
73  m_html += generateHtml( line );
74 
75  if( !m_lazyUpdate )
76  {
77  m_htmlView->AppendToPage( generateHtml( line ) );
79  }
80 }
81 
82 
83 void WX_HTML_REPORT_PANEL::SetLazyUpdate( bool aLazyUpdate )
84 {
85  m_lazyUpdate = aLazyUpdate;
86 }
87 
88 
90 {
91  m_htmlView->SetPage( addHeader( m_html ) );
93 }
94 
95 
97 {
98  int x, y, xUnit, yUnit;
99 
100  m_htmlView->GetVirtualSize( &x, &y );
101  m_htmlView->GetScrollPixelsPerUnit( &xUnit, &yUnit );
102  m_htmlView->Scroll( 0, y / yUnit );
103 
104  updateBadges();
105 }
106 
107 
108 const static wxSize BADGE_SIZE_DU( 9, 9 );
109 const static int BADGE_FONT_SIZE = 9;
110 
111 static wxBitmap makeBadge( REPORTER::SEVERITY aStyle, int aCount, wxWindow* aWindow )
112 {
113  wxSize size( aWindow->ConvertDialogToPixels( BADGE_SIZE_DU ) );
114  wxBitmap bitmap( size );
115  wxBrush brush;
116  wxMemoryDC badgeDC;
117  wxColour badgeColour;
118  wxColour textColour;
119  int fontSize = BADGE_FONT_SIZE;
120 
121  if( aCount > 99 )
122  fontSize--;
123 
124  badgeDC.SelectObject( bitmap );
125 
126  brush.SetStyle( wxBRUSHSTYLE_SOLID );
127  // We're one level deep in staticBoxes; each level is darkened by 210
128  brush.SetColour( aWindow->GetParent()->GetBackgroundColour().MakeDisabled( 210 ) );
129  badgeDC.SetBackground( brush );
130  badgeDC.Clear();
131 
132  switch( aStyle )
133  {
134  case REPORTER::RPT_ERROR:
135  badgeColour = *wxRED;
136  textColour = *wxWHITE;
137  break;
139  badgeColour = *wxYELLOW;
140  textColour = *wxBLACK;
141  break;
143  badgeColour = *wxGREEN;
144  textColour = *wxWHITE;
145  break;
146  case REPORTER::RPT_INFO:
147  default:
148  badgeColour = *wxLIGHT_GREY;
149  textColour = *wxBLACK;
150  break;
151  }
152 
153  brush.SetStyle( wxBRUSHSTYLE_SOLID );
154  brush.SetColour( badgeColour );
155  badgeDC.SetBrush( brush );
156  badgeDC.SetPen( wxPen( badgeColour, 0 ) );
157  badgeDC.DrawCircle( size.x / 2 - 1, size.y / 2, ( std::max( size.x, size.y ) / 2 ) - 1 );
158 
159  wxFont font( BADGE_FONT_SIZE, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD );
160  wxString text = wxString::Format( wxT( "%d" ), aCount );
161  wxSize textExtent = badgeDC.GetTextExtent( text );
162 
163  badgeDC.SetFont( font );
164  badgeDC.SetTextForeground( textColour );
165  badgeDC.DrawText( text, size.x / 2 - textExtent.x / 2, size.y / 2 - textExtent.y / 2 + 2 );
166 
167  return bitmap;
168 }
169 
170 
172 {
173  int count = Count( REPORTER::RPT_ERROR );
174 
175  if( count > 0 )
176  {
177  m_errorsBadge->SetBitmap( makeBadge( REPORTER::RPT_ERROR, count, m_errorsBadge ) );
178  m_errorsBadge->Show( true );
179  }
180  else
181  m_errorsBadge->Show( false );
182 
183  count = Count( REPORTER::RPT_WARNING );
184 
185  if( count > 0 )
186  {
188  m_warningsBadge->Show( true );
189  }
190  else
191  m_warningsBadge->Show( false );
192 }
193 
194 
196 {
197  wxString html;
198 
199  for( const REPORT_LINE& l : m_report )
200  {
201  html += generateHtml( l );
202  }
203 
204  m_htmlView->SetPage( addHeader( html ) );
205  scrollToBottom();
206 }
207 
208 
209 wxString WX_HTML_REPORT_PANEL::addHeader( const wxString& aBody )
210 {
211  wxColour bgcolor = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW );
212  wxColour fgcolor = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT );
213 
214  return wxString::Format( wxT( "<html><body bgcolor='%s' text='%s'>%s</body></html>" ),
215  bgcolor.GetAsString( wxC2S_HTML_SYNTAX ),
216  fgcolor.GetAsString( wxC2S_HTML_SYNTAX ),
217  aBody );
218 }
219 
220 
221 int WX_HTML_REPORT_PANEL::Count( int severityMask )
222 {
223  int count = 0;
224 
225  for( const REPORT_LINE& reportLine : m_report )
226  if( severityMask & reportLine.severity )
227  count++;
228 
229  return count;
230 }
231 
232 
234 {
235  wxString retv;
236 
237  if( !m_showAll && ! ( m_severities & aLine.severity ) )
238  return retv;
239 
240  switch( aLine.severity )
241  {
242  case REPORTER::RPT_ERROR:
243  retv = "<font color=\"red\" size=2><b>" + _( "Error: " ) + "</b></font><font size=2>" +
244  aLine.message + "</font><br>";
245  break;
247  retv = "<font color=\"orange\" size=2><b>" + _( "Warning: " ) +
248  "</b></font><font size=2>" + aLine.message + "</font><br>";
249  break;
250  case REPORTER::RPT_INFO:
251  retv = "<font color=\"dark gray\" size=2><b>" + _( "Info: " ) + "</b>" + aLine.message +
252  "</font><br>";
253  break;
255  retv = "<font color=\"dark green\" size=2>" + aLine.message + "</font><br>";
256  break;
257  default:
258  retv = "<font size=2>" + aLine.message + "</font><br>";
259  }
260 
261  return retv;
262 }
263 
264 
266 {
267  switch( aLine.severity )
268  {
269  case REPORTER::RPT_ERROR:
270  return _( "Error: " ) + aLine.message + wxT( "\n" );
272  return _( "Warning: " ) + aLine.message + wxT( "\n" );
273  case REPORTER::RPT_INFO:
274  return _( "Info: " ) + aLine.message + wxT( "\n" );
275  default:
276  return aLine.message + wxT( "\n" );
277  }
278 }
279 
280 
281 void WX_HTML_REPORT_PANEL::onRightClick( wxMouseEvent& event )
282 {
283  wxMenu popup;
284  popup.Append( wxID_COPY, "Copy" );
285  PopupMenu( &popup );
286 }
287 
288 
289 void WX_HTML_REPORT_PANEL::onMenuEvent( wxMenuEvent& event )
290 {
291  if( event.GetId() == wxID_COPY )
292  {
293  if( wxTheClipboard->Open() )
294  {
295  bool primarySelection = wxTheClipboard->IsUsingPrimarySelection();
296  wxTheClipboard->UsePrimarySelection( false ); // required to use the main clipboard
297  wxTheClipboard->SetData( new wxTextDataObject( m_htmlView->SelectionToText() ) );
298  wxTheClipboard->Close();
299  wxTheClipboard->UsePrimarySelection( primarySelection );
300  }
301  }
302 }
303 
304 
305 void WX_HTML_REPORT_PANEL::onCheckBoxShowAll( wxCommandEvent& event )
306 {
307  if( event.IsChecked() )
308  m_showAll = true;
309  else
310  m_showAll = false;
311 
312  syncCheckboxes();
313  refreshView();
314 }
315 
316 
318 {
319  m_checkBoxShowAll->SetValue( m_showAll );
324 }
325 
326 
327 void WX_HTML_REPORT_PANEL::onCheckBoxShowWarnings( wxCommandEvent& event )
328 {
329  if ( event.IsChecked() )
331  else
332  m_severities &= ~REPORTER::RPT_WARNING;
333 
334  refreshView();
335 }
336 
337 
338 void WX_HTML_REPORT_PANEL::onCheckBoxShowErrors( wxCommandEvent& event )
339 {
340  if ( event.IsChecked() )
342  else
343  m_severities &= ~REPORTER::RPT_ERROR;
344 
345  refreshView();
346 }
347 
348 
349 void WX_HTML_REPORT_PANEL::onCheckBoxShowInfos( wxCommandEvent& event )
350 {
351  if ( event.IsChecked() )
353  else
354  m_severities &= ~REPORTER::RPT_INFO;
355 
356  refreshView();
357 }
358 
359 
360 void WX_HTML_REPORT_PANEL::onCheckBoxShowActions( wxCommandEvent& event )
361 {
362  if ( event.IsChecked() )
364  else
365  m_severities &= ~REPORTER::RPT_ACTION;
366 
367  refreshView();
368 }
369 
370 
371 void WX_HTML_REPORT_PANEL::onBtnSaveToFile( wxCommandEvent& event )
372 {
373  wxFileName fn( "./report.txt" );
374 
375  wxFileDialog dlg( this, _( "Save Report to File" ), fn.GetPath(), fn.GetFullName(),
376  TextFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
377 
378  if( dlg.ShowModal() != wxID_OK )
379  return;
380 
381  fn = dlg.GetPath();
382 
383  if( fn.GetExt().IsEmpty() )
384  fn.SetExt( "txt" );
385 
386  wxFile f( fn.GetFullPath(), wxFile::write );
387 
388  if( !f.IsOpened() )
389  {
390  wxString msg;
391 
392  msg.Printf( _( "Cannot write report to file \"%s\"." ),
393  fn.GetFullPath().GetData() );
394  wxMessageBox( msg, _( "File save error" ), wxOK | wxICON_ERROR, this );
395  return;
396  }
397 
398  for( const REPORT_LINE& l : m_report )
399  {
400  f.Write( generatePlainText( l ) );
401  }
402 
403  f.Close();
404 }
405 
406 
408 {
409  m_html.clear();
410  m_report.clear();
411 }
412 
413 
414 void WX_HTML_REPORT_PANEL::SetLabel( const wxString& aLabel )
415 {
416  m_box->GetStaticBox()->SetLabel( aLabel );
417 }
418 
419 
421 {
422  if( aSeverities < 0 )
423  m_showAll = true;
424  else
425  {
426  m_showAll = false;
427  m_severities = aSeverities;
428  }
429 
430  syncCheckboxes();
431 }
432 
433 
435 {
436  return m_showAll ? m_severities | 0x80000000 : m_severities & ~0x80000000;
437 }
void SetVisibleSeverities(int aSeverities)
Set the visible severity filter.
void onCheckBoxShowInfos(wxCommandEvent &event) override
void onBtnSaveToFile(wxCommandEvent &event) override
wxString addHeader(const wxString &aBody)
void SetLazyUpdate(bool aLazyUpdate)
Sets the lasy update.
void onCheckBoxShowActions(wxCommandEvent &event) override
wxString generatePlainText(const REPORT_LINE &aLine)
Class WX_HTML_REPORT_PANEL_BASE.
static wxBitmap makeBadge(REPORTER::SEVERITY aStyle, int aCount, wxWindow *aWindow)
void onCheckBoxShowWarnings(wxCommandEvent &event) override
void onCheckBoxShowErrors(wxCommandEvent &event) override
static const int BADGE_FONT_SIZE
Class REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:61
void onRightClick(wxMouseEvent &event) override
WX_HTML_REPORT_PANEL(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(500, 300), long style=wxTAB_TRAVERSAL)
SEVERITY
Severity of the reported messages.
Definition: reporter.h:65
void Report(const wxString &aText, REPORTER::SEVERITY aSeverity)
reports a string directly.
REPORTER & Reporter()
returns the reporter object that reports to this panel
WX_HTML_PANEL_REPORTER m_reporter
the reporter
bool m_showAll
show all messages flag (overrides m_severities)
int Count(int severityMask)
return the number of messages matching the given severity mask.
The common library.
REPORT_LINES m_report
copy of the report, stored for filtering
void Flush()
Forces updating the HTML page, after the report is built in lazy mode
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
void Clear()
clears the report panel
#define max(a, b)
Definition: auxiliary.h:86
void onCheckBoxShowAll(wxCommandEvent &event) override
static const wxSize BADGE_SIZE_DU(9, 9)
wxString TextFileWildcard()
wxString generateHtml(const REPORT_LINE &aLine)
void MsgPanelSetMinSize(const wxSize &aMinSize)
Set the min size of the area which displays html messages:
void SetLabel(const wxString &aLabel) override
sets the frame label
void onMenuEvent(wxMenuEvent &event)
int m_severities
message severities to display (mask)