7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-07 17:15:31 +00:00

ODB++:Support choice compress format and specify output filename.

This commit is contained in:
Eric Zhuang 2024-12-29 17:01:27 +00:00
parent 659228de2d
commit b3259a1c42
12 changed files with 393 additions and 157 deletions

View File

@ -32,6 +32,7 @@ NLOHMANN_JSON_SERIALIZE_ENUM( JOB_EXPORT_PCB_ODB::ODB_COMPRESSION,
{
{ JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::NONE, "none" },
{ JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::ZIP, "zip" },
{ JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::TGZ, "tgz" },
} )

View File

@ -42,6 +42,7 @@ public:
{
NONE,
ZIP,
TGZ,
};
wxString m_filename;

View File

@ -49,7 +49,7 @@ CLI::PCB_EXPORT_ODB_COMMAND::PCB_EXPORT_ODB_COMMAND() :
m_argParser.add_argument( ARG_COMPRESS )
.default_value( std::string( "zip" ) )
.help( std::string( "Compression mode" ) )
.choices( "none", "zip" );
.choices( "none", "zip", "tgz" );
m_argParser.add_argument( ARG_UNITS )
.default_value( std::string( "mm" ) )
@ -87,11 +87,13 @@ int CLI::PCB_EXPORT_ODB_COMMAND::doPerform( KIWAY& aKiway )
else if( units == "in" )
job->m_units = JOB_EXPORT_PCB_ODB::ODB_UNITS::INCHES;
wxString compression = From_UTF8( m_argParser.get<std::string>( ARG_COMPRESS ).c_str() );
wxString compression = From_UTF8( m_argParser.get<std::string>( ARG_COMPRESS ).c_str() ).Lower();
if( compression == "zip" )
job->m_compressionMode = JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::ZIP;
else
else if( compression == "tgz" )
job->m_compressionMode = JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::TGZ;
else if( compression == "none" )
job->m_compressionMode = JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::NONE;
LOCALE_IO dummy;

View File

@ -42,16 +42,16 @@
#include <jobs/job_export_pcb_odb.h>
#include <pcb_io/pcb_io_mgr.h>
#include <wx/dir.h>
#include <wx/dirdlg.h>
#include <wx/filedlg.h>
#include <wx/wfstream.h>
#include <wx/zipstrm.h>
#include <wx/tarstrm.h>
#include <wx/zstream.h>
static wxString s_oemColumn = wxEmptyString;
DIALOG_EXPORT_ODBPP::DIALOG_EXPORT_ODBPP( PCB_EDIT_FRAME* aParent ) :
DIALOG_EXPORT_ODBPP_BASE( aParent ),
m_parent( aParent ),
m_job( nullptr )
DIALOG_EXPORT_ODBPP_BASE( aParent ), m_parent( aParent ), m_job( nullptr )
{
m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
@ -62,7 +62,10 @@ DIALOG_EXPORT_ODBPP::DIALOG_EXPORT_ODBPP( PCB_EDIT_FRAME* aParent ) :
if( path.IsEmpty() )
{
wxFileName brdFile( m_parent->GetBoard()->GetFileName() );
path = brdFile.GetPath();
wxFileName odbFile( brdFile.GetPath(),
wxString::Format( wxS( "%s-odb" ), brdFile.GetName() ),
FILEEXT::ArchiveFileExtension );
path = odbFile.GetFullPath();
}
m_outputFileName->SetValue( path );
@ -78,9 +81,7 @@ DIALOG_EXPORT_ODBPP::DIALOG_EXPORT_ODBPP( PCB_EDIT_FRAME* aParent ) :
DIALOG_EXPORT_ODBPP::DIALOG_EXPORT_ODBPP( JOB_EXPORT_PCB_ODB* aJob, PCB_EDIT_FRAME* aEditFrame,
wxWindow* aParent ) :
DIALOG_EXPORT_ODBPP_BASE( aParent ),
m_parent( aEditFrame ),
m_job( aJob )
DIALOG_EXPORT_ODBPP_BASE( aParent ), m_parent( aEditFrame ), m_job( aJob )
{
m_browseButton->Hide();
@ -99,23 +100,128 @@ DIALOG_EXPORT_ODBPP::DIALOG_EXPORT_ODBPP( JOB_EXPORT_PCB_ODB* aJob, PCB_EDIT_FRA
void DIALOG_EXPORT_ODBPP::onBrowseClicked( wxCommandEvent& event )
{
// clang-format off
wxString filter = _( "zip files" )
+ AddFileExtListToFilter( { FILEEXT::ArchiveFileExtension } ) + "|"
+ _( "tgz files" )
+ AddFileExtListToFilter( { "tgz" } );
// clang-format on
// Build the absolute path of current output directory to preselect it in the file browser.
wxString path = ExpandEnvVarSubstitutions( m_outputFileName->GetValue(), &Prj() );
wxFileName fn( Prj().AbsolutePath( path ) );
wxDirDialog dlg( this, _( "Export ODB++ File" ), fn.GetPath() );
wxFileName brdFile( m_parent->GetBoard()->GetFileName() );
wxString fileDialogName( wxString::Format( wxS( "%s-odb" ), brdFile.GetName() ) );
wxFileDialog dlg( this, _( "Export ODB++ File" ), fn.GetPath(), fileDialogName, filter,
wxFD_SAVE );
if( dlg.ShowModal() == wxID_CANCEL )
return;
m_outputFileName->SetValue( dlg.GetPath() );
path = dlg.GetPath();
fn = wxFileName( path );
if( fn.GetExt().Lower() == "zip" )
{
m_choiceCompress->SetSelection(
static_cast<int>( JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::ZIP ) );
}
else if( fn.GetExt().Lower() == "tgz" )
{
m_choiceCompress->SetSelection(
static_cast<int>( JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::TGZ ) );
}
else if( path.EndsWith( "/" ) || path.EndsWith( "\\" ) )
{
m_choiceCompress->SetSelection(
static_cast<int>( JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::NONE ) );
}
else
{
wxString msg;
msg.Printf( _( "The selected output file name is not a supported archive format." ) );
DisplayErrorMessage( this, msg );
return;
}
m_outputFileName->SetValue( path );
}
void DIALOG_EXPORT_ODBPP::onFormatChoice( wxCommandEvent& event )
{
OnFmtChoiceOptionChanged();
}
void DIALOG_EXPORT_ODBPP::OnFmtChoiceOptionChanged()
{
wxString fn = m_outputFileName->GetValue();
wxFileName fileName( fn );
auto compressionMode =
static_cast<JOB_EXPORT_PCB_ODB::ODB_COMPRESSION>( m_choiceCompress->GetSelection() );
int sepIdx = std::max( fn.Find( '/', true ), fn.Find( '\\', true ) );
int dotIdx = fn.Find( '.', true );
if( fileName.IsDir() )
fn = fn.Mid( 0, sepIdx );
else if( sepIdx < dotIdx )
fn = fn.Mid( 0, dotIdx );
switch( compressionMode )
{
case JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::ZIP:
fn = fn + '.' + FILEEXT::ArchiveFileExtension;
break;
case JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::TGZ: fn += ".tgz"; break;
case JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::NONE: fn = wxFileName( fn, "" ).GetFullPath(); break;
default: break;
};
m_outputFileName->SetValue( fn );
}
void DIALOG_EXPORT_ODBPP::onOKClick( wxCommandEvent& event )
{
if( !m_job )
{
wxString fn = m_outputFileName->GetValue();
if( fn.IsEmpty() )
{
wxString msg;
msg.Printf( _( "Output file name cannot be empty." ) );
DisplayErrorMessage( this, msg );
return;
}
auto compressionMode = static_cast<JOB_EXPORT_PCB_ODB::ODB_COMPRESSION>(
m_choiceCompress->GetSelection() );
wxFileName fileName( fn );
bool isDirectory = fileName.IsDir();
wxString extension = fileName.GetExt();
if( ( compressionMode == JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::NONE && !isDirectory )
|| ( compressionMode == JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::ZIP && extension != "zip" )
|| ( compressionMode == JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::TGZ
&& extension != "tgz" ) )
{
wxString msg;
msg.Printf(
_( "The output file name conflicts with the selected compression format." ) );
DisplayErrorMessage( this, msg );
return;
}
m_parent->SetLastPath( LAST_PATH_ODBPP, m_outputFileName->GetValue() );
}
event.Skip();
}
@ -130,13 +236,13 @@ bool DIALOG_EXPORT_ODBPP::Init()
{
m_choiceUnits->SetSelection( cfg->m_ExportODBPP.units );
m_precision->SetValue( cfg->m_ExportODBPP.precision );
m_cbCompress->SetValue( cfg->m_ExportODBPP.compress );
m_choiceCompress->SetSelection( cfg->m_ExportODBPP.compressFormat );
}
else
{
m_choiceUnits->SetSelection( static_cast<int>( m_job->m_units ) );
m_precision->SetValue( m_job->m_precision );
m_cbCompress->SetValue( m_job->m_compressionMode == JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::ZIP );
m_choiceCompress->SetSelection( static_cast<int>( m_job->m_compressionMode ) );
}
return true;
@ -152,17 +258,17 @@ bool DIALOG_EXPORT_ODBPP::TransferDataFromWindow()
cfg->m_ExportODBPP.units = m_choiceUnits->GetSelection();
cfg->m_ExportODBPP.precision = m_precision->GetValue();
cfg->m_ExportODBPP.compress = m_cbCompress->GetValue();
cfg->m_ExportODBPP.compressFormat = m_choiceCompress->GetSelection();
}
else
{
m_job->SetOutputPath( m_outputFileName->GetValue() );
m_job->m_precision = m_precision->GetValue();
m_job->m_units = static_cast<JOB_EXPORT_PCB_ODB::ODB_UNITS>( m_choiceUnits->GetSelection() );
m_job->m_compressionMode = m_cbCompress->GetValue()
? JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::ZIP
: JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::NONE;
m_job->m_units =
static_cast<JOB_EXPORT_PCB_ODB::ODB_UNITS>( m_choiceUnits->GetSelection() );
m_job->m_compressionMode = static_cast<JOB_EXPORT_PCB_ODB::ODB_COMPRESSION>(
m_choiceCompress->GetSelection() );
}
return true;
@ -170,9 +276,9 @@ bool DIALOG_EXPORT_ODBPP::TransferDataFromWindow()
void DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( const JOB_EXPORT_PCB_ODB& aJob, BOARD* aBoard,
PCB_EDIT_FRAME* aParentFrame,
PCB_EDIT_FRAME* aParentFrame,
PROGRESS_REPORTER* aProgressReporter,
REPORTER* aReporter )
REPORTER* aReporter )
{
wxCHECK( aBoard, /* void */ );
wxString outputPath = aJob.GetOutputPath();
@ -190,6 +296,20 @@ void DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( const JOB_EXPORT_PCB_ODB& aJob, BO
wxString msg;
if( !wxFileName::DirExists( pcbFileName.GetPath() ) )
{
// Make every directory provided when the provided path doesn't exist
if( !wxFileName::Mkdir( pcbFileName.GetPath(), wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
{
msg.Printf( _( "Cannot create output directory '%s'." ), pcbFileName.GetFullPath() );
if( aReporter )
aReporter->Report( msg, RPT_SEVERITY_ERROR );
return;
}
}
if( pcbFileName.IsDir() && !pcbFileName.IsDirWritable() )
{
msg.Printf( _( "Insufficient permissions to folder '%s'." ), pcbFileName.GetPath() );
@ -211,35 +331,17 @@ void DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( const JOB_EXPORT_PCB_ODB& aJob, BO
return;
}
if( !wxFileName::DirExists( pcbFileName.GetFullPath() ) )
{
// Make every directory provided when the provided path doesn't exist
if( !wxFileName::Mkdir( pcbFileName.GetFullPath(), wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
{
msg.Printf( _( "Cannot create output directory '%s'." ), pcbFileName.GetFullPath() );
if( aReporter )
aReporter->Report( msg, RPT_SEVERITY_ERROR );
return;
}
}
wxFileName zipFileName( pcbFileName.GetFullPath(),
wxString::Format( wxS( "%s-odb.zip" ),
aBoard->GetProject()->GetProjectName() ) );
wxFileName tempFile( pcbFileName.GetFullPath(), "" );
wxFileName tempFile( pcbFileName.GetFullPath() );
if( aJob.m_compressionMode != JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::NONE )
{
if( zipFileName.Exists() )
if( pcbFileName.Exists() )
{
if( aParentFrame )
{
msg = wxString::Format( _( "Output files '%s' already exists. "
"Do you want to overwrite it?" ),
zipFileName.GetFullPath() );
pcbFileName.GetFullPath() );
KIDIALOG errorDlg( aParentFrame, msg, _( "Confirmation" ),
wxOK | wxCANCEL | wxICON_WARNING );
@ -248,10 +350,10 @@ void DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( const JOB_EXPORT_PCB_ODB& aJob, BO
if( errorDlg.ShowModal() != wxID_OK )
return;
if( !wxRemoveFile( zipFileName.GetFullPath() ) )
if( !wxRemoveFile( pcbFileName.GetFullPath() ) )
{
msg.Printf( _( "Cannot remove existing output file '%s'." ),
zipFileName.GetFullPath() );
pcbFileName.GetFullPath() );
DisplayErrorMessage( aParentFrame, msg );
return;
}
@ -259,7 +361,7 @@ void DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( const JOB_EXPORT_PCB_ODB& aJob, BO
else
{
msg = wxString::Format( _( "Output file '%s' already exists." ),
zipFileName.GetFullPath() );
pcbFileName.GetFullPath() );
if( aReporter )
aReporter->Report( msg, RPT_SEVERITY_ERROR );
@ -284,10 +386,8 @@ void DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( const JOB_EXPORT_PCB_ODB& aJob, BO
}
else
{
// Plugin will create the 'odb' subdirectory for us, so test for it here
wxFileName odbDir( tempFile );
odbDir.AppendDir( "odb" );
wxDir testDir( odbDir.GetFullPath() );
// Test for the output directory of tempFile
wxDir testDir( tempFile.GetFullPath() );
if( testDir.IsOpened() && ( testDir.HasFiles() || testDir.HasSubDirs() ) )
{
@ -295,7 +395,7 @@ void DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( const JOB_EXPORT_PCB_ODB& aJob, BO
{
msg = wxString::Format( _( "Output directory '%s' already exists and is not empty. "
"Do you want to overwrite it?" ),
odbDir.GetFullPath() );
tempFile.GetFullPath() );
KIDIALOG errorDlg( aParentFrame, msg, _( "Confirmation" ),
wxOK | wxCANCEL | wxICON_WARNING );
@ -304,10 +404,10 @@ void DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( const JOB_EXPORT_PCB_ODB& aJob, BO
if( errorDlg.ShowModal() != wxID_OK )
return;
if( !odbDir.Rmdir( wxPATH_RMDIR_RECURSIVE ) )
if( !tempFile.Rmdir( wxPATH_RMDIR_RECURSIVE ) )
{
msg.Printf( _( "Cannot remove existing output directory '%s'." ),
odbDir.GetFullPath() );
tempFile.GetFullPath() );
DisplayErrorMessage( aParentFrame, msg );
return;
}
@ -315,7 +415,7 @@ void DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( const JOB_EXPORT_PCB_ODB& aJob, BO
else
{
msg = wxString::Format( _( "Output directory '%s' already exists." ),
odbDir.GetFullPath() );
tempFile.GetFullPath() );
if( aReporter )
aReporter->Report( msg, RPT_SEVERITY_ERROR );
@ -332,31 +432,30 @@ void DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( const JOB_EXPORT_PCB_ODB& aJob, BO
props["units"] = aJob.m_units == JOB_EXPORT_PCB_ODB::ODB_UNITS::MILLIMETERS ? "mm" : "inch";
props["sigfig"] = wxString::Format( "%d", aJob.m_precision );
auto saveFile =
[&]() -> bool
auto saveFile = [&]() -> bool
{
try
{
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( PCB_IO_MGR::ODBPP ) );
pi->SetReporter( aReporter );
pi->SetProgressReporter( aProgressReporter );
pi->SaveBoard( tempFile.GetFullPath(), aBoard, &props );
return true;
}
catch( const IO_ERROR& ioe )
{
if( aReporter )
{
try
{
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( PCB_IO_MGR::ODBPP ) );
pi->SetReporter( aReporter );
pi->SetProgressReporter( aProgressReporter );
pi->SaveBoard( tempFile.GetFullPath(), aBoard, &props );
return true;
}
catch( const IO_ERROR& ioe )
{
if( aReporter )
{
msg = wxString::Format( _( "Error generating ODBPP files '%s'.\n%s" ),
tempFile.GetFullPath(), ioe.What() );
aReporter->Report( msg, RPT_SEVERITY_ERROR );
}
msg = wxString::Format( _( "Error generating ODBPP files '%s'.\n%s" ),
tempFile.GetFullPath(), ioe.What() );
aReporter->Report( msg, RPT_SEVERITY_ERROR );
}
// In case we started a file but didn't fully write it, clean up
wxFileName::Rmdir( tempFile.GetFullPath() );
return false;
}
};
// In case we started a file but didn't fully write it, clean up
wxFileName::Rmdir( tempFile.GetFullPath() );
return false;
}
};
thread_pool& tp = GetKiCadThreadPool();
auto ret = tp.submit( saveFile );
@ -365,7 +464,7 @@ void DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( const JOB_EXPORT_PCB_ODB& aJob, BO
while( status != std::future_status::ready )
{
if( aProgressReporter)
if( aProgressReporter )
aProgressReporter->KeepRefreshing();
status = ret.wait_for( std::chrono::milliseconds( 250 ) );
@ -387,12 +486,12 @@ void DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( const JOB_EXPORT_PCB_ODB& aJob, BO
return;
}
if( aJob.m_compressionMode != JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::NONE )
if( aJob.m_compressionMode == JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::ZIP )
{
if( aProgressReporter )
aProgressReporter->AdvancePhase( _( "Compressing output" ) );
wxFFileOutputStream fnout( zipFileName.GetFullPath() );
wxFFileOutputStream fnout( pcbFileName.GetFullPath() );
wxZipOutputStream zipStream( fnout );
std::function<void( const wxString&, const wxString& )> addDirToZip =
@ -434,6 +533,54 @@ void DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( const JOB_EXPORT_PCB_ODB& aJob, BO
tempFile.Rmdir( wxPATH_RMDIR_RECURSIVE );
}
else if( aJob.m_compressionMode == JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::TGZ )
{
wxFFileOutputStream fnout( pcbFileName.GetFullPath() );
wxZlibOutputStream zlibStream( fnout, -1, wxZLIB_GZIP );
wxTarOutputStream tarStream( zlibStream );
std::function<void( const wxString&, const wxString& )> addDirToTar =
[&]( const wxString& dirPath, const wxString& parentPath )
{
wxDir dir( dirPath );
wxString fileName;
bool cont = dir.GetFirst( &fileName, wxEmptyString, wxDIR_DEFAULT );
while( cont )
{
wxFileName fileInTar( dirPath, fileName );
wxString relativePath =
parentPath.IsEmpty()
? fileName
: parentPath + wxString( wxFileName::GetPathSeparator() )
+ fileName;
if( wxFileName::DirExists( fileInTar.GetFullPath() ) )
{
tarStream.PutNextDirEntry( relativePath );
addDirToTar( fileInTar.GetFullPath(), relativePath );
}
else
{
wxFFileInputStream fileStream( fileInTar.GetFullPath() );
tarStream.PutNextEntry( relativePath, wxDateTime::Now(),
fileStream.GetLength() );
fileStream.Read( tarStream );
}
cont = dir.GetNext( &fileName );
}
};
addDirToTar(
tempFile.GetFullPath(),
tempFile.GetPath( wxPATH_NO_SEPARATOR ).AfterLast( tempFile.GetPathSeparator() ) );
tarStream.Close();
zlibStream.Close();
fnout.Close();
tempFile.Rmdir( wxPATH_RMDIR_RECURSIVE );
}
if( aProgressReporter )
aProgressReporter->SetCurrentProgress( 1 );

View File

@ -47,10 +47,10 @@
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="minimum_size">380,265</property>
<property name="name">DIALOG_EXPORT_ODBPP_BASE</property>
<property name="pos"></property>
<property name="size">380,300</property>
<property name="size">-1,-1</property>
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
<property name="title">Export ODB++</property>
@ -58,15 +58,15 @@
<property name="two_step_creation">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="window_style">wxBORDER_DEFAULT</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">bMainSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">15</property>
<property name="flag">wxBOTTOM|wxEXPAND|wxTOP</property>
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
@ -75,7 +75,7 @@
<property name="permission">protected</property>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT</property>
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="false">
<property name="BottomDockable">1</property>
@ -106,7 +106,7 @@
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Folder:</property>
<property name="label">Output File:</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
@ -137,7 +137,7 @@
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxTextCtrl" expanded="false">
<property name="BottomDockable">1</property>
@ -278,7 +278,7 @@
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="border">10</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="true">
@ -286,11 +286,11 @@
<property name="name">bSizer3</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<object class="sizeritem" expanded="false">
<property name="border">10</property>
<property name="flag">wxEXPAND|wxLEFT|wxRIGHT|wxTOP</property>
<property name="flag">wxEXPAND|wxALL</property>
<property name="proportion">1</property>
<object class="wxStaticBoxSizer" expanded="true">
<object class="wxStaticBoxSizer" expanded="false">
<property name="id">wxID_ANY</property>
<property name="label">File Format</property>
<property name="minimum_size"></property>
@ -300,12 +300,12 @@
<property name="permission">none</property>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxALL</property>
<property name="flag">wxEXPAND|wxLEFT</property>
<property name="proportion">3</property>
<object class="wxFlexGridSizer" expanded="false">
<property name="cols">2</property>
<property name="flexible_direction">wxBOTH</property>
<property name="growablecols">1</property>
<property name="growablecols">0,1</property>
<property name="growablerows"></property>
<property name="hgap">0</property>
<property name="minimum_size"></property>
@ -316,7 +316,7 @@
<property name="vgap">0</property>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property>
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="false">
<property name="BottomDockable">1</property>
@ -378,7 +378,7 @@
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxALIGN_RIGHT|wxALL</property>
<property name="flag">wxEXPAND|wxALL</property>
<property name="proportion">0</property>
<object class="wxChoice" expanded="false">
<property name="BottomDockable">1</property>
@ -415,7 +415,7 @@
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="minimum_size">-1,-1</property>
<property name="moveable">1</property>
<property name="name">m_choiceUnits</property>
<property name="pane_border">1</property>
@ -427,7 +427,7 @@
<property name="resize">Resizable</property>
<property name="selection">0</property>
<property name="show">1</property>
<property name="size">130,30</property>
<property name="size">-1,-1</property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
@ -443,7 +443,7 @@
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property>
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="false">
<property name="BottomDockable">1</property>
@ -505,7 +505,7 @@
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxALIGN_RIGHT|wxALL</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxSpinCtrl" expanded="false">
<property name="BottomDockable">1</property>
@ -536,7 +536,7 @@
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="initial">7</property>
<property name="initial">6</property>
<property name="max">16</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
@ -555,7 +555,7 @@
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size">130,30</property>
<property name="size">-1,-1</property>
<property name="style">wxSP_ARROW_KEYS</property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
@ -568,9 +568,9 @@
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND</property>
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="false">
<object class="wxStaticText" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -584,7 +584,6 @@
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
@ -600,7 +599,8 @@
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Compress output</property>
<property name="label">Compression Format:</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
@ -608,7 +608,7 @@
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_cbCompress</property>
<property name="name">m_lblCompress</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
@ -619,9 +619,71 @@
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Select the format to compress the output ODB++ files</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxChoice" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="choices">&quot;None&quot; &quot;ZIP&quot; &quot;TGZ&quot;</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">-1,-1</property>
<property name="moveable">1</property>
<property name="name">m_choiceCompress</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="selection">1</property>
<property name="show">1</property>
<property name="size">-1,-1</property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Compress output into &apos;zip&apos; file</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
@ -629,7 +691,7 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnCheckBox">onCompressCheck</event>
<event name="OnChoice">onFormatChoice</event>
</object>
</object>
</object>
@ -638,16 +700,6 @@
</object>
</object>
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="spacer" expanded="false">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>

View File

@ -45,8 +45,7 @@ public:
int GetPrecision() const { return m_precision->GetValue(); }
bool GetCompress() const { return m_cbCompress->GetValue(); }
int GetCompressFormat() const { return m_choiceCompress->GetSelection(); }
// Runs the actual generation process; shared between GUI and CLI system
static void GenerateODBPPFiles( const JOB_EXPORT_PCB_ODB& aJob, BOARD* aBoard,
@ -56,8 +55,12 @@ public:
private:
void onBrowseClicked( wxCommandEvent& event ) override;
void onFormatChoice( wxCommandEvent& event ) override;
void onOKClick( wxCommandEvent& event ) override;
void OnFmtChoiceOptionChanged();
bool Init();
bool TransferDataFromWindow() override;

View File

@ -13,28 +13,28 @@
DIALOG_EXPORT_ODBPP_BASE::DIALOG_EXPORT_ODBPP_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
this->SetSizeHints( wxSize( 380,265 ), wxDefaultSize );
wxBoxSizer* bMainSizer;
bMainSizer = new wxBoxSizer( wxVERTICAL );
bSizerTop = new wxBoxSizer( wxHORIZONTAL );
m_lblBrdFile = new wxStaticText( this, wxID_ANY, _("Folder:"), wxDefaultPosition, wxDefaultSize, 0 );
m_lblBrdFile = new wxStaticText( this, wxID_ANY, _("Output File:"), wxDefaultPosition, wxDefaultSize, 0 );
m_lblBrdFile->Wrap( -1 );
bSizerTop->Add( m_lblBrdFile, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
bSizerTop->Add( m_lblBrdFile, 0, wxALIGN_CENTER_VERTICAL, 5 );
m_outputFileName = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_outputFileName->SetToolTip( _("Enter a filename if you do not want to use default file names\nCan be used only when printing the current sheet") );
m_outputFileName->SetMinSize( wxSize( 350,-1 ) );
bSizerTop->Add( m_outputFileName, 1, wxALIGN_CENTER_VERTICAL, 5 );
bSizerTop->Add( m_outputFileName, 1, wxALL|wxEXPAND, 5 );
m_browseButton = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
bSizerTop->Add( m_browseButton, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
bMainSizer->Add( bSizerTop, 0, wxBOTTOM|wxEXPAND|wxTOP, 15 );
bMainSizer->Add( bSizerTop, 0, wxALL|wxEXPAND, 5 );
wxBoxSizer* bSizer3;
bSizer3 = new wxBoxSizer( wxHORIZONTAL );
@ -44,47 +44,52 @@ DIALOG_EXPORT_ODBPP_BASE::DIALOG_EXPORT_ODBPP_BASE( wxWindow* parent, wxWindowID
wxFlexGridSizer* fgSizer;
fgSizer = new wxFlexGridSizer( 0, 2, 0, 0 );
fgSizer->AddGrowableCol( 0 );
fgSizer->AddGrowableCol( 1 );
fgSizer->SetFlexibleDirection( wxBOTH );
fgSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_lblUnits = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("Units:"), wxDefaultPosition, wxDefaultSize, 0 );
m_lblUnits->Wrap( -1 );
fgSizer->Add( m_lblUnits, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
fgSizer->Add( m_lblUnits, 0, wxALIGN_CENTER_VERTICAL, 5 );
wxString m_choiceUnitsChoices[] = { _("Millimeters"), _("Inches") };
int m_choiceUnitsNChoices = sizeof( m_choiceUnitsChoices ) / sizeof( wxString );
m_choiceUnits = new wxChoice( sbSizer1->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxSize( 130,30 ), m_choiceUnitsNChoices, m_choiceUnitsChoices, 0 );
m_choiceUnits = new wxChoice( sbSizer1->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), m_choiceUnitsNChoices, m_choiceUnitsChoices, 0 );
m_choiceUnits->SetSelection( 0 );
fgSizer->Add( m_choiceUnits, 0, wxALIGN_RIGHT|wxALL, 5 );
fgSizer->Add( m_choiceUnits, 0, wxEXPAND|wxALL, 5 );
m_lblPrecision = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("Precision:"), wxDefaultPosition, wxDefaultSize, 0 );
m_lblPrecision->Wrap( -1 );
m_lblPrecision->SetToolTip( _("The number of values following the decimal separator") );
fgSizer->Add( m_lblPrecision, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
fgSizer->Add( m_lblPrecision, 0, wxALIGN_CENTER_VERTICAL, 5 );
m_precision = new wxSpinCtrl( sbSizer1->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 130,30 ), wxSP_ARROW_KEYS, 2, 16, 7 );
m_precision = new wxSpinCtrl( sbSizer1->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxSP_ARROW_KEYS, 2, 16, 6 );
m_precision->SetToolTip( _("The number of values following the decimal separator") );
fgSizer->Add( m_precision, 0, wxALIGN_RIGHT|wxALL, 5 );
fgSizer->Add( m_precision, 0, wxALL|wxEXPAND, 5 );
m_cbCompress = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Compress output"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbCompress->SetToolTip( _("Compress output into 'zip' file") );
m_lblCompress = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("Compression Format:"), wxDefaultPosition, wxDefaultSize, 0 );
m_lblCompress->Wrap( -1 );
m_lblCompress->SetToolTip( _("Select the format to compress the output ODB++ files") );
fgSizer->Add( m_cbCompress, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
fgSizer->Add( m_lblCompress, 0, wxALIGN_CENTER_VERTICAL, 5 );
wxString m_choiceCompressChoices[] = { _("None"), _("ZIP"), _("TGZ") };
int m_choiceCompressNChoices = sizeof( m_choiceCompressChoices ) / sizeof( wxString );
m_choiceCompress = new wxChoice( sbSizer1->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), m_choiceCompressNChoices, m_choiceCompressChoices, 0 );
m_choiceCompress->SetSelection( 1 );
fgSizer->Add( m_choiceCompress, 0, wxALL|wxEXPAND, 5 );
sbSizer1->Add( fgSizer, 3, wxEXPAND|wxALL, 5 );
sbSizer1->Add( fgSizer, 3, wxEXPAND|wxLEFT, 5 );
bSizer3->Add( sbSizer1, 1, wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 10 );
bSizer3->Add( sbSizer1, 1, wxEXPAND|wxALL, 10 );
bMainSizer->Add( bSizer3, 0, wxEXPAND, 5 );
bMainSizer->Add( 0, 0, 1, wxEXPAND, 5 );
bMainSizer->Add( bSizer3, 0, wxEXPAND, 10 );
m_stdButtons = new wxStdDialogButtonSizer();
m_stdButtonsOK = new wxButton( this, wxID_OK );
@ -98,12 +103,13 @@ DIALOG_EXPORT_ODBPP_BASE::DIALOG_EXPORT_ODBPP_BASE( wxWindow* parent, wxWindowID
this->SetSizer( bMainSizer );
this->Layout();
bMainSizer->Fit( this );
this->Centre( wxBOTH );
// Connect Events
m_browseButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onBrowseClicked ), NULL, this );
m_cbCompress->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onCompressCheck ), NULL, this );
m_choiceCompress->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onFormatChoice ), NULL, this );
m_stdButtonsOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onOKClick ), NULL, this );
}
@ -111,7 +117,7 @@ DIALOG_EXPORT_ODBPP_BASE::~DIALOG_EXPORT_ODBPP_BASE()
{
// Disconnect Events
m_browseButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onBrowseClicked ), NULL, this );
m_cbCompress->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onCompressCheck ), NULL, this );
m_choiceCompress->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onFormatChoice ), NULL, this );
m_stdButtonsOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onOKClick ), NULL, this );
}

View File

@ -28,7 +28,6 @@ class STD_BITMAP_BUTTON;
#include <wx/sizer.h>
#include <wx/choice.h>
#include <wx/spinctrl.h>
#include <wx/checkbox.h>
#include <wx/statbox.h>
#include <wx/dialog.h>
@ -50,20 +49,21 @@ class DIALOG_EXPORT_ODBPP_BASE : public DIALOG_SHIM
wxChoice* m_choiceUnits;
wxStaticText* m_lblPrecision;
wxSpinCtrl* m_precision;
wxCheckBox* m_cbCompress;
wxStaticText* m_lblCompress;
wxChoice* m_choiceCompress;
wxStdDialogButtonSizer* m_stdButtons;
wxButton* m_stdButtonsOK;
wxButton* m_stdButtonsCancel;
// Virtual event handlers, override them in your derived class
virtual void onBrowseClicked( wxCommandEvent& event ) { event.Skip(); }
virtual void onCompressCheck( wxCommandEvent& event ) { event.Skip(); }
virtual void onFormatChoice( wxCommandEvent& event ) { event.Skip(); }
virtual void onOKClick( wxCommandEvent& event ) { event.Skip(); }
public:
DIALOG_EXPORT_ODBPP_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Export ODB++"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 380,300 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
DIALOG_EXPORT_ODBPP_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Export ODB++"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxBORDER_DEFAULT );
~DIALOG_EXPORT_ODBPP_BASE();

View File

@ -1420,8 +1420,8 @@ void PCB_EDIT_FRAME::GenODBPPFiles( wxCommandEvent& event )
job.SetOutputPath( dlg.GetOutputPath() );
job.m_filename = GetBoard()->GetFileName();
job.m_compressionMode = dlg.GetCompress() ? JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::ZIP
: JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::NONE;
job.m_compressionMode = static_cast<JOB_EXPORT_PCB_ODB::ODB_COMPRESSION>( dlg.GetCompressFormat() );
job.m_precision = dlg.GetPrecision();
job.m_units = dlg.GetUnitsString() == "mm" ? JOB_EXPORT_PCB_ODB::ODB_UNITS::MILLIMETERS
: JOB_EXPORT_PCB_ODB::ODB_UNITS::INCHES;

View File

@ -90,7 +90,7 @@ bool PCB_IO_ODBPP::ExportODB( const wxString& aFileName )
try
{
std::shared_ptr<ODB_TREE_WRITER> writer =
std::make_shared<ODB_TREE_WRITER>( aFileName, "odb" );
std::make_shared<ODB_TREE_WRITER>( aFileName );
writer->SetRootPath( writer->GetCurrentPath() );
if( m_progressReporter )

View File

@ -1842,15 +1842,39 @@ int PCBNEW_JOBS_HANDLER::JobExportOdb( JOB* aJob )
if( !brd )
return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
if( job->OutputPathFullSpecified() )
{
wxFileName fn = brd->GetFileName();
fn.SetName( fn.GetName() );
fn.SetExt( "zip" );
wxFileName fn( brd->GetFileName() );
wxString path = job->GetOutputPath();
job->SetOutputPath( fn.GetName() );
if( path.IsEmpty() )
{
wxFileName outputfn( fn.GetPath(), wxString::Format( wxS( "%s-odb" ), fn.GetName() ) );
path = outputfn.GetFullPath();
}
wxFileName fileName( path );
int sepIdx = std::max( path.Find( '/', true ), path.Find( '\\', true ) );
int dotIdx = path.Find( '.', true );
if( fileName.IsDir() && path.EndsWith( wxFileName::GetPathSeparator() ) )
path = path.Mid( 0, sepIdx );
else if( sepIdx < dotIdx )
path = path.Mid( 0, dotIdx );
switch( job->m_compressionMode )
{
case JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::ZIP:
path = path + '.' + FILEEXT::ArchiveFileExtension;
break;
case JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::TGZ: path += ".tgz"; break;
case JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::NONE:
path = wxFileName( path, "" ).GetFullPath();
break;
default: break;
};
job->SetOutputPath( path );
DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( *job, brd, nullptr, m_progressReporter, m_reporter );
return CLI::EXIT_CODES::SUCCESS;

View File

@ -206,7 +206,7 @@ public:
{
int precision;
int units;
bool compress;
int compressFormat;
};
struct DIALOG_EXPORT_SVG