KiCad PCB EDA Suite
Loading...
Searching...
No Matches
ipc2581_export_job.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
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include "ipc2581_export_job.h"
21#include "pcb_io_ipc2581.h"
22
23#include <map>
24
25#include <wx/filefn.h>
26#include <wx/filename.h>
27
28#include <board.h>
29#include <core/utf8.h>
30#include <gestfich.h>
32#include <ki_exception.h>
33#include <paths.h>
34#include <project.h>
36#include <reporter.h>
38
39
40bool GenerateIpc2581File( JOB_EXPORT_PCB_IPC2581& aJob, BOARD* aBoard, PROGRESS_REPORTER* aProgressReporter,
41 REPORTER* aReporter )
42{
43 wxCHECK( aBoard, false );
44 wxString outPath = aJob.GetFullOutputPath( aBoard->GetProject() );
45
46 if( !PATHS::EnsurePathExists( outPath, true ) )
47 {
48 if( aReporter )
49 aReporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
50
51 return false;
52 }
53
54 std::map<std::string, UTF8> props;
55 props["units"] = aJob.m_units == JOB_EXPORT_PCB_FAB::UNITS::MM ? "mm" : "inch";
56 props["sigfig"] = wxString::Format( "%d", aJob.m_precision );
57 props["version"] = aJob.m_version == JOB_EXPORT_PCB_IPC2581::IPC2581_VERSION::C ? "C" : "B";
58 props["OEMRef"] = aJob.m_colInternalId;
59 props["mpn"] = aJob.m_colMfgPn;
60 props["mfg"] = aJob.m_colMfg;
61 props["dist"] = aJob.m_colDist;
62 props["distpn"] = aJob.m_colDistPn;
63
64 if( !aJob.m_variantNames.empty() )
65 props["variant"] = aJob.m_variantNames.front();
66
67 if( !aJob.SupportsDataSet( aJob.m_dataSet ) )
68 {
69 if( aReporter )
70 aReporter->Report( _( "Unsupported IPC-2581 data set." ), RPT_SEVERITY_ERROR );
71
72 return false;
73 }
74
75 props["mode"] = IPC2581::ModeToken( aJob.m_dataSet );
76
77 if( aJob.m_sections )
78 props["sections"] = *aJob.m_sections;
79
81 props["netnames"] = "anonymize";
82
84 props["refdes"] = "omit";
85
86 wxString bomRev = aJob.m_bomRev;
87
88 if( bomRev.IsEmpty() && aBoard->GetProject() )
89 {
90 const IP2581_BOM& bomSettings = aBoard->GetProject()->GetProjectFile().m_IP2581Bom;
91 bomRev = bomSettings.bomRev;
92
93 if( bomRev.IsEmpty() )
94 bomRev = bomSettings.schRevision;
95 }
96
97 if( !bomRev.IsEmpty() )
98 props["bomrev"] = bomRev;
99
100 SCOPED_TEMP_PATH temporary;
101 wxString tempFile;
102
103 // A compressed export writes the file into a directory that becomes the archive
104 if( aJob.m_compress )
105 {
106 wxFileName xmlName = outPath;
107 xmlName.SetExt( FILEEXT::Ipc2581FileExtension );
108
109 if( temporary.MakeDirectory( wxS( "pcbnew_ipc" ) ) )
110 tempFile = wxFileName( temporary.Path(), xmlName.GetFullName() ).GetFullPath();
111 }
112 else if( temporary.MakeFile( wxS( "pcbnew_ipc" ) ) )
113 {
114 tempFile = temporary.Path();
115 }
116
117 if( tempFile.IsEmpty() )
118 {
119 if( aReporter )
120 aReporter->Report( _( "Cannot create temporary IPC-2581 output." ), RPT_SEVERITY_ERROR );
121
122 return false;
123 }
124
125 try
126 {
127 PCB_IO_IPC2581 plugin;
128 plugin.SetProgressReporter( aProgressReporter );
129 plugin.SetReporter( aReporter );
130 plugin.SaveBoard( tempFile, *aBoard, &props );
131 }
132 catch( const IO_ERROR& ioe )
133 {
134 if( aReporter )
135 {
136 aReporter->Report( wxString::Format( _( "Error generating IPC-2581 file '%s'.\n%s" ),
137 outPath,
138 ioe.What() ),
140 }
141
142 return false;
143 }
144
145 if( aJob.m_compress )
146 {
147 wxString error;
148
149 if( !WriteDirectoryArchive( temporary.Path(), outPath, ARCHIVE_FORMAT::ZIP, wxEmptyString, &error ) )
150 {
151 if( aReporter )
152 {
153 aReporter->Report( wxString::Format( _( "Cannot write IPC-2581 archive '%s'.\n%s" ),
154 outPath, error ), RPT_SEVERITY_ERROR );
155 }
156
157 return false;
158 }
159
160 aJob.AddOutput( outPath );
161 return true;
162 }
163
164 // If save succeeded, replace the original with what we just wrote
165 if( !wxRenameFile( tempFile, outPath ) )
166 {
167 if( aReporter )
168 {
169 aReporter->Report( wxString::Format( _( "Error generating IPC-2581 file '%s'.\n"
170 "Failed to rename temporary file '%s'." ),
171 outPath,
172 tempFile ),
174 }
175
176 return false;
177 }
178
179 aJob.AddOutput( outPath );
180 return true;
181}
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:410
PROJECT * GetProject() const
Definition board.h:775
virtual void SetReporter(REPORTER *aReporter)
Set an optional reporter for warnings/errors.
Definition io_base.h:89
virtual void SetProgressReporter(PROGRESS_REPORTER *aReporter)
Set an optional progress reporter.
Definition io_base.h:94
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
std::optional< wxString > m_sections
Section key that replaces the optional sections of the data set Unset lets the data set select them a...
std::vector< wxString > m_variantNames
bool SupportsDataSet(DATA_SET aDataSet) const override
void AddOutput(wxString aOutputPath)
Definition job.h:216
wxString GetFullOutputPath(PROJECT *aProject) const
Returns the full output path for the job, taking into account the configured output path,...
Definition job.cpp:150
static bool EnsurePathExists(const wxString &aPath, bool aPathToFile=false)
Attempts to create a given path if it does not exist.
Definition paths.cpp:508
void SaveBoard(const wxString &aFileName, BOARD &aBoard, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Write aBoard to a storage file in a format that this PCB_IO implementation knows about or it can be u...
A progress reporter interface for use in multi-threaded environments.
struct IP2581_BOM m_IP2581Bom
Layer pair list for the board.
virtual PROJECT_FILE & GetProjectFile() const
Definition project.h:201
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Definition reporter.h:102
A temporary file or directory that is removed when the object goes out of scope.
Definition gestfich.h:62
bool MakeFile(const wxString &aPrefix)
Create an empty file with a unique name after aPrefix.
Definition gestfich.cpp:939
bool MakeDirectory(const wxString &aPrefix)
Create an empty directory with a unique name after aPrefix.
Definition gestfich.cpp:946
const wxString & Path() const
Definition gestfich.h:75
#define _(s)
bool WriteDirectoryArchive(const wxString &aSourceDir, wxOutputStream &aOut, ARCHIVE_FORMAT aFormat, const wxString &aTopDir)
Write directory entries in sorted archive path order, using the archive root when aTopDir is empty.
Definition gestfich.cpp:793
static const std::string Ipc2581FileExtension
bool GenerateIpc2581File(JOB_EXPORT_PCB_IPC2581 &aJob, BOARD *aBoard, PROGRESS_REPORTER *aProgressReporter, REPORTER *aReporter)
Write the IPC-2581 file or archive of aJob and record it as a job output.
wxString ModeToken(MODE aMode)
Table 4 function mode token such as FABRICATION.
@ RPT_SEVERITY_ERROR
BOM Data choices for IPC2581 export.
wxString bomRev
Explicit BOM revision override set by user.
wxString schRevision
Auto-propagated schematic title block revision.
Definition of file extensions used in Kicad.