Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2bc8c0ace5 | |||
| f439dfb6ea | |||
| 9fdc1257a1 | |||
| 95828ff2e2 | |||
| 98e55c0a04 | |||
| 2757d81231 | |||
| 985ceb365b |
@@ -37,7 +37,7 @@
|
||||
# KiCad.
|
||||
#
|
||||
# Note: This version string should follow the semantic versioning system
|
||||
set( KICAD_SEMANTIC_VERSION "6.0.11" )
|
||||
set( KICAD_SEMANTIC_VERSION "6.0.11-unknown" )
|
||||
|
||||
# Default the version to the semantic version.
|
||||
# This is overridden by the git repository tag though (if using git)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020-2021 CERN
|
||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Wayne Stambaugh <stambaughw@gmail.com>
|
||||
*
|
||||
@@ -25,14 +25,12 @@
|
||||
#include <bitmaps.h>
|
||||
#include <string_utils.h> // WildCompareString
|
||||
#include <kiway.h>
|
||||
#include <lib_id.h>
|
||||
#include <refdes_utils.h>
|
||||
#include <core/kicad_algo.h>
|
||||
#include <dialog_change_symbols.h>
|
||||
#include <sch_symbol.h>
|
||||
#include <sch_edit_frame.h>
|
||||
#include <sch_screen.h>
|
||||
#include <sch_sheet_path.h>
|
||||
#include <schematic.h>
|
||||
#include <template_fieldnames.h>
|
||||
#include <wx_html_report_panel.h>
|
||||
@@ -399,7 +397,9 @@ void DIALOG_CHANGE_SYMBOLS::onOkButtonClicked( wxCommandEvent& aEvent )
|
||||
m_updateFields.insert( dummy_field.GetCanonicalName() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_updateFields.insert( m_fieldsBox->GetString( i ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,15 +451,16 @@ bool DIALOG_CHANGE_SYMBOLS::isMatch( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aInsta
|
||||
}
|
||||
|
||||
|
||||
bool DIALOG_CHANGE_SYMBOLS::processMatchingSymbols()
|
||||
int DIALOG_CHANGE_SYMBOLS::processMatchingSymbols()
|
||||
{
|
||||
SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
|
||||
|
||||
wxCHECK( frame, false );
|
||||
|
||||
LIB_ID newId;
|
||||
bool appendToUndo = false;
|
||||
bool changed = false;
|
||||
wxString msg;
|
||||
int matchesProcessed = 0;
|
||||
SCH_SYMBOL* symbol = nullptr;
|
||||
SCH_SHEET_LIST hierarchy = frame->Schematic().GetSheets();
|
||||
|
||||
if( m_mode == MODE::CHANGE )
|
||||
@@ -470,70 +471,258 @@ bool DIALOG_CHANGE_SYMBOLS::processMatchingSymbols()
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols;
|
||||
|
||||
for( SCH_SHEET_PATH& instance : hierarchy )
|
||||
{
|
||||
SCH_SCREEN* screen = instance.LastScreen();
|
||||
|
||||
wxCHECK2( screen, continue );
|
||||
|
||||
std::vector<SCH_SYMBOL*> symbols;
|
||||
|
||||
// Fetch all the symbols that meet the change criteria.
|
||||
for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
|
||||
symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
|
||||
|
||||
for( SCH_SYMBOL* symbol : symbols )
|
||||
{
|
||||
symbol = static_cast<SCH_SYMBOL*>( item );
|
||||
|
||||
wxCHECK2( symbol, continue );
|
||||
|
||||
if( !isMatch( symbol, &instance ) )
|
||||
continue;
|
||||
|
||||
if( m_mode == MODE::UPDATE )
|
||||
newId = symbol->GetLibId();
|
||||
|
||||
auto it = symbols.find( symbol );
|
||||
|
||||
if( it == symbols.end() )
|
||||
{
|
||||
if( processSymbol( symbol, &instance, symbol->GetLibId(), appendToUndo ) )
|
||||
changed = true;
|
||||
SYMBOL_CHANGE_INFO info;
|
||||
|
||||
info.m_Instances.emplace_back( instance );
|
||||
info.m_LibId = newId;
|
||||
symbols.insert( { symbol, info } );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( processSymbol( symbol, &instance, newId, appendToUndo ) )
|
||||
changed = true;
|
||||
it->second.m_Instances.emplace_back( instance );
|
||||
}
|
||||
|
||||
if( changed )
|
||||
appendToUndo = true;
|
||||
}
|
||||
}
|
||||
|
||||
matchesProcessed += processSymbols( symbols );
|
||||
|
||||
frame->GetCurrentSheet().UpdateAllScreenReferences();
|
||||
|
||||
return changed;
|
||||
return matchesProcessed;
|
||||
}
|
||||
|
||||
|
||||
bool DIALOG_CHANGE_SYMBOLS::processSymbol( SCH_SYMBOL* aSymbol, const SCH_SHEET_PATH* aInstance,
|
||||
const LIB_ID& aNewId, bool aAppendToUndo )
|
||||
int DIALOG_CHANGE_SYMBOLS::processSymbols( const std::map<SCH_SYMBOL*,
|
||||
SYMBOL_CHANGE_INFO>& aSymbols )
|
||||
{
|
||||
wxCHECK( aSymbol, false );
|
||||
wxCHECK( aNewId.IsValid(), false );
|
||||
wxCHECK( !aSymbols.empty(), 0 );
|
||||
|
||||
SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
|
||||
SCH_SCREEN* screen = aInstance->LastScreen();
|
||||
int matchesProcessed = 0;
|
||||
SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
|
||||
SCH_SCREEN* screen = nullptr;
|
||||
SCH_SYMBOL* symbol = nullptr;
|
||||
LIB_SYMBOL* libSymbol = nullptr;
|
||||
std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols = aSymbols;
|
||||
|
||||
wxCHECK( frame, false );
|
||||
wxCHECK( frame, 0 );
|
||||
|
||||
LIB_ID oldId = aSymbol->GetLibId();
|
||||
wxString msg;
|
||||
wxString references;
|
||||
|
||||
for( SYMBOL_INSTANCE_REFERENCE instance : aSymbol->GetInstanceReferences() )
|
||||
auto it = symbols.begin();
|
||||
|
||||
// Remove all symbols that don't have a valid library symbol link or enough units to
|
||||
// satify the library symbol update.
|
||||
while( it != symbols.end() )
|
||||
{
|
||||
symbol = it->first;
|
||||
|
||||
wxCHECK2( symbol && it->second.m_LibId.IsValid(), continue );
|
||||
|
||||
libSymbol = frame->GetLibSymbol( it->second.m_LibId );
|
||||
|
||||
if( !libSymbol )
|
||||
{
|
||||
msg = getSymbolReferences( *symbol, it->second.m_LibId );
|
||||
msg << wxT( ": " ) << _( "*** symbol not found ***" );
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ERROR );
|
||||
it = symbols.erase( it );
|
||||
continue;
|
||||
}
|
||||
|
||||
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
|
||||
|
||||
if( flattenedSymbol->GetUnitCount() < symbol->GetUnit() )
|
||||
{
|
||||
msg = getSymbolReferences( *symbol, it->second.m_LibId );
|
||||
msg << wxT( ": " ) << _( "*** new symbol has too few units ***" );
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ERROR );
|
||||
it = symbols.erase( it );
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
// Removing the symbol needs to be done before the LIB_SYMBOL is changed to prevent stale
|
||||
// library symbols in the schematic file.
|
||||
for( auto& pair : symbols )
|
||||
{
|
||||
symbol = pair.first;
|
||||
|
||||
wxCHECK( symbol && !pair.second.m_Instances.empty(), 0 );
|
||||
|
||||
screen = pair.second.m_Instances[0].LastScreen();
|
||||
|
||||
wxCHECK( screen, 0 );
|
||||
|
||||
screen->Remove( symbol );
|
||||
frame->SaveCopyInUndoList( screen, symbol, UNDO_REDO::CHANGED, true );
|
||||
}
|
||||
|
||||
for( auto& pair : symbols )
|
||||
{
|
||||
symbol = pair.first;
|
||||
|
||||
if( pair.second.m_LibId != symbol->GetLibId() )
|
||||
symbol->SetLibId( pair.second.m_LibId );
|
||||
|
||||
libSymbol = frame->GetLibSymbol( pair.second.m_LibId );
|
||||
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
|
||||
|
||||
symbol->SetLibSymbol( flattenedSymbol.release() );
|
||||
|
||||
if( m_resetAttributes->GetValue() )
|
||||
{
|
||||
symbol->SetIncludeInBom( libSymbol->GetIncludeInBom() );
|
||||
symbol->SetIncludeOnBoard( libSymbol->GetIncludeOnBoard() );
|
||||
}
|
||||
|
||||
bool removeExtras = m_removeExtraBox->GetValue();
|
||||
bool resetVis = m_resetFieldVisibilities->GetValue();
|
||||
bool resetEffects = m_resetFieldEffects->GetValue();
|
||||
bool resetPositions = m_resetFieldPositions->GetValue();
|
||||
|
||||
for( unsigned i = 0; i < symbol->GetFields().size(); ++i )
|
||||
{
|
||||
SCH_FIELD& field = symbol->GetFields()[i];
|
||||
LIB_FIELD* libField = nullptr;
|
||||
|
||||
// Mandatory fields always exist in m_updateFields, but these names can be translated.
|
||||
// so use GetCanonicalName().
|
||||
if( !alg::contains( m_updateFields, field.GetCanonicalName() ) )
|
||||
continue;
|
||||
|
||||
if( i < MANDATORY_FIELDS )
|
||||
libField = libSymbol->GetFieldById( (int) i );
|
||||
else
|
||||
libField = libSymbol->FindField( field.GetName() );
|
||||
|
||||
if( libField )
|
||||
{
|
||||
bool resetText = libField->GetText().IsEmpty() ? m_resetEmptyFields->GetValue()
|
||||
: m_resetFieldText->GetValue();
|
||||
|
||||
if( resetText )
|
||||
{
|
||||
for( const SCH_SHEET_PATH& instance : pair.second.m_Instances )
|
||||
{
|
||||
if( i == REFERENCE_FIELD )
|
||||
symbol->SetRef( &instance,
|
||||
UTIL::GetRefDesUnannotated( libField->GetText() ) );
|
||||
else if( i == VALUE_FIELD )
|
||||
symbol->SetValue( &instance, UnescapeString( libField->GetText() ) );
|
||||
else if( i == FOOTPRINT_FIELD )
|
||||
symbol->SetFootprint( &instance, libField->GetText() );
|
||||
else
|
||||
field.SetText( libField->GetText() );
|
||||
}
|
||||
}
|
||||
|
||||
if( resetVis )
|
||||
field.SetVisible( libField->IsVisible() );
|
||||
|
||||
if( resetEffects )
|
||||
{
|
||||
// Careful: the visible bit and position are also in Effects
|
||||
bool visible = field.IsVisible();
|
||||
wxPoint pos = field.GetPosition();
|
||||
|
||||
field.SetEffects( *libField );
|
||||
|
||||
field.SetVisible( visible );
|
||||
field.SetPosition( pos );
|
||||
}
|
||||
|
||||
if( resetPositions )
|
||||
field.SetTextPos( symbol->GetPosition() + libField->GetTextPos() );
|
||||
}
|
||||
else if( i >= MANDATORY_FIELDS && removeExtras )
|
||||
{
|
||||
symbol->RemoveField( field.GetName() );
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<LIB_FIELD*> libFields;
|
||||
libSymbol->GetFields( libFields );
|
||||
|
||||
for( unsigned i = MANDATORY_FIELDS; i < libFields.size(); ++i )
|
||||
{
|
||||
const LIB_FIELD& libField = *libFields[i];
|
||||
|
||||
if( !alg::contains( m_updateFields, libField.GetCanonicalName() ) )
|
||||
continue;
|
||||
|
||||
if( !symbol->FindField( libField.GetName(), false ) )
|
||||
{
|
||||
wxString fieldName = libField.GetCanonicalName();
|
||||
SCH_FIELD newField( wxPoint( 0, 0 ), symbol->GetFieldCount(), symbol,
|
||||
fieldName );
|
||||
SCH_FIELD* schField = symbol->AddField( newField );
|
||||
|
||||
schField->SetEffects( libField );
|
||||
schField->SetText( libField.GetText() );
|
||||
schField->SetTextPos( symbol->GetPosition() + libField.GetTextPos() );
|
||||
}
|
||||
}
|
||||
|
||||
symbol->SetSchSymbolLibraryName( wxEmptyString );
|
||||
screen = pair.second.m_Instances[0].LastScreen();
|
||||
screen->Append( symbol );
|
||||
frame->GetCanvas()->GetView()->Update( symbol );
|
||||
|
||||
msg = getSymbolReferences( *symbol, pair.second.m_LibId );
|
||||
msg += wxS( ": OK" );
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ACTION );
|
||||
matchesProcessed +=1;
|
||||
}
|
||||
|
||||
return matchesProcessed;
|
||||
}
|
||||
|
||||
|
||||
wxString DIALOG_CHANGE_SYMBOLS::getSymbolReferences( SCH_SYMBOL& aSymbol, const LIB_ID& aNewId )
|
||||
{
|
||||
wxString msg;
|
||||
wxString references;
|
||||
LIB_ID oldId = aSymbol.GetLibId();
|
||||
|
||||
for( const SYMBOL_INSTANCE_REFERENCE& instance : aSymbol.GetInstanceReferences() )
|
||||
{
|
||||
if( references.IsEmpty() )
|
||||
references = instance.m_Reference;
|
||||
else
|
||||
references += wxT( " " ) + instance.m_Reference;
|
||||
}
|
||||
|
||||
if( m_mode == MODE::UPDATE )
|
||||
{
|
||||
if( aSymbol->GetInstanceReferences().size() == 1 )
|
||||
if( aSymbol.GetInstanceReferences().size() == 1 )
|
||||
{
|
||||
msg.Printf( _( "Update symbol %s from '%s' to '%s'" ),
|
||||
references,
|
||||
@@ -550,7 +739,7 @@ bool DIALOG_CHANGE_SYMBOLS::processSymbol( SCH_SYMBOL* aSymbol, const SCH_SHEET_
|
||||
}
|
||||
else
|
||||
{
|
||||
if( aSymbol->GetInstanceReferences().size() == 1 )
|
||||
if( aSymbol.GetInstanceReferences().size() == 1 )
|
||||
{
|
||||
msg.Printf( _( "Change symbol %s from '%s' to '%s'" ),
|
||||
references,
|
||||
@@ -566,132 +755,5 @@ bool DIALOG_CHANGE_SYMBOLS::processSymbol( SCH_SYMBOL* aSymbol, const SCH_SHEET_
|
||||
}
|
||||
}
|
||||
|
||||
LIB_SYMBOL* libSymbol = frame->GetLibSymbol( aNewId );
|
||||
|
||||
if( !libSymbol )
|
||||
{
|
||||
msg << wxT( ": " ) << _( "*** symbol not found ***" );
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ERROR );
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
|
||||
|
||||
if( flattenedSymbol->GetUnitCount() < aSymbol->GetUnit() )
|
||||
{
|
||||
msg << wxT( ": " ) << _( "*** new symbol has too few units ***" );
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ERROR );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Removing the symbol needs to be done before the LIB_SYMBOL is changed to prevent stale
|
||||
// library symbols in the schematic file.
|
||||
screen->Remove( aSymbol );
|
||||
frame->SaveCopyInUndoList( screen, aSymbol, UNDO_REDO::CHANGED, aAppendToUndo );
|
||||
|
||||
if( aNewId != aSymbol->GetLibId() )
|
||||
aSymbol->SetLibId( aNewId );
|
||||
|
||||
aSymbol->SetLibSymbol( flattenedSymbol.release() );
|
||||
|
||||
if( m_resetAttributes->GetValue() )
|
||||
{
|
||||
aSymbol->SetIncludeInBom( libSymbol->GetIncludeInBom() );
|
||||
aSymbol->SetIncludeOnBoard( libSymbol->GetIncludeOnBoard() );
|
||||
}
|
||||
|
||||
bool removeExtras = m_removeExtraBox->GetValue();
|
||||
bool resetVis = m_resetFieldVisibilities->GetValue();
|
||||
bool resetEffects = m_resetFieldEffects->GetValue();
|
||||
bool resetPositions = m_resetFieldPositions->GetValue();
|
||||
|
||||
for( unsigned i = 0; i < aSymbol->GetFields().size(); ++i )
|
||||
{
|
||||
SCH_FIELD& field = aSymbol->GetFields()[i];
|
||||
LIB_FIELD* libField = nullptr;
|
||||
|
||||
// Mandatory fields always exist in m_updateFields, but these names can be translated.
|
||||
// so use GetCanonicalName().
|
||||
if( !alg::contains( m_updateFields, field.GetCanonicalName() ) )
|
||||
continue;
|
||||
|
||||
if( i < MANDATORY_FIELDS )
|
||||
libField = libSymbol->GetFieldById( (int) i );
|
||||
else
|
||||
libField = libSymbol->FindField( field.GetName() );
|
||||
|
||||
if( libField )
|
||||
{
|
||||
bool resetText = libField->GetText().IsEmpty() ? m_resetEmptyFields->GetValue()
|
||||
: m_resetFieldText->GetValue();
|
||||
|
||||
if( resetText )
|
||||
{
|
||||
if( i == REFERENCE_FIELD )
|
||||
aSymbol->SetRef( aInstance, UTIL::GetRefDesUnannotated( libField->GetText() ) );
|
||||
else if( i == VALUE_FIELD )
|
||||
aSymbol->SetValue( aInstance, UnescapeString( libField->GetText() ) );
|
||||
else if( i == FOOTPRINT_FIELD )
|
||||
aSymbol->SetFootprint( aInstance, libField->GetText() );
|
||||
else
|
||||
field.SetText( libField->GetText() );
|
||||
}
|
||||
|
||||
if( resetVis )
|
||||
field.SetVisible( libField->IsVisible() );
|
||||
|
||||
if( resetEffects )
|
||||
{
|
||||
// Careful: the visible bit and position are also in Effects
|
||||
bool visible = field.IsVisible();
|
||||
wxPoint pos = field.GetPosition();
|
||||
|
||||
field.SetEffects( *libField );
|
||||
|
||||
field.SetVisible( visible );
|
||||
field.SetPosition( pos );
|
||||
}
|
||||
|
||||
if( resetPositions )
|
||||
field.SetTextPos( aSymbol->GetPosition() + libField->GetTextPos() );
|
||||
}
|
||||
else if( i >= MANDATORY_FIELDS && removeExtras )
|
||||
{
|
||||
aSymbol->RemoveField( field.GetName() );
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<LIB_FIELD*> libFields;
|
||||
libSymbol->GetFields( libFields );
|
||||
|
||||
for( unsigned i = MANDATORY_FIELDS; i < libFields.size(); ++i )
|
||||
{
|
||||
const LIB_FIELD& libField = *libFields[i];
|
||||
|
||||
if( !alg::contains( m_updateFields, libField.GetCanonicalName() ) )
|
||||
continue;
|
||||
|
||||
if( !aSymbol->FindField( libField.GetName(), false ) )
|
||||
{
|
||||
wxString fieldName = libField.GetCanonicalName();
|
||||
SCH_FIELD newField( wxPoint( 0, 0), aSymbol->GetFieldCount(), aSymbol, fieldName );
|
||||
SCH_FIELD* schField = aSymbol->AddField( newField );
|
||||
|
||||
schField->SetEffects( libField );
|
||||
schField->SetText( libField.GetText() );
|
||||
schField->SetTextPos( aSymbol->GetPosition() + libField.GetTextPos() );
|
||||
}
|
||||
}
|
||||
|
||||
aSymbol->SetSchSymbolLibraryName( wxEmptyString );
|
||||
screen->Append( aSymbol );
|
||||
frame->GetCanvas()->GetView()->Update( aSymbol );
|
||||
|
||||
msg += wxT( ": OK" );
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ACTION );
|
||||
|
||||
return true;
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020 CERN
|
||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Wayne Stambaugh <stambaughw@gmail.com>
|
||||
*
|
||||
@@ -25,11 +25,21 @@
|
||||
|
||||
#include <dialog_change_symbols_base.h>
|
||||
|
||||
class LIB_ID;
|
||||
#include <lib_id.h>
|
||||
#include <sch_sheet_path.h>
|
||||
|
||||
|
||||
class SCH_SYMBOL;
|
||||
class SCH_EDIT_FRAME;
|
||||
class SCH_SCREEN;
|
||||
class SCH_SHEET_PATH;
|
||||
|
||||
|
||||
struct SYMBOL_CHANGE_INFO
|
||||
{
|
||||
std::vector<SCH_SHEET_PATH> m_Instances;
|
||||
LIB_ID m_LibId;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Dialog to update or change schematic library symbols.
|
||||
@@ -73,9 +83,9 @@ private:
|
||||
void updateFieldsList();
|
||||
|
||||
bool isMatch( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aInstance );
|
||||
bool processMatchingSymbols();
|
||||
bool processSymbol( SCH_SYMBOL* aSymbol, const SCH_SHEET_PATH* aInstance,
|
||||
const LIB_ID& aNewId, bool aAppendToUndo );
|
||||
int processMatchingSymbols();
|
||||
int processSymbols( const std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO>& aSymbols );
|
||||
wxString getSymbolReferences( SCH_SYMBOL& aSymbol, const LIB_ID& aNewId );
|
||||
|
||||
SCH_SYMBOL* m_symbol;
|
||||
MODE m_mode;
|
||||
|
||||
+79
-23
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 1992-2021 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
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -145,14 +145,14 @@ bool SCH_SCREEN::ClassOf( const EDA_ITEM* aItem )
|
||||
}
|
||||
|
||||
|
||||
void SCH_SCREEN::Append( SCH_ITEM* aItem )
|
||||
void SCH_SCREEN::Append( SCH_ITEM* aItem, bool aUpdateLibSymbol )
|
||||
{
|
||||
if( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T )
|
||||
{
|
||||
// Ensure the item can reach the SCHEMATIC through this screen
|
||||
aItem->SetParent( this );
|
||||
|
||||
if( aItem->Type() == SCH_SYMBOL_T )
|
||||
if( aItem->Type() == SCH_SYMBOL_T && aUpdateLibSymbol )
|
||||
{
|
||||
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( aItem );
|
||||
|
||||
@@ -179,30 +179,63 @@ void SCH_SCREEN::Append( SCH_ITEM* aItem )
|
||||
|
||||
if( *foundSymbol != *symbol->GetLibSymbolRef() )
|
||||
{
|
||||
int cnt = 1;
|
||||
wxString newName;
|
||||
std::vector<wxString> matches;
|
||||
|
||||
newName.Printf( wxT( "%s_%d" ), symbol->GetLibId().GetUniStringLibItemName(),
|
||||
cnt );
|
||||
getLibSymbolNameMatches( *symbol, matches );
|
||||
foundSymbol = nullptr;
|
||||
|
||||
while( m_libSymbols.find( newName ) != m_libSymbols.end() )
|
||||
for( const wxString& libSymbolName : matches )
|
||||
{
|
||||
cnt += 1;
|
||||
newName.Printf( wxT( "%s_%d" ), symbol->GetLibId().GetUniStringLibItemName(),
|
||||
cnt );
|
||||
it = m_libSymbols.find( libSymbolName );
|
||||
|
||||
if( it == m_libSymbols.end() )
|
||||
continue;
|
||||
|
||||
foundSymbol = it->second;
|
||||
|
||||
wxCHECK2( foundSymbol, continue );
|
||||
|
||||
if( *foundSymbol == *symbol->GetLibSymbolRef() )
|
||||
{
|
||||
newName = libSymbolName;
|
||||
break;
|
||||
}
|
||||
|
||||
foundSymbol = nullptr;
|
||||
}
|
||||
|
||||
if( !foundSymbol )
|
||||
{
|
||||
int cnt = 1;
|
||||
|
||||
newName.Printf( wxT( "%s_%d" ),
|
||||
symbol->GetLibId().GetUniStringLibItemName(),
|
||||
cnt );
|
||||
|
||||
while( m_libSymbols.find( newName ) != m_libSymbols.end() )
|
||||
{
|
||||
cnt += 1;
|
||||
newName.Printf( wxT( "%s_%d" ),
|
||||
symbol->GetLibId().GetUniStringLibItemName(),
|
||||
cnt );
|
||||
}
|
||||
}
|
||||
|
||||
// Update the schematic symbol library link as this symbol only exists
|
||||
// in the schematic.
|
||||
symbol->SetSchSymbolLibraryName( newName );
|
||||
|
||||
LIB_SYMBOL* newLibSymbol = new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
|
||||
LIB_ID newLibId( wxEmptyString, newName );
|
||||
if( !foundSymbol )
|
||||
{
|
||||
// Update the schematic symbol library link as this symbol does not
|
||||
// exist in any symbol library.
|
||||
LIB_ID newLibId( wxEmptyString, newName );
|
||||
LIB_SYMBOL* newLibSymbol = new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
|
||||
|
||||
newLibSymbol->SetLibId( newLibId );
|
||||
newLibSymbol->SetName( newName );
|
||||
symbol->SetLibSymbol( newLibSymbol->Flatten().release() );
|
||||
m_libSymbols[newName] = newLibSymbol;
|
||||
newLibSymbol->SetLibId( newLibId );
|
||||
newLibSymbol->SetName( newName );
|
||||
symbol->SetLibSymbol( newLibSymbol->Flatten().release() );
|
||||
m_libSymbols[newName] = newLibSymbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -265,19 +298,19 @@ void SCH_SCREEN::FreeDrawList()
|
||||
}
|
||||
|
||||
|
||||
void SCH_SCREEN::Update( SCH_ITEM* aItem )
|
||||
void SCH_SCREEN::Update( SCH_ITEM* aItem, bool aUpdateLibSymbol )
|
||||
{
|
||||
if( Remove( aItem ) )
|
||||
Append( aItem );
|
||||
if( Remove( aItem, aUpdateLibSymbol ) )
|
||||
Append( aItem, aUpdateLibSymbol );
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SCREEN::Remove( SCH_ITEM* aItem )
|
||||
bool SCH_SCREEN::Remove( SCH_ITEM* aItem, bool aUpdateLibSymbol )
|
||||
{
|
||||
bool retv = m_rtree.remove( aItem );
|
||||
|
||||
// Check if the library symbol for the removed schematic symbol is still required.
|
||||
if( retv && aItem->Type() == SCH_SYMBOL_T )
|
||||
if( retv && aItem->Type() == SCH_SYMBOL_T && aUpdateLibSymbol )
|
||||
{
|
||||
SCH_SYMBOL* removedSymbol = static_cast<SCH_SYMBOL*>( aItem );
|
||||
|
||||
@@ -1198,6 +1231,29 @@ void SCH_SCREEN::SetLegacySymbolInstanceData()
|
||||
}
|
||||
|
||||
|
||||
size_t SCH_SCREEN::getLibSymbolNameMatches( const SCH_SYMBOL& aSymbol,
|
||||
std::vector<wxString>& aMatches )
|
||||
{
|
||||
wxString searchName = aSymbol.GetLibId().GetUniStringLibId();
|
||||
|
||||
if( m_libSymbols.find( searchName ) != m_libSymbols.end() )
|
||||
aMatches.emplace_back( searchName );
|
||||
|
||||
searchName = aSymbol.GetLibId().GetUniStringLibItemName() + wxS( "_" );
|
||||
|
||||
long tmp;
|
||||
wxString suffix;
|
||||
|
||||
for( auto pair : m_libSymbols )
|
||||
{
|
||||
if( pair.first.StartsWith( searchName, &suffix ) && suffix.ToLong( &tmp ) )
|
||||
aMatches.emplace_back( pair.first );
|
||||
}
|
||||
|
||||
return aMatches.size();
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEBUG)
|
||||
void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
|
||||
{
|
||||
|
||||
+23
-6
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
|
||||
* Copyright (C) 1992-2021 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
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -181,7 +181,7 @@ public:
|
||||
return m_clientSheetPathList;
|
||||
}
|
||||
|
||||
void Append( SCH_ITEM* aItem );
|
||||
void Append( SCH_ITEM* aItem, bool aUpdateLibSymbol = true );
|
||||
|
||||
/**
|
||||
* Copy the contents of \a aScreen into this #SCH_SCREEN object.
|
||||
@@ -264,16 +264,18 @@ public:
|
||||
*
|
||||
* @note The removed item is not deleted. It is only unlinked from the item list.
|
||||
* @param[in] aItem Item to be removed from schematic.
|
||||
* @param aUpdateLibSymbol removes the library symbol as required when true.
|
||||
* @return True if we successfully removed the item
|
||||
*/
|
||||
bool Remove( SCH_ITEM* aItem );
|
||||
bool Remove( SCH_ITEM* aItem, bool aUpdateLibSymbol = true );
|
||||
|
||||
/**
|
||||
* Update \a aItem's bounding box in the tree
|
||||
*
|
||||
* @param[in] aItem Item that needs to be updated.
|
||||
* @param aUpdateLibSymbol removes the library symbol as required when true.
|
||||
*/
|
||||
void Update( SCH_ITEM* aItem );
|
||||
void Update( SCH_ITEM* aItem, bool aUpdateLibSymbol = true );
|
||||
|
||||
/**
|
||||
* Removes \a aItem from the linked list and deletes the object.
|
||||
@@ -516,13 +518,28 @@ private:
|
||||
bool doIsJunction( const wxPoint& aPosition, bool aBreakCrossings,
|
||||
bool* aHasExplicitJunctionDot, bool* aHasBusEntry ) const;
|
||||
|
||||
void clearLibSymbols();
|
||||
|
||||
/**
|
||||
* Return a list of potential library symbol matches for \a aSymbol.
|
||||
*
|
||||
* When and existing library symbol named with the full #LIB_ID object is found, there may
|
||||
* be more potential matches if the #SCH_SCREEN::Append() method need to create an alternate
|
||||
* symbol due to differences from the original symbol. This process creates a new library
|
||||
* symbol name by adding a "_#" suffix to the existing #LIB_ID item name.
|
||||
*
|
||||
* @param[in] aSymbol is the schematic symbol to search for potential library symbol matches.
|
||||
* @param[out] aMatches contains library cache names of all of the potential matches.
|
||||
*
|
||||
* @return the number of potential matches found for \a aSymbol.
|
||||
*/
|
||||
size_t getLibSymbolNameMatches( const SCH_SYMBOL& aSymbol, std::vector<wxString>& aMatches );
|
||||
|
||||
private:
|
||||
friend SCH_EDIT_FRAME; // Only to populate m_symbolInstances.
|
||||
friend SCH_SEXPR_PARSER; // Only to load instance information from schematic file.
|
||||
friend SCH_SEXPR_PLUGIN; // Only to save the loaded instance information to schematic file.
|
||||
|
||||
void clearLibSymbols();
|
||||
|
||||
wxString m_fileName; // File used to load the screen.
|
||||
int m_fileFormatVersionAtLoad;
|
||||
int m_refCount; // Number of sheets referencing this screen.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 1992-2021 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
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -310,7 +310,7 @@ void SCH_SHEET_PATH::UpdateAllScreenReferences()
|
||||
symbol->GetField( VALUE_FIELD )->SetText( symbol->GetValue( this, false ) );
|
||||
symbol->GetField( FOOTPRINT_FIELD )->SetText( symbol->GetFootprint( this, false ) );
|
||||
symbol->UpdateUnit( symbol->GetUnitSelection( this ) );
|
||||
LastScreen()->Update( item );
|
||||
LastScreen()->Update( item, false );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -340,15 +340,32 @@ SCH_ITEM* SCH_EDITOR_CONTROL::nextMatch( SCH_SCREEN* aScreen, SCH_SHEET_PATH* aS
|
||||
if( aAfter != nullptr )
|
||||
{
|
||||
past_item = false;
|
||||
|
||||
if( aAfter->Type() == SCH_PIN_T || aAfter->Type() == SCH_FIELD_T )
|
||||
aAfter = static_cast<SCH_ITEM*>( aAfter->GetParent() );
|
||||
}
|
||||
|
||||
std::vector<SCH_ITEM*> sorted_items;
|
||||
|
||||
for( SCH_ITEM* item : aScreen->Items() )
|
||||
{
|
||||
if( SCH_SYMBOL* sym = dyn_cast<SCH_SYMBOL*>( item ) )
|
||||
{
|
||||
for( SCH_FIELD& field : sym->GetFields() )
|
||||
sorted_items.push_back( &field );
|
||||
|
||||
for( SCH_PIN* pin : sym->GetPins() )
|
||||
sorted_items.push_back( pin );
|
||||
}
|
||||
|
||||
if( SCH_SHEET* sheet = dyn_cast<SCH_SHEET*>( item ) )
|
||||
{
|
||||
for( SCH_FIELD& field : sheet->GetFields() )
|
||||
sorted_items.push_back( &field );
|
||||
|
||||
for( SCH_SHEET_PIN* pin : sheet->GetPins() )
|
||||
sorted_items.push_back( pin );
|
||||
}
|
||||
|
||||
sorted_items.push_back( item );
|
||||
}
|
||||
|
||||
std::sort( sorted_items.begin(), sorted_items.end(),
|
||||
[&]( SCH_ITEM* a, SCH_ITEM* b )
|
||||
@@ -379,40 +396,6 @@ SCH_ITEM* SCH_EDITOR_CONTROL::nextMatch( SCH_SCREEN* aScreen, SCH_SHEET_PATH* aS
|
||||
|
||||
if( item->Matches( aData, aSheet ) )
|
||||
return item;
|
||||
|
||||
if( item->Type() == SCH_SYMBOL_T )
|
||||
{
|
||||
SCH_SYMBOL* cmp = static_cast<SCH_SYMBOL*>( item );
|
||||
|
||||
for( SCH_FIELD& field : cmp->GetFields() )
|
||||
{
|
||||
if( field.Matches( aData, aSheet ) )
|
||||
return &field;
|
||||
}
|
||||
|
||||
for( SCH_PIN* pin : cmp->GetPins() )
|
||||
{
|
||||
if( pin->Matches( aData, aSheet ) )
|
||||
return pin;
|
||||
}
|
||||
}
|
||||
|
||||
if( item->Type() == SCH_SHEET_T )
|
||||
{
|
||||
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
|
||||
|
||||
for( SCH_FIELD& field : sheet->GetFields() )
|
||||
{
|
||||
if( field.Matches( aData, aSheet ) )
|
||||
return &field;
|
||||
}
|
||||
|
||||
for( SCH_SHEET_PIN* pin : sheet->GetPins() )
|
||||
{
|
||||
if( pin->Matches( aData, aSheet ) )
|
||||
return pin;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2014-2017 CERN
|
||||
* Copyright (C) 2018-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2018-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -1332,7 +1332,9 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent )
|
||||
|
||||
int DRAWING_TOOL::SetAnchor( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
wxASSERT( m_isFootprintEditor );
|
||||
// Make sense only in FP editor
|
||||
if( !m_isFootprintEditor )
|
||||
return 0;
|
||||
|
||||
if( !m_frame->GetModel() )
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user