From fa11e9138daa2c1abe368716a4e9dec286ca47b5 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Fri, 29 Sep 2023 17:02:57 +0100 Subject: [PATCH] ADDED support for pin and fp filtering in FOOTPRINT_CHOOSER. Fixes https://gitlab.com/kicad/code/kicad/-/issues/7176 --- common/lib_tree_model.cpp | 32 +++- common/lib_tree_model_adapter.cpp | 41 ++--- common/widgets/grid_text_button_helpers.cpp | 13 +- eeschema/fields_grid_table.cpp | 26 +-- eeschema/lib_symbol.h | 2 +- .../netlist_exporter_xml.cpp | 12 ++ eeschema/symbol_chooser_frame.h | 2 +- eeschema/symbol_tree_model_adapter.cpp | 7 +- eeschema/widgets/panel_symbol_chooser.cpp | 12 +- include/footprint_info.h | 2 + include/lib_tree_item.h | 5 + include/lib_tree_model.h | 15 +- include/lib_tree_model_adapter.h | 43 ++--- include/mail_type.h | 4 +- pcbnew/dialogs/dialog_exchange_footprints.cpp | 20 ++- pcbnew/dialogs/dialog_footprint_chooser.cpp | 14 +- pcbnew/footprint.h | 4 + pcbnew/footprint_chooser_frame.cpp | 162 ++++++++++++++---- pcbnew/footprint_chooser_frame.h | 13 +- pcbnew/footprint_viewer_frame.cpp | 39 +---- .../netlist_reader/board_netlist_updater.cpp | 39 ++++- pcbnew/pcbnew_settings.cpp | 6 + pcbnew/pcbnew_settings.h | 12 +- pcbnew/plugins/kicad/pcb_parser.cpp | 13 +- pcbnew/plugins/kicad/pcb_plugin.cpp | 6 + pcbnew/widgets/panel_footprint_chooser.cpp | 5 +- pcbnew/widgets/panel_footprint_chooser.h | 12 +- 27 files changed, 367 insertions(+), 194 deletions(-) diff --git a/common/lib_tree_model.cpp b/common/lib_tree_model.cpp index 16822c1bea..15b92ddc46 100644 --- a/common/lib_tree_model.cpp +++ b/common/lib_tree_model.cpp @@ -34,10 +34,10 @@ static const unsigned kLowestDefaultScore = 1; -void LIB_TREE_NODE::ResetScore() +void LIB_TREE_NODE::ResetScore( std::function* aFilter ) { for( std::unique_ptr& child: m_Children ) - child->ResetScore(); + child->ResetScore( aFilter ); m_Score = kLowestDefaultScore; } @@ -175,6 +175,7 @@ LIB_TREE_NODE_LIB_ID::LIB_TREE_NODE_LIB_ID( LIB_TREE_NODE* aParent, LIB_TREE_ITE m_Name = aItem->GetName(); m_Desc = aItem->GetDescription(); m_Footprint = aItem->GetFootprint(); + m_PinCount = aItem->GetPinCount(); aItem->GetChooserFields( m_Fields ); @@ -218,7 +219,21 @@ void LIB_TREE_NODE_LIB_ID::Update( LIB_TREE_ITEM* aItem ) } -void LIB_TREE_NODE_LIB_ID::UpdateScore( EDA_COMBINED_MATCHER& aMatcher, const wxString& aLib ) +void LIB_TREE_NODE_LIB_ID::ResetScore( std::function* aFilter ) +{ + for( std::unique_ptr& child: m_Children ) + child->ResetScore( aFilter ); + + if( !aFilter ) + m_Score = kLowestDefaultScore; + else if( (*aFilter)(*this) ) + m_Score = kLowestDefaultScore + 1; + else + m_Score = 0; +} + + +void LIB_TREE_NODE_LIB_ID::UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxString& aLib ) { if( m_Score <= 0 ) return; // Leaf nodes without scores are out of the game. @@ -229,7 +244,8 @@ void LIB_TREE_NODE_LIB_ID::UpdateScore( EDA_COMBINED_MATCHER& aMatcher, const wx return; } - m_Score = aMatcher.ScoreTerms( m_SearchTerms ); + if( aMatcher ) + m_Score = aMatcher->ScoreTerms( m_SearchTerms ); } @@ -252,7 +268,7 @@ LIB_TREE_NODE_LIB_ID& LIB_TREE_NODE_LIB::AddItem( LIB_TREE_ITEM* aItem ) } -void LIB_TREE_NODE_LIB::UpdateScore( EDA_COMBINED_MATCHER& aMatcher, const wxString& aLib ) +void LIB_TREE_NODE_LIB::UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxString& aLib ) { m_Score = 0; @@ -266,11 +282,11 @@ void LIB_TREE_NODE_LIB::UpdateScore( EDA_COMBINED_MATCHER& aMatcher, const wxStr m_Score = std::max( m_Score, child->m_Score ); } } - else + else if( aMatcher ) { // No children; we are a leaf. - m_Score = aMatcher.ScoreTerms( m_SearchTerms ); + m_Score = aMatcher->ScoreTerms( m_SearchTerms ); } } @@ -289,7 +305,7 @@ LIB_TREE_NODE_LIB& LIB_TREE_NODE_ROOT::AddLib( wxString const& aName, wxString c } -void LIB_TREE_NODE_ROOT::UpdateScore( EDA_COMBINED_MATCHER& aMatcher, const wxString& aLib ) +void LIB_TREE_NODE_ROOT::UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxString& aLib ) { for( std::unique_ptr& child: m_Children ) child->UpdateScore( aMatcher, aLib ); diff --git a/common/lib_tree_model_adapter.cpp b/common/lib_tree_model_adapter.cpp index 273f4aa31c..fe9153bba2 100644 --- a/common/lib_tree_model_adapter.cpp +++ b/common/lib_tree_model_adapter.cpp @@ -49,12 +49,12 @@ LIB_TREE_NODE* LIB_TREE_MODEL_ADAPTER::ToNode( wxDataViewItem aItem ) LIB_TREE_MODEL_ADAPTER::LIB_TREE_MODEL_ADAPTER( EDA_BASE_FRAME* aParent, const wxString& aPinnedKey ) : m_parent( aParent ), - m_filter( SYM_FILTER_NONE ), m_sort_mode( BEST_MATCH ), m_show_units( true ), m_preselect_unit( 0 ), m_freeze( 0 ), - m_widget( nullptr ) + m_widget( nullptr ), + m_filter( nullptr ) { // Default column widths. Do not translate these names. m_colWidths[ _HKI( "Item" ) ] = 300; @@ -96,12 +96,6 @@ void LIB_TREE_MODEL_ADAPTER::SaveSettings() } -void LIB_TREE_MODEL_ADAPTER::SetFilter( SYM_FILTER_TYPE aFilter ) -{ - m_filter = aFilter; -} - - void LIB_TREE_MODEL_ADAPTER::ShowUnits( bool aShow ) { m_show_units = aShow; @@ -171,24 +165,31 @@ void LIB_TREE_MODEL_ADAPTER::UpdateSearchString( const wxString& aSearch, bool a Freeze(); BeforeReset(); - m_tree.ResetScore(); + m_tree.ResetScore( m_filter ); wxStringTokenizer tokenizer( aSearch ); - while( tokenizer.HasMoreTokens() ) + if( tokenizer.HasMoreTokens() ) { - wxString lib; - wxString term = tokenizer.GetNextToken().Lower(); - - if( term.Contains( ":" ) ) + while( tokenizer.HasMoreTokens() ) { - lib = term.BeforeFirst( ':' ); - term = term.AfterFirst( ':' ); + wxString lib; + wxString term = tokenizer.GetNextToken().Lower(); + + if( term.Contains( ":" ) ) + { + lib = term.BeforeFirst( ':' ); + term = term.AfterFirst( ':' ); + } + + EDA_COMBINED_MATCHER matcher( term, CTX_LIBITEM ); + + m_tree.UpdateScore( &matcher, lib ); } - - EDA_COMBINED_MATCHER matcher( term, CTX_LIBITEM ); - - m_tree.UpdateScore( matcher, lib ); + } + else + { + m_tree.UpdateScore( nullptr, wxEmptyString ); } m_tree.SortNodes( m_sort_mode == BEST_MATCH ); diff --git a/common/widgets/grid_text_button_helpers.cpp b/common/widgets/grid_text_button_helpers.cpp index 66c708feae..a508813be2 100644 --- a/common/widgets/grid_text_button_helpers.cpp +++ b/common/widgets/grid_text_button_helpers.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2021 CERN - * Copyright (C) 2018-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2018-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -271,7 +271,7 @@ protected: if( !m_symbolNetlist.empty() ) { - KIWAY_EXPRESS event( FRAME_FOOTPRINT_VIEWER, MAIL_SYMBOL_NETLIST, m_symbolNetlist ); + KIWAY_EXPRESS event( FRAME_FOOTPRINT_CHOOSER, MAIL_SYMBOL_NETLIST, m_symbolNetlist ); frame->KiwayMailIn( event ); } @@ -281,17 +281,14 @@ protected: frame->Destroy(); } +protected: DIALOG_SHIM* m_dlg; wxString m_preselect; /* * Symbol netlist format: - * library:footprint - * reference - * value - * pinName,netName,pinFunction,pinType - * pinName,netName,pinFunction,pinType - * ... + * pinCount + * fpFilters */ std::string m_symbolNetlist; }; diff --git a/eeschema/fields_grid_table.cpp b/eeschema/fields_grid_table.cpp index ef11a6dd23..24cc12ba5e 100644 --- a/eeschema/fields_grid_table.cpp +++ b/eeschema/fields_grid_table.cpp @@ -64,27 +64,19 @@ static wxString netList( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH& aSheetPath ) { /* * Symbol netlist format: - * library:footprint - * reference - * value - * pinName,netName,pinFunction,pinType - * pinName,netName,pinFunction,pinType - * ... + * pinCount + * fpFilters */ wxString netlist; - netlist << EscapeString( aSymbol->GetFootprintFieldText( true, &aSheetPath, false ), CTX_LINE ) << wxS( "\r" ); - netlist << EscapeString( aSymbol->GetRef( &aSheetPath ), CTX_LINE ) << wxS( "\r" ); - netlist << EscapeString( aSymbol->GetValueFieldText( true, &aSheetPath, false ), CTX_LINE ); + netlist << wxString::Format( wxS( "%d\r" ), aSymbol->GetPins().size() ); - for( SCH_PIN* pin : aSymbol->GetPins( &aSheetPath ) ) - { - netlist << wxS( "\r" ); - netlist << EscapeString( pin->GetNumber(), CTX_CSV ) << wxS( "," ); - netlist << EscapeString( pin->GetDefaultNetName( aSheetPath ), CTX_CSV ) << wxS( "," ); - netlist << EscapeString( pin->GetName(), CTX_CSV ) << wxS( "," ); - netlist << EscapeString( pin->GetCanonicalElectricalTypeName(), CTX_CSV ); - } + wxArrayString fpFilters = aSymbol->GetLibSymbolRef()->GetFPFilters(); + + if( !fpFilters.IsEmpty() ) + netlist << EscapeString( wxJoin( fpFilters, ' ' ), CTX_LINE ); + + netlist << wxS( "\r" ); return netlist; } diff --git a/eeschema/lib_symbol.h b/eeschema/lib_symbol.h index 982933b532..127258623d 100644 --- a/eeschema/lib_symbol.h +++ b/eeschema/lib_symbol.h @@ -456,7 +456,7 @@ public: /** * @return a count of pins for all units / converts. */ - size_t GetFullPinCount() { return GetAllLibPins().size(); } + int GetPinCount() override { return GetAllLibPins().size(); } /** * Return pin object with the requested pin \a aNumber. diff --git a/eeschema/netlist_exporters/netlist_exporter_xml.cpp b/eeschema/netlist_exporters/netlist_exporter_xml.cpp index 7dec9aa23e..9e9eab7ed4 100644 --- a/eeschema/netlist_exporters/netlist_exporter_xml.cpp +++ b/eeschema/netlist_exporters/netlist_exporter_xml.cpp @@ -399,6 +399,18 @@ XNODE* NETLIST_EXPORTER_XML::makeSymbols( unsigned aCtl ) xproperty->AddAttribute( wxT( "name" ), wxT( "ki_keywords" ) ); xproperty->AddAttribute( wxT( "value" ), part->GetKeyWords() ); } + + if( !part->GetFPFilters().IsEmpty() ) + { + wxString filters; + + for( const wxString& filter : part->GetFPFilters() ) + filters += ' ' + filter; + + xcomp->AddChild( xproperty = node( wxT( "property" ) ) ); + xproperty->AddAttribute( wxT( "name" ), wxT( "ki_fp_filters" ) ); + xproperty->AddAttribute( wxT( "value" ), filters.Trim( false ) ); + } } XNODE* xsheetpath; diff --git a/eeschema/symbol_chooser_frame.h b/eeschema/symbol_chooser_frame.h index 557d70b7df..4bb310b1de 100644 --- a/eeschema/symbol_chooser_frame.h +++ b/eeschema/symbol_chooser_frame.h @@ -61,7 +61,7 @@ public: * see SCH_BASE_FRAME::SelectSymbolFromLibrary() for details. * if aFilter == NULL, remove all filtering. */ - void SetFilter( const SYMBOL_LIBRARY_FILTER* aFilter ); + void SetFilter( std::function* aFilter ); private: void OnPaint( wxPaintEvent& aEvent ); diff --git a/eeschema/symbol_tree_model_adapter.cpp b/eeschema/symbol_tree_model_adapter.cpp index 563eb5dd81..192e4cdc49 100644 --- a/eeschema/symbol_tree_model_adapter.cpp +++ b/eeschema/symbol_tree_model_adapter.cpp @@ -80,9 +80,8 @@ bool SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( const std::vector& aNick std::unordered_map> loadedSymbols; - SYMBOL_ASYNC_LOADER loader( aNicknames, m_libs, - GetFilter() == LIB_TREE_MODEL_ADAPTER::SYM_FILTER_POWER, - &loadedSymbols, progressReporter.get() ); + SYMBOL_ASYNC_LOADER loader( aNicknames, m_libs, GetFilter() != nullptr, &loadedSymbols, + progressReporter.get() ); LOCALE_IO toggle; @@ -204,7 +203,7 @@ bool SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( const std::vector& aNick void SYMBOL_TREE_MODEL_ADAPTER::AddLibrary( wxString const& aLibNickname, bool pinned ) { - bool onlyPowerSymbols = ( GetFilter() == SYM_FILTER_POWER ); + bool onlyPowerSymbols = ( GetFilter() != nullptr ); std::vector symbols; std::vector comp_list; diff --git a/eeschema/widgets/panel_symbol_chooser.cpp b/eeschema/widgets/panel_symbol_chooser.cpp index 952a92b52b..d2a56cca11 100644 --- a/eeschema/widgets/panel_symbol_chooser.cpp +++ b/eeschema/widgets/panel_symbol_chooser.cpp @@ -102,7 +102,17 @@ PANEL_SYMBOL_CHOOSER::PANEL_SYMBOL_CHOOSER( SCH_BASE_FRAME* aFrame, wxWindow* aP if( aFilter->GetFilterPowerSymbols() ) { - adapter->SetFilter( SYMBOL_TREE_MODEL_ADAPTER::SYM_FILTER_POWER ); + // Note: there is only a single filter ever used for symbols (the power filter), + // so the code simply sets a flag based on the filter being non-null. The filter + // is not (at present) actually called. + static std::function powerFilter = + []( LIB_TREE_NODE& ) -> bool + { + return true; + }; + + adapter->SetFilter( &powerFilter ); + m_showPower = true; m_show_footprints = false; } diff --git a/include/footprint_info.h b/include/footprint_info.h index 6daa5589f9..93003b0c43 100644 --- a/include/footprint_info.h +++ b/include/footprint_info.h @@ -72,6 +72,8 @@ public: wxString GetName() const override { return m_fpname; } + int GetPinCount() override { return GetUniquePadCount(); } + LIB_ID GetLibId() const override { return LIB_ID( m_nickname, m_fpname ); diff --git a/include/lib_tree_item.h b/include/lib_tree_item.h index 00910135d2..c26871db7f 100644 --- a/include/lib_tree_item.h +++ b/include/lib_tree_item.h @@ -68,6 +68,11 @@ public: */ virtual wxString GetFootprint() { return wxEmptyString; } + /** + * The pin count for symbols or the unique pad count for footprints. + */ + virtual int GetPinCount() { return 0; } + /** * For items with units, return the number of units. */ diff --git a/include/lib_tree_model.h b/include/lib_tree_model.h index 1b98568fc2..9e1cfb2472 100644 --- a/include/lib_tree_model.h +++ b/include/lib_tree_model.h @@ -80,12 +80,12 @@ public: * * @param aMatcher an EDA_COMBINED_MATCHER initialized with the search term */ - virtual void UpdateScore( EDA_COMBINED_MATCHER& aMatcher, const wxString& aLib ) = 0; + virtual void UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxString& aLib ) = 0; /** * Initialize score to kLowestDefaultScore, recursively. */ - void ResetScore(); + virtual void ResetScore( std::function* aFilter ); /** * Store intrinsic ranks on all children of this node. See m_IntrinsicRank @@ -135,6 +135,7 @@ public: wxString m_Name; // Actual name of the part wxString m_Desc; // Description to be displayed wxString m_Footprint; // Footprint ID as a string (ie: the footprint field text) + int m_PinCount; // Pin count from symbol, or unique pad count from footprint std::vector m_SearchTerms; /// List of weighted search terms std::map m_Fields; /// @see LIB_TREE_ITEMS::GetChooserFields @@ -174,7 +175,7 @@ public: /** * Do nothing, units just take the parent's score */ - virtual void UpdateScore( EDA_COMBINED_MATCHER& aMatcher, const wxString& aLib ) override {} + virtual void UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxString& aLib ) override {} }; @@ -210,10 +211,12 @@ public: */ void Update( LIB_TREE_ITEM* aItem ); + void ResetScore( std::function* aFilter ) override; + /** * Perform the actual search. */ - virtual void UpdateScore( EDA_COMBINED_MATCHER& aMatcher, const wxString& aLib ) override; + virtual void UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxString& aLib ) override; protected: /** @@ -254,7 +257,7 @@ public: */ LIB_TREE_NODE_LIB_ID& AddItem( LIB_TREE_ITEM* aItem ); - virtual void UpdateScore( EDA_COMBINED_MATCHER& aMatcher, const wxString& aLib ) override; + virtual void UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxString& aLib ) override; }; @@ -281,7 +284,7 @@ public: */ LIB_TREE_NODE_LIB& AddLib( wxString const& aName, wxString const& aDesc ); - virtual void UpdateScore( EDA_COMBINED_MATCHER& aMatcher, const wxString& aLib ) override; + virtual void UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxString& aLib ) override; }; diff --git a/include/lib_tree_model_adapter.h b/include/lib_tree_model_adapter.h index f434e1c361..ac8dbedfec 100644 --- a/include/lib_tree_model_adapter.h +++ b/include/lib_tree_model_adapter.h @@ -114,15 +114,6 @@ public: */ ~LIB_TREE_MODEL_ADAPTER(); - /** - * This enum allows a selective filtering of symbols to list - */ - enum SYM_FILTER_TYPE - { - SYM_FILTER_NONE, ///< no filtering - SYM_FILTER_POWER, ///< list symbols flagged PWR - }; - /** * This enum defines the order of the default columns in the tree view */ @@ -150,12 +141,12 @@ public: * * @param aFilter if SYM_FILTER_POWER, only power parts are loaded */ - void SetFilter( SYM_FILTER_TYPE aFilter ); + void SetFilter( std::function* aFilter ) { m_filter = aFilter; } /** * Return the active filter. */ - SYM_FILTER_TYPE GetFilter() const { return m_filter; } + std::function* GetFilter() const { return m_filter; } void SetSortMode( SORT_MODE aMode ) { m_sort_mode = aMode; } SORT_MODE GetSortMode() const { return m_sort_mode; } @@ -397,11 +388,6 @@ protected: void resortTree(); private: - /** - * Find any results worth highlighting and expand them. - */ - void Find( LIB_TREE_NODE& aNode, std::function aFunc ); - /** * Find and expand successful search results. Return the best match (if any). */ @@ -419,21 +405,22 @@ protected: std::vector m_availableColumns; private: - EDA_BASE_FRAME* m_parent; + EDA_BASE_FRAME* m_parent; - SYM_FILTER_TYPE m_filter; - SORT_MODE m_sort_mode; - bool m_show_units; - LIB_ID m_preselect_lib_id; - int m_preselect_unit; - int m_freeze; + SORT_MODE m_sort_mode; + bool m_show_units; + LIB_ID m_preselect_lib_id; + int m_preselect_unit; + int m_freeze; - wxDataViewCtrl* m_widget; + wxDataViewCtrl* m_widget; - std::vector m_columns; - std::map m_colNameMap; - std::map m_colWidths; - std::vector m_shownColumns; // Stored in display order + std::function* m_filter; + + std::vector m_columns; + std::map m_colNameMap; + std::map m_colWidths; + std::vector m_shownColumns; // Stored in display order }; #endif // LIB_TREE_MODEL_ADAPTER_H diff --git a/include/mail_type.h b/include/mail_type.h index edc3e92fd9..212e747bc4 100644 --- a/include/mail_type.h +++ b/include/mail_type.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2014 CERN - * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.TXT for contributors. + * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.TXT for contributors. * @author Maciej Suminski * * This program is free software; you can redistribute it and/or @@ -42,7 +42,7 @@ enum MAIL_T MAIL_ASSIGN_FOOTPRINTS, // CVPCB->SCH footprint stuffing MAIL_SCH_SAVE, // CVPCB->SCH save the schematic MAIL_EESCHEMA_NETLIST, // SCH->CVPCB netlist immediately after launching CVPCB - MAIL_SYMBOL_NETLIST, // SCH->FP_VIEWER symbol pin information + MAIL_SYMBOL_NETLIST, // SCH->FP_CHOOSER symbol pin & fp_filter information MAIL_PCB_UPDATE, // SCH->PCB forward update MAIL_SCH_UPDATE, // PCB->SCH forward update MAIL_IMPORT_FILE, // Import a different format file diff --git a/pcbnew/dialogs/dialog_exchange_footprints.cpp b/pcbnew/dialogs/dialog_exchange_footprints.cpp index 000eb52cf0..26cb5e5dcd 100644 --- a/pcbnew/dialogs/dialog_exchange_footprints.cpp +++ b/pcbnew/dialogs/dialog_exchange_footprints.cpp @@ -4,7 +4,7 @@ * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2013 Wayne Stambaugh - * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -403,6 +404,23 @@ void DIALOG_EXCHANGE_FOOTPRINTS::ViewAndSelectFootprint( wxCommandEvent& event ) KIWAY_PLAYER* frame = Kiway().Player( FRAME_FOOTPRINT_CHOOSER, true ); + if( m_currentFootprint ) + { + /* + * Symbol netlist format: + * pinCount + * fpFilters + */ + wxString netlist; + + netlist << wxString::Format( wxS( "%ld\r" ), m_currentFootprint->Pads().size() ); + netlist << EscapeString( m_currentFootprint->GetFilters(), CTX_LINE ) << wxS( "\r" ); + + std::string payload( netlist.ToStdString() ); + KIWAY_EXPRESS mail( FRAME_FOOTPRINT_CHOOSER, MAIL_SYMBOL_NETLIST, payload ); + frame->KiwayMailIn( mail ); + } + if( frame->ShowModal( &newname, this ) ) { if( event.GetEventObject() == m_newIDBrowseButton ) diff --git a/pcbnew/dialogs/dialog_footprint_chooser.cpp b/pcbnew/dialogs/dialog_footprint_chooser.cpp index 51cd1d490f..ee92cb6c49 100644 --- a/pcbnew/dialogs/dialog_footprint_chooser.cpp +++ b/pcbnew/dialogs/dialog_footprint_chooser.cpp @@ -36,10 +36,16 @@ DIALOG_FOOTPRINT_CHOOSER::DIALOG_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aParent, { wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL ); m_chooserPanel = new PANEL_FOOTPRINT_CHOOSER( aParent, this, aFootprintHistoryList, - [this]() - { - EndModal( wxID_OK ); - } ); + // Filter + []( LIB_TREE_NODE& aNode ) -> bool + { + return true; + }, + // Close handler + [this]() + { + EndModal( wxID_OK ); + } ); sizer->Add( m_chooserPanel, 1, wxEXPAND, 5 ); diff --git a/pcbnew/footprint.h b/pcbnew/footprint.h index 9dfdd477ee..87b3f80613 100644 --- a/pcbnew/footprint.h +++ b/pcbnew/footprint.h @@ -248,6 +248,9 @@ public: wxString GetSheetfile() const { return m_sheetfile; } void SetSheetfile( const wxString& aSheetfile ) { m_sheetfile = aSheetfile; } + wxString GetFilters() const { return m_filters; } + void SetFilters( const wxString& aFilters ) { m_filters = aFilters; } + int GetLocalSolderMaskMargin() const { return m_localSolderMaskMargin; } void SetLocalSolderMaskMargin( int aMargin ) { m_localSolderMaskMargin = aMargin; } @@ -983,6 +986,7 @@ private: KIID_PATH m_path; // Path to associated symbol ([sheetUUID, .., symbolUUID]). wxString m_sheetname; // Name of the sheet containing the symbol for this footprint wxString m_sheetfile; // File of the sheet containing the symbol for this footprint + wxString m_filters; // Footprint filters from symbol timestamp_t m_lastEditTime; int m_arflag; // Use to trace ratsnest and auto routing. KIID m_link; // Temporary logical link used during editing diff --git a/pcbnew/footprint_chooser_frame.cpp b/pcbnew/footprint_chooser_frame.cpp index 552608614d..4483acd21e 100644 --- a/pcbnew/footprint_chooser_frame.cpp +++ b/pcbnew/footprint_chooser_frame.cpp @@ -22,9 +22,11 @@ */ #include +#include #include #include #include +#include #include #include #include @@ -38,7 +40,7 @@ static unsigned s_FootprintHistoryMaxCount = 8; static void AddFootprintToHistory( const wxString& aName ) { // Remove duplicates - for( int ii = s_FootprintHistoryList.GetCount() - 1; ii >= 0; --ii ) + for( int ii = (int) s_FootprintHistoryList.GetCount() - 1; ii >= 0; --ii ) { if( s_FootprintHistoryList[ ii ] == aName ) s_FootprintHistoryList.RemoveAt( (size_t) ii ); @@ -54,9 +56,9 @@ static void AddFootprintToHistory( const wxString& aName ) BEGIN_EVENT_TABLE( FOOTPRINT_CHOOSER_FRAME, PCB_BASE_FRAME ) - EVT_MENU( wxID_CLOSE, FOOTPRINT_CHOOSER_FRAME::CloseFootprintChooser ) + EVT_MENU( wxID_CLOSE, FOOTPRINT_CHOOSER_FRAME::closeFootprintChooser ) EVT_BUTTON( wxID_OK, FOOTPRINT_CHOOSER_FRAME::OnOK ) - EVT_BUTTON( wxID_CANCEL, FOOTPRINT_CHOOSER_FRAME::CloseFootprintChooser ) + EVT_BUTTON( wxID_CANCEL, FOOTPRINT_CHOOSER_FRAME::closeFootprintChooser ) EVT_PAINT( FOOTPRINT_CHOOSER_FRAME::OnPaint ) END_EVENT_TABLE() @@ -68,31 +70,62 @@ END_EVENT_TABLE() FOOTPRINT_CHOOSER_FRAME::FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aParent ) : - PCB_BASE_FRAME( aKiway, aParent, FRAME_FOOTPRINT_CHOOSER, _( "Footprint Chooser" ), - wxDefaultPosition, wxDefaultSize, aParent ? PARENT_STYLE : MODAL_STYLE, - FOOTPRINT_CHOOSER_FRAME_NAME ), - m_comp( LIB_ID(), wxEmptyString, wxEmptyString, KIID_PATH(), {} ) + PCB_BASE_FRAME( aKiway, aParent, FRAME_FOOTPRINT_CHOOSER, _( "Footprint Chooser" ), + wxDefaultPosition, wxDefaultSize, aParent ? PARENT_STYLE : MODAL_STYLE, + FOOTPRINT_CHOOSER_FRAME_NAME ), + m_filterByPinCount( nullptr ), + m_filterByFPFilters( nullptr ), + m_pinCount( 0 ) { SetModal( true ); wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL ); m_chooserPanel = new PANEL_FOOTPRINT_CHOOSER( this, this, s_FootprintHistoryList, - [this]() - { - wxCommandEvent dummy; - OnOK( dummy ); - } ); + // Filter + [this]( LIB_TREE_NODE& aNode ) -> bool + { + return filterFootprint( aNode ); + }, + // Close handler + [this]() + { + wxCommandEvent dummy; + OnOK( dummy ); + } ); sizer->Add( m_chooserPanel, 1, wxEXPAND, 5 ); + wxBoxSizer* fpFilterSizer = new wxBoxSizer( wxVERTICAL ); + + m_filterByFPFilters = new wxCheckBox( this, wxID_ANY, _( "Apply footprint filters" ) ); + fpFilterSizer->Add( m_filterByFPFilters, 0, wxTOP | wxEXPAND, 8 ); + m_filterByFPFilters->Show( false ); + + sizer->Add( fpFilterSizer, 0, wxEXPAND | wxLEFT, 10 ); + + wxBoxSizer* buttonsSizer = new wxBoxSizer( wxHORIZONTAL ); + + m_filterByPinCount = new wxCheckBox( this, wxID_ANY, _( "Filter by pin count" ) ); + buttonsSizer->Add( m_filterByPinCount, 0, wxLEFT | wxTOP | wxALIGN_TOP, 5 ); + m_filterByPinCount->Show( false ); + + if( PCBNEW_SETTINGS* cfg = dynamic_cast( Kiface().KifaceSettings() ) ) + { + m_filterByFPFilters->SetValue( cfg->m_FootprintChooser.use_fp_filters ); + m_filterByPinCount->SetValue( cfg->m_FootprintChooser.filter_on_pin_count ); + } + wxStdDialogButtonSizer* sdbSizer = new wxStdDialogButtonSizer(); wxButton* okButton = new wxButton( this, wxID_OK ); wxButton* cancelButton = new wxButton( this, wxID_CANCEL ); + sdbSizer->AddButton( okButton ); sdbSizer->AddButton( cancelButton ); sdbSizer->Realize(); - sizer->Add( sdbSizer, 0, wxEXPAND | wxALL, 5 ); + buttonsSizer->Add( sdbSizer, 1, wxALL, 5 ); + + sizer->Add( buttonsSizer, 0, wxEXPAND | wxLEFT, 5 ); SetSizer( sizer ); SetTitle( GetTitle() + wxString::Format( _( " (%d items loaded)" ), @@ -100,6 +133,61 @@ FOOTPRINT_CHOOSER_FRAME::FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aPare Layout(); m_chooserPanel->FinishSetup(); + + m_filterByPinCount->Bind( wxEVT_CHECKBOX, + [&]( wxCommandEvent& evt ) + { + m_chooserPanel->Regenerate(); + } ); + + m_filterByFPFilters->Bind( wxEVT_CHECKBOX, + [&]( wxCommandEvent& evt ) + { + m_chooserPanel->Regenerate(); + } ); +} + + +FOOTPRINT_CHOOSER_FRAME::~FOOTPRINT_CHOOSER_FRAME() +{ + if( PCBNEW_SETTINGS* cfg = dynamic_cast( Kiface().KifaceSettings() ) ) + { + cfg->m_FootprintChooser.use_fp_filters = m_filterByFPFilters->GetValue(); + cfg->m_FootprintChooser.filter_on_pin_count = m_filterByPinCount->GetValue(); + } +} + +bool FOOTPRINT_CHOOSER_FRAME::filterFootprint( LIB_TREE_NODE& aNode ) +{ + if( m_pinCount > 0 && m_filterByPinCount->GetValue() ) + { + if( aNode.m_PinCount != m_pinCount ) + return false; + } + + if( !m_fpFilters.empty() && m_filterByFPFilters->GetValue() ) + { + // The matching is case insensitive + wxString name; + + for( const std::unique_ptr& each_filter : m_fpFilters ) + { + name.Empty(); + + // If the filter contains a ':' character, include the library name in the pattern + if( each_filter->GetPattern().Contains( wxS( ":" ) ) ) + name = aNode.m_LibId.GetUniStringLibNickname().Lower() + wxS( ":" ); + + name += aNode.m_LibId.GetUniStringLibItemName().Lower(); + + if( each_filter->Find( name ) ) + return true; + } + + return false; + } + + return true; } @@ -136,44 +224,48 @@ COLOR_SETTINGS* FOOTPRINT_CHOOSER_FRAME::GetColorSettings( bool aForceRefresh ) void FOOTPRINT_CHOOSER_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail ) { - // JEY TODO: don't delete this just yet. We can use it to pass in symbol info so that we - // can filter on footprint filters, symbol pin count, etc. - const std::string& payload = mail.GetPayload(); switch( mail.Command() ) { case MAIL_SYMBOL_NETLIST: { + m_pinCount = 0; + m_fpFilters.clear(); + /* * Symbol netlist format: - * library:footprint - * reference - * value - * pinName,netName,pinFunction,pinType - * pinName,netName,pinFunction,pinType - * ... + * pinCount + * fpFilters */ std::vector strings = split( payload, "\r" ); - LIB_ID libid; - if( strings.size() >= 3 ) + if( strings.size() >= 1 ) { - libid.Parse( strings[0] ); + wxString pinCountStr( strings[0] ); + pinCountStr.ToInt( &m_pinCount ); - m_comp.SetFPID( libid ); - m_comp.SetReference( strings[1] ); - m_comp.SetValue( strings[2] ); - - m_comp.ClearNets(); - - for( size_t ii = 3; ii < strings.size(); ++ii ) + if( m_pinCount > 0 ) { - std::vector pinData = split( strings[ii], "," ); - m_comp.AddNet( pinData[0], pinData[1], pinData[2], pinData[3] ); + m_filterByPinCount->SetLabel( m_filterByPinCount->GetLabel() + + wxString::Format( wxS( " (%d)" ), m_pinCount ) ); + m_filterByPinCount->Show( true ); } } + if( strings.size() >= 2 && !strings[1].empty() ) + { + for( const wxString& filter : wxSplit( strings[1], ' ' ) ) + { + m_fpFilters.push_back( std::make_unique() ); + m_fpFilters.back()->SetPattern( filter.Lower() ); + } + + m_filterByFPFilters->SetLabel( m_filterByFPFilters->GetLabel() + + wxString::Format( wxS( " (%s)" ), strings[1] ) ); + m_filterByFPFilters->Show( true ); + } + break; } @@ -231,7 +323,7 @@ void FOOTPRINT_CHOOSER_FRAME::OnOK( wxCommandEvent& aEvent ) } -void FOOTPRINT_CHOOSER_FRAME::CloseFootprintChooser( wxCommandEvent& aEvent ) +void FOOTPRINT_CHOOSER_FRAME::closeFootprintChooser( wxCommandEvent& aEvent ) { Close( false ); } diff --git a/pcbnew/footprint_chooser_frame.h b/pcbnew/footprint_chooser_frame.h index 62ee11f155..da5ae3e2ed 100644 --- a/pcbnew/footprint_chooser_frame.h +++ b/pcbnew/footprint_chooser_frame.h @@ -31,6 +31,7 @@ #include class PANEL_FOOTPRINT_CHOOSER; +class wxCheckBox; namespace PCB { struct IFACE; } @@ -38,7 +39,7 @@ namespace PCB { struct IFACE; } class FOOTPRINT_CHOOSER_FRAME : public PCB_BASE_FRAME { public: - ~FOOTPRINT_CHOOSER_FRAME() {}; + ~FOOTPRINT_CHOOSER_FRAME(); ///< @copydoc PCB_BASE_FRAME::GetModel() BOARD_ITEM_CONTAINER* GetModel() const override { return nullptr; } @@ -55,11 +56,13 @@ protected: FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aParent ); private: + bool filterFootprint( LIB_TREE_NODE& aNode ); + void OnPaint( wxPaintEvent& aEvent ); void OnOK( wxCommandEvent& aEvent ); void doCloseWindow() override; - void CloseFootprintChooser( wxCommandEvent& aEvent ); + void closeFootprintChooser( wxCommandEvent& aEvent ); WINDOW_SETTINGS* GetWindowSettings( APP_SETTINGS_BASE* aCfg ) override; COLOR_SETTINGS* GetColorSettings( bool aForceRefresh ) const override; @@ -70,7 +73,11 @@ private: private: PANEL_FOOTPRINT_CHOOSER* m_chooserPanel; - COMPONENT m_comp; + wxCheckBox* m_filterByPinCount; + wxCheckBox* m_filterByFPFilters; + + int m_pinCount; + std::vector> m_fpFilters; // On MacOS (at least) SetFocus() calls made in the constructor will fail because a // window that isn't yet visible will return false to AcceptsFocus(). So we must delay diff --git a/pcbnew/footprint_viewer_frame.cpp b/pcbnew/footprint_viewer_frame.cpp index 1600f35e68..b80d0f527e 100644 --- a/pcbnew/footprint_viewer_frame.cpp +++ b/pcbnew/footprint_viewer_frame.cpp @@ -954,51 +954,14 @@ void FOOTPRINT_VIEWER_FRAME::ReloadFootprint( FOOTPRINT* aFootprint ) void FOOTPRINT_VIEWER_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail ) { - const std::string& payload = mail.GetPayload(); - switch( mail.Command() ) { - case MAIL_SYMBOL_NETLIST: - { - /* - * Symbol netlist format: - * library:footprint - * reference - * value - * pinName,netName,pinFunction,pinType - * pinName,netName,pinFunction,pinType - * ... - */ - std::vector strings = split( payload, "\r" ); - LIB_ID libid; - - if( strings.size() >= 3 ) - { - libid.Parse( strings[0] ); - - m_comp.SetFPID( libid ); - m_comp.SetReference( strings[1] ); - m_comp.SetValue( strings[2] ); - - m_comp.ClearNets(); - - for( size_t ii = 3; ii < strings.size(); ++ii ) - { - std::vector pinData = split( strings[ii], "," ); - m_comp.AddNet( pinData[0], pinData[1], pinData[2], pinData[3] ); - } - } - - break; - } case MAIL_RELOAD_LIB: - { ReCreateLibraryList(); break; - } default: - ; + break; } } diff --git a/pcbnew/netlist_reader/board_netlist_updater.cpp b/pcbnew/netlist_reader/board_netlist_updater.cpp index 8f688d2e8d..f2bde2a273 100644 --- a/pcbnew/netlist_reader/board_netlist_updater.cpp +++ b/pcbnew/netlist_reader/board_netlist_updater.cpp @@ -413,6 +413,7 @@ bool BOARD_NETLIST_UPDATER::updateFootprintParameters( FOOTPRINT* aPcbFootprint, wxString sheetname; wxString sheetfile; + wxString fpFilters; if( aNetlistComponent->GetProperties().count( wxT( "Sheetname" ) ) > 0 ) sheetname = aNetlistComponent->GetProperties().at( wxT( "Sheetname" ) ); @@ -420,15 +421,22 @@ bool BOARD_NETLIST_UPDATER::updateFootprintParameters( FOOTPRINT* aPcbFootprint, if( aNetlistComponent->GetProperties().count( wxT( "Sheetfile" ) ) > 0 ) sheetfile = aNetlistComponent->GetProperties().at( wxT( "Sheetfile" ) ); + if( aNetlistComponent->GetProperties().count( wxT( "ki_fp_filters" ) ) > 0 ) + fpFilters = aNetlistComponent->GetProperties().at( wxT( "ki_fp_filters" ) ); + if( sheetname != aPcbFootprint->GetSheetname() ) { if( m_isDryRun ) - msg.Printf( _( "Update %s sheetname to '%s'." ), aPcbFootprint->GetReference(), + { + msg.Printf( _( "Update %s sheetname to '%s'." ), + aPcbFootprint->GetReference(), sheetname ); + } else { aPcbFootprint->SetSheetname( sheetname ); - msg.Printf( _( "Updated %s sheetname to '%s'." ), aPcbFootprint->GetReference(), + msg.Printf( _( "Updated %s sheetname to '%s'." ), + aPcbFootprint->GetReference(), sheetname ); } @@ -438,18 +446,41 @@ bool BOARD_NETLIST_UPDATER::updateFootprintParameters( FOOTPRINT* aPcbFootprint, if( sheetfile != aPcbFootprint->GetSheetfile() ) { if( m_isDryRun ) - msg.Printf( _( "Update %s sheetfile to '%s'." ), aPcbFootprint->GetReference(), + { + msg.Printf( _( "Update %s sheetfile to '%s'." ), + aPcbFootprint->GetReference(), sheetfile ); + } else { aPcbFootprint->SetSheetfile( sheetfile ); - msg.Printf( _( "Updated %s sheetfile to '%s'." ), aPcbFootprint->GetReference(), + msg.Printf( _( "Updated %s sheetfile to '%s'." ), + aPcbFootprint->GetReference(), sheetfile ); } m_reporter->Report( msg, RPT_SEVERITY_ACTION ); } + if( fpFilters != aPcbFootprint->GetFilters() ) + { + if( m_isDryRun ) + { + msg.Printf( _( "Update %s footprint filters to '%s'." ), + aPcbFootprint->GetReference(), + fpFilters ); + } + else + { + aPcbFootprint->SetFilters( fpFilters ); + msg.Printf( _( "Updated %s footprint filters to '%s'." ), + aPcbFootprint->GetReference(), + fpFilters ); + } + + m_reporter->Report( msg, RPT_SEVERITY_ACTION ); + } + if( ( aNetlistComponent->GetProperties().count( wxT( "exclude_from_bom" ) ) > 0 ) != ( ( aPcbFootprint->GetAttributes() & FP_EXCLUDE_FROM_BOM ) > 0 ) ) { diff --git a/pcbnew/pcbnew_settings.cpp b/pcbnew/pcbnew_settings.cpp index b6b37cbf06..a4e6754ef5 100644 --- a/pcbnew/pcbnew_settings.cpp +++ b/pcbnew/pcbnew_settings.cpp @@ -142,6 +142,12 @@ PCBNEW_SETTINGS::PCBNEW_SETTINGS() m_params.emplace_back( new PARAM( "footprint_chooser.sort_mode", &m_FootprintChooser.sort_mode, 0 ) ); + m_params.emplace_back( new PARAM( "footprint_chooser.filter_on_pin_count", + &m_FootprintChooser.filter_on_pin_count, false ) ); + + m_params.emplace_back( new PARAM( "footprint_chooser.use_fp_filters", + &m_FootprintChooser.use_fp_filters, false ) ); + m_params.emplace_back( new PARAM( "editing.flip_left_right", &m_FlipLeftRight, true ) ); diff --git a/pcbnew/pcbnew_settings.h b/pcbnew/pcbnew_settings.h index 401af144f8..e2858f509b 100644 --- a/pcbnew/pcbnew_settings.h +++ b/pcbnew/pcbnew_settings.h @@ -298,11 +298,13 @@ public: struct FOOTPRINT_CHOOSER { - int width; - int height; - int sash_h; - int sash_v; - int sort_mode; + int width; + int height; + int sash_h; + int sash_v; + int sort_mode; + bool use_fp_filters; + bool filter_on_pin_count; }; struct ZONES diff --git a/pcbnew/plugins/kicad/pcb_parser.cpp b/pcbnew/plugins/kicad/pcb_parser.cpp index 37fccfcc38..b58791ba53 100644 --- a/pcbnew/plugins/kicad/pcb_parser.cpp +++ b/pcbnew/plugins/kicad/pcb_parser.cpp @@ -3853,7 +3853,7 @@ FOOTPRINT* PCB_PARSER::parseFOOTPRINT_unchecked( wxArrayString* aInitialComments // Skip legacy non-field properties sent from symbols that should not be kept // in footprints. - if( pName == "ki_keywords" || pName == "ki_fp_filters" || pName == "ki_locked" ) + if( pName == "ki_keywords" || pName == "ki_locked" ) { NeedRIGHT(); break; @@ -3868,6 +3868,13 @@ FOOTPRINT* PCB_PARSER::parseFOOTPRINT_unchecked( wxArrayString* aInitialComments break; } + if( pName == "ki_fp_filters" ) + { + footprint->SetFilters( pValue ); + NeedRIGHT(); + break; + } + // Sheet file and name used to be stored as properties invisible to the user if( pName == "Sheetfile" || pName == "Sheet file" ) { @@ -3892,8 +3899,8 @@ FOOTPRINT* PCB_PARSER::parseFOOTPRINT_unchecked( wxArrayString* aInitialComments } else { - field = footprint->AddField( - PCB_FIELD( footprint.get(), footprint->GetFieldCount(), pName ) ); + field = footprint->AddField( PCB_FIELD( footprint.get(), footprint->GetFieldCount(), + pName ) ); field->SetText( pValue ); field->SetLayer( footprint->GetLayer() == F_Cu ? F_Fab : B_Fab ); diff --git a/pcbnew/plugins/kicad/pcb_plugin.cpp b/pcbnew/plugins/kicad/pcb_plugin.cpp index 61ca98d891..f00bbf669a 100644 --- a/pcbnew/plugins/kicad/pcb_plugin.cpp +++ b/pcbnew/plugins/kicad/pcb_plugin.cpp @@ -1154,6 +1154,12 @@ void PCB_PLUGIN::format( const FOOTPRINT* aFootprint, int aNestLevel ) const m_out->Print( aNestLevel + 1, ")\n" ); } + if( !aFootprint->GetFilters().empty() ) + { + m_out->Print( aNestLevel + 1, "(property ki_fp_filters %s)\n", + m_out->Quotew( aFootprint->GetFilters() ).c_str() ); + } + if( !( m_ctl & CTL_OMIT_PATH ) && !aFootprint->GetPath().empty() ) { m_out->Print( aNestLevel+1, "(path %s)\n", diff --git a/pcbnew/widgets/panel_footprint_chooser.cpp b/pcbnew/widgets/panel_footprint_chooser.cpp index 911a9fe146..ac9eeedaf5 100644 --- a/pcbnew/widgets/panel_footprint_chooser.cpp +++ b/pcbnew/widgets/panel_footprint_chooser.cpp @@ -43,11 +43,13 @@ PANEL_FOOTPRINT_CHOOSER::PANEL_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aFrame, wxTopLevelWindow* aParent, const wxArrayString& aFootprintHistoryList, + std::function aFilter, std::function aCloseHandler ) : wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize ), m_hsplitter( nullptr ), m_vsplitter( nullptr ), m_frame( aFrame ), + m_filter( std::move( aFilter ) ), m_closeHandler( std::move( aCloseHandler ) ) { FP_LIB_TABLE* fpTable = PROJECT_PCB::PcbFootprintLibs( &aFrame->Prj() ); @@ -87,7 +89,8 @@ PANEL_FOOTPRINT_CHOOSER::PANEL_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aFrame, wxTopL if( historyInfos.size() ) adapter->SetPreselectNode( historyInfos[0]->GetLibId(), 0 ); - adapter->AddLibraries( aFrame ); + adapter->SetFilter( &m_filter ); + adapter->AddLibraries( m_frame ); // ------------------------------------------------------------------------------------- // Construct the actual panel diff --git a/pcbnew/widgets/panel_footprint_chooser.h b/pcbnew/widgets/panel_footprint_chooser.h index 07a609b46b..412ca5f4db 100644 --- a/pcbnew/widgets/panel_footprint_chooser.h +++ b/pcbnew/widgets/panel_footprint_chooser.h @@ -46,6 +46,7 @@ public: */ PANEL_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aFrame, wxTopLevelWindow* aParent, const wxArrayString& aFootprintHistoryList, + std::function aFilter, std::function aCloseHandler ); ~PANEL_FOOTPRINT_CHOOSER(); @@ -65,6 +66,8 @@ public: wxWindow* GetFocusTarget() const { return m_tree->GetFocusTarget(); } + void Regenerate() { m_tree->Regenerate( true ); } + protected: static constexpr int DblClickDelay = 100; // milliseconds @@ -87,11 +90,12 @@ protected: wxObjectDataPtr m_adapter; - FOOTPRINT_PREVIEW_WIDGET* m_preview_ctrl; - LIB_TREE* m_tree; + FOOTPRINT_PREVIEW_WIDGET* m_preview_ctrl; + LIB_TREE* m_tree; - PCB_BASE_FRAME* m_frame; - std::function m_closeHandler; + PCB_BASE_FRAME* m_frame; + std::function m_filter; + std::function m_closeHandler; }; #endif /* PANEL_FOOTPRINT_CHOOSER_H */