From 09cdca876c7c2cae7713768541d28bad1ab5318e Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Wed, 20 Aug 2025 08:27:38 -0700 Subject: [PATCH] Add embed option to standard file dialog for 3dmodels Fixes https://gitlab.com/kicad/code/kicad/-/issues/20025 --- common/widgets/grid_text_button_helpers.cpp | 34 +++++++++++++++---- include/widgets/grid_text_button_helpers.h | 17 ++++++---- .../dialogs/panel_fp_properties_3d_model.cpp | 18 +++++++++- 3 files changed, 55 insertions(+), 14 deletions(-) diff --git a/common/widgets/grid_text_button_helpers.cpp b/common/widgets/grid_text_button_helpers.cpp index ebf07eac06..159a390e73 100644 --- a/common/widgets/grid_text_button_helpers.cpp +++ b/common/widgets/grid_text_button_helpers.cpp @@ -443,7 +443,8 @@ public: TEXT_BUTTON_FILE_BROWSER( wxWindow* aParent, DIALOG_SHIM* aParentDlg, WX_GRID* aGrid, wxString* aCurrentDir, const wxString& aFileFilter = wxEmptyString, bool aNormalize = false, - const wxString& aNormalizeBasePath = wxEmptyString ) : + const wxString& aNormalizeBasePath = wxEmptyString, + std::function aEmbedCallback = nullptr ) : wxComboCtrl( aParent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 0, 0 ), wxTE_PROCESS_ENTER | wxBORDER_NONE ), m_dlg( aParentDlg ), @@ -451,7 +452,8 @@ public: m_currentDir( aCurrentDir ), m_normalize( aNormalize ), m_normalizeBasePath( aNormalizeBasePath ), - m_fileFilter( aFileFilter ) + m_fileFilter( aFileFilter ), + m_embedCallback( std::move( aEmbedCallback ) ) { SetButtonBitmaps( KiBitmapBundle( BITMAPS::small_folder ) ); @@ -463,7 +465,8 @@ public: wxString* aCurrentDir, std::function aFileFilterFn, bool aNormalize = false, - const wxString& aNormalizeBasePath = wxEmptyString ) : + const wxString& aNormalizeBasePath = wxEmptyString, + std::function aEmbedCallback = nullptr ) : wxComboCtrl( aParent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 0, 0 ), wxTE_PROCESS_ENTER | wxBORDER_NONE ), m_dlg( aParentDlg ), @@ -471,7 +474,8 @@ public: m_currentDir( aCurrentDir ), m_normalize( aNormalize ), m_normalizeBasePath( aNormalizeBasePath ), - m_fileFilterFn( std::move( aFileFilterFn ) ) + m_fileFilterFn( std::move( aFileFilterFn ) ), + m_embedCallback( std::move( aEmbedCallback ) ) { SetButtonBitmaps( KiBitmapBundle( BITMAPS::small_folder ) ); @@ -502,16 +506,30 @@ protected: if( !m_fileFilter.IsEmpty() ) { + FILEDLG_HOOK_EMBED_FILE customize( false ); wxFileDialog dlg( m_dlg, _( "Select a File" ), fn.GetPath(), fn.GetFullName(), m_fileFilter, wxFD_FILE_MUST_EXIST | wxFD_OPEN ); + if( m_embedCallback ) + dlg.SetCustomizeHook( customize ); + if( dlg.ShowModal() == wxID_OK ) { wxString filePath = dlg.GetPath(); wxString lastPath = dlg.GetDirectory(); wxString relPath = wxEmptyString; - if( m_normalize ) + if( m_embedCallback && customize.GetEmbed() ) + { + relPath = m_embedCallback( filePath ); + + if( relPath.IsEmpty() ) + { + m_dlg->CleanupAfterModalSubDialog(); + return; + } + } + else if( m_normalize ) { relPath = NormalizePath( filePath, &Pgm().GetLocalEnvVariables(), m_normalizeBasePath ); @@ -573,6 +591,7 @@ protected: wxString m_fileFilter; std::function m_fileFilterFn; + std::function m_embedCallback; }; @@ -583,12 +602,13 @@ void GRID_CELL_PATH_EDITOR::Create( wxWindow* aParent, wxWindowID aId, { m_control = new TEXT_BUTTON_FILE_BROWSER( aParent, m_dlg, m_grid, m_currentDir, m_fileFilterFn, m_normalize, - m_normalizeBasePath ); + m_normalizeBasePath, m_embedCallback ); } else { m_control = new TEXT_BUTTON_FILE_BROWSER( aParent, m_dlg, m_grid, m_currentDir, - m_fileFilter, m_normalize, m_normalizeBasePath ); + m_fileFilter, m_normalize, m_normalizeBasePath, + m_embedCallback ); } WX_GRID::CellEditorSetMargins( Combo() ); diff --git a/include/widgets/grid_text_button_helpers.h b/include/widgets/grid_text_button_helpers.h index 8ffec42a57..7a1c4259fd 100644 --- a/include/widgets/grid_text_button_helpers.h +++ b/include/widgets/grid_text_button_helpers.h @@ -158,13 +158,15 @@ public: */ GRID_CELL_PATH_EDITOR( DIALOG_SHIM* aParentDialog, WX_GRID* aGrid, wxString* aCurrentDir, bool aNormalize, const wxString& aNormalizeBasePath, - std::function aFileFilterFn ) : + std::function aFileFilterFn, + std::function aEmbedCallback = nullptr ) : m_dlg( aParentDialog ), m_grid( aGrid ), m_currentDir( aCurrentDir ), m_normalize( aNormalize ), m_normalizeBasePath( aNormalizeBasePath ), - m_fileFilterFn( std::move( aFileFilterFn ) ) + m_fileFilterFn( std::move( aFileFilterFn ) ), + m_embedCallback( std::move( aEmbedCallback ) ) { } /** @@ -180,13 +182,15 @@ public: */ GRID_CELL_PATH_EDITOR( DIALOG_SHIM* aParentDialog, WX_GRID* aGrid, wxString* aCurrentDir, const wxString& aFileFilter, bool aNormalize = false, - const wxString& aNormalizeBasePath = wxEmptyString ) : + const wxString& aNormalizeBasePath = wxEmptyString, + std::function aEmbedCallback = nullptr ) : m_dlg( aParentDialog ), m_grid( aGrid ), m_currentDir( aCurrentDir ), m_normalize( aNormalize ), m_normalizeBasePath( aNormalizeBasePath ), - m_fileFilter( aFileFilter ) + m_fileFilter( aFileFilter ), + m_embedCallback( std::move( aEmbedCallback ) ) { } wxGridCellEditor* Clone() const override @@ -194,12 +198,12 @@ public: if( m_fileFilterFn ) { return new GRID_CELL_PATH_EDITOR( m_dlg, m_grid, m_currentDir, m_normalize, - m_normalizeBasePath, m_fileFilterFn ); + m_normalizeBasePath, m_fileFilterFn, m_embedCallback ); } else { return new GRID_CELL_PATH_EDITOR( m_dlg, m_grid, m_currentDir, m_fileFilter, - m_normalize, m_normalizeBasePath ); + m_normalize, m_normalizeBasePath, m_embedCallback ); } } @@ -214,6 +218,7 @@ protected: wxString m_fileFilter; std::function m_fileFilterFn; + std::function m_embedCallback; }; diff --git a/pcbnew/dialogs/panel_fp_properties_3d_model.cpp b/pcbnew/dialogs/panel_fp_properties_3d_model.cpp index 39fbab073a..e91d208248 100644 --- a/pcbnew/dialogs/panel_fp_properties_3d_model.cpp +++ b/pcbnew/dialogs/panel_fp_properties_3d_model.cpp @@ -108,7 +108,23 @@ PANEL_FP_PROPERTIES_3D_MODEL::PANEL_FP_PROPERTIES_3D_MODEL( PCB_BASE_EDIT_FRAME* { attr->SetEditor( new GRID_CELL_PATH_EDITOR( m_parentDialog, m_modelsGrid, &cfg->m_LastFootprint3dDir, wxT( "*.*" ), true, - m_frame->Prj().GetProjectPath() ) ); + m_frame->Prj().GetProjectPath(), + [this]( const wxString& aFile ) -> wxString + { + EMBEDDED_FILES::EMBEDDED_FILE* result = + m_filesPanel->AddEmbeddedFile( aFile ); + + if( !result ) + { + wxString msg = wxString::Format( + _( "Error adding 3D model" ) ); + wxMessageBox( msg, _( "Error" ), + wxICON_ERROR | wxOK, this ); + return wxString(); + } + + return result->GetLink(); + } ) ); } m_modelsGrid->SetColAttr( COL_FILENAME, attr );