46#include <wx/filedlg.h>
47#include <wx/wfstream.h>
48#include <wx/zipstrm.h>
49#include <wx/tarstrm.h>
50#include <wx/zstream.h>
68 wxFileName odbFile( brdFile.GetPath(),
69 wxString::Format( wxS(
"%s-odb" ), brdFile.GetName() ),
71 path = odbFile.GetFullPath();
88 m_parent( aEditFrame ),
109 wxString
filter =
_(
"zip files" )
117 wxFileName fn(
Prj().AbsolutePath(
path ) );
121 wxString fileDialogName( wxString::Format( wxS(
"%s-odb" ), brdFile.GetName() ) );
123 wxFileDialog dlg(
this,
_(
"Export ODB++ File" ), fn.GetPath(), fileDialogName,
filter,
126 if( dlg.ShowModal() == wxID_CANCEL )
129 path = dlg.GetPath();
131 fn = wxFileName(
path );
133 if( fn.GetExt().Lower() ==
"zip" )
138 else if( fn.GetExt().Lower() ==
"tgz" )
143 else if(
path.EndsWith(
"/" ) ||
path.EndsWith(
"\\" ) )
151 msg.Printf(
_(
"The selected output file name is not a supported archive format." ) );
169 wxFileName fileName( fn );
171 auto compressionMode =
174 int sepIdx = std::max( fn.Find(
'/',
true ), fn.Find(
'\\',
true ) );
175 int dotIdx = fn.Find(
'.',
true );
177 if( fileName.IsDir() )
178 fn = fn.Mid( 0, sepIdx );
179 else if( sepIdx < dotIdx )
180 fn = fn.Mid( 0, dotIdx );
182 switch( compressionMode )
204 msg.Printf(
_(
"Output file name cannot be empty." ) );
212 wxFileName fileName( fn );
213 bool isDirectory = fileName.IsDir();
214 wxString extension = fileName.GetExt();
219 && extension !=
"tgz" ) )
223 _(
"The output file name conflicts with the selected compression format." ) );
299 if( outputPath.IsEmpty() )
300 outputPath = wxFileName( aJob.
m_filename ).GetPath();
302 wxFileName outputFn( outputPath );
307 if( outputFn.GetPath().IsEmpty() && outputFn.HasName() )
308 outputFn.MakeAbsolute();
315 msg.Printf(
_(
"Cannot create output directory '%s'." ), outputFn.GetFullPath() );
322 if( outputFn.IsDir() && !outputFn.IsDirWritable() )
324 msg.Printf(
_(
"Insufficient permissions to folder '%s'." ), outputFn.GetPath() );
326 else if( !outputFn.FileExists() && !outputFn.IsDirWritable() )
328 msg.Printf(
_(
"Insufficient permissions to save file '%s'." ), outputFn.GetFullPath() );
330 else if( outputFn.FileExists() && !outputFn.IsFileWritable() )
332 msg.Printf(
_(
"Insufficient permissions to save file '%s'." ), outputFn.GetFullPath() );
343 wxFileName tempFile( outputFn.GetFullPath() );
347 if( outputFn.Exists() )
351 msg = wxString::Format(
_(
"Output files '%s' already exists. "
352 "Do you want to overwrite it?" ),
353 outputFn.GetFullPath() );
355 KIDIALOG errorDlg( aParentFrame, msg,
_(
"Confirmation" ),
356 wxOK | wxCANCEL | wxICON_WARNING );
357 errorDlg.SetOKLabel(
_(
"Overwrite" ) );
362 if( !wxRemoveFile( outputFn.GetFullPath() ) )
364 msg.Printf(
_(
"Cannot remove existing output file '%s'." ),
365 outputFn.GetFullPath() );
372 msg = wxString::Format(
_(
"Output file '%s' already exists." ),
373 outputFn.GetFullPath() );
382 tempFile.AssignDir( wxFileName::GetTempDir() );
383 tempFile.AppendDir(
"kicad" );
384 tempFile.AppendDir(
"odb" );
386 if( !wxFileName::Mkdir( tempFile.GetFullPath(), wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
388 msg.Printf(
_(
"Cannot create temporary output directory." ) );
399 wxDir testDir( tempFile.GetFullPath() );
401 if( testDir.IsOpened() && ( testDir.HasFiles() || testDir.HasSubDirs() ) )
405 msg = wxString::Format(
_(
"Output directory '%s' already exists and is not empty. "
406 "Do you want to overwrite it?" ),
407 tempFile.GetFullPath() );
409 KIDIALOG errorDlg( aParentFrame, msg,
_(
"Confirmation" ),
410 wxOK | wxCANCEL | wxICON_WARNING );
411 errorDlg.SetOKLabel(
_(
"Overwrite" ) );
416 if( !tempFile.Rmdir( wxPATH_RMDIR_RECURSIVE ) )
418 msg.Printf(
_(
"Cannot remove existing output directory '%s'." ),
419 tempFile.GetFullPath() );
426 msg = wxString::Format(
_(
"Output directory '%s' already exists." ),
427 tempFile.GetFullPath() );
439 std::map<std::string, UTF8> props;
442 props[
"sigfig"] = wxString::Format(
"%d", aJob.
m_precision );
444 auto saveFile = [&]() ->
bool
449 pi->SetReporter( aReporter );
450 pi->SetProgressReporter( aProgressReporter );
451 pi->SaveBoard( tempFile.GetFullPath(), aBoard, &props );
458 msg = wxString::Format(
_(
"Error generating ODBPP files '%s'.\n%s" ),
459 tempFile.GetFullPath(), ioe.
What() );
464 wxFileName::Rmdir( tempFile.GetFullPath() );
470 auto ret =
tp.submit( saveFile );
472 std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
474 while( status != std::future_status::ready )
476 if( aProgressReporter )
479 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
487 catch(
const std::exception& e )
491 aReporter->
Report( wxString::Format(
"Exception in ODB++ generation: %s", e.what() ),
500 if( aProgressReporter )
501 aProgressReporter->
AdvancePhase(
_(
"Compressing output" ) );
503 wxFFileOutputStream fnout( outputFn.GetFullPath() );
504 wxZipOutputStream zipStream( fnout );
506 std::function<void(
const wxString&,
const wxString& )> addDirToZip =
507 [&](
const wxString& dirPath,
const wxString& parentPath )
509 wxDir dir( dirPath );
512 bool cont = dir.GetFirst( &fileName, wxEmptyString, wxDIR_DEFAULT );
516 wxFileName fileInZip( dirPath, fileName );
517 wxString relativePath =
520 : parentPath + wxString( wxFileName::GetPathSeparator() )
523 if( wxFileName::DirExists( fileInZip.GetFullPath() ) )
525 zipStream.PutNextDirEntry( relativePath );
526 addDirToZip( fileInZip.GetFullPath(), relativePath );
530 wxFFileInputStream fileStream( fileInZip.GetFullPath() );
531 zipStream.PutNextEntry( relativePath );
532 fileStream.Read( zipStream );
534 cont = dir.GetNext( &fileName );
538 addDirToZip( tempFile.GetFullPath(), wxEmptyString );
543 tempFile.Rmdir( wxPATH_RMDIR_RECURSIVE );
547 wxFFileOutputStream fnout( outputFn.GetFullPath() );
548 wxZlibOutputStream zlibStream( fnout, -1, wxZLIB_GZIP );
549 wxTarOutputStream tarStream( zlibStream );
551 std::function<void(
const wxString&,
const wxString& )> addDirToTar =
552 [&](
const wxString& dirPath,
const wxString& parentPath )
554 wxDir dir( dirPath );
557 bool cont = dir.GetFirst( &fileName, wxEmptyString, wxDIR_DEFAULT );
560 wxFileName fileInTar( dirPath, fileName );
561 wxString relativePath =
564 : parentPath + wxString( wxFileName::GetPathSeparator() )
567 if( wxFileName::DirExists( fileInTar.GetFullPath() ) )
569 tarStream.PutNextDirEntry( relativePath );
570 addDirToTar( fileInTar.GetFullPath(), relativePath );
574 wxFFileInputStream fileStream( fileInTar.GetFullPath() );
575 tarStream.PutNextEntry( relativePath, wxDateTime::Now(),
576 fileStream.GetLength() );
577 fileStream.Read( tarStream );
579 cont = dir.GetNext( &fileName );
584 tempFile.GetFullPath(),
585 tempFile.GetPath( wxPATH_NO_SEPARATOR ).AfterLast( tempFile.GetPathSeparator() ) );
591 tempFile.Rmdir( wxPATH_RMDIR_RECURSIVE );
594 if( aProgressReporter )
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
Information pertinent to a Pcbnew printed circuit board.
const wxString & GetFileName() 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)
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.
DIALOG_EXPORT_ODBPP m_ExportODBPP
The main frame for Pcbnew.
void SetLastPath(LAST_PATH_TYPE aType, const wxString &aLastPath)
Set the path of the last file successfully read.
wxString GetLastPath(LAST_PATH_TYPE aType)
Get the last path for a particular type.
static PCB_IO * PluginFind(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
virtual SETTINGS_MANAGER & GetSettingsManager() const
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)=0
Report a string with a given severity.
T * GetAppSettings(const wxString &aFilename)
Return a handle to the a given settings by type.
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 wxString s_oemColumn
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.
PGM_BASE & Pgm()
The global program "get" accessor.
#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.