KiCad PCB EDA Suite
Loading...
Searching...
No Matches
reporter.cpp
Go to the documentation of this file.
1
4/*
5 * This program source code file is part of KiCad, a free EDA CAD application.
6 *
7 * Copyright (C) 2013 Wayne Stambaugh <[email protected]>
8 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 */
23
24#include <cwchar>
25#include <mutex>
26#include <macros.h>
27#include <reporter.h>
28#include <font/fontconfig.h>
29#include <string_utils.h>
30#include <widgets/kistatusbar.h>
31#include <widgets/wx_infobar.h>
32#include <wx/crt.h>
33#include <wx/log.h>
34#include <wx/msgout.h>
35#include <wx/textctrl.h>
36#include <wx/statusbr.h>
37#include <wx/tokenzr.h>
38#include <wx/weakref.h>
39
40#ifdef __WXMSW__
41#include <io.h>
42#endif
43
44
50static const wxChar traceReporter[] = wxT( "KICAD_REPORTER" );
51
52static std::mutex g_logReporterMutex;
53
54
56{
57public:
58 STATUSBAR_WARNING_REPORTER_IMPL( KISTATUSBAR* aStatusBar, const wxString& aSource ) :
59 m_statusBar( aStatusBar ),
60 m_source( aSource )
61 {
62 }
63
65 {
66 KISTATUSBAR* statusBar = m_statusBar.get();
67
68 if( statusBar && !statusBar->IsBeingDeleted() )
69 return statusBar;
70
71 return nullptr;
72 }
73
74 wxWeakRef<KISTATUSBAR> m_statusBar;
75 wxString m_source;
76};
77
78
79REPORTER& REPORTER::Report( const char* aText, SEVERITY aSeverity )
80{
81 Report( From_UTF8( aText ) );
82 return *this;
83}
84
85
87{
88 return Report( aError.AsString(), aError.GetSeverity() );
89}
90
91
92REPORTER& WX_TEXT_CTRL_REPORTER::Report( const wxString& aText, SEVERITY aSeverity )
93{
94 REPORTER::Report( aText, aSeverity );
95
96 wxCHECK_MSG( m_textCtrl != nullptr, *this,
97 wxT( "No wxTextCtrl object defined in WX_TEXT_CTRL_REPORTER." ) );
98
99 m_textCtrl->AppendText( aText + wxS( "\n" ) );
100 return *this;
101}
102
103
104REPORTER& WX_STRING_REPORTER::Report( const wxString& aText, SEVERITY aSeverity )
105{
106 REPORTER::Report( aText, aSeverity );
107
108 m_string << aText << wxS( "\n" );
109 return *this;
110}
111
112
113REPORTER& SYNC_REPORTER::Report( const wxString& aText, SEVERITY aSeverity )
114{
115 std::lock_guard lock( m_mutex );
116
117 m_reporter->Report( aText, aSeverity );
118 return *this;
119}
120
121
122REPORTER& SYNC_REPORTER::ReportTail( const wxString& aText, SEVERITY aSeverity )
123{
124 std::lock_guard lock( m_mutex );
125
126 m_reporter->ReportTail( aText, aSeverity );
127 return *this;
128}
129
130
131REPORTER& SYNC_REPORTER::ReportHead( const wxString& aText, SEVERITY aSeverity )
132{
133 std::lock_guard lock( m_mutex );
134
135 m_reporter->ReportHead( aText, aSeverity );
136 return *this;
137}
138
139
141{
142 std::lock_guard lock( m_mutex );
143
144 m_reporter->Clear();
145}
146
147
149{
150 std::lock_guard lock( m_mutex );
151
152 m_reporter->Finalize();
153}
154
155
157{
158 std::lock_guard lock( m_mutex );
159
161}
162
163
165{
166 std::lock_guard lock( m_mutex );
167
168 return m_reporter->HasMessage();
169}
170
171
172bool SYNC_REPORTER::HasMessageOfSeverity( int aSeverityMask ) const
173{
174 std::lock_guard lock( m_mutex );
175
176 return m_reporter->HasMessageOfSeverity( aSeverityMask );
177}
178
179
181{
182 std::lock_guard lock( m_mutex );
183
184 return m_reporter->GetUnits();
185}
186
187
188const wxString& WX_STRING_REPORTER::GetMessages() const
189{
190 return m_string;
191}
192
193
195{
197 m_string.clear();
198}
199
200
201REPORTER& NULL_REPORTER::Report( const wxString& aText, SEVERITY aSeverity )
202{
203 return REPORTER::Report( aText, aSeverity );
204}
205
206
208{
209 static REPORTER* s_nullReporter = nullptr;
210
211 if( !s_nullReporter )
212 s_nullReporter = new NULL_REPORTER();
213
214 return *s_nullReporter;
215}
216
217
218REPORTER& CLI_REPORTER::Report( const wxString& aMsg, SEVERITY aSeverity )
219{
220 REPORTER::Report( aMsg, aSeverity );
221
222 // Skip debug messages unless verbose mode is enabled
223 if( aSeverity == RPT_SEVERITY_DEBUG && !m_verbose )
224 return *this;
225
226 FILE* target = stdout;
227
228 if( aSeverity == RPT_SEVERITY_ERROR )
229 target = stderr;
230
231#ifdef __WXMSW__
232 const int fd = _fileno( target );
233
234 if( fd >= 0 && !_isatty( fd ) )
235 {
236 wxMessageOutputStderr( target, wxConvUTF8 ).Output( aMsg );
237 return *this;
238 }
239#else
240 // Tracing can orient the stream for byte output before the first report.
241 if( std::fwide( target, 0 ) < 0 )
242 {
243 wxMessageOutputStderr( target ).Output( aMsg );
244 return *this;
245 }
246#endif
247
248 if( aMsg.EndsWith( wxS( "\n" ) ) )
249 wxFprintf( target, aMsg );
250 else
251 wxFprintf( target, aMsg + wxS( "\n" ) );
252
253 // Needed after wxPrintf (or printf) to be sure the message is immediately printed
254 // (i.e. not stored in some i/o buffer)
255 fflush( target );
256
257 return *this;
258}
259
260
262{
263 static CLI_REPORTER s_cliReporter;
264
265 return s_cliReporter;
266}
267
268
269REPORTER& STDOUT_REPORTER::Report( const wxString& aMsg, SEVERITY aSeverity )
270{
271 REPORTER::Report( aMsg, aSeverity );
272
273 switch( aSeverity )
274 {
275 case RPT_SEVERITY_UNDEFINED: std::cout << "SEVERITY_UNDEFINED: "; break;
276 case RPT_SEVERITY_INFO: std::cout << "SEVERITY_INFO: "; break;
277 case RPT_SEVERITY_WARNING: std::cout << "SEVERITY_WARNING: "; break;
278 case RPT_SEVERITY_ERROR: std::cout << "SEVERITY_ERROR: "; break;
279 case RPT_SEVERITY_ACTION: std::cout << "SEVERITY_ACTION: "; break;
280 case RPT_SEVERITY_DEBUG: std::cout << "SEVERITY_DEBUG: "; break;
282 case RPT_SEVERITY_IGNORE: break;
283 }
284
285 std::cout << aMsg << std::endl;
286
287 return *this;
288}
289
290
292{
293 static REPORTER* s_stdoutReporter = nullptr;
294
295 if( !s_stdoutReporter )
296 s_stdoutReporter = new STDOUT_REPORTER();
297
298 return *s_stdoutReporter;
299}
300
301
302REPORTER& WXLOG_REPORTER::Report( const wxString& aMsg, SEVERITY aSeverity )
303{
304 REPORTER::Report( aMsg, aSeverity );
305
306 // aMsg is finished content; pass it as a "%s" argument so a stray '%' in
307 // reported data is not read as a format specifier (bogus varargs -> assert).
308 switch( aSeverity )
309 {
310 case RPT_SEVERITY_ERROR: wxLogError( wxS( "%s" ), aMsg ); break;
311 case RPT_SEVERITY_WARNING: wxLogWarning( wxS( "%s" ), aMsg ); break;
312 case RPT_SEVERITY_UNDEFINED: wxLogMessage( wxS( "%s" ), aMsg ); break;
313 case RPT_SEVERITY_INFO: wxLogInfo( wxS( "%s" ), aMsg ); break;
314 case RPT_SEVERITY_ACTION: wxLogInfo( wxS( "%s" ), aMsg ); break;
315 case RPT_SEVERITY_DEBUG: wxLogTrace( traceReporter, wxS( "%s" ), aMsg ); break;
316 case RPT_SEVERITY_EXCLUSION: break;
317 case RPT_SEVERITY_IGNORE: break;
318 }
319
320 return *this;
321}
322
323
325{
326 static REPORTER* s_wxLogReporter = nullptr;
327 std::lock_guard lock( g_logReporterMutex );
328
329 if( !s_wxLogReporter )
330 s_wxLogReporter = new WXLOG_REPORTER();
331
332 return *s_wxLogReporter;
333}
334
335
336REPORTER& LOAD_INFO_REPORTER::Report( const wxString& aMsg, SEVERITY aSeverity )
337{
338 REPORTER::Report( aMsg, aSeverity );
339
340 REPORTER* target = m_redirectTarget;
341
342 if( !target )
343 target = &WXLOG_REPORTER::GetInstance();
344
345 target->Report( aMsg, aSeverity );
346
347 return *this;
348}
349
350
352{
353 static LOAD_INFO_REPORTER s_loadInfoReporter;
354 std::lock_guard lock( g_logReporterMutex );
355
356 return s_loadInfoReporter;
357}
358
359
361{
362 std::lock_guard lock( g_logReporterMutex );
363 m_redirectTarget = aReporter;
364}
365
366
368{
369 std::lock_guard lock( g_logReporterMutex );
370 return m_redirectTarget;
371}
372
373
375 m_reporter( LOAD_INFO_REPORTER::GetInstance() ),
376 m_previousReporter( m_reporter.GetRedirectTarget() )
377{
378 m_reporter.SetRedirectTarget( aReporter );
379}
380
381
386
387
393
394
399
400
401REPORTER& REDIRECT_REPORTER::Report( const wxString& aText, SEVERITY aSeverity )
402{
403 REPORTER::Report( aText, aSeverity );
404
405 if( m_redirectTarget )
406 m_redirectTarget->Report( aText, aSeverity );
407
408 return *this;
409}
410
411
412REPORTER& STATUSBAR_REPORTER::Report( const wxString& aText, SEVERITY aSeverity )
413{
414 REPORTER::Report( aText, aSeverity );
415
416 if( m_statusBar )
417 {
418 wxStatusBar* statusBar = m_statusBar;
419 int position = m_position;
420
421 if( wxIsMainThread() )
422 {
423 // The message will be ellipsized automatically
424 statusBar->SetStatusText( aText, position );
425 }
426 else
427 {
428 statusBar->CallAfter(
429 [statusBar, position, aText]()
430 {
431 statusBar->SetStatusText( aText, position );
432 } );
433 }
434 }
435
436 return *this;
437}
438
439
441 const wxString& aSource ) :
442 m_impl( std::make_shared<STATUSBAR_WARNING_REPORTER_IMPL>( aStatusBar, aSource ) )
443{
444}
445
446
448
449
450REPORTER& STATUSBAR_WARNING_REPORTER::Report( const wxString& aText, SEVERITY aSeverity )
451{
452 REPORTER::Report( aText, aSeverity );
453
454 KISTATUSBAR* statusBar = m_impl ? m_impl->GetStatusBar() : nullptr;
455
456 if( !statusBar || aText.IsEmpty() )
457 return *this;
458
459 std::vector<KI_ERROR> messages;
460 wxStringTokenizer tokenizer( aText, wxS( "\n" ), wxTOKEN_STRTOK );
461 SEVERITY severity = aSeverity == RPT_SEVERITY_UNDEFINED ? RPT_SEVERITY_WARNING : aSeverity;
462
463 while( tokenizer.HasMoreTokens() )
464 {
465 KI_ERROR message;
466 message.SetTitle( tokenizer.GetNextToken() );
467 message.SetSeverity( severity );
468 messages.emplace_back( std::move( message ) );
469 }
470
471 if( messages.empty() )
472 {
473 KI_ERROR message;
474 message.SetTitle( aText );
475 message.SetSeverity( severity );
476 messages.emplace_back( std::move( message ) );
477 }
478
479 statusBar->AddWarningMessages( m_impl->m_source, messages );
480 return *this;
481}
482
483
485{
486 REPORTER::Report( aError.AsString(), aError.GetSeverity() );
487
488 if( KISTATUSBAR* statusBar = m_impl ? m_impl->GetStatusBar() : nullptr )
489 statusBar->AddWarningMessages( m_impl->m_source, { aError } );
490
491 return *this;
492}
REPORTER & Report(const wxString &aMsg, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
Definition reporter.cpp:218
static CLI_REPORTER & GetInstance()
Definition reporter.cpp:261
bool m_verbose
Definition reporter.h:308
FONTCONFIG_REPORTER_SCOPE(REPORTER *aReporter)
Definition reporter.cpp:388
REPORTER * m_previousReporter
Definition reporter.h:391
KISTATUSBAR is a wxStatusBar suitable for Kicad manager.
Definition kistatusbar.h:50
void AddWarningMessages(const wxString &aSource, const wxString &aMessages)
Add warning/error messages (not thread-safe, use the std::vector<KI_ERROR> variant from other threads...
Holds a structured error message.
Definition ki_error.h:38
SEVERITY GetSeverity() const
Definition ki_error.h:54
wxString AsString() const
Definition ki_error.cpp:27
KI_ERROR & SetSeverity(SEVERITY aSeverity)
Definition ki_error.h:76
KI_ERROR & SetTitle(const wxString &aTitle)
Definition ki_error.h:58
LOAD_INFO_REPORTER_SCOPE(REPORTER *aReporter)
Definition reporter.cpp:374
LOAD_INFO_REPORTER & m_reporter
Definition reporter.h:373
REPORTER * m_previousReporter
Definition reporter.h:374
REPORTER * GetRedirectTarget() const
Definition reporter.cpp:367
REPORTER * m_redirectTarget
Definition reporter.h:362
static LOAD_INFO_REPORTER & GetInstance()
Definition reporter.cpp:351
void SetRedirectTarget(REPORTER *aReporter)
Definition reporter.cpp:360
REPORTER & Report(const wxString &aMsg, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
Definition reporter.cpp:336
static REPORTER & GetInstance()
Definition reporter.cpp:207
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
Definition reporter.cpp:201
REPORTER * m_redirectTarget
Definition reporter.h:402
REPORTER & Report(const wxString &aMsg, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
Definition reporter.cpp:401
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
virtual void Clear()
Definition reporter.h:162
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Definition reporter.h:102
REPORTER()
Definition reporter.h:75
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
Definition reporter.cpp:412
wxStatusBar * m_statusBar
Definition reporter.h:421
wxWeakRef< KISTATUSBAR > m_statusBar
Definition reporter.cpp:74
KISTATUSBAR * GetStatusBar() const
Definition reporter.cpp:64
STATUSBAR_WARNING_REPORTER_IMPL(KISTATUSBAR *aStatusBar, const wxString &aSource)
Definition reporter.cpp:58
STATUSBAR_WARNING_REPORTER(KISTATUSBAR *aStatusBar, const wxString &aSource)
Definition reporter.cpp:440
~STATUSBAR_WARNING_REPORTER() override
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
Definition reporter.cpp:450
std::shared_ptr< STATUSBAR_WARNING_REPORTER_IMPL > m_impl
Definition reporter.h:436
REPORTER & Report(const wxString &aMsg, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
Definition reporter.cpp:269
static REPORTER & GetInstance()
Definition reporter.cpp:291
REPORTER * m_reporter
Definition reporter.h:209
void Finalize() override
Definition reporter.cpp:148
bool HasMessage() const override
Returns true if any messages were reported.
Definition reporter.cpp:164
REPORTER & ReportHead(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Places the report at the beginning of the list for objects that support ordering.
Definition reporter.cpp:131
void SetNullReporter()
Definition reporter.cpp:156
EDA_UNITS GetUnits() const override
Definition reporter.cpp:180
bool HasMessageOfSeverity(int aSeverityMask) const override
Returns true if the reporter has one or more messages matching the specified severity mask.
Definition reporter.cpp:172
REPORTER & ReportTail(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Places the report at the end of the list, for objects that support report ordering.
Definition reporter.cpp:122
void Clear() override
Definition reporter.cpp:140
std::mutex m_mutex
Definition reporter.h:210
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
Definition reporter.cpp:113
REPORTER & Report(const wxString &aMsg, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
Definition reporter.cpp:302
static REPORTER & GetInstance()
Definition reporter.cpp:324
wxString m_string
Definition reporter.h:257
void Clear() override
Definition reporter.cpp:194
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
Definition reporter.cpp:104
const wxString & GetMessages() const
Definition reporter.cpp:188
wxTextCtrl * m_textCtrl
Definition reporter.h:234
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
Definition reporter.cpp:92
static void SetReporter(REPORTER *aReporter)
Set the reporter to use for reporting font substitution warnings.
EDA_UNITS
Definition eda_units.h:44
static const wxChar traceReporter[]
Flag to enable reporter debugging output.
Definition reporter.cpp:50
This file contains miscellaneous commonly used macros and functions.
STL namespace.
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_UNDEFINED
@ RPT_SEVERITY_EXCLUSION
@ RPT_SEVERITY_IGNORE
@ RPT_SEVERITY_DEBUG
@ RPT_SEVERITY_INFO
@ RPT_SEVERITY_ACTION
static std::mutex g_logReporterMutex
Definition reporter.cpp:52
wxString From_UTF8(const char *cstring)