Promote PathsAndReferences from wxArrayString to first-class-citizen.

Keeping the data in an un-serialized format greatly simplifies usage,
and should make it more robust.
This commit is contained in:
Jeff Young 2020-02-22 21:39:59 +00:00
parent b4786e4121
commit c68b554c8e
20 changed files with 155 additions and 215 deletions

View File

@ -648,7 +648,7 @@ public:
for( unsigned compRef = 0; compRef < m_componentRefs.GetCount(); ++ compRef ) for( unsigned compRef = 0; compRef < m_componentRefs.GetCount(); ++ compRef )
{ {
const KIID& compId = m_componentRefs[ compRef ].GetComp()->m_Uuid; const KIID& compId = m_componentRefs[ compRef ].GetComp()->m_Uuid;
wxString text = m_dataStore[ compId ][ column_label ]; wxString text = m_dataStore[ compId ][ column_label ];
width = std::max( width, GetTextSize( text, GetView() ).x ); width = std::max( width, GetTextSize( text, GetView() ).x );
} }

View File

@ -643,8 +643,8 @@ struct compare_labels
{ {
bool operator() ( const NETLIST_OBJECT* lab1, const NETLIST_OBJECT* lab2 ) const bool operator() ( const NETLIST_OBJECT* lab1, const NETLIST_OBJECT* lab2 ) const
{ {
wxString str1 = lab1->m_SheetPath.Path() + lab1->m_Label; wxString str1 = lab1->m_SheetPath.PathAsString() + lab1->m_Label;
wxString str2 = lab2->m_SheetPath.Path() + lab2->m_Label; wxString str2 = lab2->m_SheetPath.PathAsString() + lab2->m_Label;
return str1.Cmp( str2 ) < 0; return str1.Cmp( str2 ) < 0;
} }
@ -662,7 +662,7 @@ struct compare_paths
{ {
bool operator() ( const NETLIST_OBJECT* lab1, const NETLIST_OBJECT* lab2 ) const bool operator() ( const NETLIST_OBJECT* lab1, const NETLIST_OBJECT* lab2 ) const
{ {
return lab1->m_SheetPath.Path().Cmp( lab2->m_SheetPath.Path() ) < 0; return lab1->m_SheetPath.Path() < lab2->m_SheetPath.Path();
} }
}; };
@ -756,7 +756,7 @@ void NETLIST_OBJECT_LIST::TestforSimilarLabels()
for( ; it_uniq != uniqueLabelList.end(); ++it_uniq ) for( ; it_uniq != uniqueLabelList.end(); ++it_uniq )
{ {
if( ( *it )->m_SheetPath.Path() == ( *it_uniq )->m_SheetPath.Path() ) if(( *it )->m_SheetPath.Path() == ( *it_uniq )->m_SheetPath.Path() )
loc_labelList.insert( *it_uniq ); loc_labelList.insert( *it_uniq );
} }

View File

@ -270,7 +270,7 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeComponents()
xcomp->AddChild( xsheetpath = node( "sheetpath" ) ); xcomp->AddChild( xsheetpath = node( "sheetpath" ) );
xsheetpath->AddAttribute( "names", sheetList[i].PathHumanReadable() ); xsheetpath->AddAttribute( "names", sheetList[i].PathHumanReadable() );
xsheetpath->AddAttribute( "tstamps", sheetList[i].Path() ); xsheetpath->AddAttribute( "tstamps", sheetList[i].PathAsString() );
xcomp->AddChild( node( "tstamp", comp->m_Uuid.AsString() ) ); xcomp->AddChild( node( "tstamp", comp->m_Uuid.AsString() ) );
} }
} }
@ -314,7 +314,7 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeDesignHeader()
sheetTxt.Printf( "%u", i + 1 ); sheetTxt.Printf( "%u", i + 1 );
xsheet->AddAttribute( "number", sheetTxt ); xsheet->AddAttribute( "number", sheetTxt );
xsheet->AddAttribute( "name", sheetList[i].PathHumanReadable() ); xsheet->AddAttribute( "name", sheetList[i].PathHumanReadable() );
xsheet->AddAttribute( "tstamps", sheetList[i].Path() ); xsheet->AddAttribute( "tstamps", sheetList[i].PathAsString() );
TITLE_BLOCK tb = screen->GetTitleBlock(); TITLE_BLOCK tb = screen->GetTitleBlock();

View File

@ -102,7 +102,7 @@ bool NETLIST_EXPORTER_ORCADPCB2::WriteNetlist( const wxString& aOutFileName,
field = comp->GetRef( &sheetList[i] ); field = comp->GetRef( &sheetList[i] );
ret |= fprintf( f, " ( %s %s", ret |= fprintf( f, " ( %s %s",
TO_UTF8( comp->GetPath( &sheetList[i] ) ), TO_UTF8( sheetList[i].PathAsString() + comp->m_Uuid.AsString() ),
TO_UTF8( footprint ) ); TO_UTF8( footprint ) );
ret |= fprintf( f, " %s", TO_UTF8( field ) ); ret |= fprintf( f, " %s", TO_UTF8( field ) );

View File

@ -312,14 +312,12 @@ static bool evalLabelsPriority( const NETLIST_OBJECT* aLabel1, const NETLIST_OBJ
// Global labels have the highest prioriy. // Global labels have the highest prioriy.
// For local labels: names are prefixed by their sheetpath // For local labels: names are prefixed by their sheetpath
// use name defined in the more top level hierarchical sheet // use name defined in the more top level hierarchical sheet
// (i.e. shorter timestamp path because paths are /<timestamp1>/<timestamp2>/...
// and timestamp = 8 letters.
// Note: the final net name uses human sheetpath name, not timestamp sheetpath name // Note: the final net name uses human sheetpath name, not timestamp sheetpath name
// They are equivalent, but not for human readers. // They are equivalent, but not for human readers.
if( ! aLabel1->IsLabelGlobal() && ! aLabel2->IsLabelGlobal() ) if( ! aLabel1->IsLabelGlobal() && ! aLabel2->IsLabelGlobal() )
{ {
if( aLabel1->m_SheetPath.Path().Length() != aLabel2->m_SheetPath.Path().Length() ) if( aLabel1->m_SheetPath.size() != aLabel2->m_SheetPath.size() )
return aLabel1->m_SheetPath.Path().Length() < aLabel2->m_SheetPath.Path().Length(); return aLabel1->m_SheetPath.size() < aLabel2->m_SheetPath.size();
} }
int priority1 = getPriority( aLabel1 ); int priority1 = getPriority( aLabel1 );

View File

@ -183,7 +183,7 @@ SCH_COMPONENT::SCH_COMPONENT( const SCH_COMPONENT& aComponent ) :
m_transform = aComponent.m_transform; m_transform = aComponent.m_transform;
m_prefix = aComponent.m_prefix; m_prefix = aComponent.m_prefix;
m_PathsAndReferences = aComponent.m_PathsAndReferences; m_instanceReferences = aComponent.m_instanceReferences;
m_Fields = aComponent.m_Fields; m_Fields = aComponent.m_Fields;
// Re-parent the fields, which before this had aComponent as parent // Re-parent the fields, which before this had aComponent as parent
@ -563,55 +563,35 @@ void SCH_COMPONENT::Print( wxDC* aDC, const wxPoint& aOffset )
} }
void SCH_COMPONENT::AddHierarchicalReference( const wxString& aPath, const wxString& aRef, void SCH_COMPONENT::AddHierarchicalReference( const KIID_PATH& aPath, const wxString& aRef,
int aMulti ) int aUnit )
{ {
wxString h_path, h_ref;
wxStringTokenizer tokenizer;
wxString separators( wxT( " " ) );
// Search for an existing path and remove it if found (should not occur) // Search for an existing path and remove it if found (should not occur)
for( unsigned ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ ) for( unsigned ii = 0; ii < m_instanceReferences.size(); ii++ )
{ {
tokenizer.SetString( m_PathsAndReferences[ii], separators ); if( m_instanceReferences[ii].m_Path == aPath )
h_path = tokenizer.GetNextToken();
if( h_path.Cmp( aPath ) == 0 )
{ {
m_PathsAndReferences.RemoveAt( ii ); m_instanceReferences.erase( m_instanceReferences.begin() + ii );
ii--; ii--;
} }
} }
h_ref = aPath + wxT( " " ) + aRef; COMPONENT_INSTANCE_REFERENCE instance;
h_ref << wxT( " " ) << aMulti; instance.m_Path = aPath;
m_PathsAndReferences.Add( h_ref ); instance.m_Reference = aRef;
} instance.m_Unit = aUnit;
m_instanceReferences.push_back( instance );
wxString SCH_COMPONENT::GetPath( const SCH_SHEET_PATH* sheet ) const
{
wxCHECK_MSG( sheet != NULL, wxEmptyString,
wxT( "Cannot get component path with invalid sheet object." ) );
return sheet->Path() + m_Uuid.AsString();
} }
const wxString SCH_COMPONENT::GetRef( const SCH_SHEET_PATH* sheet ) const wxString SCH_COMPONENT::GetRef( const SCH_SHEET_PATH* sheet )
{ {
wxString path = GetPath( sheet ); KIID_PATH path = sheet->Path();
wxString h_path;
wxStringTokenizer tokenizer;
wxString separators( wxT( " " ) );
for( const wxString& entry : m_PathsAndReferences ) for( const COMPONENT_INSTANCE_REFERENCE& instance : m_instanceReferences )
{ {
tokenizer.SetString( entry, separators ); if( instance.m_Path == path )
h_path = tokenizer.GetNextToken(); return instance.m_Reference;
if( h_path.Cmp( path ) == 0 )
return tokenizer.GetNextToken();
} }
// If it was not found in m_Paths array, then see if it is in m_Field[REFERENCE] -- if so, // If it was not found in m_Paths array, then see if it is in m_Field[REFERENCE] -- if so,
@ -646,30 +626,15 @@ bool SCH_COMPONENT::IsReferenceStringValid( const wxString& aReferenceString )
void SCH_COMPONENT::SetRef( const SCH_SHEET_PATH* sheet, const wxString& ref ) void SCH_COMPONENT::SetRef( const SCH_SHEET_PATH* sheet, const wxString& ref )
{ {
wxString path = GetPath( sheet ); KIID_PATH path = sheet->Path();
bool notInArray = true;
bool notInArray = true;
wxString h_path, h_ref;
wxStringTokenizer tokenizer;
wxString separators( wxT( " " ) );
// check to see if it is already there before inserting it // check to see if it is already there before inserting it
for( unsigned ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ ) for( COMPONENT_INSTANCE_REFERENCE& instance : m_instanceReferences )
{ {
tokenizer.SetString( m_PathsAndReferences[ii], separators ); if( instance.m_Path == path )
h_path = tokenizer.GetNextToken();
if( h_path.Cmp( path ) == 0 )
{ {
// just update the reference text, not the timestamp. instance.m_Reference = ref;
h_ref = h_path + wxT( " " ) + ref;
h_ref += wxT( " " );
tokenizer.GetNextToken(); // Skip old reference
h_ref += tokenizer.GetNextToken(); // Add part selection
// Add the part selection
m_PathsAndReferences[ii] = h_ref;
notInArray = false; notInArray = false;
} }
} }
@ -713,21 +678,12 @@ void SCH_COMPONENT::SetRef( const SCH_SHEET_PATH* sheet, const wxString& ref )
bool SCH_COMPONENT::IsAnnotated( const SCH_SHEET_PATH* aSheet ) bool SCH_COMPONENT::IsAnnotated( const SCH_SHEET_PATH* aSheet )
{ {
wxString path = GetPath( aSheet ); KIID_PATH path = aSheet->Path();
wxString h_path;
wxStringTokenizer tokenizer;
wxString separators( wxT( " " ) );
for( const wxString& entry : m_PathsAndReferences ) for( const COMPONENT_INSTANCE_REFERENCE& instance : m_instanceReferences )
{ {
tokenizer.SetString( entry, separators ); if( instance.m_Path == path )
h_path = tokenizer.GetNextToken(); return instance.m_Reference.Last() != '?';
if( h_path.Cmp( path ) == 0 )
{
wxString ref = tokenizer.GetNextToken();
return ref.Last() != '?';
}
} }
return false; return false;
@ -736,24 +692,12 @@ bool SCH_COMPONENT::IsAnnotated( const SCH_SHEET_PATH* aSheet )
int SCH_COMPONENT::GetUnitSelection( const SCH_SHEET_PATH* aSheet ) const int SCH_COMPONENT::GetUnitSelection( const SCH_SHEET_PATH* aSheet ) const
{ {
wxString path = GetPath( aSheet ); KIID_PATH path = aSheet->Path();
wxString h_path, h_multi;
wxStringTokenizer tokenizer;
wxString separators( wxT( " " ) );
for( const wxString& entry : m_PathsAndReferences ) for( const COMPONENT_INSTANCE_REFERENCE& instance : m_instanceReferences )
{ {
tokenizer.SetString( entry, separators ); if( instance.m_Path == path )
h_path = tokenizer.GetNextToken(); return instance.m_Unit;
if( h_path.Cmp( path ) == 0 )
{
tokenizer.GetNextToken(); // Skip reference
h_multi = tokenizer.GetNextToken();
long imulti = 1;
h_multi.ToLong( &imulti );
return imulti;
}
} }
// If it was not found in m_Paths array, then use m_unit. This will happen if we load a // If it was not found in m_Paths array, then use m_unit. This will happen if we load a
@ -764,30 +708,15 @@ int SCH_COMPONENT::GetUnitSelection( const SCH_SHEET_PATH* aSheet ) const
void SCH_COMPONENT::SetUnitSelection( const SCH_SHEET_PATH* aSheet, int aUnitSelection ) void SCH_COMPONENT::SetUnitSelection( const SCH_SHEET_PATH* aSheet, int aUnitSelection )
{ {
wxString path = GetPath( aSheet ); KIID_PATH path = aSheet->Path();
bool notInArray = true;
bool notInArray = true; // check to see if it is already there before inserting it
for( COMPONENT_INSTANCE_REFERENCE& instance : m_instanceReferences )
wxString h_path, h_ref;
wxStringTokenizer tokenizer;
wxString separators( wxT( " " ) );
//check to see if it is already there before inserting it
for( wxString& entry : m_PathsAndReferences )
{ {
tokenizer.SetString( entry, separators ); if( instance.m_Path == path )
h_path = tokenizer.GetNextToken();
if( h_path.Cmp( path ) == 0 )
{ {
//just update the unit selection. instance.m_Unit = aUnitSelection;
h_ref = h_path + wxT( " " );
h_ref += tokenizer.GetNextToken(); // Add reference
h_ref += wxT( " " );
h_ref << aUnitSelection; // Add part selection
// Ann the part selection
entry = h_ref;
notInArray = false; notInArray = false;
} }
} }
@ -1021,15 +950,12 @@ void SCH_COMPONENT::SwapData( SCH_ITEM* aItem )
m_transform = component->m_transform; m_transform = component->m_transform;
component->m_transform = tmp; component->m_transform = tmp;
std::swap( m_PathsAndReferences, component->m_PathsAndReferences ); std::swap( m_instanceReferences, component->m_instanceReferences );
} }
void SCH_COMPONENT::ClearAnnotation( SCH_SHEET_PATH* aSheetPath ) void SCH_COMPONENT::ClearAnnotation( SCH_SHEET_PATH* aSheetPath )
{ {
wxArrayString reference_fields;
static const wxChar separators[] = wxT( " " );
// Build a reference with no annotation, // Build a reference with no annotation,
// i.e. a reference ended by only one '?' // i.e. a reference ended by only one '?'
wxString defRef = m_prefix; wxString defRef = m_prefix;
@ -1044,25 +970,21 @@ void SCH_COMPONENT::ClearAnnotation( SCH_SHEET_PATH* aSheetPath )
defRef.Append( wxT( "?" ) ); defRef.Append( wxT( "?" ) );
wxString path;
if( aSheetPath ) if( aSheetPath )
path = GetPath( aSheetPath );
for( wxString& entry : m_PathsAndReferences )
{ {
// Break hierarchical reference in path, ref and multi selection: KIID_PATH path = aSheetPath->Path();
reference_fields = wxStringTokenize( entry, separators );
// For all components: if aSheetPath is not NULL, for( COMPONENT_INSTANCE_REFERENCE& instance : m_instanceReferences )
// remove annotation only for the given path
if( aSheetPath == NULL || reference_fields[0].Cmp( path ) == 0 )
{ {
wxString newHref = reference_fields[0]; if( instance.m_Path == path )
newHref << wxT( " " ) << defRef << wxT( " " ) << reference_fields[2]; instance.m_Reference = defRef;
entry = newHref;
} }
} }
else
{
for( COMPONENT_INSTANCE_REFERENCE& instance : m_instanceReferences )
instance.m_Reference = defRef;
}
// These 2 changes do not work in complex hierarchy. // These 2 changes do not work in complex hierarchy.
// When a clear annotation is made, the calling function must call a // When a clear annotation is made, the calling function must call a
@ -1074,29 +996,22 @@ void SCH_COMPONENT::ClearAnnotation( SCH_SHEET_PATH* aSheetPath )
} }
bool SCH_COMPONENT::AddSheetPathReferenceEntryIfMissing( const wxString& aSheetPathName ) bool SCH_COMPONENT::AddSheetPathReferenceEntryIfMissing( const KIID_PATH& aSheetPath )
{ {
// a empty sheet path is illegal: // a empty sheet path is illegal:
wxCHECK( !aSheetPathName.IsEmpty(), false ); wxCHECK( aSheetPath.size() > 0, false );
wxString reference_path; wxString reference_path;
// The full component reference path is aSheetPathName + the component time stamp itself for( const COMPONENT_INSTANCE_REFERENCE& instance : m_instanceReferences )
// full_AR_path is the alternate reference path to search
wxString full_AR_path = aSheetPathName + m_Uuid.AsString();
for( unsigned int ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ )
{ {
// Break hierarchical reference in path, ref and multi selection:
reference_path = m_PathsAndReferences[ii].BeforeFirst( ' ' );
// if aSheetPath is found, nothing to do: // if aSheetPath is found, nothing to do:
if( reference_path.Cmp( full_AR_path ) == 0 ) if( instance.m_Path == aSheetPath )
return false; return false;
} }
// This entry does not exist: add it, with a (temporary?) reference (last ref used for display) // This entry does not exist: add it, with its last-used reference
AddHierarchicalReference( full_AR_path, m_Fields[REFERENCE].GetText(), m_unit ); AddHierarchicalReference( aSheetPath, m_Fields[REFERENCE].GetText(), m_unit );
return true; return true;
} }
@ -1785,7 +1700,7 @@ SCH_COMPONENT& SCH_COMPONENT::operator=( const SCH_ITEM& aItem )
m_convert = c->m_convert; m_convert = c->m_convert;
m_transform = c->m_transform; m_transform = c->m_transform;
m_PathsAndReferences = c->m_PathsAndReferences; m_instanceReferences = c->m_instanceReferences;
m_Fields = c->m_Fields; // std::vector's assignment operator m_Fields = c->m_Fields; // std::vector's assignment operator

View File

@ -84,6 +84,14 @@ typedef std::weak_ptr<LIB_PART> PART_REF;
extern std::string toUTFTildaText( const wxString& txt ); extern std::string toUTFTildaText( const wxString& txt );
struct COMPONENT_INSTANCE_REFERENCE
{
KIID_PATH m_Path;
wxString m_Reference;
int m_Unit;
};
/** /**
* SCH_COMPONENT * SCH_COMPONENT
* describes a real schematic component * describes a real schematic component
@ -121,13 +129,9 @@ private:
bool m_isInNetlist; ///< True if the component should appear in the netlist bool m_isInNetlist; ///< True if the component should appear in the netlist
/** // Defines the hierarchical path and reference of the component. This allows support
* Defines the hierarchical path and reference of the component. This allows support // for multiple references to a single sub-sheet.
* for hierarchical sheets that reference the same schematic. The format for the path std::vector<COMPONENT_INSTANCE_REFERENCE> m_instanceReferences;
* is /&ltsheet time stamp&gt/&ltsheet time stamp&gt/.../&lscomponent time stamp&gt.
* A single / denotes the root sheet.
*/
wxArrayString m_PathsAndReferences;
void Init( const wxPoint& pos = wxPoint( 0, 0 ) ); void Init( const wxPoint& pos = wxPoint( 0, 0 ) );
@ -176,7 +180,10 @@ public:
return wxT( "SCH_COMPONENT" ); return wxT( "SCH_COMPONENT" );
} }
const wxArrayString& GetPathsAndReferences() const { return m_PathsAndReferences; } const std::vector<COMPONENT_INSTANCE_REFERENCE>& GetInstanceReferences()
{
return m_instanceReferences;
}
void ViewGetLayers( int aLayers[], int& aCount ) const override; void ViewGetLayers( int aLayers[], int& aCount ) const override;
@ -314,8 +321,8 @@ public:
void ClearAnnotation( SCH_SHEET_PATH* aSheetPath ); void ClearAnnotation( SCH_SHEET_PATH* aSheetPath );
/** /**
* Add aSheetPath in m_PathsAndReferences alternate references list, * Add an instance to the alternate references list (m_instanceReferences), if this entry
* if this entry does not exist * does not already exist.
* Do nothing if already exists. * Do nothing if already exists.
* In component lists shared by more than one sheet path, an entry for each * In component lists shared by more than one sheet path, an entry for each
* sheet path must exist to manage references * sheet path must exist to manage references
@ -324,7 +331,7 @@ public:
* not the full component sheet path * not the full component sheet path
* @return false if the alternate reference was existing, true if added. * @return false if the alternate reference was existing, true if added.
*/ */
bool AddSheetPathReferenceEntryIfMissing( const wxString& aSheetPathName ); bool AddSheetPathReferenceEntryIfMissing( const KIID_PATH& aSheetPath );
/** /**
* Clear the HIGHLIGHTED flag of all items of the component (fields, pins ...) * Clear the HIGHLIGHTED flag of all items of the component (fields, pins ...)
@ -492,9 +499,6 @@ public:
void SwapData( SCH_ITEM* aItem ) override; void SwapData( SCH_ITEM* aItem ) override;
// returns a unique ID, in the form of a path.
wxString GetPath( const SCH_SHEET_PATH* sheet ) const;
/** /**
* Tests for an acceptable reference string. * Tests for an acceptable reference string.
* *
@ -534,11 +538,11 @@ public:
* @param aPath is the hierarchical path (/&ltsheet timestamp&gt/&ltcomponent * @param aPath is the hierarchical path (/&ltsheet timestamp&gt/&ltcomponent
* timestamp&gt like /05678E50/A23EF560) * timestamp&gt like /05678E50/A23EF560)
* @param aRef is the local reference like C45, R56 * @param aRef is the local reference like C45, R56
* @param aMulti is the unit selection used for symbols with multiple units per package. * @param aUnit is the unit selection used for symbols with multiple units per package.
*/ */
void AddHierarchicalReference( const wxString& aPath, void AddHierarchicalReference( const KIID_PATH& aPath,
const wxString& aRef, const wxString& aRef,
int aMulti ); int aUnit );
// returns the unit selection, for the given sheet path. // returns the unit selection, for the given sheet path.
int GetUnitSelection( const SCH_SHEET_PATH* aSheet ) const; int GetUnitSelection( const SCH_SHEET_PATH* aSheet ) const;

View File

@ -1154,8 +1154,7 @@ void SCH_EAGLE_PLUGIN::loadInstance( wxXmlNode* aInstanceNode )
SCH_SHEET_PATH sheetpath; SCH_SHEET_PATH sheetpath;
m_rootSheet->LocatePathOfScreen( screen, &sheetpath ); m_rootSheet->LocatePathOfScreen( screen, &sheetpath );
wxString current_sheetpath = sheetpath.Path(); wxString current_sheetpath = sheetpath.PathAsString() + component->m_Uuid.AsString();
current_sheetpath += component->m_Uuid.AsString();
component->GetField( REFERENCE )->SetText( reference ); component->GetField( REFERENCE )->SetText( reference );
component->AddHierarchicalReference( current_sheetpath, reference, unit ); component->AddHierarchicalReference( current_sheetpath, reference, unit );

View File

@ -368,20 +368,17 @@ void SCH_EDIT_FRAME::SetSheetNumberAndCount()
SCH_SCREEN* screen; SCH_SCREEN* screen;
SCH_SCREENS s_list; SCH_SCREENS s_list;
/* Set the sheet count, and the sheet number (1 for root sheet) // Set the sheet count, and the sheet number (1 for root sheet)
*/ int sheet_count = g_RootSheet->CountSheets();
int sheet_count = g_RootSheet->CountSheets(); int SheetNumber = 1;
int SheetNumber = 1; const KIID_PATH& current_sheetpath = g_CurrentSheet->Path();
wxString current_sheetpath = g_CurrentSheet->Path(); SCH_SHEET_LIST sheetList( g_RootSheet );
SCH_SHEET_LIST sheetList( g_RootSheet );
// Examine all sheets path to find the current sheets path, // Examine all sheets path to find the current sheets path,
// and count them from root to the current sheet path: // and count them from root to the current sheet path:
for( const SCH_SHEET_PATH& sheet : sheetList ) for( const SCH_SHEET_PATH& sheet : sheetList )
{ {
wxString sheetpath = sheet.Path(); if( sheet.Path() == current_sheetpath ) // Current sheet path found
if( sheetpath == current_sheetpath ) // Current sheet path found
break; break;
SheetNumber++; // Not found, increment before this current path SheetNumber++; // Not found, increment before this current path

View File

@ -1583,9 +1583,23 @@ SCH_COMPONENT* SCH_LEGACY_PLUGIN::loadComponent( LINE_READER& aReader )
SCH_PARSE_ERROR( "missing 'Path=' token", aReader, line ); SCH_PARSE_ERROR( "missing 'Path=' token", aReader, line );
line += len; line += len;
wxString path, reference, unit; wxString pathStr, reference, unit;
parseQuotedString( path, aReader, line, &line ); parseQuotedString( pathStr, aReader, line, &line );
// Note: AR path excludes root sheet, but includes component. Normalize to
// internal format by shifting everything down one and adding the root sheet.
KIID_PATH path( pathStr );
if( path.size() > 0 )
{
for( size_t i = path.size() - 1; i > 0; --i )
path[i] = path[i-1];
path[0] = m_rootSheet->m_Uuid;
}
else
path.push_back( m_rootSheet->m_Uuid );
strCompare = "Ref="; strCompare = "Ref=";
len = strlen( strCompare ); len = strlen( strCompare );
@ -1968,10 +1982,10 @@ void SCH_LEGACY_PLUGIN::saveComponent( SCH_COMPONENT* aComponent )
static wxString delimiters( wxT( " " ) ); static wxString delimiters( wxT( " " ) );
// This is redundant with the AR entries below, but it makes the files backwards-compatible. // This is redundant with the AR entries below, but it makes the files backwards-compatible.
if( aComponent->GetPathsAndReferences().GetCount() > 0 ) if( aComponent->GetInstanceReferences().size() > 0 )
{ {
reference_fields = wxStringTokenize( aComponent->GetPathsAndReferences()[0], delimiters ); const COMPONENT_INSTANCE_REFERENCE& instance = aComponent->GetInstanceReferences()[0];
name1 = toUTFTildaText( reference_fields[1] ); name1 = toUTFTildaText( instance.m_Reference );
} }
else else
{ {
@ -2011,9 +2025,9 @@ void SCH_LEGACY_PLUGIN::saveComponent( SCH_COMPONENT* aComponent )
* the reference inf is already saved * the reference inf is already saved
* this is useful for old Eeschema version compatibility * this is useful for old Eeschema version compatibility
*/ */
if( aComponent->GetPathsAndReferences().GetCount() > 1 ) if( aComponent->GetInstanceReferences().size() > 1 )
{ {
for( unsigned int ii = 0; ii < aComponent->GetPathsAndReferences().GetCount(); ii++ ) for( const COMPONENT_INSTANCE_REFERENCE& instance : aComponent->GetInstanceReferences() )
{ {
/*format: /*format:
* AR Path="/140/2" Ref="C99" Part="1" * AR Path="/140/2" Ref="C99" Part="1"
@ -2023,23 +2037,16 @@ void SCH_LEGACY_PLUGIN::saveComponent( SCH_COMPONENT* aComponent )
* Ref is the conventional component reference for this 'path' * Ref is the conventional component reference for this 'path'
* Part is the conventional component part selection for this 'path' * Part is the conventional component part selection for this 'path'
*/ */
reference_fields = wxStringTokenize( aComponent->GetPathsAndReferences()[ii], wxString path = "/";
delimiters );
// Convert Alternate Reference paths back to legacy timestamps: // Skip root sheet
wxArrayString pathParts = wxSplit( reference_fields[0], '/' ); for( int i = 1; i < instance.m_Path.size(); ++i )
wxString path; path += instance.m_Path[i].AsLegacyTimestampString() + "/";
for( const wxString& pathPart : pathParts ) m_out->Print( 0, "AR Path=\"%s\" Ref=\"%s\" Part=\"%d\" \n",
{ TO_UTF8( path + aComponent->m_Uuid.AsLegacyTimestampString() ),
if( !pathPart.IsEmpty() ) TO_UTF8( instance.m_Reference ),
path += "/" + KIID( pathPart ).AsLegacyTimestampString(); instance.m_Unit );
}
m_out->Print( 0, "AR Path=\"%s\" Ref=\"%s\" Part=\"%s\" \n",
TO_UTF8( path ),
TO_UTF8( reference_fields[1] ),
TO_UTF8( reference_fields[2] ) );
} }
} }

View File

@ -60,7 +60,7 @@ class SCH_REFERENCE
SCH_SHEET_PATH m_SheetPath; ///< The sheet path for this reference. SCH_SHEET_PATH m_SheetPath; ///< The sheet path for this reference.
bool m_IsNew; ///< True if not yet annotated. bool m_IsNew; ///< True if not yet annotated.
int m_SheetNum; ///< The sheet number for the reference. int m_SheetNum; ///< The sheet number for the reference.
KIID m_Uuid; ///< UUID of the component. KIID m_Uuid; ///< UUID of the component.
EDA_TEXT* m_Value; ///< The component value of the reference. It is the EDA_TEXT* m_Value; ///< The component value of the reference. It is the
///< same for all instances. ///< same for all instances.
int m_NumRef; ///< The numeric part of the reference designator. int m_NumRef; ///< The numeric part of the reference designator.
@ -101,7 +101,7 @@ public:
const wxString GetPath() const const wxString GetPath() const
{ {
return m_RootCmp ? m_RootCmp->GetPath( &m_SheetPath ) : ""; return m_RootCmp ? m_SheetPath.PathAsString() + m_RootCmp->m_Uuid.AsString() : "";
} }
/** /**
@ -189,7 +189,9 @@ public:
*/ */
bool IsSameInstance( const SCH_REFERENCE& other ) const bool IsSameInstance( const SCH_REFERENCE& other ) const
{ {
return GetComp() == other.GetComp() && GetSheetPath().Path() == other.GetSheetPath().Path(); // JEY TODO: should this be checking unit as well?
return GetComp() == other.GetComp()
&& GetSheetPath().Path() == other.GetSheetPath().Path();
} }
bool IsUnitsLocked() bool IsUnitsLocked()

View File

@ -1308,7 +1308,7 @@ void SCH_SCREENS::BuildClientSheetPathList()
{ {
if( used_screen == curr_screen ) if( used_screen == curr_screen )
{ {
curr_screen->GetClientSheetPaths().Add( sheetpath.Path() ); curr_screen->GetClientSheetPaths().Add( sheetpath.PathAsString() );
break; break;
} }
} }

View File

@ -116,7 +116,7 @@ SCH_SCREEN* SCH_SHEET_PATH::LastScreen() const
} }
wxString SCH_SHEET_PATH::Path() const wxString SCH_SHEET_PATH::PathAsString() const
{ {
wxString s; wxString s;
@ -131,6 +131,17 @@ wxString SCH_SHEET_PATH::Path() const
} }
KIID_PATH SCH_SHEET_PATH::Path() const
{
KIID_PATH path;
for( const SCH_SHEET* sheet : m_sheets )
path.push_back( sheet->m_Uuid );
return path;
}
wxString SCH_SHEET_PATH::GetRootPathName( bool aUseShortName ) wxString SCH_SHEET_PATH::GetRootPathName( bool aUseShortName )
{ {
// return a PathName for the root sheet (like "/" or "<root>" // return a PathName for the root sheet (like "/" or "<root>"

View File

@ -194,12 +194,18 @@ public:
SCH_SCREEN* LastScreen() const; SCH_SCREEN* LastScreen() const;
/** /**
* Function Path * Function PathAsString
* the path uses the time stamps which do not changes even when editing * the path uses the time stamps which do not changes even when editing
* sheet parameters * sheet parameters
* a path is something like / (root) or /34005677 or /34005677/00AE4523 * a path is something like / (root) or /34005677 or /34005677/00AE4523
*/ */
wxString Path() const; wxString PathAsString() const;
/**
* Get the sheet path as an KIID_PATH.
* @return
*/
KIID_PATH Path() const;
/** /**
* Function PathHumanReadable * Function PathHumanReadable

View File

@ -290,9 +290,10 @@ int BACK_ANNOTATE::checkSharedSchematicErrors()
// We will count how many times every component used in our changelist // We will count how many times every component used in our changelist
// Component in this case is SCH_COMPONENT which can be used by more than one symbol // Component in this case is SCH_COMPONENT which can be used by more than one symbol
int usageCount = 1; int usageCount = 1;
for( auto it = m_changelist.begin(); it != m_changelist.end(); ++it ) for( auto it = m_changelist.begin(); it != m_changelist.end(); ++it )
{ {
int compUsage = it->first.GetComp()->GetPathsAndReferences().Count(); int compUsage = it->first.GetComp()->GetInstanceReferences().size();
if( compUsage == 1 ) if( compUsage == 1 )
continue; continue;

View File

@ -705,10 +705,10 @@ private:
wxString m_Doc; // File name and path for documentation file. wxString m_Doc; // File name and path for documentation file.
wxString m_KeyWord; // Search keywords to find module in library. wxString m_KeyWord; // Search keywords to find module in library.
KIID_PATH m_Path; // Path to associated symbol ([sheetUUID, .., symbolUUID]). KIID_PATH m_Path; // Path to associated symbol ([sheetUUID, .., symbolUUID]).
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
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 ).

View File

@ -298,8 +298,8 @@ void KICAD_NETLIST_PARSER::parseComponent()
wxString value; wxString value;
wxString library; wxString library;
wxString name; wxString name;
KIID_PATH path; KIID_PATH path;
KIID uuid; KIID uuid;
// 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 )

View File

@ -86,7 +86,7 @@ class COMPONENT
wxString m_value; ///< The component value found in netlist. wxString m_value; ///< The component value found in netlist.
/// A fully specified path to the component: [ sheetUUID, sheetUUID, .., componentUUID ] /// A fully specified path to the component: [ sheetUUID, sheetUUID, .., componentUUID ]
KIID_PATH m_path; KIID_PATH m_path;
/// The name of the component in #m_library used when it was placed on the schematic.. /// The name of the component in #m_library used when it was placed on the schematic..
wxString m_name; wxString m_name;

View File

@ -52,7 +52,7 @@ public:
char m_objType; char m_objType;
int m_PCadLayer; int m_PCadLayer;
PCB_LAYER_ID m_KiCadLayer; PCB_LAYER_ID m_KiCadLayer;
KIID m_uuid; KIID m_uuid;
int m_positionX; int m_positionX;
int m_positionY; int m_positionY;
int m_rotation; int m_rotation;

View File

@ -91,7 +91,7 @@ BOOST_AUTO_TEST_CASE( Empty )
BOOST_CHECK_EQUAL( m_empty_path.Last(), nullptr ); BOOST_CHECK_EQUAL( m_empty_path.Last(), nullptr );
BOOST_CHECK_EQUAL( m_empty_path.LastScreen(), nullptr ); BOOST_CHECK_EQUAL( m_empty_path.LastScreen(), nullptr );
BOOST_CHECK_EQUAL( m_empty_path.Path(), "/" ); BOOST_CHECK_EQUAL( m_empty_path.PathAsString(), "/" );
BOOST_CHECK_EQUAL( m_empty_path.PathHumanReadable(), "/" ); BOOST_CHECK_EQUAL( m_empty_path.PathHumanReadable(), "/" );
} }
@ -114,7 +114,7 @@ BOOST_AUTO_TEST_CASE( NonEmpty )
// don't know what the timestamps will be, but we know the format: /<8 chars>/<8 chars>/ // don't know what the timestamps will be, but we know the format: /<8 chars>/<8 chars>/
BOOST_CHECK_PREDICATE( BOOST_CHECK_PREDICATE(
KI_TEST::IsTimestampStringWithLevels, ( m_linear.Path().ToStdString() )( 2 ) ); KI_TEST::IsTimestampStringWithLevels, ( m_linear.PathAsString().ToStdString() )( 2 ) );
// Sheet0 is the root sheet and isn't in the path // Sheet0 is the root sheet and isn't in the path
BOOST_CHECK_EQUAL( m_linear.PathHumanReadable(), "/Sheet1/Sheet2/" ); BOOST_CHECK_EQUAL( m_linear.PathHumanReadable(), "/Sheet1/Sheet2/" );