diff --git a/eeschema/dialogs/dialog_symbol_fields_table.cpp b/eeschema/dialogs/dialog_symbol_fields_table.cpp index 71700169e9..7387fedf1f 100644 --- a/eeschema/dialogs/dialog_symbol_fields_table.cpp +++ b/eeschema/dialogs/dialog_symbol_fields_table.cpp @@ -23,6 +23,7 @@ */ +#include #include #include #include @@ -1030,6 +1031,46 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnPreviewRefresh( wxCommandEvent& event ) } +void DIALOG_SYMBOL_FIELDS_TABLE::OnOutputFileBrowseClicked( wxCommandEvent& event ) +{ + // Build the absolute path of current output directory to preselect it in the file browser. + wxString path = ExpandEnvVarSubstitutions( m_outputFileName->GetValue(), &Prj() ); + path = Prj().AbsolutePath( path ); + + + // Calculate the export filename + wxFileName fn( Prj().AbsolutePath( m_parent->Schematic().GetFileName() ) ); + fn.SetExt( CsvFileExtension ); + + wxFileDialog saveDlg( this, _( "Selected Output Filename" ), path, fn.GetFullName(), + CsvFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); + + if( saveDlg.ShowModal() == wxID_CANCEL ) + return; + + + wxFileName file = wxFileName( saveDlg.GetPath() ); + wxString defaultPath = fn.GetPathWithSep(); + wxString msg; + msg.Printf( _( "Do you want to use a path relative to\n'%s'?" ), defaultPath ); + + wxMessageDialog dialog( this, msg, _( "BOM Output File" ), + wxYES_NO | wxICON_QUESTION | wxYES_DEFAULT ); + + if( dialog.ShowModal() == wxID_YES ) + { + if( !file.MakeRelativeTo( defaultPath ) ) + { + wxMessageBox( _( "Cannot make path relative (target volume different from schematic " + "file volume)!" ), + _( "BOM Output File" ), wxOK | wxICON_ERROR ); + } + } + + m_outputFileName->SetValue( file.GetFullPath() ); +} + + void DIALOG_SYMBOL_FIELDS_TABLE::OnExport( wxCommandEvent& aEvent ) { if( m_dataModel->IsEdited() ) @@ -1039,21 +1080,45 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnExport( wxCommandEvent& aEvent ) == wxID_CANCEL ) return; + // Create output directory if it does not exist (also transform it in absolute form). + // Bail if it fails. - // Calculate the netlist filename - wxFileName fn = m_parent->Schematic().GetFileName(); - fn.SetExt( CsvFileExtension ); + std::function textResolver = + [&]( wxString* token ) -> bool + { + // Handles m_board->GetTitleBlock() *and* m_board->GetProject() + return m_parent->Schematic().ResolveTextVar( token, 0 ); + }; - wxFileDialog saveDlg( this, _( "Save as CSV" ), wxPathOnly( Prj().GetProjectFullName() ), - fn.GetFullName(), CsvFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); + wxString path = m_outputFileName->GetValue(); + path = ExpandTextVars( path, &textResolver ); + path = ExpandEnvVarSubstitutions( path, nullptr ); - if( saveDlg.ShowModal() == wxID_CANCEL ) + wxFileName outputFile = wxFileName::FileName( path ); + + auto displayErr = [&]() + { + wxString msg; + msg.Printf( _( "Could not write BOM output to '%s'." ), + outputFile.GetPath() ); + DisplayError( this, msg ); + }; + + if( !EnsureFileDirectoryExists( &outputFile, + Prj().AbsolutePath( m_parent->Schematic().GetFileName() ), + &NULL_REPORTER::GetInstance() ) ) + { + displayErr(); return; + } - wxFFile out( saveDlg.GetPath(), "wb" ); + wxFFile out( outputFile.GetFullPath(), "wb" ); if( !out.IsOpened() ) + { + displayErr(); return; + } BOM_EXPORT_SETTINGS settings = ( BOM_EXPORT_SETTINGS ){ .FieldDelimiter = m_textFieldDelimiter->GetValue(), @@ -1063,7 +1128,15 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnExport( wxCommandEvent& aEvent ) .RemoveLineBreaks = m_checkRemoveLineBreaks->GetValue(), }; - out.Write( m_dataModel->Export( settings ) ); + if( !out.Write( m_dataModel->Export( settings ) ) ) + { + displayErr(); + return; + } + + wxString msg; + msg.Printf( _( "Wrote BOM output to '%s'" ), outputFile.GetFullPath() ); + DisplayInfoMessage( this, msg ); } diff --git a/eeschema/dialogs/dialog_symbol_fields_table.h b/eeschema/dialogs/dialog_symbol_fields_table.h index 3fe9768907..1732534be6 100644 --- a/eeschema/dialogs/dialog_symbol_fields_table.h +++ b/eeschema/dialogs/dialog_symbol_fields_table.h @@ -81,6 +81,7 @@ private: void OnFieldsCtrlSelectionChanged( wxDataViewEvent& event ) override; bool TryBefore( wxEvent& aEvent ) override; + void OnOutputFileBrowseClicked( wxCommandEvent& event ) override; void OnPreviewRefresh( wxCommandEvent& event ) override; std::vector GetUserBomPresets() const; diff --git a/eeschema/dialogs/dialog_symbol_fields_table_base.cpp b/eeschema/dialogs/dialog_symbol_fields_table_base.cpp index ca3c30065a..94962d4143 100644 --- a/eeschema/dialogs/dialog_symbol_fields_table_base.cpp +++ b/eeschema/dialogs/dialog_symbol_fields_table_base.cpp @@ -225,12 +225,12 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::DIALOG_SYMBOL_FIELDS_TABLE_BASE( wxWindow* pare wxBoxSizer* bOutputDirectory; bOutputDirectory = new wxBoxSizer( wxHORIZONTAL ); - m_labelOutputDirectory = new wxStaticText( m_panelExport, wxID_ANY, _("Output folder:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_labelOutputDirectory = new wxStaticText( m_panelExport, wxID_ANY, _("Output file:"), wxDefaultPosition, wxDefaultSize, 0 ); m_labelOutputDirectory->Wrap( -1 ); bOutputDirectory->Add( m_labelOutputDirectory, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - m_outputDirectoryName = new wxTextCtrl( m_panelExport, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - bOutputDirectory->Add( m_outputDirectoryName, 1, wxALL|wxEXPAND, 5 ); + m_outputFileName = new wxTextCtrl( m_panelExport, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bOutputDirectory->Add( m_outputFileName, 1, wxALL|wxEXPAND, 5 ); m_browseButton = new wxBitmapButton( m_panelExport, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); m_browseButton->SetMinSize( wxSize( 30,30 ) ); @@ -323,7 +323,7 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::DIALOG_SYMBOL_FIELDS_TABLE_BASE( wxWindow* pare m_grid->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnTableItemContextMenu ), NULL, this ); m_grid->Connect( wxEVT_GRID_COL_SIZE, wxGridSizeEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnTableColSize ), NULL, this ); m_grid->Connect( wxEVT_GRID_RANGE_SELECT, wxGridRangeSelectEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnTableRangeSelected ), NULL, this ); - m_browseButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnRegroupSymbols ), NULL, this ); + m_browseButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnOutputFileBrowseClicked ), NULL, this ); m_bRefreshPreview->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnPreviewRefresh ), NULL, this ); m_buttonExport->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnExport ), NULL, this ); m_buttonApply->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnSaveAndContinue ), NULL, this ); @@ -350,7 +350,7 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::~DIALOG_SYMBOL_FIELDS_TABLE_BASE() m_grid->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnTableItemContextMenu ), NULL, this ); m_grid->Disconnect( wxEVT_GRID_COL_SIZE, wxGridSizeEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnTableColSize ), NULL, this ); m_grid->Disconnect( wxEVT_GRID_RANGE_SELECT, wxGridRangeSelectEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnTableRangeSelected ), NULL, this ); - m_browseButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnRegroupSymbols ), NULL, this ); + m_browseButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnOutputFileBrowseClicked ), NULL, this ); m_bRefreshPreview->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnPreviewRefresh ), NULL, this ); m_buttonExport->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnExport ), NULL, this ); m_buttonApply->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnSaveAndContinue ), NULL, this ); diff --git a/eeschema/dialogs/dialog_symbol_fields_table_base.fbp b/eeschema/dialogs/dialog_symbol_fields_table_base.fbp index f6bfe035a1..c8aeef2fa8 100644 --- a/eeschema/dialogs/dialog_symbol_fields_table_base.fbp +++ b/eeschema/dialogs/dialog_symbol_fields_table_base.fbp @@ -2239,7 +2239,7 @@ 0 0 wxID_ANY - Output folder: + Output file: 0 0 @@ -2308,7 +2308,7 @@ 0 1 - m_outputDirectoryName + m_outputFileName 1 @@ -2403,7 +2403,7 @@ - OnRegroupSymbols + OnOutputFileBrowseClicked diff --git a/eeschema/dialogs/dialog_symbol_fields_table_base.h b/eeschema/dialogs/dialog_symbol_fields_table_base.h index d9bc14540b..624aba9da7 100644 --- a/eeschema/dialogs/dialog_symbol_fields_table_base.h +++ b/eeschema/dialogs/dialog_symbol_fields_table_base.h @@ -83,7 +83,7 @@ class DIALOG_SYMBOL_FIELDS_TABLE_BASE : public DIALOG_SHIM wxStaticText* m_labelRemoveLineBreaks; wxCheckBox* m_checkRemoveLineBreaks; wxStaticText* m_labelOutputDirectory; - wxTextCtrl* m_outputDirectoryName; + wxTextCtrl* m_outputFileName; wxBitmapButton* m_browseButton; wxStaticText* m_labelPreview; wxBitmapButton* m_bRefreshPreview; @@ -111,6 +111,7 @@ class DIALOG_SYMBOL_FIELDS_TABLE_BASE : public DIALOG_SHIM virtual void OnTableItemContextMenu( wxGridEvent& event ) { event.Skip(); } virtual void OnTableColSize( wxGridSizeEvent& event ) { event.Skip(); } virtual void OnTableRangeSelected( wxGridRangeSelectEvent& event ) { event.Skip(); } + virtual void OnOutputFileBrowseClicked( wxCommandEvent& event ) { event.Skip(); } virtual void OnPreviewRefresh( wxCommandEvent& event ) { event.Skip(); } virtual void OnExport( wxCommandEvent& event ) { event.Skip(); } virtual void OnSaveAndContinue( wxCommandEvent& event ) { event.Skip(); }