ADDED support for pin and fp filtering in FOOTPRINT_CHOOSER.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/7176
This commit is contained in:
Jeff Young 2023-09-29 17:02:57 +01:00
parent 98685b37ff
commit fa11e9138d
27 changed files with 367 additions and 194 deletions

View File

@ -34,10 +34,10 @@
static const unsigned kLowestDefaultScore = 1; static const unsigned kLowestDefaultScore = 1;
void LIB_TREE_NODE::ResetScore() void LIB_TREE_NODE::ResetScore( std::function<bool( LIB_TREE_NODE& aNode )>* aFilter )
{ {
for( std::unique_ptr<LIB_TREE_NODE>& child: m_Children ) for( std::unique_ptr<LIB_TREE_NODE>& child: m_Children )
child->ResetScore(); child->ResetScore( aFilter );
m_Score = kLowestDefaultScore; 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_Name = aItem->GetName();
m_Desc = aItem->GetDescription(); m_Desc = aItem->GetDescription();
m_Footprint = aItem->GetFootprint(); m_Footprint = aItem->GetFootprint();
m_PinCount = aItem->GetPinCount();
aItem->GetChooserFields( m_Fields ); 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<bool( LIB_TREE_NODE& aNode )>* aFilter )
{
for( std::unique_ptr<LIB_TREE_NODE>& 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 ) if( m_Score <= 0 )
return; // Leaf nodes without scores are out of the game. 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; 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; 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 ); m_Score = std::max( m_Score, child->m_Score );
} }
} }
else else if( aMatcher )
{ {
// No children; we are a leaf. // 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<LIB_TREE_NODE>& child: m_Children ) for( std::unique_ptr<LIB_TREE_NODE>& child: m_Children )
child->UpdateScore( aMatcher, aLib ); child->UpdateScore( aMatcher, aLib );

View File

@ -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, LIB_TREE_MODEL_ADAPTER::LIB_TREE_MODEL_ADAPTER( EDA_BASE_FRAME* aParent,
const wxString& aPinnedKey ) : const wxString& aPinnedKey ) :
m_parent( aParent ), m_parent( aParent ),
m_filter( SYM_FILTER_NONE ),
m_sort_mode( BEST_MATCH ), m_sort_mode( BEST_MATCH ),
m_show_units( true ), m_show_units( true ),
m_preselect_unit( 0 ), m_preselect_unit( 0 ),
m_freeze( 0 ), m_freeze( 0 ),
m_widget( nullptr ) m_widget( nullptr ),
m_filter( nullptr )
{ {
// Default column widths. Do not translate these names. // Default column widths. Do not translate these names.
m_colWidths[ _HKI( "Item" ) ] = 300; 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 ) void LIB_TREE_MODEL_ADAPTER::ShowUnits( bool aShow )
{ {
m_show_units = aShow; m_show_units = aShow;
@ -171,24 +165,31 @@ void LIB_TREE_MODEL_ADAPTER::UpdateSearchString( const wxString& aSearch, bool a
Freeze(); Freeze();
BeforeReset(); BeforeReset();
m_tree.ResetScore(); m_tree.ResetScore( m_filter );
wxStringTokenizer tokenizer( aSearch ); wxStringTokenizer tokenizer( aSearch );
while( tokenizer.HasMoreTokens() ) if( tokenizer.HasMoreTokens() )
{ {
wxString lib; while( tokenizer.HasMoreTokens() )
wxString term = tokenizer.GetNextToken().Lower();
if( term.Contains( ":" ) )
{ {
lib = term.BeforeFirst( ':' ); wxString lib;
term = term.AfterFirst( ':' ); 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 ); else
{
m_tree.UpdateScore( matcher, lib ); m_tree.UpdateScore( nullptr, wxEmptyString );
} }
m_tree.SortNodes( m_sort_mode == BEST_MATCH ); m_tree.SortNodes( m_sort_mode == BEST_MATCH );

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2021 CERN * 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -271,7 +271,7 @@ protected:
if( !m_symbolNetlist.empty() ) 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 ); frame->KiwayMailIn( event );
} }
@ -281,17 +281,14 @@ protected:
frame->Destroy(); frame->Destroy();
} }
protected:
DIALOG_SHIM* m_dlg; DIALOG_SHIM* m_dlg;
wxString m_preselect; wxString m_preselect;
/* /*
* Symbol netlist format: * Symbol netlist format:
* library:footprint * pinCount
* reference * fpFilters
* value
* pinName,netName,pinFunction,pinType
* pinName,netName,pinFunction,pinType
* ...
*/ */
std::string m_symbolNetlist; std::string m_symbolNetlist;
}; };

View File

@ -64,27 +64,19 @@ static wxString netList( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH& aSheetPath )
{ {
/* /*
* Symbol netlist format: * Symbol netlist format:
* library:footprint * pinCount
* reference * fpFilters
* value
* pinName,netName,pinFunction,pinType
* pinName,netName,pinFunction,pinType
* ...
*/ */
wxString netlist; wxString netlist;
netlist << EscapeString( aSymbol->GetFootprintFieldText( true, &aSheetPath, false ), CTX_LINE ) << wxS( "\r" ); netlist << wxString::Format( wxS( "%d\r" ), aSymbol->GetPins().size() );
netlist << EscapeString( aSymbol->GetRef( &aSheetPath ), CTX_LINE ) << wxS( "\r" );
netlist << EscapeString( aSymbol->GetValueFieldText( true, &aSheetPath, false ), CTX_LINE );
for( SCH_PIN* pin : aSymbol->GetPins( &aSheetPath ) ) wxArrayString fpFilters = aSymbol->GetLibSymbolRef()->GetFPFilters();
{
netlist << wxS( "\r" ); if( !fpFilters.IsEmpty() )
netlist << EscapeString( pin->GetNumber(), CTX_CSV ) << wxS( "," ); netlist << EscapeString( wxJoin( fpFilters, ' ' ), CTX_LINE );
netlist << EscapeString( pin->GetDefaultNetName( aSheetPath ), CTX_CSV ) << wxS( "," );
netlist << EscapeString( pin->GetName(), CTX_CSV ) << wxS( "," ); netlist << wxS( "\r" );
netlist << EscapeString( pin->GetCanonicalElectricalTypeName(), CTX_CSV );
}
return netlist; return netlist;
} }

View File

@ -456,7 +456,7 @@ public:
/** /**
* @return a count of pins for all units / converts. * @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. * Return pin object with the requested pin \a aNumber.

View File

@ -399,6 +399,18 @@ XNODE* NETLIST_EXPORTER_XML::makeSymbols( unsigned aCtl )
xproperty->AddAttribute( wxT( "name" ), wxT( "ki_keywords" ) ); xproperty->AddAttribute( wxT( "name" ), wxT( "ki_keywords" ) );
xproperty->AddAttribute( wxT( "value" ), part->GetKeyWords() ); 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; XNODE* xsheetpath;

View File

@ -61,7 +61,7 @@ public:
* see SCH_BASE_FRAME::SelectSymbolFromLibrary() for details. * see SCH_BASE_FRAME::SelectSymbolFromLibrary() for details.
* if aFilter == NULL, remove all filtering. * if aFilter == NULL, remove all filtering.
*/ */
void SetFilter( const SYMBOL_LIBRARY_FILTER* aFilter ); void SetFilter( std::function<bool( LIB_TREE_NODE& aNode )>* aFilter );
private: private:
void OnPaint( wxPaintEvent& aEvent ); void OnPaint( wxPaintEvent& aEvent );

View File

@ -80,9 +80,8 @@ bool SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( const std::vector<wxString>& aNick
std::unordered_map<wxString, std::vector<LIB_SYMBOL*>> loadedSymbols; std::unordered_map<wxString, std::vector<LIB_SYMBOL*>> loadedSymbols;
SYMBOL_ASYNC_LOADER loader( aNicknames, m_libs, SYMBOL_ASYNC_LOADER loader( aNicknames, m_libs, GetFilter() != nullptr, &loadedSymbols,
GetFilter() == LIB_TREE_MODEL_ADAPTER::SYM_FILTER_POWER, progressReporter.get() );
&loadedSymbols, progressReporter.get() );
LOCALE_IO toggle; LOCALE_IO toggle;
@ -204,7 +203,7 @@ bool SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( const std::vector<wxString>& aNick
void SYMBOL_TREE_MODEL_ADAPTER::AddLibrary( wxString const& aLibNickname, bool pinned ) void SYMBOL_TREE_MODEL_ADAPTER::AddLibrary( wxString const& aLibNickname, bool pinned )
{ {
bool onlyPowerSymbols = ( GetFilter() == SYM_FILTER_POWER ); bool onlyPowerSymbols = ( GetFilter() != nullptr );
std::vector<LIB_SYMBOL*> symbols; std::vector<LIB_SYMBOL*> symbols;
std::vector<LIB_TREE_ITEM*> comp_list; std::vector<LIB_TREE_ITEM*> comp_list;

View File

@ -102,7 +102,17 @@ PANEL_SYMBOL_CHOOSER::PANEL_SYMBOL_CHOOSER( SCH_BASE_FRAME* aFrame, wxWindow* aP
if( aFilter->GetFilterPowerSymbols() ) 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<bool( LIB_TREE_NODE& )> powerFilter =
[]( LIB_TREE_NODE& ) -> bool
{
return true;
};
adapter->SetFilter( &powerFilter );
m_showPower = true; m_showPower = true;
m_show_footprints = false; m_show_footprints = false;
} }

View File

@ -72,6 +72,8 @@ public:
wxString GetName() const override { return m_fpname; } wxString GetName() const override { return m_fpname; }
int GetPinCount() override { return GetUniquePadCount(); }
LIB_ID GetLibId() const override LIB_ID GetLibId() const override
{ {
return LIB_ID( m_nickname, m_fpname ); return LIB_ID( m_nickname, m_fpname );

View File

@ -68,6 +68,11 @@ public:
*/ */
virtual wxString GetFootprint() { return wxEmptyString; } 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. * For items with units, return the number of units.
*/ */

View File

@ -80,12 +80,12 @@ public:
* *
* @param aMatcher an EDA_COMBINED_MATCHER initialized with the search term * @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. * Initialize score to kLowestDefaultScore, recursively.
*/ */
void ResetScore(); virtual void ResetScore( std::function<bool( LIB_TREE_NODE& aNode )>* aFilter );
/** /**
* Store intrinsic ranks on all children of this node. See m_IntrinsicRank * 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_Name; // Actual name of the part
wxString m_Desc; // Description to be displayed wxString m_Desc; // Description to be displayed
wxString m_Footprint; // Footprint ID as a string (ie: the footprint field text) 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<SEARCH_TERM> m_SearchTerms; /// List of weighted search terms std::vector<SEARCH_TERM> m_SearchTerms; /// List of weighted search terms
std::map<wxString, wxString> m_Fields; /// @see LIB_TREE_ITEMS::GetChooserFields std::map<wxString, wxString> m_Fields; /// @see LIB_TREE_ITEMS::GetChooserFields
@ -174,7 +175,7 @@ public:
/** /**
* Do nothing, units just take the parent's score * 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 Update( LIB_TREE_ITEM* aItem );
void ResetScore( std::function<bool( LIB_TREE_NODE& aNode )>* aFilter ) override;
/** /**
* Perform the actual search. * 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: protected:
/** /**
@ -254,7 +257,7 @@ public:
*/ */
LIB_TREE_NODE_LIB_ID& AddItem( LIB_TREE_ITEM* aItem ); 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 ); 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;
}; };

View File

@ -114,15 +114,6 @@ public:
*/ */
~LIB_TREE_MODEL_ADAPTER(); ~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 * 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 * @param aFilter if SYM_FILTER_POWER, only power parts are loaded
*/ */
void SetFilter( SYM_FILTER_TYPE aFilter ); void SetFilter( std::function<bool( LIB_TREE_NODE& aNode )>* aFilter ) { m_filter = aFilter; }
/** /**
* Return the active filter. * Return the active filter.
*/ */
SYM_FILTER_TYPE GetFilter() const { return m_filter; } std::function<bool( LIB_TREE_NODE& aNode )>* GetFilter() const { return m_filter; }
void SetSortMode( SORT_MODE aMode ) { m_sort_mode = aMode; } void SetSortMode( SORT_MODE aMode ) { m_sort_mode = aMode; }
SORT_MODE GetSortMode() const { return m_sort_mode; } SORT_MODE GetSortMode() const { return m_sort_mode; }
@ -397,11 +388,6 @@ protected:
void resortTree(); void resortTree();
private: private:
/**
* Find any results worth highlighting and expand them.
*/
void Find( LIB_TREE_NODE& aNode, std::function<bool( const LIB_TREE_NODE* )> aFunc );
/** /**
* Find and expand successful search results. Return the best match (if any). * Find and expand successful search results. Return the best match (if any).
*/ */
@ -419,21 +405,22 @@ protected:
std::vector<wxString> m_availableColumns; std::vector<wxString> m_availableColumns;
private: private:
EDA_BASE_FRAME* m_parent; EDA_BASE_FRAME* m_parent;
SYM_FILTER_TYPE m_filter; SORT_MODE m_sort_mode;
SORT_MODE m_sort_mode; bool m_show_units;
bool m_show_units; LIB_ID m_preselect_lib_id;
LIB_ID m_preselect_lib_id; int m_preselect_unit;
int m_preselect_unit; int m_freeze;
int m_freeze;
wxDataViewCtrl* m_widget; wxDataViewCtrl* m_widget;
std::vector<wxDataViewColumn*> m_columns; std::function<bool( LIB_TREE_NODE& aNode )>* m_filter;
std::map<wxString, wxDataViewColumn*> m_colNameMap;
std::map<wxString, int> m_colWidths; std::vector<wxDataViewColumn*> m_columns;
std::vector<wxString> m_shownColumns; // Stored in display order std::map<wxString, wxDataViewColumn*> m_colNameMap;
std::map<wxString, int> m_colWidths;
std::vector<wxString> m_shownColumns; // Stored in display order
}; };
#endif // LIB_TREE_MODEL_ADAPTER_H #endif // LIB_TREE_MODEL_ADAPTER_H

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2014 CERN * 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 <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
* This program is free software; you can redistribute it and/or * 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_ASSIGN_FOOTPRINTS, // CVPCB->SCH footprint stuffing
MAIL_SCH_SAVE, // CVPCB->SCH save the schematic MAIL_SCH_SAVE, // CVPCB->SCH save the schematic
MAIL_EESCHEMA_NETLIST, // SCH->CVPCB netlist immediately after launching CVPCB 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_PCB_UPDATE, // SCH->PCB forward update
MAIL_SCH_UPDATE, // PCB->SCH forward update MAIL_SCH_UPDATE, // PCB->SCH forward update
MAIL_IMPORT_FILE, // Import a different format file MAIL_IMPORT_FILE, // Import a different format file

View File

@ -4,7 +4,7 @@
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2013 Wayne Stambaugh <stambaughw@gmail.com> * Copyright (C) 2013 Wayne Stambaugh <stambaughw@gmail.com>
* 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -30,6 +30,7 @@
#include <dialog_exchange_footprints.h> #include <dialog_exchange_footprints.h>
#include <string_utils.h> #include <string_utils.h>
#include <kiway.h> #include <kiway.h>
#include <kiway_express.h>
#include <macros.h> #include <macros.h>
#include <pcb_edit_frame.h> #include <pcb_edit_frame.h>
#include <pcbnew_settings.h> #include <pcbnew_settings.h>
@ -403,6 +404,23 @@ void DIALOG_EXCHANGE_FOOTPRINTS::ViewAndSelectFootprint( wxCommandEvent& event )
KIWAY_PLAYER* frame = Kiway().Player( FRAME_FOOTPRINT_CHOOSER, true ); 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( frame->ShowModal( &newname, this ) )
{ {
if( event.GetEventObject() == m_newIDBrowseButton ) if( event.GetEventObject() == m_newIDBrowseButton )

View File

@ -36,10 +36,16 @@ DIALOG_FOOTPRINT_CHOOSER::DIALOG_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aParent,
{ {
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL ); wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
m_chooserPanel = new PANEL_FOOTPRINT_CHOOSER( aParent, this, aFootprintHistoryList, m_chooserPanel = new PANEL_FOOTPRINT_CHOOSER( aParent, this, aFootprintHistoryList,
[this]() // Filter
{ []( LIB_TREE_NODE& aNode ) -> bool
EndModal( wxID_OK ); {
} ); return true;
},
// Close handler
[this]()
{
EndModal( wxID_OK );
} );
sizer->Add( m_chooserPanel, 1, wxEXPAND, 5 ); sizer->Add( m_chooserPanel, 1, wxEXPAND, 5 );

View File

@ -248,6 +248,9 @@ public:
wxString GetSheetfile() const { return m_sheetfile; } wxString GetSheetfile() const { return m_sheetfile; }
void SetSheetfile( const wxString& aSheetfile ) { m_sheetfile = aSheetfile; } 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; } int GetLocalSolderMaskMargin() const { return m_localSolderMaskMargin; }
void SetLocalSolderMaskMargin( int aMargin ) { m_localSolderMaskMargin = aMargin; } void SetLocalSolderMaskMargin( int aMargin ) { m_localSolderMaskMargin = aMargin; }
@ -983,6 +986,7 @@ private:
KIID_PATH m_path; // Path to associated symbol ([sheetUUID, .., symbolUUID]). 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_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_sheetfile; // File of the sheet containing the symbol for this footprint
wxString m_filters; // Footprint filters from symbol
timestamp_t m_lastEditTime; timestamp_t m_lastEditTime;
int m_arflag; // Use to trace ratsnest and auto routing. int m_arflag; // Use to trace ratsnest and auto routing.
KIID m_link; // Temporary logical link used during editing KIID m_link; // Temporary logical link used during editing

View File

@ -22,9 +22,11 @@
*/ */
#include <pgm_base.h> #include <pgm_base.h>
#include <kiface_base.h>
#include <kiway.h> #include <kiway.h>
#include <kiway_express.h> #include <kiway_express.h>
#include <wx/button.h> #include <wx/button.h>
#include <wx/checkbox.h>
#include <kiplatform/ui.h> #include <kiplatform/ui.h>
#include <widgets/panel_footprint_chooser.h> #include <widgets/panel_footprint_chooser.h>
#include <settings/settings_manager.h> #include <settings/settings_manager.h>
@ -38,7 +40,7 @@ static unsigned s_FootprintHistoryMaxCount = 8;
static void AddFootprintToHistory( const wxString& aName ) static void AddFootprintToHistory( const wxString& aName )
{ {
// Remove duplicates // 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 ) if( s_FootprintHistoryList[ ii ] == aName )
s_FootprintHistoryList.RemoveAt( (size_t) ii ); 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 ) 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_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 ) EVT_PAINT( FOOTPRINT_CHOOSER_FRAME::OnPaint )
END_EVENT_TABLE() END_EVENT_TABLE()
@ -68,31 +70,62 @@ END_EVENT_TABLE()
FOOTPRINT_CHOOSER_FRAME::FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aParent ) : FOOTPRINT_CHOOSER_FRAME::FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
PCB_BASE_FRAME( aKiway, aParent, FRAME_FOOTPRINT_CHOOSER, _( "Footprint Chooser" ), PCB_BASE_FRAME( aKiway, aParent, FRAME_FOOTPRINT_CHOOSER, _( "Footprint Chooser" ),
wxDefaultPosition, wxDefaultSize, aParent ? PARENT_STYLE : MODAL_STYLE, wxDefaultPosition, wxDefaultSize, aParent ? PARENT_STYLE : MODAL_STYLE,
FOOTPRINT_CHOOSER_FRAME_NAME ), FOOTPRINT_CHOOSER_FRAME_NAME ),
m_comp( LIB_ID(), wxEmptyString, wxEmptyString, KIID_PATH(), {} ) m_filterByPinCount( nullptr ),
m_filterByFPFilters( nullptr ),
m_pinCount( 0 )
{ {
SetModal( true ); SetModal( true );
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL ); wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
m_chooserPanel = new PANEL_FOOTPRINT_CHOOSER( this, this, s_FootprintHistoryList, m_chooserPanel = new PANEL_FOOTPRINT_CHOOSER( this, this, s_FootprintHistoryList,
[this]() // Filter
{ [this]( LIB_TREE_NODE& aNode ) -> bool
wxCommandEvent dummy; {
OnOK( dummy ); return filterFootprint( aNode );
} ); },
// Close handler
[this]()
{
wxCommandEvent dummy;
OnOK( dummy );
} );
sizer->Add( m_chooserPanel, 1, wxEXPAND, 5 ); 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<PCBNEW_SETTINGS*>( 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(); wxStdDialogButtonSizer* sdbSizer = new wxStdDialogButtonSizer();
wxButton* okButton = new wxButton( this, wxID_OK ); wxButton* okButton = new wxButton( this, wxID_OK );
wxButton* cancelButton = new wxButton( this, wxID_CANCEL ); wxButton* cancelButton = new wxButton( this, wxID_CANCEL );
sdbSizer->AddButton( okButton ); sdbSizer->AddButton( okButton );
sdbSizer->AddButton( cancelButton ); sdbSizer->AddButton( cancelButton );
sdbSizer->Realize(); sdbSizer->Realize();
sizer->Add( sdbSizer, 0, wxEXPAND | wxALL, 5 ); buttonsSizer->Add( sdbSizer, 1, wxALL, 5 );
sizer->Add( buttonsSizer, 0, wxEXPAND | wxLEFT, 5 );
SetSizer( sizer ); SetSizer( sizer );
SetTitle( GetTitle() + wxString::Format( _( " (%d items loaded)" ), SetTitle( GetTitle() + wxString::Format( _( " (%d items loaded)" ),
@ -100,6 +133,61 @@ FOOTPRINT_CHOOSER_FRAME::FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aPare
Layout(); Layout();
m_chooserPanel->FinishSetup(); 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<PCBNEW_SETTINGS*>( 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<EDA_PATTERN_MATCH>& 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 ) 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(); const std::string& payload = mail.GetPayload();
switch( mail.Command() ) switch( mail.Command() )
{ {
case MAIL_SYMBOL_NETLIST: case MAIL_SYMBOL_NETLIST:
{ {
m_pinCount = 0;
m_fpFilters.clear();
/* /*
* Symbol netlist format: * Symbol netlist format:
* library:footprint * pinCount
* reference * fpFilters
* value
* pinName,netName,pinFunction,pinType
* pinName,netName,pinFunction,pinType
* ...
*/ */
std::vector<std::string> strings = split( payload, "\r" ); std::vector<std::string> 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 ); if( m_pinCount > 0 )
m_comp.SetReference( strings[1] );
m_comp.SetValue( strings[2] );
m_comp.ClearNets();
for( size_t ii = 3; ii < strings.size(); ++ii )
{ {
std::vector<std::string> pinData = split( strings[ii], "," ); m_filterByPinCount->SetLabel( m_filterByPinCount->GetLabel()
m_comp.AddNet( pinData[0], pinData[1], pinData[2], pinData[3] ); + 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<EDA_PATTERN_MATCH_WILDCARD_ANCHORED>() );
m_fpFilters.back()->SetPattern( filter.Lower() );
}
m_filterByFPFilters->SetLabel( m_filterByFPFilters->GetLabel()
+ wxString::Format( wxS( " (%s)" ), strings[1] ) );
m_filterByFPFilters->Show( true );
}
break; 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 ); Close( false );
} }

View File

@ -31,6 +31,7 @@
#include <netlist_reader/pcb_netlist.h> #include <netlist_reader/pcb_netlist.h>
class PANEL_FOOTPRINT_CHOOSER; class PANEL_FOOTPRINT_CHOOSER;
class wxCheckBox;
namespace PCB { struct IFACE; } namespace PCB { struct IFACE; }
@ -38,7 +39,7 @@ namespace PCB { struct IFACE; }
class FOOTPRINT_CHOOSER_FRAME : public PCB_BASE_FRAME class FOOTPRINT_CHOOSER_FRAME : public PCB_BASE_FRAME
{ {
public: public:
~FOOTPRINT_CHOOSER_FRAME() {}; ~FOOTPRINT_CHOOSER_FRAME();
///< @copydoc PCB_BASE_FRAME::GetModel() ///< @copydoc PCB_BASE_FRAME::GetModel()
BOARD_ITEM_CONTAINER* GetModel() const override { return nullptr; } BOARD_ITEM_CONTAINER* GetModel() const override { return nullptr; }
@ -55,11 +56,13 @@ protected:
FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aParent ); FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aParent );
private: private:
bool filterFootprint( LIB_TREE_NODE& aNode );
void OnPaint( wxPaintEvent& aEvent ); void OnPaint( wxPaintEvent& aEvent );
void OnOK( wxCommandEvent& aEvent ); void OnOK( wxCommandEvent& aEvent );
void doCloseWindow() override; void doCloseWindow() override;
void CloseFootprintChooser( wxCommandEvent& aEvent ); void closeFootprintChooser( wxCommandEvent& aEvent );
WINDOW_SETTINGS* GetWindowSettings( APP_SETTINGS_BASE* aCfg ) override; WINDOW_SETTINGS* GetWindowSettings( APP_SETTINGS_BASE* aCfg ) override;
COLOR_SETTINGS* GetColorSettings( bool aForceRefresh ) const override; COLOR_SETTINGS* GetColorSettings( bool aForceRefresh ) const override;
@ -70,7 +73,11 @@ private:
private: private:
PANEL_FOOTPRINT_CHOOSER* m_chooserPanel; PANEL_FOOTPRINT_CHOOSER* m_chooserPanel;
COMPONENT m_comp; wxCheckBox* m_filterByPinCount;
wxCheckBox* m_filterByFPFilters;
int m_pinCount;
std::vector<std::unique_ptr<EDA_PATTERN_MATCH>> m_fpFilters;
// On MacOS (at least) SetFocus() calls made in the constructor will fail because a // 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 // window that isn't yet visible will return false to AcceptsFocus(). So we must delay

View File

@ -954,51 +954,14 @@ void FOOTPRINT_VIEWER_FRAME::ReloadFootprint( FOOTPRINT* aFootprint )
void FOOTPRINT_VIEWER_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail ) void FOOTPRINT_VIEWER_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
{ {
const std::string& payload = mail.GetPayload();
switch( mail.Command() ) switch( mail.Command() )
{ {
case MAIL_SYMBOL_NETLIST:
{
/*
* Symbol netlist format:
* library:footprint
* reference
* value
* pinName,netName,pinFunction,pinType
* pinName,netName,pinFunction,pinType
* ...
*/
std::vector<std::string> 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<std::string> pinData = split( strings[ii], "," );
m_comp.AddNet( pinData[0], pinData[1], pinData[2], pinData[3] );
}
}
break;
}
case MAIL_RELOAD_LIB: case MAIL_RELOAD_LIB:
{
ReCreateLibraryList(); ReCreateLibraryList();
break; break;
}
default: default:
; break;
} }
} }

View File

@ -413,6 +413,7 @@ bool BOARD_NETLIST_UPDATER::updateFootprintParameters( FOOTPRINT* aPcbFootprint,
wxString sheetname; wxString sheetname;
wxString sheetfile; wxString sheetfile;
wxString fpFilters;
if( aNetlistComponent->GetProperties().count( wxT( "Sheetname" ) ) > 0 ) if( aNetlistComponent->GetProperties().count( wxT( "Sheetname" ) ) > 0 )
sheetname = aNetlistComponent->GetProperties().at( wxT( "Sheetname" ) ); sheetname = aNetlistComponent->GetProperties().at( wxT( "Sheetname" ) );
@ -420,15 +421,22 @@ bool BOARD_NETLIST_UPDATER::updateFootprintParameters( FOOTPRINT* aPcbFootprint,
if( aNetlistComponent->GetProperties().count( wxT( "Sheetfile" ) ) > 0 ) if( aNetlistComponent->GetProperties().count( wxT( "Sheetfile" ) ) > 0 )
sheetfile = aNetlistComponent->GetProperties().at( wxT( "Sheetfile" ) ); 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( sheetname != aPcbFootprint->GetSheetname() )
{ {
if( m_isDryRun ) if( m_isDryRun )
msg.Printf( _( "Update %s sheetname to '%s'." ), aPcbFootprint->GetReference(), {
msg.Printf( _( "Update %s sheetname to '%s'." ),
aPcbFootprint->GetReference(),
sheetname ); sheetname );
}
else else
{ {
aPcbFootprint->SetSheetname( sheetname ); aPcbFootprint->SetSheetname( sheetname );
msg.Printf( _( "Updated %s sheetname to '%s'." ), aPcbFootprint->GetReference(), msg.Printf( _( "Updated %s sheetname to '%s'." ),
aPcbFootprint->GetReference(),
sheetname ); sheetname );
} }
@ -438,18 +446,41 @@ bool BOARD_NETLIST_UPDATER::updateFootprintParameters( FOOTPRINT* aPcbFootprint,
if( sheetfile != aPcbFootprint->GetSheetfile() ) if( sheetfile != aPcbFootprint->GetSheetfile() )
{ {
if( m_isDryRun ) if( m_isDryRun )
msg.Printf( _( "Update %s sheetfile to '%s'." ), aPcbFootprint->GetReference(), {
msg.Printf( _( "Update %s sheetfile to '%s'." ),
aPcbFootprint->GetReference(),
sheetfile ); sheetfile );
}
else else
{ {
aPcbFootprint->SetSheetfile( sheetfile ); aPcbFootprint->SetSheetfile( sheetfile );
msg.Printf( _( "Updated %s sheetfile to '%s'." ), aPcbFootprint->GetReference(), msg.Printf( _( "Updated %s sheetfile to '%s'." ),
aPcbFootprint->GetReference(),
sheetfile ); sheetfile );
} }
m_reporter->Report( msg, RPT_SEVERITY_ACTION ); 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 ) if( ( aNetlistComponent->GetProperties().count( wxT( "exclude_from_bom" ) ) > 0 )
!= ( ( aPcbFootprint->GetAttributes() & FP_EXCLUDE_FROM_BOM ) > 0 ) ) != ( ( aPcbFootprint->GetAttributes() & FP_EXCLUDE_FROM_BOM ) > 0 ) )
{ {

View File

@ -142,6 +142,12 @@ PCBNEW_SETTINGS::PCBNEW_SETTINGS()
m_params.emplace_back( new PARAM<int>( "footprint_chooser.sort_mode", m_params.emplace_back( new PARAM<int>( "footprint_chooser.sort_mode",
&m_FootprintChooser.sort_mode, 0 ) ); &m_FootprintChooser.sort_mode, 0 ) );
m_params.emplace_back( new PARAM<bool>( "footprint_chooser.filter_on_pin_count",
&m_FootprintChooser.filter_on_pin_count, false ) );
m_params.emplace_back( new PARAM<bool>( "footprint_chooser.use_fp_filters",
&m_FootprintChooser.use_fp_filters, false ) );
m_params.emplace_back( new PARAM<bool>( "editing.flip_left_right", m_params.emplace_back( new PARAM<bool>( "editing.flip_left_right",
&m_FlipLeftRight, true ) ); &m_FlipLeftRight, true ) );

View File

@ -298,11 +298,13 @@ public:
struct FOOTPRINT_CHOOSER struct FOOTPRINT_CHOOSER
{ {
int width; int width;
int height; int height;
int sash_h; int sash_h;
int sash_v; int sash_v;
int sort_mode; int sort_mode;
bool use_fp_filters;
bool filter_on_pin_count;
}; };
struct ZONES struct ZONES

View File

@ -3853,7 +3853,7 @@ FOOTPRINT* PCB_PARSER::parseFOOTPRINT_unchecked( wxArrayString* aInitialComments
// Skip legacy non-field properties sent from symbols that should not be kept // Skip legacy non-field properties sent from symbols that should not be kept
// in footprints. // in footprints.
if( pName == "ki_keywords" || pName == "ki_fp_filters" || pName == "ki_locked" ) if( pName == "ki_keywords" || pName == "ki_locked" )
{ {
NeedRIGHT(); NeedRIGHT();
break; break;
@ -3868,6 +3868,13 @@ FOOTPRINT* PCB_PARSER::parseFOOTPRINT_unchecked( wxArrayString* aInitialComments
break; 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 // Sheet file and name used to be stored as properties invisible to the user
if( pName == "Sheetfile" || pName == "Sheet file" ) if( pName == "Sheetfile" || pName == "Sheet file" )
{ {
@ -3892,8 +3899,8 @@ FOOTPRINT* PCB_PARSER::parseFOOTPRINT_unchecked( wxArrayString* aInitialComments
} }
else else
{ {
field = footprint->AddField( field = footprint->AddField( PCB_FIELD( footprint.get(), footprint->GetFieldCount(),
PCB_FIELD( footprint.get(), footprint->GetFieldCount(), pName ) ); pName ) );
field->SetText( pValue ); field->SetText( pValue );
field->SetLayer( footprint->GetLayer() == F_Cu ? F_Fab : B_Fab ); field->SetLayer( footprint->GetLayer() == F_Cu ? F_Fab : B_Fab );

View File

@ -1154,6 +1154,12 @@ void PCB_PLUGIN::format( const FOOTPRINT* aFootprint, int aNestLevel ) const
m_out->Print( aNestLevel + 1, ")\n" ); 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() ) if( !( m_ctl & CTL_OMIT_PATH ) && !aFootprint->GetPath().empty() )
{ {
m_out->Print( aNestLevel+1, "(path %s)\n", m_out->Print( aNestLevel+1, "(path %s)\n",

View File

@ -43,11 +43,13 @@
PANEL_FOOTPRINT_CHOOSER::PANEL_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aFrame, wxTopLevelWindow* aParent, PANEL_FOOTPRINT_CHOOSER::PANEL_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aFrame, wxTopLevelWindow* aParent,
const wxArrayString& aFootprintHistoryList, const wxArrayString& aFootprintHistoryList,
std::function<bool( LIB_TREE_NODE& )> aFilter,
std::function<void()> aCloseHandler ) : std::function<void()> aCloseHandler ) :
wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize ), wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize ),
m_hsplitter( nullptr ), m_hsplitter( nullptr ),
m_vsplitter( nullptr ), m_vsplitter( nullptr ),
m_frame( aFrame ), m_frame( aFrame ),
m_filter( std::move( aFilter ) ),
m_closeHandler( std::move( aCloseHandler ) ) m_closeHandler( std::move( aCloseHandler ) )
{ {
FP_LIB_TABLE* fpTable = PROJECT_PCB::PcbFootprintLibs( &aFrame->Prj() ); 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() ) if( historyInfos.size() )
adapter->SetPreselectNode( historyInfos[0]->GetLibId(), 0 ); adapter->SetPreselectNode( historyInfos[0]->GetLibId(), 0 );
adapter->AddLibraries( aFrame ); adapter->SetFilter( &m_filter );
adapter->AddLibraries( m_frame );
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
// Construct the actual panel // Construct the actual panel

View File

@ -46,6 +46,7 @@ public:
*/ */
PANEL_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aFrame, wxTopLevelWindow* aParent, PANEL_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aFrame, wxTopLevelWindow* aParent,
const wxArrayString& aFootprintHistoryList, const wxArrayString& aFootprintHistoryList,
std::function<bool( LIB_TREE_NODE& )> aFilter,
std::function<void()> aCloseHandler ); std::function<void()> aCloseHandler );
~PANEL_FOOTPRINT_CHOOSER(); ~PANEL_FOOTPRINT_CHOOSER();
@ -65,6 +66,8 @@ public:
wxWindow* GetFocusTarget() const { return m_tree->GetFocusTarget(); } wxWindow* GetFocusTarget() const { return m_tree->GetFocusTarget(); }
void Regenerate() { m_tree->Regenerate( true ); }
protected: protected:
static constexpr int DblClickDelay = 100; // milliseconds static constexpr int DblClickDelay = 100; // milliseconds
@ -87,11 +90,12 @@ protected:
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER> m_adapter; wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER> m_adapter;
FOOTPRINT_PREVIEW_WIDGET* m_preview_ctrl; FOOTPRINT_PREVIEW_WIDGET* m_preview_ctrl;
LIB_TREE* m_tree; LIB_TREE* m_tree;
PCB_BASE_FRAME* m_frame; PCB_BASE_FRAME* m_frame;
std::function<void()> m_closeHandler; std::function<bool( LIB_TREE_NODE& )> m_filter;
std::function<void()> m_closeHandler;
}; };
#endif /* PANEL_FOOTPRINT_CHOOSER_H */ #endif /* PANEL_FOOTPRINT_CHOOSER_H */