void mapExistingAnnotation( std::map<timestamp_t, wxString>& aMap )
{
    SCH_SHEET_LIST     sheets( g_RootSheet );
    SCH_REFERENCE_LIST references;

    sheets.GetComponents( references );

    for( size_t i = 0; i < references.GetCount(); i++ )
    {
        SCH_COMPONENT* comp = references[ i ].GetComp();
        wxString       ref = comp->GetField( REFERENCE )->GetFullyQualifiedText();

        if( !ref.Contains( wxT( "?" ) ) )
            aMap[ comp->GetTimeStamp() ] = ref;
    }
}
Exemple #2
0
bool SCH_EDIT_FRAME::ProcessCmpToFootprintLinkFile( wxString& aFullFilename,
                                                    bool aForceFieldsVisibleAttribute,
                                                    bool aFieldsVisibleAttributeState )
{
    // Build a flat list of components in schematic:
    SCH_REFERENCE_LIST referencesList;
    SCH_SHEET_LIST SheetList;
    SheetList.GetComponents( referencesList, false );

    FILE* cmpFile = wxFopen( aFullFilename, wxT( "rt" ) );
    if( cmpFile == NULL )
        return false;

    // cmpFileReader dtor will close cmpFile
    FILE_LINE_READER cmpFileReader( cmpFile, aFullFilename );

    // Now, for each component found in file,
    // replace footprint field value by the new value:
    wxString reference;
    wxString footprint;
    wxString buffer;
    wxString value;

    while( cmpFileReader.ReadLine() )
    {
        buffer = FROM_UTF8( cmpFileReader.Line() );

        if( ! buffer.StartsWith( wxT("BeginCmp") ) )
            continue;

        // Begin component description.
        reference.Empty();
        footprint.Empty();

        while( cmpFileReader.ReadLine() )
        {
            buffer = FROM_UTF8( cmpFileReader.Line() );

            if( buffer.StartsWith( wxT("EndCmp") ) )
                break;

            // store string value, stored between '=' and ';' delimiters.
            value = buffer.AfterFirst( '=' );
            value = value.BeforeLast( ';');
            value.Trim(true);
            value.Trim(false);

            if( buffer.StartsWith( wxT("Reference") ) )
            {
                reference = value;
                continue;
            }

            if( buffer.StartsWith( wxT("IdModule  =" ) ) )
            {
                footprint = value;
                continue;
            }
        }

        // A block is read: initialize the footprint field of the correponding component
        // if the footprint name is not empty
        if( reference.IsEmpty() )
            continue;
        // Search the component in the flat list
        for( unsigned ii = 0; ii < referencesList.GetCount(); ii++ )
        {
            if( reference.CmpNoCase( referencesList[ii].GetRef() ) == 0 )
            {
                // We have found a candidate.
                // Note: it can be not unique (multiple parts per package)
                // So we *do not* stop the search here
                SCH_COMPONENT* component = referencesList[ii].GetComponent();
                SCH_FIELD * fpfield = component->GetField( FOOTPRINT );
                fpfield->SetText( footprint );

                if( aForceFieldsVisibleAttribute )
                {
                        component->GetField( FOOTPRINT )
                            ->SetVisible( aFieldsVisibleAttributeState );
                }
            }
        }
    }
    return true;
}
void SCH_EDIT_FRAME::backAnnotateFootprints( const std::string& aChangedSetOfReferences )
    throw( IO_ERROR, boost::bad_pointer )
{
    // Build a flat list of components in schematic:
    SCH_REFERENCE_LIST  refs;
    SCH_SHEET_LIST      sheets( g_RootSheet );
    bool                isChanged = false;

    sheets.GetComponents( Prj().SchLibs(), refs, false );

    DSNLEXER    lexer( aChangedSetOfReferences, FROM_UTF8( __func__ ) );
    PTREE       doc;

    try
    {
        Scan( &doc, &lexer );

#if defined(DEBUG) && 0
        STRING_FORMATTER sf;
        Format( &sf, 0, 0, doc );
        printf( "%s: '%s'\n", __func__, sf.GetString().c_str() );
#endif

        CPTREE& back_anno = doc.get_child( "back_annotation" );
        wxString footprint;

        for( PTREE::const_iterator ref = back_anno.begin();  ref != back_anno.end();  ++ref )
        {
            wxASSERT( ref->first == "ref" );

            wxString reference = (UTF8&) ref->second.front().first;

            // Ensure the "fpid" node contains a footprint name,
            // and get it if exists
            if( ref->second.get_child( "fpid" ).size() )
            {
                wxString tmp = (UTF8&) ref->second.get_child( "fpid" ).front().first;
                footprint = tmp;
            }
            else
                footprint.Empty();

            // DBG( printf( "%s: ref:%s  fpid:%s\n", __func__, TO_UTF8( reference ), TO_UTF8( footprint ) ); )

            // Search the component in the flat list
            for( unsigned ii = 0;  ii < refs.GetCount();  ++ii )
            {
                if( reference == refs[ii].GetRef() )
                {
                    // We have found a candidate.
                    // Note: it can be not unique (multiple parts per package)
                    // So we *do not* stop the search here
                    SCH_COMPONENT*  component = refs[ii].GetComp();
                    SCH_FIELD*      fpfield   = component->GetField( FOOTPRINT );
                    const wxString& oldfp = fpfield->GetText();

                    if( !oldfp && fpfield->IsVisible() )
                    {
                        fpfield->SetVisible( false );
                    }

                    // DBG( printf("%s: ref:%s  fpid:%s\n", __func__, TO_UTF8( refs[ii].GetRef() ), TO_UTF8( footprint ) );)
                    if( oldfp != footprint )
                        isChanged = true;

                    fpfield->SetText( footprint );
                }
            }
        }
    }
    catch( const PTREE_ERROR& ex )
    {
        // remap the exception to something the caller is likely to understand.
        THROW_IO_ERROR( ex.what() );
    }

    if( isChanged )
        OnModify();
}
void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId, int aStartNumber,
      SCH_MULTI_UNIT_REFERENCE_MAP aLockedUnitMap )
{
    if ( componentFlatList.size() == 0 )
        return;

    int LastReferenceNumber = 0;
    int NumberOfUnits, Unit;

    /* calculate index of the first component with the same reference prefix
     * than the current component.  All components having the same reference
     * prefix will receive a reference number with consecutive values:
     * IC .. will be set to IC4, IC4, IC5 ...
     */
    unsigned first = 0;

    // calculate the last used number for this reference prefix:
#ifdef USE_OLD_ALGO
    int minRefId = 0;

    // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
    if( aUseSheetNum )
        minRefId = componentFlatList[first].m_SheetNum * aSheetIntervalId;

    LastReferenceNumber = GetLastReference( first, minRefId );
#else
    int minRefId;

    // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
    if( aUseSheetNum )
        minRefId = componentFlatList[first].m_SheetNum * aSheetIntervalId + 1;
    else
        minRefId = aStartNumber + 1;

    // For multi units components, when "keep order of multi unit" option is selected,
    // store the list of already used full references.
    // The algorithm try to allocate the new reference to components having the same
    // old reference.
    // This algo works fine as long as the previous annotation has no duplicates.
    // But when a hierarchy is reannotated with this option, the previous anotation can
    // have duplicate references, and obviously we must fix these duplicate.
    // therefore do not try to allocate a full reference more than once when trying
    // to keep this order of multi units.
    // inUseRefs keep trace of previously allocated references
    std::unordered_set<wxString> inUseRefs;

    // This is the list of all Id already in use for a given reference prefix.
    // Will be refilled for each new reference prefix.
    std::vector<int>idList;
    GetRefsInUse( first, idList, minRefId );
#endif
    for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
    {
        if( componentFlatList[ii].m_Flag )
            continue;

        // Check whether this component is in aLockedUnitMap.
        SCH_REFERENCE_LIST* lockedList = NULL;
        for( SCH_MULTI_UNIT_REFERENCE_MAP::value_type& pair : aLockedUnitMap )
        {
            unsigned n_refs = pair.second.GetCount();
            for( unsigned thisRefI = 0; thisRefI < n_refs; ++thisRefI )
            {
                SCH_REFERENCE &thisRef = pair.second[thisRefI];

                if( thisRef.IsSameInstance( componentFlatList[ii] ) )
                {
                    lockedList = &pair.second;
                    break;
                }
            }
            if( lockedList != NULL ) break;
        }

        if(  ( componentFlatList[first].CompareRef( componentFlatList[ii] ) != 0 )
          || ( aUseSheetNum && ( componentFlatList[first].m_SheetNum != componentFlatList[ii].m_SheetNum ) )  )
        {
            // New reference found: we need a new ref number for this reference
            first = ii;
#ifdef USE_OLD_ALGO
            minRefId = 0;

            // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
            if( aUseSheetNum )
                minRefId = componentFlatList[ii].m_SheetNum * aSheetIntervalId;

            LastReferenceNumber = GetLastReference( ii, minRefId );

#else
            // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
            if( aUseSheetNum )
                minRefId = componentFlatList[ii].m_SheetNum * aSheetIntervalId + 1;
            else
                minRefId = aStartNumber + 1;

            GetRefsInUse( first, idList, minRefId );
#endif
        }

        // Annotation of one part per package components (trivial case).
        if( componentFlatList[ii].GetLibPart()->GetUnitCount() <= 1 )
        {
            if( componentFlatList[ii].m_IsNew )
            {
#ifdef USE_OLD_ALGO
                LastReferenceNumber++;
#else
                LastReferenceNumber = CreateFirstFreeRefId( idList, minRefId );
#endif
                componentFlatList[ii].m_NumRef = LastReferenceNumber;
            }

            componentFlatList[ii].m_Unit  = 1;
            componentFlatList[ii].m_Flag  = 1;
            componentFlatList[ii].m_IsNew = false;
            continue;
        }

        // Annotation of multi-unit parts ( n units per part ) (complex case)
        NumberOfUnits = componentFlatList[ii].GetLibPart()->GetUnitCount();

        if( componentFlatList[ii].m_IsNew )
        {
#ifdef USE_OLD_ALGO
            LastReferenceNumber++;
#else
            LastReferenceNumber = CreateFirstFreeRefId( idList, minRefId );
#endif
            componentFlatList[ii].m_NumRef = LastReferenceNumber;

            if( !componentFlatList[ii].IsUnitsLocked() )
                componentFlatList[ii].m_Unit = 1;

            componentFlatList[ii].m_Flag = 1;
        }

        // If this component is in aLockedUnitMap, copy the annotation to all
        // components that are not it
        if( lockedList != NULL )
        {
            unsigned n_refs = lockedList->GetCount();

            for( unsigned thisRefI = 0; thisRefI < n_refs; ++thisRefI )
            {
                SCH_REFERENCE &thisRef = (*lockedList)[thisRefI];

                if( thisRef.IsSameInstance( componentFlatList[ii] ) )
                {
                    // This is the component we're currently annotating. Hold the unit!
                    componentFlatList[ii].m_Unit = thisRef.m_Unit;
                }

                if( thisRef.CompareValue( componentFlatList[ii] ) != 0 )
                    continue;

                if( thisRef.CompareLibName( componentFlatList[ii] ) != 0 )
                    continue;

                // Find the matching component
                for( unsigned jj = ii + 1; jj < componentFlatList.size(); jj++ )
                {
                    if( ! thisRef.IsSameInstance( componentFlatList[jj] ) )
                        continue;

                    wxString ref_candidate = buildFullReference( componentFlatList[ii] );

                    // propagate the new reference and unit selection to the "old" component,
                    // if this new full reference is not already used (can happens when initial
                    // multiunits components have duplicate references)
                    if( inUseRefs.find( ref_candidate ) == inUseRefs.end() )
                    {
                        componentFlatList[jj].m_NumRef = componentFlatList[ii].m_NumRef;
                        componentFlatList[jj].m_Unit = thisRef.m_Unit;
                        componentFlatList[jj].m_IsNew = false;
                        componentFlatList[jj].m_Flag = 1;
                        // lock this new full reference
                        inUseRefs.insert( ref_candidate );
                        break;
                    }
                }
            }
        }

        else
        {
            /* search for others units of this component.
            * we search for others parts that have the same value and the same
            * reference prefix (ref without ref number)
            */
            for( Unit = 1; Unit <= NumberOfUnits; Unit++ )
            {
                if( componentFlatList[ii].m_Unit == Unit )
                    continue;

                int found = FindUnit( ii, Unit );

                if( found >= 0 )
                    continue; // this unit exists for this reference (unit already annotated)

                // Search a component to annotate ( same prefix, same value, not annotated)
                for( unsigned jj = ii + 1; jj < componentFlatList.size(); jj++ )
                {
                    if( componentFlatList[jj].m_Flag )    // already tested
                        continue;

                    if( componentFlatList[ii].CompareRef( componentFlatList[jj] ) != 0 )
                        continue;

                    if( componentFlatList[jj].CompareValue( componentFlatList[ii] ) != 0 )
                        continue;

                    if( componentFlatList[jj].CompareLibName( componentFlatList[ii] ) != 0 )
                        continue;

                    if( !componentFlatList[jj].m_IsNew )
                        continue;

                    // Component without reference number found, annotate it if possible
                    if( !componentFlatList[jj].IsUnitsLocked()
                        || ( componentFlatList[jj].m_Unit == Unit ) )
                    {
                        componentFlatList[jj].m_NumRef = componentFlatList[ii].m_NumRef;
                        componentFlatList[jj].m_Unit   = Unit;
                        componentFlatList[jj].m_Flag   = 1;
                        componentFlatList[jj].m_IsNew  = false;
                        break;
                    }
                }
            }
        }
    }
}
void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId,
      SCH_MULTI_UNIT_REFERENCE_MAP aLockedUnitMap )
{
    if ( componentFlatList.size() == 0 )
        return;

    int LastReferenceNumber = 0;
    int NumberOfUnits, Unit;

    /* calculate index of the first component with the same reference prefix
     * than the current component.  All components having the same reference
     * prefix will receive a reference number with consecutive values:
     * IC .. will be set to IC4, IC4, IC5 ...
     */
    unsigned first = 0;

    // calculate the last used number for this reference prefix:
#ifdef USE_OLD_ALGO
    int minRefId = 0;

    // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
    if( aUseSheetNum )
        minRefId = componentFlatList[first].m_SheetNum * aSheetIntervalId;

    LastReferenceNumber = GetLastReference( first, minRefId );
#else
    int minRefId = 1;

    // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
    if( aUseSheetNum )
        minRefId = componentFlatList[first].m_SheetNum * aSheetIntervalId + 1;

    // This is the list of all Id already in use for a given reference prefix.
    // Will be refilled for each new reference prefix.
    std::vector<int>idList;
    GetRefsInUse( first, idList, minRefId );
#endif
    for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
    {
        if( componentFlatList[ii].m_Flag )
            continue;

        // Check whether this component is in aLockedUnitMap.
        SCH_REFERENCE_LIST* lockedList = NULL;
        for( SCH_MULTI_UNIT_REFERENCE_MAP::value_type& pair : aLockedUnitMap )
        {
            unsigned n_refs = pair.second.GetCount();
            for( unsigned thisRefI = 0; thisRefI < n_refs; ++thisRefI )
            {
                SCH_REFERENCE &thisRef = pair.second[thisRefI];

                if( thisRef.IsSameInstance( componentFlatList[ii] ) )
                {
                    lockedList = &pair.second;
                    break;
                }
            }
            if( lockedList != NULL ) break;
        }

        if(  ( componentFlatList[first].CompareRef( componentFlatList[ii] ) != 0 )
          || ( aUseSheetNum && ( componentFlatList[first].m_SheetNum != componentFlatList[ii].m_SheetNum ) )  )
        {
            // New reference found: we need a new ref number for this reference
            first = ii;
#ifdef USE_OLD_ALGO
            minRefId = 0;

            // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
            if( aUseSheetNum )
                minRefId = componentFlatList[ii].m_SheetNum * aSheetIntervalId;

            LastReferenceNumber = componentFlatList.GetLastReference( ii, minRefId );
#else
            minRefId = 1;

            // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
            if( aUseSheetNum )
                minRefId = componentFlatList[ii].m_SheetNum * aSheetIntervalId + 1;

            GetRefsInUse( first, idList, minRefId );
#endif
        }

        // Annotation of one part per package components (trivial case).
        if( componentFlatList[ii].GetLibPart()->GetUnitCount() <= 1 )
        {
            if( componentFlatList[ii].m_IsNew )
            {
#ifdef USE_OLD_ALGO
                LastReferenceNumber++;
#else
                LastReferenceNumber = CreateFirstFreeRefId( idList, minRefId );
#endif
                componentFlatList[ii].m_NumRef = LastReferenceNumber;
            }

            componentFlatList[ii].m_Unit  = 1;
            componentFlatList[ii].m_Flag  = 1;
            componentFlatList[ii].m_IsNew = false;
            continue;
        }

        // Annotation of multi-unit parts ( n units per part ) (complex case)
        NumberOfUnits = componentFlatList[ii].GetLibPart()->GetUnitCount();

        if( componentFlatList[ii].m_IsNew )
        {
#ifdef USE_OLD_ALGO
            LastReferenceNumber++;
#else
            LastReferenceNumber = CreateFirstFreeRefId( idList, minRefId );
#endif
            componentFlatList[ii].m_NumRef = LastReferenceNumber;

            if( !componentFlatList[ii].IsUnitsLocked() )
                componentFlatList[ii].m_Unit = 1;

            componentFlatList[ii].m_Flag = 1;
        }

        // If this component is in aLockedUnitMap, copy the annotation to all
        // components that are not it
        if( lockedList != NULL )
        {
            unsigned n_refs = lockedList->GetCount();
            for( unsigned thisRefI = 0; thisRefI < n_refs; ++thisRefI )
            {
                SCH_REFERENCE &thisRef = (*lockedList)[thisRefI];
                if( thisRef.IsSameInstance( componentFlatList[ii] ) )
                {
                    // This is the component we're currently annotating. Hold the unit!
                    componentFlatList[ii].m_Unit = thisRef.m_Unit;
                }

                if( thisRef.CompareValue( componentFlatList[ii] ) != 0 ) continue;
                if( thisRef.CompareLibName( componentFlatList[ii] ) != 0 ) continue;

                // Find the matching component
                for( unsigned jj = ii + 1; jj < componentFlatList.size(); jj++ )
                {
                    if( ! thisRef.IsSameInstance( componentFlatList[jj] ) ) continue;
                    componentFlatList[jj].m_NumRef = componentFlatList[ii].m_NumRef;
                    componentFlatList[jj].m_Unit = thisRef.m_Unit;
                    componentFlatList[jj].m_IsNew = false;
                    componentFlatList[jj].m_Flag = 1;
                    break;
                }
            }
        }

        else
        {
            /* search for others units of this component.
            * we search for others parts that have the same value and the same
            * reference prefix (ref without ref number)
            */
            for( Unit = 1; Unit <= NumberOfUnits; Unit++ )
            {
                if( componentFlatList[ii].m_Unit == Unit )
                    continue;

                int found = FindUnit( ii, Unit );

                if( found >= 0 )
                    continue; // this unit exists for this reference (unit already annotated)

                // Search a component to annotate ( same prefix, same value, not annotated)
                for( unsigned jj = ii + 1; jj < componentFlatList.size(); jj++ )
                {
                    if( componentFlatList[jj].m_Flag )    // already tested
                        continue;

                    if( componentFlatList[ii].CompareRef( componentFlatList[jj] ) != 0 )
                        continue;

                    if( componentFlatList[jj].CompareValue( componentFlatList[ii] ) != 0 )
                        continue;

                    if( componentFlatList[jj].CompareLibName( componentFlatList[ii] ) != 0 )
                        continue;

                    if( !componentFlatList[jj].m_IsNew )
                        continue;

                    // Component without reference number found, annotate it if possible
                    if( !componentFlatList[jj].IsUnitsLocked()
                        || ( componentFlatList[jj].m_Unit == Unit ) )
                    {
                        componentFlatList[jj].m_NumRef = componentFlatList[ii].m_NumRef;
                        componentFlatList[jj].m_Unit   = Unit;
                        componentFlatList[jj].m_Flag   = 1;
                        componentFlatList[jj].m_IsNew  = false;
                        break;
                    }
                }
            }
        }
    }
}
void SCH_EDIT_FRAME::AnnotateComponents( bool              aAnnotateSchematic,
                                         ANNOTATE_ORDER_T  aSortOption,
                                         ANNOTATE_OPTION_T aAlgoOption,
                                         int               aStartNumber,
                                         bool              aResetAnnotation,
                                         bool              aRepairTimestamps,
                                         bool              aLockUnits,
                                         REPORTER&         aReporter )
{
    SCH_REFERENCE_LIST references;

    SCH_SCREENS screens;

    // Build the sheet list.
    SCH_SHEET_LIST sheets( g_RootSheet );

    // Map of locked components
    SCH_MULTI_UNIT_REFERENCE_MAP lockedComponents;

    // Map of previous annotation for building info messages
    std::map<timestamp_t, wxString> previousAnnotation;

    // Test for and replace duplicate time stamps in components and sheets.  Duplicate
    // time stamps can happen with old schematics, schematic conversions, or manual
    // editing of files.
    if( aRepairTimestamps )
    {
        int count = screens.ReplaceDuplicateTimeStamps();

        if( count )
        {
            wxString msg;
            msg.Printf( _( "%d duplicate time stamps were found and replaced." ), count );
            aReporter.ReportTail( msg, REPORTER::RPT_WARNING );
        }
    }

    // If units must be locked, collect all the sets that must be annotated together.
    if( aLockUnits )
    {
        if( aAnnotateSchematic )
        {
            sheets.GetMultiUnitComponents( lockedComponents );
        }
        else
        {
            m_CurrentSheet->GetMultiUnitComponents( lockedComponents );
        }
    }

    // Store previous annotations for building info messages
    mapExistingAnnotation( previousAnnotation );

    // If it is an annotation for all the components, reset previous annotation.
    if( aResetAnnotation )
        DeleteAnnotation( !aAnnotateSchematic );

    // Set sheet number and number of sheets.
    SetSheetNumberAndCount();

    // Build component list
    if( aAnnotateSchematic )
    {
        sheets.GetComponents( references );
    }
    else
    {
        m_CurrentSheet->GetComponents( references );
    }

    // Break full components reference in name (prefix) and number:
    // example: IC1 become IC, and 1
    references.SplitReferences();

    switch( aSortOption )
    {
    default:
    case SORT_BY_X_POSITION:
        references.SortByXCoordinate();
        break;

    case SORT_BY_Y_POSITION:
        references.SortByYCoordinate();
        break;
    }

    bool useSheetNum = false;
    int idStep = 100;

    switch( aAlgoOption )
    {
    default:
    case INCREMENTAL_BY_REF:
        break;

    case SHEET_NUMBER_X_100:
        useSheetNum = true;
        break;

    case SHEET_NUMBER_X_1000:
        useSheetNum = true;
        idStep = 1000;
        break;
    }

    // Recalculate and update reference numbers in schematic
    references.Annotate( useSheetNum, idStep, aStartNumber, lockedComponents );
    references.UpdateAnnotation();

    for( size_t i = 0; i < references.GetCount(); i++ )
    {
        SCH_COMPONENT* comp = references[ i ].GetComp();
        wxString       prevRef = previousAnnotation[ comp->GetTimeStamp() ];
        wxString       newRef  = comp->GetField( REFERENCE )->GetFullyQualifiedText();
        wxString       msg;

        if( prevRef.Length() )
        {
            if( newRef == prevRef )
                continue;

            if( comp->GetUnitCount() > 1 )
                msg.Printf( _( "Updated %s (unit %s) from %s to %s" ),
                            GetChars( comp->GetField( VALUE )->GetShownText() ),
                            LIB_PART::SubReference( comp->GetUnit(), false ),
                            GetChars( prevRef ),
                            GetChars( newRef ) );
            else
                msg.Printf( _( "Updated %s from %s to %s" ),
                            GetChars( comp->GetField( VALUE )->GetShownText() ),
                            GetChars( prevRef ),
                            GetChars( newRef ) );
        }
        else
        {
            if( comp->GetUnitCount() > 1 )
                msg.Printf( _( "Annotated %s (unit %s) as %s" ),
                            GetChars( comp->GetField( VALUE )->GetShownText() ),
                            LIB_PART::SubReference( comp->GetUnit(), false ),
                            GetChars( newRef ) );
            else
                msg.Printf( _( "Annotated %s as %s" ),
                            GetChars( comp->GetField( VALUE )->GetShownText() ),
                            GetChars( newRef ) );
        }

        aReporter.Report( msg, REPORTER::RPT_ACTION );
    }

    // Final control (just in case ... ).
    if( !CheckAnnotate( aReporter, !aAnnotateSchematic ) )
        aReporter.ReportTail( _( "Annotation complete." ), REPORTER::RPT_ACTION );

    // Update on screen references, that can be modified by previous calculations:
    m_CurrentSheet->UpdateAllScreenReferences();
    SetSheetNumberAndCount();

    SyncView();
    GetCanvas()->Refresh();
    OnModify();
}
Exemple #7
0
/**
 * Add a list of component items to the BOM manager
 * Creates consolidated groups of components as required
 */
void BOM_TABLE_MODEL::SetComponents( SCH_REFERENCE_LIST aRefs, const TEMPLATE_FIELDNAMES& aTemplateFields )
{

    // Add default columns
    AddDefaultColumns();

    // Extract all component fields
    for( unsigned int ii=0; ii<aRefs.GetCount(); ii++ )
    {
        auto ref = aRefs.GetItem( ii );
        auto cmp = ref.GetComp();

        if( cmp )
        {
            AddComponentFields( cmp );
        }
    }

    // Add template fields if they are not already added
    for( auto field : aTemplateFields )
    {
        BOM_COLUMN* col;

        col = ColumnList.GetColumnByTitle( field.m_Name );

        if( !col )
        {
            col = new BOM_COLUMN( ColumnList.NextFieldId(),
                                       BOM_COL_TYPE_USER,
                                       field.m_Name,
                                       true, false );

            ColumnList.AddColumn( col );
        }

        // Add template value for that field
        m_fieldTemplates[col->Id()] = field.m_Value;
    }

    // Group multi-unit components together
    m_components.clear();
    m_fieldValues.clear();


    // Iterate through each unique component
    for( unsigned int ii=0; ii<aRefs.GetCount(); ii++ )
    {
        auto ref = aRefs.GetItem( ii );

        bool found = false;

        for( auto& cmp : m_components )
        {
            if( cmp->AddUnit( ref ) )
            {
                found = true;
                break;
            }
        }

        if( !found )
        {
            // Find the field:value map associated with this component
            wxString refDes = ref.GetComp()->GetField( REFERENCE )->GetText();

            bool dataFound = false;

            BOM_FIELD_VALUES* values;

            for( auto& data : m_fieldValues )
            {
                // Look for a match based on RefDes
                if( data->GetReference().Cmp( refDes ) == 0 )
                {
                    dataFound = true;
                    values = &*data;
                }
            }

            if( !dataFound )
            {
                values = new BOM_FIELD_VALUES( refDes, &m_fieldTemplates );
                m_fieldValues.push_back( std::unique_ptr<BOM_FIELD_VALUES>( values ) );
            }

            auto* newComponent = new BOM_TABLE_COMPONENT( nullptr, &ColumnList, values );
            newComponent->AddUnit( ref );

            m_components.push_back( std::unique_ptr<BOM_TABLE_COMPONENT>( newComponent ) );
        }
    }

    SetBackupPoint();
}