From 963a8ee42dd4a58bdb928c326853c122770de9c3 Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Fri, 24 Sep 2021 09:15:54 -0700 Subject: [PATCH] Warn users when creating footprints about mismatch Checks to see if the footprint attribute matches the type of pads contained in the footprint. Can prevent issues during fabrication if users forget to adjust them during creation. Fixes https://gitlab.com/kicad/code/kicad/issues/9215 --- pcbnew/footprint.cpp | 42 ++++++++++++++++++++++++++++ pcbnew/footprint.h | 13 +++++++++ pcbnew/footprint_libraries_utils.cpp | 32 +++++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/pcbnew/footprint.cpp b/pcbnew/footprint.cpp index 456d6260c0..0725e1f343 100644 --- a/pcbnew/footprint.cpp +++ b/pcbnew/footprint.cpp @@ -650,6 +650,48 @@ double FOOTPRINT::GetArea( int aPadding ) const } +int FOOTPRINT::GetLikelyAttribute() const +{ + int smd_count = 0; + int tht_count = 0; + + for( PAD* pad : m_pads ) + { + switch( pad->GetAttribute() ) + { + case PAD_ATTRIB::PTH: + tht_count++; + break; + case PAD_ATTRIB::SMD: + smd_count++; + break; + default: + break; + } + } + + if( tht_count > 0 ) + return FP_THROUGH_HOLE; + + if( smd_count > 0 ) + return FP_SMD; + + return 0; +} + + +wxString FOOTPRINT::GetTypeName() const +{ + if( ( m_attributes & FP_SMD ) == FP_SMD ) + return _( "SMD" ); + + if( ( m_attributes & FP_THROUGH_HOLE ) == FP_THROUGH_HOLE ) + return _( "Through hole" ); + + return _( "Other" ); +} + + EDA_RECT FOOTPRINT::GetFpPadsLocalBbox() const { EDA_RECT area; diff --git a/pcbnew/footprint.h b/pcbnew/footprint.h index 8ce689943d..5292f538fe 100644 --- a/pcbnew/footprint.h +++ b/pcbnew/footprint.h @@ -245,6 +245,13 @@ public: return GetKeywords().StartsWith( wxT( "net tie" ) ); } + /** + * Returns the most likely attribute based on pads + * Either FP_THROUGH_HOLE/FP_SMD/OTHER(0) + * @return 0/FP_SMD/FP_THROUGH_HOLE + */ + int GetLikelyAttribute() const; + void Move( const wxPoint& aMoveVector ) override; void Rotate( const wxPoint& aRotCentre, double aAngle ) override; @@ -531,6 +538,12 @@ public: */ wxString GetNextPadNumber( const wxString& aLastPadName ) const; + /** + * Get the type of footprint + * @return "SMD"/"Through hole"/"Other" based on attributes + */ + wxString GetTypeName() const; + double GetArea( int aPadding = 0 ) const; KIID GetLink() const { return m_link; } diff --git a/pcbnew/footprint_libraries_utils.cpp b/pcbnew/footprint_libraries_utils.cpp index 121622c924..3ff96c8580 100644 --- a/pcbnew/footprint_libraries_utils.cpp +++ b/pcbnew/footprint_libraries_utils.cpp @@ -784,6 +784,38 @@ bool FOOTPRINT_EDIT_FRAME::SaveFootprint( FOOTPRINT* aFootprint ) wxString libraryName = aFootprint->GetFPID().GetLibNickname(); wxString footprintName = aFootprint->GetFPID().GetLibItemName(); bool nameChanged = m_footprintNameWhenLoaded != footprintName; + int likelyAttr = aFootprint->GetLikelyAttribute(); + int setAttr = ( aFootprint->GetAttributes() & ( FP_SMD | FP_THROUGH_HOLE ) ); + + // This is only valid if the footprint doesn't have FP_SMD and FP_THROUGH_HOLE set + // Which is, unfortunately, possible in theory but not in the UI (I think) + if( likelyAttr != setAttr ) + { + wxString msg; + + if( likelyAttr == FP_THROUGH_HOLE ) + { + msg.Printf( _( "Your footprint has plated through hole pads but " + "its type is set to \"%s\"" ), aFootprint->GetTypeName() ); + } + else if( likelyAttr == FP_SMD ) + { + msg.Printf( _( "Your footprint has SMD pads but " + "its type is set to \"%s\"" ), aFootprint->GetTypeName() ); + } + else + { + msg.Printf( _( "Your footprint has no SMD or plated through hole pads but " + "its type is set to \"%s\"" ), aFootprint->GetTypeName() ); + } + + KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING ); + errorDlg.SetOKLabel( _( "Continue" ) ); + errorDlg.DoNotShowCheckbox( __FILE__, __LINE__ ); + + if( errorDlg.ShowModal() == wxID_CANCEL ) + return false; + } if( aFootprint->GetLink() != niluuid ) {