ADDED properties passed between eescema and pcbnew.

And referencable from textVars.

Fixes https://gitlab.com/kicad/code/kicad/issues/5079
This commit is contained in:
Jeff Young 2020-08-08 22:47:57 +01:00
parent 32a7d00256
commit 6b7503be8e
12 changed files with 138 additions and 40 deletions

View File

@ -28,6 +28,7 @@ part
pin pin
pins pins
pinfunction pinfunction
property
ref ref
sheetpath sheetpath
source source

View File

@ -205,9 +205,9 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeComponents( unsigned aCtl )
// Output is xml, so there is no reason to remove spaces from the field values. // Output is xml, so there is no reason to remove spaces from the field values.
// And XML element names need not be translated to various languages. // And XML element names need not be translated to various languages.
for( unsigned i = 0; i < sheetList.size(); i++ ) for( unsigned ii = 0; ii < sheetList.size(); ii++ )
{ {
SCH_SHEET_PATH sheet = sheetList[i]; SCH_SHEET_PATH sheet = sheetList[ii];
auto cmp = auto cmp =
[sheet]( SCH_COMPONENT* a, SCH_COMPONENT* b ) [sheet]( SCH_COMPONENT* a, SCH_COMPONENT* b )
@ -218,10 +218,10 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeComponents( unsigned aCtl )
std::set<SCH_COMPONENT*, decltype( cmp )> ordered_components( cmp ); std::set<SCH_COMPONENT*, decltype( cmp )> ordered_components( cmp );
for( auto item : sheetList[i].LastScreen()->Items().OfType( SCH_COMPONENT_T ) ) for( SCH_ITEM* item : sheetList[ii].LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
{ {
auto comp = static_cast<SCH_COMPONENT*>( item ); SCH_COMPONENT* comp = static_cast<SCH_COMPONENT*>( item );
auto test = ordered_components.insert( comp ); auto test = ordered_components.insert( comp );
if( !test.second ) if( !test.second )
{ {
@ -233,7 +233,7 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeComponents( unsigned aCtl )
} }
} }
for( auto item : ordered_components ) for( EDA_ITEM* item : ordered_components )
{ {
SCH_COMPONENT* comp = findNextComponent( item, &sheet ); SCH_COMPONENT* comp = findNextComponent( item, &sheet );
@ -242,17 +242,16 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeComponents( unsigned aCtl )
|| ( ( aCtl & GNL_OPT_KICAD ) && !comp->GetIncludeOnBoard() ) ) || ( ( aCtl & GNL_OPT_KICAD ) && !comp->GetIncludeOnBoard() ) )
continue; continue;
XNODE* xcomp; // current component being constructed
// Output the component's elements in order of expected access frequency. // Output the component's elements in order of expected access frequency.
// This may not always look best, but it will allow faster execution // This may not always look best, but it will allow faster execution
// under XSL processing systems which do sequential searching within // under XSL processing systems which do sequential searching within
// an element. // an element.
XNODE* xcomp; // current component being constructed
xcomps->AddChild( xcomp = node( "comp" ) ); xcomps->AddChild( xcomp = node( "comp" ) );
xcomp->AddAttribute( "ref", comp->GetRef( &sheet ) );
addComponentFields( xcomp, comp, &sheetList[i] ); xcomp->AddAttribute( "ref", comp->GetRef( &sheet ) );
addComponentFields( xcomp, comp, &sheetList[ii] );
XNODE* xlibsource; XNODE* xlibsource;
xcomp->AddChild( xlibsource = node( "libsource" ) ); xcomp->AddChild( xlibsource = node( "libsource" ) );
@ -268,9 +267,20 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeComponents( unsigned aCtl )
xlibsource->AddAttribute( "description", comp->GetDescription() ); xlibsource->AddAttribute( "description", comp->GetDescription() );
XNODE* xsheetpath; std::vector<SCH_FIELD>& fields = comp->GetFields();
for( size_t jj = MANDATORY_FIELDS; jj < fields.size(); ++jj )
{
XNODE* xproperty;
xcomp->AddChild( xproperty = node( "property" ) );
xproperty->AddAttribute( "name", fields[jj].GetName() );
xproperty->AddAttribute( "value", fields[jj].GetText() );
}
XNODE* xsheetpath;
xcomp->AddChild( xsheetpath = node( "sheetpath" ) ); xcomp->AddChild( xsheetpath = node( "sheetpath" ) );
xsheetpath->AddAttribute( "names", sheet.PathHumanReadable() ); xsheetpath->AddAttribute( "names", sheet.PathHumanReadable() );
xsheetpath->AddAttribute( "tstamps", sheet.PathAsString() ); xsheetpath->AddAttribute( "tstamps", sheet.PathAsString() );
xcomp->AddChild( node( "tstamp", comp->m_Uuid.AsString() ) ); xcomp->AddChild( node( "tstamp", comp->m_Uuid.AsString() ) );

View File

@ -373,6 +373,11 @@ bool MODULE::ResolveTextVar( wxString* token, int aDepth ) const
*token = GetLayerName(); *token = GetLayerName();
return true; return true;
} }
else if( m_properties.count( *token ) )
{
*token = m_properties.at( *token );
return true;
}
return false; return false;
} }

View File

@ -488,6 +488,9 @@ public:
TEXTE_MODULE& Value() const { return *m_Value; } TEXTE_MODULE& Value() const { return *m_Value; }
TEXTE_MODULE& Reference() const { return *m_Reference; } TEXTE_MODULE& Reference() const { return *m_Reference; }
const std::map<wxString, wxString>& GetProperties() const { return m_properties; }
void SetProperties( const std::map<wxString, wxString>& aProps ) { m_properties = aProps; }
/** /**
* Function FindPadByName * Function FindPadByName
* returns a D_PAD* with a matching name. Note that names may not be * returns a D_PAD* with a matching name. Note that names may not be
@ -696,10 +699,9 @@ public:
#endif #endif
private: private:
DRAWINGS m_drawings; // BOARD_ITEMs for drawings on the board, owned by pointer. DRAWINGS m_drawings; // BOARD_ITEMs for drawings on the board, owned by pointer.
PADS m_pads; // D_PAD items, owned by pointer PADS m_pads; // D_PAD items, owned by pointer
MODULE_ZONE_CONTAINERS m_fp_zones; // MODULE_ZONE_CONTAINER items, owned by pointer MODULE_ZONE_CONTAINERS m_fp_zones; // MODULE_ZONE_CONTAINER items, owned by pointer
std::list<MODULE_3D_SETTINGS> m_3D_Drawings; // Linked list of 3D models.
double m_Orient; // Orientation in tenths of a degree, 900=90.0 degrees. double m_Orient; // Orientation in tenths of a degree, 900=90.0 degrees.
wxPoint m_Pos; // Position of module on the board in internal units. wxPoint m_Pos; // Position of module on the board in internal units.
@ -727,13 +729,13 @@ private:
int m_CntRot90; // Horizontal automatic placement cost ( 0..10 ). int m_CntRot90; // Horizontal automatic placement cost ( 0..10 ).
int m_CntRot180; // Vertical automatic placement cost ( 0..10 ). int m_CntRot180; // Vertical automatic placement cost ( 0..10 ).
wxArrayString* m_initial_comments; ///< leading s-expression comments in the module, std::list<MODULE_3D_SETTINGS> m_3D_Drawings; // Linked list of 3D models.
///< lazily allocated only if needed for speed std::map<wxString, wxString> m_properties;
wxArrayString* m_initial_comments; // s-expression comments in the module,
// lazily allocated only if needed for speed
/// Used in DRC to test the courtyard area (a polygon which can be not basic SHAPE_POLY_SET m_poly_courtyard_front; // Note that a module can have both front and back
/// Note also a footprint can have courtyards on both board sides SHAPE_POLY_SET m_poly_courtyard_back; // courtyards populated.
SHAPE_POLY_SET m_poly_courtyard_front;
SHAPE_POLY_SET m_poly_courtyard_back;
}; };
#endif // MODULE_H_ #endif // MODULE_H_

View File

@ -954,6 +954,15 @@ void PCB_IO::format( MODULE* aModule, int aNestLevel ) const
m_out->Print( aNestLevel+1, "(tags %s)\n", m_out->Print( aNestLevel+1, "(tags %s)\n",
m_out->Quotew( aModule->GetKeywords() ).c_str() ); m_out->Quotew( aModule->GetKeywords() ).c_str() );
const std::map<wxString, wxString>& props = aModule->GetProperties();
for( const std::pair<const wxString, wxString>& prop : props )
{
m_out->Print( aNestLevel+1, "(property %s %s)\n",
m_out->Quotew( prop.first ).c_str(),
m_out->Quotew( prop.second ).c_str() );
}
if( !( m_ctl & CTL_OMIT_PATH ) && !aModule->GetPath().empty() ) if( !( m_ctl & CTL_OMIT_PATH ) && !aModule->GetPath().empty() )
m_out->Print( aNestLevel+1, "(path %s)\n", m_out->Print( aNestLevel+1, "(path %s)\n",
m_out->Quotew( aModule->GetPath().AsString() ).c_str() ); m_out->Quotew( aModule->GetPath().AsString() ).c_str() );

View File

@ -73,7 +73,8 @@ class TEXTE_PCB;
//#define SEXPR_BOARD_FILE_VERSION 20200625 // Multilayer zones, zone names, island controls //#define SEXPR_BOARD_FILE_VERSION 20200625 // Multilayer zones, zone names, island controls
//#define SEXPR_BOARD_FILE_VERSION 20200628 // remove visibility settings //#define SEXPR_BOARD_FILE_VERSION 20200628 // remove visibility settings
//#define SEXPR_BOARD_FILE_VERSION 20200724 // Add KIID to module components //#define SEXPR_BOARD_FILE_VERSION 20200724 // Add KIID to module components
#define SEXPR_BOARD_FILE_VERSION 20200807 // Add zone hatch advanced settings //#define SEXPR_BOARD_FILE_VERSION 20200807 // Add zone hatch advanced settings
#define SEXPR_BOARD_FILE_VERSION 20200808 // Add properties to modules
#define CTL_STD_LAYER_NAMES (1 << 0) ///< Use English Standard layer names #define CTL_STD_LAYER_NAMES (1 << 0) ///< Use English Standard layer names
#define CTL_OMIT_NETS (1 << 1) ///< Omit pads net names (useless in library) #define CTL_OMIT_NETS (1 << 1) ///< Omit pads net names (useless in library)

View File

@ -285,7 +285,7 @@ bool BOARD_NETLIST_UPDATER::updateComponentParameters( MODULE* aPcbComponent,
aPcbComponent->GetReference(), aPcbComponent->GetReference(),
aPcbComponent->GetPath().AsString(), aPcbComponent->GetPath().AsString(),
aNewComponent->GetPath().AsString() ); aNewComponent->GetPath().AsString() );
m_reporter->Report( msg, RPT_SEVERITY_INFO ); m_reporter->Report( msg, RPT_SEVERITY_ACTION );
if( !m_isDryRun ) if( !m_isDryRun )
{ {
@ -294,6 +294,19 @@ bool BOARD_NETLIST_UPDATER::updateComponentParameters( MODULE* aPcbComponent,
} }
} }
if( aPcbComponent->GetProperties() != aNewComponent->GetProperties() )
{
msg.Printf( _( "Update %s properties." ),
aPcbComponent->GetReference() );
m_reporter->Report( msg, RPT_SEVERITY_ACTION );
if( !m_isDryRun )
{
changed = true;
aPcbComponent->SetProperties( aNewComponent->GetProperties() );
}
}
if( changed && copy ) if( changed && copy )
m_commit.Modified( aPcbComponent, copy ); m_commit.Modified( aPcbComponent, copy );
else else

View File

@ -282,11 +282,12 @@ void KICAD_NETLIST_PARSER::parseComponent()
{ {
/* Parses a section like /* Parses a section like
* (comp (ref P1) * (comp (ref P1)
* (value DB25FEMALE) * (value DB25FEMALE)
* (footprint DB25FC) * (footprint DB25FC)
* (libsource (lib conn) (part DB25)) * (libsource (lib conn) (part DB25))
* (sheetpath (names /) (tstamps /)) * (property (name PINCOUNT) (value 25))
* (tstamp 68183921-93a5-49ac-91b0-49d05a0e1647)) * (sheetpath (names /) (tstamps /))
* (tstamp 68183921-93a5-49ac-91b0-49d05a0e1647))
* *
* other fields (unused) are skipped * other fields (unused) are skipped
* A component need a reference, value, footprint name and a full time stamp * A component need a reference, value, footprint name and a full time stamp
@ -300,6 +301,7 @@ void KICAD_NETLIST_PARSER::parseComponent()
wxString name; wxString name;
KIID_PATH path; KIID_PATH path;
KIID uuid; KIID uuid;
std::map<wxString, wxString> properties;
// The token comp was read, so the next data is (ref P1) // The token comp was read, so the next data is (ref P1)
while( (token = NextTok()) != T_RIGHT ) while( (token = NextTok()) != T_RIGHT )
@ -329,7 +331,7 @@ void KICAD_NETLIST_PARSER::parseComponent()
case T_libsource: case T_libsource:
// Read libsource // Read libsource
while( (token = NextTok()) != T_RIGHT ) while( ( token = NextTok() ) != T_RIGHT )
{ {
if( token == T_LEFT ) if( token == T_LEFT )
token = NextTok(); token = NextTok();
@ -358,6 +360,39 @@ void KICAD_NETLIST_PARSER::parseComponent()
} }
break; break;
case T_property:
{
wxString propName;
wxString propValue;
while( (token = NextTok() ) != T_RIGHT )
{
if( token == T_LEFT )
token = NextTok();
if( token == T_name )
{
NeedSYMBOLorNUMBER();
propName = FROM_UTF8( CurText() );
NeedRIGHT();
}
else if( token == T_value )
{
NeedSYMBOLorNUMBER();
propValue = FROM_UTF8( CurText() );
NeedRIGHT();
}
else
{
Expecting( "name or value" );
}
}
if( !propName.IsEmpty() )
properties[ propName ] = propValue;
}
break;
case T_sheetpath: case T_sheetpath:
while( ( token = NextTok() ) != T_EOF ) while( ( token = NextTok() ) != T_EOF )
{ {
@ -397,6 +432,7 @@ void KICAD_NETLIST_PARSER::parseComponent()
COMPONENT* component = new COMPONENT( fpid, ref, value, path ); COMPONENT* component = new COMPONENT( fpid, ref, value, path );
component->SetName( name ); component->SetName( name );
component->SetLibrary( library ); component->SetLibrary( library );
component->SetProperties( properties );
m_netlist->AddComponent( component ); m_netlist->AddComponent( component );
} }

View File

@ -309,11 +309,12 @@ private:
* Function parseComponent * Function parseComponent
* parse a component description: * parse a component description:
* (comp (ref P1) * (comp (ref P1)
* (value DB25FEMELLE) * (value DB25FEMELLE)
* (footprint DB25FC) * (footprint DB25FC)
* (libsource (lib conn) (part DB25)) * (libsource (lib conn) (part DB25))
* (sheetpath (names /) (tstamps /)) * (property (name PINCOUNT) (value 25))
* (tstamp 3256759C)) * (sheetpath (names /) (tstamps /))
* (tstamp 3256759C))
*/ */
void parseComponent(); void parseComponent();
@ -321,9 +322,9 @@ private:
* Function parseNet * Function parseNet
* Parses a section like * Parses a section like
* (net (code 20) (name /PC-A0) * (net (code 20) (name /PC-A0)
* (node (ref BUS1) (pin 62)) * (node (ref BUS1) (pin 62))
* (node (ref U3) (pin 3)) * (node (ref U3) (pin 3))
* (node (ref U9) (pin M6))) * (node (ref U9) (pin M6)))
* *
* and set the corresponding pads netnames * and set the corresponding pads netnames
*/ */

View File

@ -48,6 +48,7 @@ void COMPONENT::SetModule( MODULE* aModule )
aModule->SetValue( m_value ); aModule->SetValue( m_value );
aModule->SetFPID( m_fpid ); aModule->SetFPID( m_fpid );
aModule->SetPath( m_path ); aModule->SetPath( m_path );
aModule->SetProperties( m_properties );
} }
@ -56,10 +57,10 @@ COMPONENT_NET COMPONENT::m_emptyNet;
const COMPONENT_NET& COMPONENT::GetNet( const wxString& aPinName ) const const COMPONENT_NET& COMPONENT::GetNet( const wxString& aPinName ) const
{ {
for( unsigned i = 0; i < m_nets.size(); i++ ) for( const COMPONENT_NET& net : m_nets )
{ {
if( m_nets[i].GetPinName() == aPinName ) if( net.GetPinName() == aPinName )
return m_nets[i]; return net;
} }
return m_emptyNet; return m_emptyNet;

View File

@ -105,6 +105,9 @@ class COMPONENT
/// The #MODULE loaded for #m_fpid. /// The #MODULE loaded for #m_fpid.
std::unique_ptr< MODULE > m_footprint; std::unique_ptr< MODULE > m_footprint;
/// Component-specific properties found in the netlist.
std::map<wxString, wxString> m_properties;
static COMPONENT_NET m_emptyNet; static COMPONENT_NET m_emptyNet;
public: public:
@ -142,9 +145,14 @@ public:
const wxString& GetLibrary() const { return m_library; } const wxString& GetLibrary() const { return m_library; }
const wxString& GetReference() const { return m_reference; } const wxString& GetReference() const { return m_reference; }
const wxString& GetValue() const { return m_value; } const wxString& GetValue() const { return m_value; }
void SetProperties( std::map<wxString, wxString>& aProps )
{
m_properties = std::move( aProps );
}
const std::map<wxString, wxString>& GetProperties() const { return m_properties; }
void SetFPID( const LIB_ID& aFPID ) { m_fpid = aFPID; } void SetFPID( const LIB_ID& aFPID ) { m_fpid = aFPID; }
const LIB_ID& GetFPID() const { return m_fpid; } const LIB_ID& GetFPID() const { return m_fpid; }

View File

@ -2454,6 +2454,8 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
std::unique_ptr<MODULE> module( new MODULE( m_board ) ); std::unique_ptr<MODULE> module( new MODULE( m_board ) );
std::map<wxString, wxString> properties;
module->SetInitialComments( aInitialComments ); module->SetInitialComments( aInitialComments );
token = NextTok(); token = NextTok();
@ -2550,6 +2552,14 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
NeedRIGHT(); NeedRIGHT();
break; break;
case T_property:
NeedSYMBOL();
name = FromUTF8();
NeedSYMBOL();
properties[ name ] = FromUTF8();
NeedRIGHT();
break;
case T_path: case T_path:
NeedSYMBOLorNUMBER(); // Paths can be numerical so a number is also a symbol here NeedSYMBOLorNUMBER(); // Paths can be numerical so a number is also a symbol here
module->SetPath( KIID_PATH( FromUTF8() ) ); module->SetPath( KIID_PATH( FromUTF8() ) );
@ -2717,6 +2727,7 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
} }
module->SetFPID( fpid ); module->SetFPID( fpid );
module->SetProperties( properties );
module->CalculateBoundingBox(); module->CalculateBoundingBox();
return module.release(); return module.release();