45#include <wx/filedlg.h>
46#include <wx/wfstream.h>
47#include <wx/zipstrm.h>
48#include <wx/tarstrm.h>
49#include <wx/zstream.h>
73 m_parent( aEditFrame ),
96 wxFileName odbFile( brdFile.GetPath(), wxString::Format( wxS(
"%s-odb" ), brdFile.GetName() ),
120 wxString
filter =
_(
"zip files" )
128 wxFileName fn(
Prj().AbsolutePath(
path ) );
132 wxString fileDialogName( wxString::Format( wxS(
"%s-odb" ), brdFile.GetName() ) );
134 wxFileDialog dlg(
this,
_(
"Export ODB++ File" ), fn.GetPath(), fileDialogName,
filter, wxFD_SAVE );
136 if( dlg.ShowModal() == wxID_CANCEL )
139 path = dlg.GetPath();
141 fn = wxFileName(
path );
143 if( fn.GetExt().Lower() ==
"zip" )
147 else if( fn.GetExt().Lower() ==
"tgz" )
151 else if(
path.EndsWith(
"/" ) ||
path.EndsWith(
"\\" ) )
157 DisplayErrorMessage(
this,
_(
"The selected output file name is not a supported archive format." ) );
175 wxFileName fileName( fn );
179 int sepIdx = std::max( fn.Find(
'/',
true ), fn.Find(
'\\',
true ) );
180 int dotIdx = fn.Find(
'.',
true );
182 if( fileName.IsDir() )
183 fn = fn.Mid( 0, sepIdx );
184 else if( sepIdx < dotIdx )
185 fn = fn.Mid( 0, dotIdx );
187 switch( compressionMode )
196 fn = wxFileName( fn,
"" ).GetFullPath();
219 wxFileName fileName( fn );
220 bool isDirectory = fileName.IsDir();
221 wxString extension = fileName.GetExt();
227 DisplayErrorMessage(
this,
_(
"The output file name conflicts with the selected compression format." ) );
258 if( outputPath.IsEmpty() )
259 outputPath = wxFileName( aJob.
m_filename ).GetPath();
261 wxFileName outputFn( outputPath );
266 if( outputFn.GetPath().IsEmpty() && outputFn.HasName() )
267 outputFn.MakeAbsolute();
274 msg.Printf(
_(
"Cannot create output directory '%s'." ), outputFn.GetFullPath() );
282 if( outputFn.IsDir() && !outputFn.IsDirWritable() )
284 msg.Printf(
_(
"Insufficient permissions to folder '%s'." ), outputFn.GetPath() );
292 if( outputIsSingleFile )
294 bool writeable = outputFn.FileExists() ? outputFn.IsFileWritable() : outputFn.IsDirWritable();
298 msg.Printf(
_(
"Insufficient permissions to save file '%s'." ), outputFn.GetFullPath() );
307 wxFileName tempFile( outputFn.GetFullPath() );
309 if( outputIsSingleFile )
311 if( outputFn.Exists() )
315 msg = wxString::Format(
_(
"Output files '%s' already exists. Do you want to overwrite it?" ),
316 outputFn.GetFullPath() );
318 KIDIALOG errorDlg( aParentFrame, msg,
_(
"Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
319 errorDlg.SetOKLabel(
_(
"Overwrite" ) );
324 if( !wxRemoveFile( outputFn.GetFullPath() ) )
326 msg.Printf(
_(
"Cannot remove existing output file '%s'." ), outputFn.GetFullPath() );
333 msg = wxString::Format(
_(
"Output file '%s' already exists." ), outputFn.GetFullPath() );
342 tempFile.AssignDir( wxFileName::GetTempDir() );
343 tempFile.AppendDir(
"kicad" );
344 tempFile.AppendDir(
"odb" );
346 if( !wxFileName::Mkdir( tempFile.GetFullPath(), wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
348 msg.Printf(
_(
"Cannot create temporary output directory." ) );
359 wxDir testDir( tempFile.GetFullPath() );
361 if( testDir.IsOpened() && ( testDir.HasFiles() || testDir.HasSubDirs() ) )
365 msg = wxString::Format(
_(
"Output directory '%s' already exists and is not empty. "
366 "Do you want to overwrite it?" ),
367 tempFile.GetFullPath() );
369 KIDIALOG errorDlg( aParentFrame, msg,
_(
"Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
370 errorDlg.SetOKLabel(
_(
"Overwrite" ) );
375 if( !tempFile.Rmdir( wxPATH_RMDIR_RECURSIVE ) )
377 msg.Printf(
_(
"Cannot remove existing output directory '%s'." ), tempFile.GetFullPath() );
384 msg = wxString::Format(
_(
"Output directory '%s' already exists." ), tempFile.GetFullPath() );
394 std::map<std::string, UTF8> props;
397 props[
"sigfig"] = wxString::Format(
"%d", aJob.
m_precision );
405 pi->SetReporter( aReporter );
406 pi->SetProgressReporter( aProgressReporter );
407 pi->SaveBoard( tempFile.GetFullPath(), aBoard, &props );
414 msg = wxString::Format(
_(
"Error generating ODBPP files '%s'.\n%s" ),
415 tempFile.GetFullPath(), ioe.
What() );
420 wxFileName::Rmdir( tempFile.GetFullPath() );
426 auto ret =
tp.submit( saveFile );
428 std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
430 while( status != std::future_status::ready )
432 if( aProgressReporter )
435 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
443 catch(
const std::exception& e )
447 aReporter->
Report( wxString::Format(
"Exception in ODB++ generation: %s", e.what() ),
456 if( aProgressReporter )
457 aProgressReporter->
AdvancePhase(
_(
"Compressing output" ) );
459 wxFFileOutputStream fnout( outputFn.GetFullPath() );
460 wxZipOutputStream zipStream( fnout );
462 std::function<void(
const wxString&,
const wxString& )> addDirToZip =
463 [&](
const wxString& dirPath,
const wxString& parentPath )
465 wxDir dir( dirPath );
468 bool cont = dir.GetFirst( &fileName, wxEmptyString, wxDIR_DEFAULT );
472 wxFileName fileInZip( dirPath, fileName );
473 wxString relativePath = fileName;
475 if( !parentPath.IsEmpty() )
476 relativePath = parentPath + wxString( wxFileName::GetPathSeparator() ) + fileName;
478 if( wxFileName::DirExists( fileInZip.GetFullPath() ) )
480 zipStream.PutNextDirEntry( relativePath );
481 addDirToZip( fileInZip.GetFullPath(), relativePath );
485 wxFFileInputStream fileStream( fileInZip.GetFullPath() );
486 zipStream.PutNextEntry( relativePath );
487 fileStream.Read( zipStream );
489 cont = dir.GetNext( &fileName );
493 addDirToZip( tempFile.GetFullPath(), wxEmptyString );
498 tempFile.Rmdir( wxPATH_RMDIR_RECURSIVE );
502 wxFFileOutputStream fnout( outputFn.GetFullPath() );
503 wxZlibOutputStream zlibStream( fnout, -1, wxZLIB_GZIP );
504 wxTarOutputStream tarStream( zlibStream );
506 std::function<void(
const wxString&,
const wxString& )> addDirToTar =
507 [&](
const wxString& dirPath,
const wxString& parentPath )
509 wxDir dir( dirPath );
512 bool cont = dir.GetFirst( &fileName, wxEmptyString, wxDIR_DEFAULT );
515 wxFileName fileInTar( dirPath, fileName );
516 wxString relativePath = fileName;
518 if( !parentPath.IsEmpty() )
519 relativePath = parentPath + wxString( wxFileName::GetPathSeparator() ) + fileName;
521 if( wxFileName::DirExists( fileInTar.GetFullPath() ) )
523 tarStream.PutNextDirEntry( relativePath );
524 addDirToTar( fileInTar.GetFullPath(), relativePath );
528 wxFFileInputStream fileStream( fileInTar.GetFullPath() );
529 tarStream.PutNextEntry( relativePath, wxDateTime::Now(), fileStream.GetLength() );
530 fileStream.Read( tarStream );
532 cont = dir.GetNext( &fileName );
536 addDirToTar( tempFile.GetFullPath(),
537 tempFile.GetPath( wxPATH_NO_SEPARATOR ).AfterLast( tempFile.GetPathSeparator() ) );
543 tempFile.Rmdir( wxPATH_RMDIR_RECURSIVE );
546 if( aProgressReporter )
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Information pertinent to a Pcbnew printed circuit board.
const wxString & GetFileName() const
PROJECT * GetProject() const
Class DIALOG_EXPORT_ODBPP_BASE.
wxTextCtrl * m_outputFileName
wxChoice * m_choiceCompress
STD_BITMAP_BUTTON * m_browseButton
bool TransferDataFromWindow() override
void OnFmtChoiceOptionChanged()
void onFormatChoice(wxCommandEvent &event) override
static void GenerateODBPPFiles(const JOB_EXPORT_PCB_ODB &aJob, BOARD *aBoard, PCB_EDIT_FRAME *aParentFrame=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr, REPORTER *aErrorReporter=nullptr)
bool TransferDataToWindow() override
void onBrowseClicked(wxCommandEvent &event) override
JOB_EXPORT_PCB_ODB * m_job
DIALOG_EXPORT_ODBPP(PCB_EDIT_FRAME *aParent)
PCB_EDIT_FRAME * m_parent
void onOKClick(wxCommandEvent &event) override
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
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()
wxString GetSettingsDialogTitle() const override
ODB_COMPRESSION m_compressionMode
void SetConfiguredOutputPath(const wxString &aPath)
Sets the configured output path for the job, this path is always saved to file.
wxString GetFullOutputPath(PROJECT *aProject) const
Returns the full output path for the job, taking into account the configured output path,...
wxString GetConfiguredOutputPath() const
Returns the configured output path for the job.
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
static bool EnsurePathExists(const wxString &aPath, bool aPathToFile=false)
Attempts to create a given path if it does not exist.
The main frame for Pcbnew.
static PCB_IO * PluginFind(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
A progress reporter interface for use in multi-threaded environments.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void AdvancePhase()=0
Use the next available virtual zone of the dialog progress bar.
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
A pure virtual class used to derive REPORTER objects from.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
static void ResolvePossibleSymlinks(wxFileName &aFilename)
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
This file is part of the common library.
static const std::string ArchiveFileExtension
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
This file is part of the common library.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
BS::thread_pool thread_pool
wxString AddFileExtListToFilter(const std::vector< std::string > &aExts)
Build the wildcard extension file dialog wildcard filter to add to the base message dialog.