|
|
|
@ -1,12 +1,8 @@ |
|
|
|
/**
|
|
|
|
* @file eeschema/tools/backannotate.cpp |
|
|
|
*/ |
|
|
|
|
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application. |
|
|
|
* |
|
|
|
* Copyright (C) 2019 Alexander Shuklin <Jasuramme@gmail.com> |
|
|
|
* Copyright (C) 2004-2019 KiCad Developers, see AUTHORS.txt for contributors. |
|
|
|
* Copyright (C) 2004-2020 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 |
|
|
|
@ -31,18 +27,25 @@ |
|
|
|
#include <boost/property_tree/ptree.hpp>
|
|
|
|
#include <confirm.h>
|
|
|
|
#include <dsnlexer.h>
|
|
|
|
#include <kiface_i.h>
|
|
|
|
#include <macros.h>
|
|
|
|
#include <ptree.h>
|
|
|
|
#include <reporter.h>
|
|
|
|
#include <sch_edit_frame.h>
|
|
|
|
#include <sch_sheet_path.h>
|
|
|
|
#include <schematic.h>
|
|
|
|
#include <utf8.h>
|
|
|
|
#include <kiface_i.h>
|
|
|
|
|
|
|
|
|
|
|
|
BACK_ANNOTATE::BACK_ANNOTATE( SCH_EDIT_FRAME* aFrame, SETTINGS aSettings ) : |
|
|
|
m_settings( aSettings ), |
|
|
|
BACK_ANNOTATE::BACK_ANNOTATE( SCH_EDIT_FRAME* aFrame, REPORTER& aReporter, |
|
|
|
bool aProcessFootprints, bool aProcessValues, |
|
|
|
bool aProcessReferences, bool aProcessNetNames, |
|
|
|
bool aIgnoreOtherProjects, bool aDryRun ) : |
|
|
|
m_reporter( aReporter ), |
|
|
|
m_processFootprints( aProcessFootprints ), |
|
|
|
m_processValues( aProcessValues ), |
|
|
|
m_processReferences( aProcessReferences ), |
|
|
|
m_processNetNames( aProcessNetNames ), |
|
|
|
m_ignoreOtherProjects( aIgnoreOtherProjects ), |
|
|
|
m_dryRun( aDryRun ), |
|
|
|
m_frame( aFrame ), |
|
|
|
m_changesCount( 0 ) |
|
|
|
{ |
|
|
|
@ -59,103 +62,100 @@ bool BACK_ANNOTATE::BackAnnotateSymbols( const std::string& aNetlist ) |
|
|
|
m_changesCount = 0; |
|
|
|
wxString msg; |
|
|
|
|
|
|
|
if( !m_settings.processValues && !m_settings.processFootprints |
|
|
|
&& !m_settings.processReferences ) |
|
|
|
if( !m_processValues && !m_processFootprints && !m_processReferences && !m_processNetNames ) |
|
|
|
{ |
|
|
|
m_settings.reporter.ReportTail( |
|
|
|
_( "Select at least one property to back annotate" ), RPT_SEVERITY_ERROR ); |
|
|
|
m_reporter.ReportTail( _( "Select at least one property to back annotate." ), |
|
|
|
RPT_SEVERITY_ERROR ); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
int errors = getPcbModulesFromString( aNetlist ); |
|
|
|
getPcbModulesFromString( aNetlist ); |
|
|
|
|
|
|
|
SCH_SHEET_LIST sheets = m_frame->Schematic().GetSheets(); |
|
|
|
sheets.GetComponents( m_refs, false ); |
|
|
|
sheets.GetMultiUnitComponents( m_multiUnitsRefs ); |
|
|
|
|
|
|
|
errors += getChangeList(); |
|
|
|
errors += checkForUnusedSymbols(); |
|
|
|
errors += checkSharedSchematicErrors(); |
|
|
|
getChangeList(); |
|
|
|
checkForUnusedSymbols(); |
|
|
|
checkSharedSchematicErrors(); |
|
|
|
|
|
|
|
if( errors > 0 ) |
|
|
|
m_settings.dryRun = true; |
|
|
|
SCH_SHEET_PATH current = m_frame->GetCurrentSheet(); |
|
|
|
applyChangelist(); |
|
|
|
m_frame->SetCurrentSheet( current ); |
|
|
|
|
|
|
|
if( !errors ) |
|
|
|
{ |
|
|
|
|
|
|
|
if( !m_settings.dryRun ) |
|
|
|
{ |
|
|
|
msg.Printf( _( "Schematic is back-annotated. %d changes applied." ), m_changesCount ); |
|
|
|
m_settings.reporter.ReportTail( msg, RPT_SEVERITY_ACTION ); |
|
|
|
} |
|
|
|
else |
|
|
|
m_settings.reporter.ReportTail( |
|
|
|
_( "No errors during dry run. Ready to go." ), RPT_SEVERITY_ACTION ); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
msg.Printf( _( "Found %d errors. Fix them and run back annotation." ), errors ); |
|
|
|
m_settings.reporter.ReportTail( msg, RPT_SEVERITY_ERROR ); |
|
|
|
} |
|
|
|
|
|
|
|
return !errors; |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
bool BACK_ANNOTATE::FetchNetlistFromPCB( std::string& aNetlist ) |
|
|
|
{ |
|
|
|
|
|
|
|
if( Kiface().IsSingle() ) |
|
|
|
{ |
|
|
|
DisplayErrorMessage( |
|
|
|
m_frame, _( "Cannot fetch PCB netlist because eeschema is opened in " |
|
|
|
"stand-alone mode.\n" |
|
|
|
"You must launch the KiCad project manager " |
|
|
|
"and create a project." ) ); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
KIWAY_PLAYER* player = m_frame->Kiway().Player( FRAME_PCB_EDITOR, false ); |
|
|
|
|
|
|
|
if( !player ) |
|
|
|
{ |
|
|
|
DisplayErrorMessage( |
|
|
|
this->m_frame, _( "Please open Pcbnew and run back annotation again" ) ); |
|
|
|
DisplayErrorMessage( m_frame, _( "Cannot fetch PCB netlist because eeschema is opened " |
|
|
|
"in stand-alone mode.\n" |
|
|
|
"You must launch the KiCad project manager and create " |
|
|
|
"a project." ) ); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
m_frame->Kiway().Player( FRAME_PCB_EDITOR, true ); |
|
|
|
m_frame->Kiway().ExpressMail( FRAME_PCB_EDITOR, MAIL_PCB_GET_NETLIST, aNetlist ); |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int BACK_ANNOTATE::getPcbModulesFromString( const std::string& aPayload ) |
|
|
|
void BACK_ANNOTATE::getPcbModulesFromString( const std::string& aPayload ) |
|
|
|
{ |
|
|
|
auto getStr = []( const PTREE& pt ) -> wxString |
|
|
|
{ |
|
|
|
return UTF8( pt.front().first ); |
|
|
|
}; |
|
|
|
|
|
|
|
DSNLEXER lexer( aPayload, FROM_UTF8( __func__ ) ); |
|
|
|
PTREE doc; |
|
|
|
|
|
|
|
// NOTE: KiCad's PTREE scanner constructs a property *name* tree, not a property tree.
|
|
|
|
// Every token in the s-expr is stored as a property name; the property's value is then
|
|
|
|
// either the nested s-exprs or an empty PTREE; there are *no* literal property values.
|
|
|
|
|
|
|
|
Scan( &doc, &lexer ); |
|
|
|
CPTREE& tree = doc.get_child( "pcb_netlist" ); |
|
|
|
wxString msg; |
|
|
|
|
|
|
|
int errors = 0; |
|
|
|
PTREE& tree = doc.get_child( "pcb_netlist" ); |
|
|
|
wxString msg; |
|
|
|
m_pcbModules.clear(); |
|
|
|
for( auto& item : tree ) |
|
|
|
|
|
|
|
for( const std::pair<const std::string, PTREE>& item : tree ) |
|
|
|
{ |
|
|
|
wxString path, value, footprint; |
|
|
|
std::map<wxString, wxString> pinNetMap; |
|
|
|
wxASSERT( item.first == "ref" ); |
|
|
|
wxString ref = UTF8( item.second.front().first ); |
|
|
|
wxString ref = getStr( item.second ); |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
path = UTF8( item.second.get_child( "timestamp" ).front().first ); |
|
|
|
path = getStr( item.second.get_child( "timestamp" ) ); |
|
|
|
|
|
|
|
if( path == "" ) |
|
|
|
{ |
|
|
|
msg.Printf( _( "Footprint \"%s\" has no symbol associated." ), ref ); |
|
|
|
m_settings.reporter.ReportHead( msg, RPT_SEVERITY_WARNING ); |
|
|
|
m_reporter.ReportHead( msg, RPT_SEVERITY_WARNING ); |
|
|
|
continue; |
|
|
|
} |
|
|
|
footprint = UTF8( item.second.get_child( "fpid" ).front().first ); |
|
|
|
value = UTF8( item.second.get_child( "value" ).front().first ); |
|
|
|
|
|
|
|
footprint = getStr( item.second.get_child( "fpid" ) ); |
|
|
|
value = getStr( item.second.get_child( "value" ) ); |
|
|
|
|
|
|
|
boost::optional<const PTREE&> nets = item.second.get_child_optional( "nets" ); |
|
|
|
|
|
|
|
if( nets ) |
|
|
|
{ |
|
|
|
for( const std::pair<const std::string, PTREE>& pin_net : nets.get() ) |
|
|
|
{ |
|
|
|
wxASSERT( pin_net.first == "pin_net" ); |
|
|
|
wxString pinNumber = UTF8( pin_net.second.front().first ); |
|
|
|
wxString netName = UTF8( pin_net.second.back().first ); |
|
|
|
pinNetMap[ pinNumber ] = netName; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
catch( ... ) |
|
|
|
{ |
|
|
|
@ -169,34 +169,30 @@ int BACK_ANNOTATE::getPcbModulesFromString( const std::string& aPayload ) |
|
|
|
{ |
|
|
|
// Module with this path already exists - generate error
|
|
|
|
msg.Printf( _( "Pcb footprints \"%s\" and \"%s\" linked to same symbol" ), |
|
|
|
nearestItem->second->ref, ref ); |
|
|
|
m_settings.reporter.ReportHead( msg, RPT_SEVERITY_ERROR ); |
|
|
|
++errors; |
|
|
|
nearestItem->second->m_ref, ref ); |
|
|
|
m_reporter.ReportHead( msg, RPT_SEVERITY_ERROR ); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// Add module to the map
|
|
|
|
PCB_MODULE_DATA data( ref, footprint, value ); |
|
|
|
m_pcbModules.insert( nearestItem, |
|
|
|
std::make_pair( path, std::make_shared<PCB_MODULE_DATA>( data ) ) ); |
|
|
|
auto data = std::make_shared<PCB_MODULE_DATA>( ref, footprint, value, pinNetMap ); |
|
|
|
m_pcbModules.insert( nearestItem, std::make_pair( path, data ) ); |
|
|
|
} |
|
|
|
} |
|
|
|
return errors; |
|
|
|
} |
|
|
|
|
|
|
|
int BACK_ANNOTATE::getChangeList() |
|
|
|
{ |
|
|
|
int errors = 0; |
|
|
|
|
|
|
|
for( auto& module : m_pcbModules ) |
|
|
|
void BACK_ANNOTATE::getChangeList() |
|
|
|
{ |
|
|
|
for( std::pair<const wxString, std::shared_ptr<PCB_MODULE_DATA>>& module : m_pcbModules ) |
|
|
|
{ |
|
|
|
auto& pcbPath = module.first; |
|
|
|
auto& pcbData = module.second; |
|
|
|
bool foundInMultiunit = false; |
|
|
|
const wxString& pcbPath = module.first; |
|
|
|
auto& pcbData = module.second; |
|
|
|
bool foundInMultiunit = false; |
|
|
|
|
|
|
|
for( auto& item : m_multiUnitsRefs ) |
|
|
|
{ |
|
|
|
auto& refList = item.second; |
|
|
|
SCH_REFERENCE_LIST& refList = item.second; |
|
|
|
|
|
|
|
if( refList.FindRefByPath( pcbPath ) >= 0 ) |
|
|
|
{ |
|
|
|
@ -206,8 +202,10 @@ int BACK_ANNOTATE::getChangeList() |
|
|
|
foundInMultiunit = true; |
|
|
|
for( size_t i = 0; i < refList.GetCount(); ++i ) |
|
|
|
{ |
|
|
|
m_changelist.push_back( CHANGELIST_ITEM( refList[i], pcbData ) ); |
|
|
|
refList[i].GetComp()->ClearFlags( SKIP_STRUCT ); |
|
|
|
m_changelist.emplace_back( CHANGELIST_ITEM( refList[i], pcbData ) ); |
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -218,23 +216,22 @@ int BACK_ANNOTATE::getChangeList() |
|
|
|
int refIndex = m_refs.FindRefByPath( pcbPath ); |
|
|
|
|
|
|
|
if( refIndex >= 0 ) |
|
|
|
m_changelist.push_back( CHANGELIST_ITEM( m_refs[refIndex], pcbData ) ); |
|
|
|
{ |
|
|
|
m_refs[refIndex].GetComp()->ClearFlags( SKIP_STRUCT ); |
|
|
|
m_changelist.emplace_back( CHANGELIST_ITEM( m_refs[refIndex], pcbData ) ); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// Haven't found linked symbol in multiunits or common refs. Generate error
|
|
|
|
wxString msg; |
|
|
|
msg.Printf( _( "Cannot find symbol for \"%s\" footprint" ), pcbData->ref ); |
|
|
|
++errors; |
|
|
|
m_settings.reporter.ReportTail( msg, RPT_SEVERITY_ERROR ); |
|
|
|
msg.Printf( _( "Cannot find symbol for \"%s\" footprint" ), pcbData->m_ref ); |
|
|
|
m_reporter.ReportTail( msg, RPT_SEVERITY_ERROR ); |
|
|
|
} |
|
|
|
} |
|
|
|
return errors; |
|
|
|
} |
|
|
|
|
|
|
|
int BACK_ANNOTATE::checkForUnusedSymbols() |
|
|
|
void BACK_ANNOTATE::checkForUnusedSymbols() |
|
|
|
{ |
|
|
|
int errors = 0; |
|
|
|
|
|
|
|
m_refs.SortByTimeStamp(); |
|
|
|
|
|
|
|
std::sort( m_changelist.begin(), m_changelist.end(), |
|
|
|
@ -244,32 +241,31 @@ int BACK_ANNOTATE::checkForUnusedSymbols() |
|
|
|
} ); |
|
|
|
|
|
|
|
size_t i = 0; |
|
|
|
|
|
|
|
for( auto& item : m_changelist ) |
|
|
|
{ |
|
|
|
// Refs and changelist are both sorted by paths, so we just go over m_refs and
|
|
|
|
// generate errors before we will find m_refs member to which item linked
|
|
|
|
while( i < m_refs.GetCount() && m_refs[i].GetPath() != item.first.GetPath() ) |
|
|
|
{ |
|
|
|
++errors; |
|
|
|
wxString msg; |
|
|
|
msg.Printf( _( "Cannot find footprint for \"%s\" symbol" ), m_refs[i++].GetFullRef() ); |
|
|
|
m_settings.reporter.ReportTail( msg, RPT_SEVERITY_ERROR ); |
|
|
|
m_reporter.ReportTail( msg, RPT_SEVERITY_ERROR ); |
|
|
|
} |
|
|
|
|
|
|
|
++i; |
|
|
|
} |
|
|
|
return errors; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool BACK_ANNOTATE::checkReuseViolation( PCB_MODULE_DATA& aFirst, PCB_MODULE_DATA& aSecond ) |
|
|
|
{ |
|
|
|
|
|
|
|
if( m_settings.processFootprints && aFirst.footprint != aSecond.footprint ) |
|
|
|
if( m_processFootprints && aFirst.m_footprint != aSecond.m_footprint ) |
|
|
|
return false; |
|
|
|
|
|
|
|
if( m_settings.processValues && aFirst.value != aSecond.value ) |
|
|
|
if( m_processValues && aFirst.m_value != aSecond.m_value ) |
|
|
|
return false; |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
@ -279,18 +275,17 @@ wxString BACK_ANNOTATE::getTextFromField( const SCH_REFERENCE& aRef, const NumFi |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int BACK_ANNOTATE::checkSharedSchematicErrors() |
|
|
|
void BACK_ANNOTATE::checkSharedSchematicErrors() |
|
|
|
{ |
|
|
|
|
|
|
|
std::sort( m_changelist.begin(), m_changelist.end(), |
|
|
|
[]( CHANGELIST_ITEM& a, CHANGELIST_ITEM& b ) { |
|
|
|
return a.first.GetComp() > b.first.GetComp(); |
|
|
|
} ); |
|
|
|
[]( CHANGELIST_ITEM& a, CHANGELIST_ITEM& b ) |
|
|
|
{ |
|
|
|
return a.first.GetComp() > b.first.GetComp(); |
|
|
|
} ); |
|
|
|
|
|
|
|
// We don't check that if no footprints or values updating
|
|
|
|
if( !m_settings.processFootprints && !m_settings.processValues ) |
|
|
|
return 0; |
|
|
|
int errors = 0; |
|
|
|
if( !m_processFootprints && !m_processValues ) |
|
|
|
return; |
|
|
|
|
|
|
|
// 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
|
|
|
|
@ -307,90 +302,302 @@ int BACK_ANNOTATE::checkSharedSchematicErrors() |
|
|
|
if( ( it + 1 ) != m_changelist.end() && it->first.GetComp() == ( it + 1 )->first.GetComp() ) |
|
|
|
{ |
|
|
|
++usageCount; |
|
|
|
|
|
|
|
if( !checkReuseViolation( *it->second, *( it + 1 )->second ) ) |
|
|
|
{ |
|
|
|
// Refs share same component but have different values or footprints
|
|
|
|
++errors; |
|
|
|
it->first.GetComp()->SetFlags( SKIP_STRUCT ); |
|
|
|
|
|
|
|
wxString msg; |
|
|
|
msg.Printf( _( "\"%s\" and \"%s\" use the same schematic symbol.\n" |
|
|
|
"They cannot have different footprints or values." ), |
|
|
|
( it + 1 )->second->ref, it->second->ref ); |
|
|
|
m_settings.reporter.ReportTail( msg, RPT_SEVERITY_ERROR ); |
|
|
|
( it + 1 )->second->m_ref, |
|
|
|
it->second->m_ref ); |
|
|
|
m_reporter.ReportTail( msg, RPT_SEVERITY_ERROR ); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
/* Next ref uses different component, so we count all components number for current
|
|
|
|
one. We compare that number to stored in the component itself. If that differs, it |
|
|
|
means that this particular component is reused in some another project. */ |
|
|
|
if( !m_settings.ignoreOtherProjects && compUsage > usageCount ) |
|
|
|
means that this particular component is reused in some other project. */ |
|
|
|
if( !m_ignoreOtherProjects && compUsage > usageCount ) |
|
|
|
{ |
|
|
|
PCB_MODULE_DATA tmp{ "", getTextFromField( it->first, FOOTPRINT ), |
|
|
|
getTextFromField( it->first, VALUE ) }; |
|
|
|
PCB_MODULE_DATA tmp{ "", |
|
|
|
getTextFromField( it->first, FOOTPRINT ), |
|
|
|
getTextFromField( it->first, VALUE ), |
|
|
|
{} }; |
|
|
|
|
|
|
|
if( !checkReuseViolation( tmp, *it->second ) ) |
|
|
|
{ |
|
|
|
it->first.GetComp()->SetFlags( SKIP_STRUCT ); |
|
|
|
|
|
|
|
wxString msg; |
|
|
|
msg.Printf( _( "Unable to change \"%s\" footprint or value because associated" |
|
|
|
" symbol is reused in the another project" ), |
|
|
|
it->second->ref ); |
|
|
|
m_settings.reporter.ReportTail( msg, RPT_SEVERITY_ERROR ); |
|
|
|
++errors; |
|
|
|
it->second->m_ref ); |
|
|
|
m_reporter.ReportTail( msg, RPT_SEVERITY_ERROR ); |
|
|
|
} |
|
|
|
} |
|
|
|
usageCount = 1; |
|
|
|
} |
|
|
|
} |
|
|
|
return errors; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void BACK_ANNOTATE::applyChangelist() |
|
|
|
{ |
|
|
|
wxString msg; |
|
|
|
int leftUnchanged = 0; |
|
|
|
std::set<wxString> handledNetChanges; |
|
|
|
wxString msg; |
|
|
|
int leftUnchanged = 0; |
|
|
|
|
|
|
|
// Apply changes from change list
|
|
|
|
for( auto& item : m_changelist ) |
|
|
|
for( CHANGELIST_ITEM& item : m_changelist ) |
|
|
|
{ |
|
|
|
SCH_REFERENCE& ref = item.first; |
|
|
|
PCB_MODULE_DATA& module = *item.second; |
|
|
|
wxString oldFootprint = getTextFromField( ref, FOOTPRINT ); |
|
|
|
wxString oldValue = getTextFromField( ref, VALUE ); |
|
|
|
int changesCountBefore = m_changesCount; |
|
|
|
bool skip = ( ref.GetComp()->GetFlags() & SKIP_STRUCT ) > 0; |
|
|
|
|
|
|
|
if( m_settings.processReferences && ref.GetRef() != module.ref ) |
|
|
|
if( m_processReferences && ref.GetRef() != module.m_ref && !skip ) |
|
|
|
{ |
|
|
|
++m_changesCount; |
|
|
|
msg.Printf( _( "Change \"%s\" reference designator to \"%s\"." ), ref.GetFullRef(), module.ref ); |
|
|
|
if( !m_settings.dryRun ) |
|
|
|
ref.GetComp()->SetRef( &ref.GetSheetPath(), module.ref ); |
|
|
|
m_settings.reporter.ReportHead( msg, RPT_SEVERITY_ACTION ); |
|
|
|
msg.Printf( _( "Change \"%s\" reference designator to \"%s\"." ), |
|
|
|
ref.GetFullRef(), |
|
|
|
module.m_ref ); |
|
|
|
|
|
|
|
if( !m_dryRun ) |
|
|
|
ref.GetComp()->SetRef( &ref.GetSheetPath(), module.m_ref ); |
|
|
|
|
|
|
|
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION ); |
|
|
|
} |
|
|
|
|
|
|
|
if( m_settings.processFootprints && oldFootprint != module.footprint ) |
|
|
|
if( m_processFootprints && oldFootprint != module.m_footprint && !skip ) |
|
|
|
{ |
|
|
|
++m_changesCount; |
|
|
|
msg.Printf( _( "Change %s footprint from \"%s\" to \"%s\"." ), ref.GetFullRef(), |
|
|
|
getTextFromField( ref, FOOTPRINT ), module.footprint ); |
|
|
|
msg.Printf( _( "Change %s footprint from \"%s\" to \"%s\"." ), |
|
|
|
ref.GetFullRef(), |
|
|
|
getTextFromField( ref, FOOTPRINT ), |
|
|
|
module.m_footprint ); |
|
|
|
|
|
|
|
if( !m_settings.dryRun ) |
|
|
|
ref.GetComp()->GetField( FOOTPRINT )->SetText( module.footprint ); |
|
|
|
m_settings.reporter.ReportHead( msg, RPT_SEVERITY_ACTION ); |
|
|
|
if( !m_dryRun ) |
|
|
|
ref.GetComp()->GetField( FOOTPRINT )->SetText( module.m_footprint ); |
|
|
|
|
|
|
|
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION ); |
|
|
|
} |
|
|
|
|
|
|
|
if( m_settings.processValues && oldValue != module.value ) |
|
|
|
if( m_processValues && oldValue != module.m_value && !skip ) |
|
|
|
{ |
|
|
|
++m_changesCount; |
|
|
|
msg.Printf( _( "Change \"%s\" value from \"%s\" to \"\"%s\"." ), ref.GetFullRef(), |
|
|
|
getTextFromField( ref, VALUE ), module.value ); |
|
|
|
if( !m_settings.dryRun ) |
|
|
|
item.first.GetComp()->GetField( VALUE )->SetText( module.value ); |
|
|
|
m_settings.reporter.ReportHead( msg, RPT_SEVERITY_ACTION ); |
|
|
|
msg.Printf( _( "Change %s value from \"%s\" to \"%s\"." ), |
|
|
|
ref.GetFullRef(), |
|
|
|
getTextFromField( ref, VALUE ), |
|
|
|
module.m_value ); |
|
|
|
|
|
|
|
if( !m_dryRun ) |
|
|
|
item.first.GetComp()->GetField( VALUE )->SetText( module.m_value ); |
|
|
|
|
|
|
|
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION ); |
|
|
|
} |
|
|
|
|
|
|
|
if( m_processNetNames ) |
|
|
|
{ |
|
|
|
for( const std::pair<const wxString, wxString>& entry : module.m_pinMap ) |
|
|
|
{ |
|
|
|
const wxString& pinNumber = entry.first; |
|
|
|
const wxString& shortNetName = entry.second; |
|
|
|
SCH_COMPONENT* comp = ref.GetComp(); |
|
|
|
LIB_PIN* pin = comp->GetPin( pinNumber ); |
|
|
|
SCH_CONNECTION* conn = comp->GetConnectionForPin( pin, ref.GetSheetPath() ); |
|
|
|
|
|
|
|
wxString key = shortNetName + ref.GetSheetPath().PathAsString(); |
|
|
|
|
|
|
|
if( handledNetChanges.count( key ) ) |
|
|
|
continue; |
|
|
|
else |
|
|
|
handledNetChanges.insert( key ); |
|
|
|
|
|
|
|
if( conn && conn->Name( true ) != shortNetName ) |
|
|
|
processNetNameChange( conn, conn->Name( true ), shortNetName ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if( changesCountBefore == m_changesCount ) |
|
|
|
++leftUnchanged; |
|
|
|
} |
|
|
|
msg.Printf( _( "%d symbols left unchanged" ), leftUnchanged ); |
|
|
|
m_settings.reporter.ReportHead( msg, RPT_SEVERITY_INFO ); |
|
|
|
m_reporter.ReportHead( msg, RPT_SEVERITY_INFO ); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void BACK_ANNOTATE::processNetNameChange( SCH_CONNECTION* aConn, const wxString& aOldName, |
|
|
|
const wxString& aNewName ) |
|
|
|
{ |
|
|
|
wxString msg; |
|
|
|
SCH_ITEM* driver = aConn->Driver(); |
|
|
|
|
|
|
|
auto editMatchingLabels = |
|
|
|
[this]( SCH_SCREEN* aScreen, KICAD_T aType, const wxString& oldName, |
|
|
|
const wxString& newName ) |
|
|
|
{ |
|
|
|
for( SCH_ITEM* schItem : aScreen->Items().OfType( aType ) ) |
|
|
|
{ |
|
|
|
SCH_TEXT* label = static_cast<SCH_TEXT*>( schItem ); |
|
|
|
|
|
|
|
if( EscapeString( label->GetShownText(), CTX_NETNAME ) == oldName ) |
|
|
|
{ |
|
|
|
m_frame->SaveCopyInUndoList( label, UR_CHANGED ); |
|
|
|
static_cast<SCH_TEXT*>( label )->SetText( newName ); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
switch( driver->Type() ) |
|
|
|
{ |
|
|
|
case SCH_LABEL_T: |
|
|
|
++m_changesCount; |
|
|
|
msg.Printf( _( "Change \"%s\" labels to \"%s\"." ), |
|
|
|
aOldName, |
|
|
|
aNewName ); |
|
|
|
|
|
|
|
if( !m_dryRun ) |
|
|
|
{ |
|
|
|
m_frame->Schematic().SetCurrentSheet( aConn->Sheet() ); |
|
|
|
|
|
|
|
for( SCH_ITEM* label : m_frame->GetScreen()->Items().OfType( SCH_LABEL_T ) ) |
|
|
|
{ |
|
|
|
SCH_CONNECTION* conn = label->Connection( aConn->Sheet() ); |
|
|
|
|
|
|
|
if( conn && conn->Driver() == driver ) |
|
|
|
{ |
|
|
|
m_frame->SaveCopyInUndoList( label, UR_CHANGED ); |
|
|
|
static_cast<SCH_TEXT*>( label )->SetText( aNewName ); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION ); |
|
|
|
break; |
|
|
|
|
|
|
|
case SCH_GLOBAL_LABEL_T: |
|
|
|
++m_changesCount; |
|
|
|
msg.Printf( _( "Change \"%s\" global labels to \"%s\"." ), |
|
|
|
aConn->Name( true ), |
|
|
|
aNewName ); |
|
|
|
|
|
|
|
if( !m_dryRun ) |
|
|
|
{ |
|
|
|
SCH_SHEET_LIST all_sheets = m_frame->Schematic().GetSheets(); |
|
|
|
|
|
|
|
for( const SCH_SHEET_PATH& sheet : all_sheets ) |
|
|
|
{ |
|
|
|
m_frame->Schematic().SetCurrentSheet( sheet ); |
|
|
|
editMatchingLabels( m_frame->GetScreen(), SCH_GLOBAL_LABEL_T, aOldName, aNewName ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION ); |
|
|
|
break; |
|
|
|
|
|
|
|
case SCH_HIER_LABEL_T: |
|
|
|
++m_changesCount; |
|
|
|
msg.Printf( _( "Change \"%s\" hierarchical label to \"%s\"." ), |
|
|
|
aConn->Name( true ), |
|
|
|
aNewName ); |
|
|
|
|
|
|
|
if( !m_dryRun ) |
|
|
|
{ |
|
|
|
m_frame->Schematic().SetCurrentSheet( aConn->Sheet() ); |
|
|
|
editMatchingLabels( m_frame->GetScreen(), SCH_HIER_LABEL_T, aOldName, aNewName ); |
|
|
|
|
|
|
|
SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( driver->GetParent() ); |
|
|
|
m_frame->SetScreen( sheet->GetScreen() ); |
|
|
|
|
|
|
|
for( SCH_SHEET_PIN* pin : sheet->GetPins() ) |
|
|
|
{ |
|
|
|
if( EscapeString( pin->GetShownText(), CTX_NETNAME ) == aOldName ) |
|
|
|
{ |
|
|
|
m_frame->SaveCopyInUndoList( pin, UR_CHANGED ); |
|
|
|
static_cast<SCH_TEXT*>( pin )->SetText( aNewName ); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION ); |
|
|
|
break; |
|
|
|
|
|
|
|
case SCH_SHEET_PIN_T: |
|
|
|
++m_changesCount; |
|
|
|
msg.Printf( _( "Change \"%s\" hierarchical label to \"%s\"." ), |
|
|
|
aConn->Name( true ), |
|
|
|
aNewName ); |
|
|
|
|
|
|
|
if( !m_dryRun ) |
|
|
|
{ |
|
|
|
m_frame->Schematic().SetCurrentSheet( aConn->Sheet() ); |
|
|
|
m_frame->SaveCopyInUndoList( driver, UR_CHANGED ); |
|
|
|
static_cast<SCH_TEXT*>( driver )->SetText( aNewName ); |
|
|
|
|
|
|
|
SCH_SHEET* sheet = static_cast<SCH_SHEET_PIN*>( driver )->GetParent(); |
|
|
|
m_frame->SetScreen( sheet->GetScreen() ); |
|
|
|
editMatchingLabels( sheet->GetScreen(), SCH_HIER_LABEL_T, aOldName, aNewName ); |
|
|
|
} |
|
|
|
|
|
|
|
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION ); |
|
|
|
break; |
|
|
|
|
|
|
|
case LIB_PIN_T: |
|
|
|
{ |
|
|
|
LIB_PIN* pin = dynamic_cast<LIB_PIN*>( driver ); |
|
|
|
LABEL_SPIN_STYLE spin = LABEL_SPIN_STYLE::RIGHT; |
|
|
|
|
|
|
|
if( pin->IsPowerConnection() ) |
|
|
|
{ |
|
|
|
msg.Printf( _( "Net \"%s\" cannot be changed to \"%s\" because it " |
|
|
|
"is driven by a power pin." ), |
|
|
|
aOldName, |
|
|
|
aNewName ); |
|
|
|
|
|
|
|
m_reporter.ReportHead( msg, RPT_SEVERITY_ERROR ); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
switch( pin->GetOrientation() ) |
|
|
|
{ |
|
|
|
case PIN_UP: spin = LABEL_SPIN_STYLE::UP; break; |
|
|
|
case PIN_DOWN: spin = LABEL_SPIN_STYLE::BOTTOM; break; |
|
|
|
case PIN_LEFT: spin = LABEL_SPIN_STYLE::LEFT; break; |
|
|
|
case PIN_RIGHT: spin = LABEL_SPIN_STYLE::RIGHT; break; |
|
|
|
} |
|
|
|
|
|
|
|
++m_changesCount; |
|
|
|
msg.Printf( _( "Add label \"%s\" to net \"%s\"." ), |
|
|
|
aNewName, |
|
|
|
aConn->Name( true ) ); |
|
|
|
|
|
|
|
if( !m_dryRun ) |
|
|
|
{ |
|
|
|
SCHEMATIC_SETTINGS& settings = m_frame->Schematic().Settings(); |
|
|
|
SCH_LABEL* label = new SCH_LABEL( driver->GetPosition(), aNewName ); |
|
|
|
label->SetParent( &m_frame->Schematic() ); |
|
|
|
label->SetTextSize( wxSize( settings.m_DefaultTextSize, |
|
|
|
settings.m_DefaultTextSize ) ); |
|
|
|
label->SetLabelSpinStyle( spin ); |
|
|
|
label->SetFlags( IS_NEW ); |
|
|
|
|
|
|
|
m_frame->Schematic().SetCurrentSheet( aConn->Sheet() ); |
|
|
|
m_frame->AddItemToScreenAndUndoList( label ); |
|
|
|
} |
|
|
|
|
|
|
|
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION ); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
m_frame->Schematic().SetCurrentSheet( SCH_SHEET_PATH() ); |
|
|
|
} |