KiCad PCB EDA Suite
Loading...
Searching...
No Matches
job_import_utils.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
21#include <reporter.h>
22#include <string_utils.h>
23#include <wx/file.h>
24#include <wx/ffile.h>
25#include <wx/filename.h>
26#include <wx/intl.h>
27
28
29bool ParseImportReportFormat( const wxString& aText, IMPORT_REPORT_FORMAT& aFormat )
30{
31 if( aText == wxS( "none" ) )
33 else if( aText == wxS( "json" ) )
35 else if( aText == wxS( "text" ) )
37 else
38 return false;
39
40 return true;
41}
42
43
44wxString DefaultImportOutputPath( const wxString& aInputFile, const wxString& aKiCadExt )
45{
46 wxFileName fn( aInputFile );
47 fn.SetExt( aKiCadExt );
48
49 return fn.GetFullPath();
50}
51
52
53bool LoadLayerMapFile( const wxString& aFile, std::map<wxString, wxString>& aMap, wxString& aError )
54{
55 wxFFile file( aFile, wxS( "rb" ) );
56
57 if( !file.IsOpened() )
58 {
59 aError = wxString::Format( _( "Could not open layer map file '%s'" ), aFile );
60 return false;
61 }
62
63 wxString content;
64
65 if( !file.ReadAll( &content ) )
66 {
67 aError = wxString::Format( _( "Could not read layer map file '%s'" ), aFile );
68 return false;
69 }
70
71 nlohmann::json json;
72
73 try
74 {
75 json = nlohmann::json::parse( content.ToStdString() );
76 }
77 catch( const nlohmann::json::exception& e )
78 {
79 aError = wxString::Format( _( "Layer map file '%s' is not valid JSON: %s" ), aFile,
80 From_UTF8( e.what() ) );
81 return false;
82 }
83
84 if( !json.is_object() )
85 {
86 aError = wxString::Format( _( "Layer map file '%s' must be a JSON object mapping source "
87 "layer names to KiCad layer names" ), aFile );
88 return false;
89 }
90
91 std::map<wxString, wxString> parsed;
92
93 for( auto it = json.begin(); it != json.end(); ++it )
94 {
95 if( !it.value().is_string() )
96 {
97 aError = wxString::Format( _( "Layer map entry for '%s' must be a KiCad layer name "
98 "string" ), From_UTF8( it.key().c_str() ) );
99 return false;
100 }
101
102 parsed[From_UTF8( it.key().c_str() )] = From_UTF8( it.value().get<std::string>().c_str() );
103 }
104
105 aMap = std::move( parsed );
106 return true;
107}
108
109
110REPORTER& IMPORT_MESSAGE_COLLECTOR::Report( const wxString& aText, SEVERITY aSeverity )
111{
112 REPORTER::Report( aText, aSeverity );
113
114 wxString text = aText;
115 text.Trim();
116
117 if( aSeverity == RPT_SEVERITY_WARNING )
118 m_warnings.push_back( text );
119 else if( aSeverity == RPT_SEVERITY_ERROR )
120 m_errors.push_back( text );
121
122 return *this;
123}
124
125
127{
129 m_warnings.clear();
130 m_errors.clear();
131}
132
133
138
139
141{
142 for( const wxString& warning : m_warnings )
143 m_jobReporter.Report( warning + wxS( "\n" ), RPT_SEVERITY_WARNING );
144
145 for( const wxString& error : m_errors )
146 m_jobReporter.Report( error + wxS( "\n" ), RPT_SEVERITY_ERROR );
147
148 Clear();
149}
150
151
152void IMPORT_MESSAGE_COLLECTOR::Flush( IMPORT_REPORT_FORMAT aFormat, IMPORT_REPORT_DATA& aData )
153{
154 if( aFormat == IMPORT_REPORT_FORMAT::NONE )
155 {
156 forward();
157 return;
158 }
159
160 aData.m_warnings.insert( aData.m_warnings.end(), m_warnings.begin(), m_warnings.end() );
161 aData.m_errors.insert( aData.m_errors.end(), m_errors.begin(), m_errors.end() );
162 Clear();
163}
164
165
167 const wxString& aReportFile, const IMPORT_REPORT_DATA& aData )
168{
169 if( aFormat == IMPORT_REPORT_FORMAT::NONE )
170 return true;
171
172 wxString output;
173
174 if( aFormat == IMPORT_REPORT_FORMAT::JSON )
175 {
176 nlohmann::json report;
177
178 report["source_file"] = aData.m_sourceFile.ToStdString();
179 report["source_format"] = aData.m_sourceFormat.ToStdString();
180 report["output_file"] = aData.m_outputFile.ToStdString();
181
182 nlohmann::json statistics = nlohmann::json::object();
183
184 for( const auto& [key, value] : aData.m_statistics )
185 statistics[key.ToStdString()] = value;
186
187 report["statistics"] = statistics;
188
189 for( auto it = aData.m_extraJson.begin(); it != aData.m_extraJson.end(); ++it )
190 report[it.key()] = it.value();
191
192 nlohmann::json warningsJson = nlohmann::json::array();
193
194 for( const wxString& warning : aData.m_warnings )
195 warningsJson.push_back( warning.ToStdString() );
196
197 report["warnings"] = warningsJson;
198
199 nlohmann::json errorsJson = nlohmann::json::array();
200
201 for( const wxString& error : aData.m_errors )
202 errorsJson.push_back( error.ToStdString() );
203
204 report["errors"] = errorsJson;
205
206 output = wxString::FromUTF8( report.dump( 2 ) );
207 }
208 else
209 {
210 output += wxS( "Import Report\n" );
211 output += wxS( "=============\n\n" );
212 output += wxString::Format( wxS( "Source file: %s\n" ), aData.m_sourceFile );
213 output += wxString::Format( wxS( "Source format: %s\n" ), aData.m_sourceFormat );
214 output += wxString::Format( wxS( "Output file: %s\n\n" ), aData.m_outputFile );
215 output += wxS( "Statistics:\n" );
216
217 for( const auto& [key, value] : aData.m_statistics )
218 {
219 wxString label = key.Left( 1 ).Upper() + key.Mid( 1 );
220 output += wxString::Format( wxS( " %s: %zu\n" ), label, value );
221 }
222
223 if( !aData.m_warnings.empty() )
224 {
225 output += wxS( "\nWarnings:\n" );
226
227 for( const wxString& warning : aData.m_warnings )
228 output += wxString::Format( wxS( " - %s\n" ), warning );
229 }
230
231 if( !aData.m_errors.empty() )
232 {
233 output += wxS( "\nErrors:\n" );
234
235 for( const wxString& error : aData.m_errors )
236 output += wxString::Format( wxS( " - %s\n" ), error );
237 }
238 }
239
240 if( aReportFile.IsEmpty() )
241 {
242 if( aReporter )
243 aReporter->Report( output + wxS( "\n" ), RPT_SEVERITY_INFO );
244
245 return true;
246 }
247
248 wxFile file( aReportFile, wxFile::write );
249 bool written = file.IsOpened() && file.Write( output );
250
251 written = file.Close() && written;
252
253 if( !written && aReporter )
254 {
255 aReporter->Report( wxString::Format( _( "Failed to write import report to '%s'\n" ), aReportFile ),
257 }
258
259 return written;
260}
void Flush(IMPORT_REPORT_FORMAT aFormat, IMPORT_REPORT_DATA &aData)
Move the collected messages into aData when a report will be written, otherwise forward them to the j...
std::vector< wxString > m_warnings
std::vector< wxString > m_errors
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
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
#define _(s)
nlohmann::json json
Definition gerbview.cpp:50
static wxString From_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition idf_helpers.h:44
wxString DefaultImportOutputPath(const wxString &aInputFile, const wxString &aKiCadExt)
Build the default output path for an import by swapping the input file's extension for the given KiCa...
bool WriteImportReport(REPORTER *aReporter, IMPORT_REPORT_FORMAT aFormat, const wxString &aReportFile, const IMPORT_REPORT_DATA &aData)
Emit an import report in the requested format to aReportFile, or to aReporter (at INFO severity) when...
bool ParseImportReportFormat(const wxString &aText, IMPORT_REPORT_FORMAT &aFormat)
Parse the user-facing report format name ("none", "json" or "text") into its enum.
bool LoadLayerMapFile(const wxString &aFile, std::map< wxString, wxString > &aMap, wxString &aError)
Load an explicit layer-mapping file into aMap.
IMPORT_REPORT_FORMAT
Output format for the report shared by the board and schematic import jobs.
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO