KiCad PCB EDA Suite
eeschema/annotate.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2004-2021 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <algorithm>
25 
26 #include <confirm.h>
27 #include <reporter.h>
28 #include <sch_edit_frame.h>
29 #include <schematic.h>
30 #include <erc_settings.h>
31 #include <sch_reference_list.h>
32 #include <class_library.h>
33 
34 
35 void SCH_EDIT_FRAME::mapExistingAnnotation( std::map<wxString, wxString>& aMap )
36 {
37  SCH_REFERENCE_LIST references;
38 
39  Schematic().GetSheets().GetSymbols( references );
40 
41  for( size_t i = 0; i < references.GetCount(); i++ )
42  {
43  SCH_COMPONENT* symbol = references[ i ].GetSymbol();
44  SCH_SHEET_PATH* curr_sheetpath = &references[ i ].GetSheetPath();
45  KIID_PATH curr_full_uuid = curr_sheetpath->Path();
46 
47  curr_full_uuid.push_back( symbol->m_Uuid );
48 
49  wxString ref = symbol->GetRef( curr_sheetpath );
50 
51  if( symbol->GetUnitCount() > 1 )
52  ref << LIB_PART::SubReference( symbol->GetUnitSelection( curr_sheetpath ) );
53 
54  if( symbol->IsAnnotated( curr_sheetpath ) )
55  aMap[ curr_full_uuid.AsString() ] = ref;
56  }
57 }
58 
59 
60 void SCH_EDIT_FRAME::DeleteAnnotation( bool aCurrentSheetOnly, bool* aAppendUndo )
61 {
62  auto clearAnnotation =
63  [&]( SCH_SCREEN* aScreen, SCH_SHEET_PATH* aSheet )
64  {
65  for( SCH_ITEM* item : aScreen->Items().OfType( SCH_COMPONENT_T ) )
66  {
67  SCH_COMPONENT* component = static_cast<SCH_COMPONENT*>( item );
68 
69  SaveCopyInUndoList( aScreen, component, UNDO_REDO::CHANGED, *aAppendUndo );
70  *aAppendUndo = true;
71  component->ClearAnnotation( aSheet );
72  }
73  };
74 
75  if( aCurrentSheetOnly )
76  {
77  clearAnnotation( GetScreen(), &GetCurrentSheet() );
78  }
79  else
80  {
81  for( const SCH_SHEET_PATH& sheet : Schematic().GetSheets() )
82  clearAnnotation( sheet.LastScreen(), nullptr );
83  }
84 
85  // Update the references for the sheet that is currently being displayed.
87 
88  SyncView();
89  GetCanvas()->Refresh();
90  OnModify();
91 
92  // Must go after OnModify() so the connectivity graph has been updated
94 }
95 
96 
97 void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic,
98  ANNOTATE_ORDER_T aSortOption,
99  ANNOTATE_OPTION_T aAlgoOption,
100  int aStartNumber,
101  bool aResetAnnotation,
102  bool aRepairTimestamps,
103  bool aLockUnits,
104  REPORTER& aReporter )
105 {
106  SCH_REFERENCE_LIST references;
107  SCH_SCREENS screens( Schematic().Root() );
108  SCH_SHEET_LIST sheets = Schematic().GetSheets();
109  bool appendUndo = false;
110 
111  // Map of locked components
112  SCH_MULTI_UNIT_REFERENCE_MAP lockedComponents;
113 
114  // Map of previous annotation for building info messages
115  std::map<wxString, wxString> previousAnnotation;
116 
117  // Test for and replace duplicate time stamps in components and sheets. Duplicate
118  // time stamps can happen with old schematics, schematic conversions, or manual
119  // editing of files.
120  if( aRepairTimestamps )
121  {
122  int count = screens.ReplaceDuplicateTimeStamps();
123 
124  if( count )
125  {
126  wxString msg;
127  msg.Printf( _( "%d duplicate time stamps were found and replaced." ), count );
128  aReporter.ReportTail( msg, RPT_SEVERITY_WARNING );
129  }
130  }
131 
132  // If units must be locked, collect all the sets that must be annotated together.
133  if( aLockUnits )
134  {
135  if( aAnnotateSchematic )
136  sheets.GetMultiUnitSymbols( lockedComponents );
137  else
138  GetCurrentSheet().GetMultiUnitComponents( lockedComponents );
139  }
140 
141  // Store previous annotations for building info messages
142  mapExistingAnnotation( previousAnnotation );
143 
144  // If it is an annotation for all the components, reset previous annotation.
145  if( aResetAnnotation )
146  DeleteAnnotation( !aAnnotateSchematic, &appendUndo );
147 
148  // Set sheet number and number of sheets.
150 
151  // Build component list
152  if( aAnnotateSchematic )
153  sheets.GetSymbols( references );
154  else
155  GetCurrentSheet().GetSymbols( references );
156 
157  // Break full components reference in name (prefix) and number:
158  // example: IC1 become IC, and 1
159  references.SplitReferences();
160 
161  switch( aSortOption )
162  {
163  default:
164  case SORT_BY_X_POSITION: references.SortByXCoordinate(); break;
165  case SORT_BY_Y_POSITION: references.SortByYCoordinate(); break;
166  }
167 
168  bool useSheetNum = false;
169  int idStep = 100;
170 
171  switch( aAlgoOption )
172  {
173  default:
174  case INCREMENTAL_BY_REF:
175  break;
176 
177  case SHEET_NUMBER_X_100:
178  useSheetNum = true;
179  break;
180 
181  case SHEET_NUMBER_X_1000:
182  useSheetNum = true;
183  idStep = 1000;
184  break;
185  }
186 
187  // Recalculate and update reference numbers in schematic
188  references.Annotate( useSheetNum, idStep, aStartNumber, lockedComponents );
189 
190  for( size_t i = 0; i < references.GetCount(); i++ )
191  {
192  SCH_REFERENCE& ref = references[i];
193  SCH_COMPONENT* symbol = ref.GetSymbol();
194  SCH_SHEET_PATH* sheet = &ref.GetSheetPath();
195 
196  SaveCopyInUndoList( sheet->LastScreen(), symbol, UNDO_REDO::CHANGED, appendUndo );
197  appendUndo = true;
198  ref.Annotate();
199 
200  KIID_PATH full_uuid = sheet->Path();
201  full_uuid.push_back( symbol->m_Uuid );
202 
203  wxString prevRef = previousAnnotation[ full_uuid.AsString() ];
204  wxString newRef = symbol->GetRef( sheet );
205 
206  if( symbol->GetUnitCount() > 1 )
207  newRef << LIB_PART::SubReference( symbol->GetUnitSelection( sheet ) );
208 
209  wxString msg;
210 
211  if( prevRef.Length() )
212  {
213  if( newRef == prevRef )
214  continue;
215 
216  if( symbol->GetUnitCount() > 1 )
217  msg.Printf( _( "Updated %s (unit %s) from %s to %s" ),
218  symbol->GetValue( sheet, true ),
219  LIB_PART::SubReference( symbol->GetUnit(), false ),
220  prevRef,
221  newRef );
222  else
223  msg.Printf( _( "Updated %s from %s to %s" ),
224  symbol->GetValue( sheet, true ),
225  prevRef,
226  newRef );
227  }
228  else
229  {
230  if( symbol->GetUnitCount() > 1 )
231  msg.Printf( _( "Annotated %s (unit %s) as %s" ),
232  symbol->GetValue( sheet, true ),
233  LIB_PART::SubReference( symbol->GetUnit(), false ),
234  newRef );
235  else
236  msg.Printf( _( "Annotated %s as %s" ),
237  symbol->GetValue( sheet, true ),
238  newRef );
239  }
240 
241  aReporter.Report( msg, RPT_SEVERITY_ACTION );
242  }
243 
244  // Final control (just in case ... ).
245  if( !CheckAnnotate(
246  [ &aReporter ]( ERCE_T , const wxString& aMsg, SCH_REFERENCE* , SCH_REFERENCE* )
247  {
248  aReporter.Report( aMsg, RPT_SEVERITY_ERROR );
249  },
250  !aAnnotateSchematic ) )
251  {
252  aReporter.ReportTail( _( "Annotation complete." ), RPT_SEVERITY_ACTION );
253  }
254 
255  // Update on screen references, that can be modified by previous calculations:
258 
259  SyncView();
260  GetCanvas()->Refresh();
261  OnModify();
262 
263  // Must go after OnModify() so the connectivity graph has been updated
265 }
266 
267 
268 int SCH_EDIT_FRAME::CheckAnnotate( ANNOTATION_ERROR_HANDLER aErrorHandler, bool aOneSheetOnly )
269 {
270  SCH_REFERENCE_LIST referenceList;
271  constexpr bool includePowerSymbols = false;
272 
273  // Build the list of symbols
274  if( !aOneSheetOnly )
275  Schematic().GetSheets().GetSymbols( referenceList, includePowerSymbols );
276  else
277  GetCurrentSheet().GetSymbols( referenceList );
278 
279  // Empty schematic does not need annotation
280  if( referenceList.GetCount() == 0 )
281  return 0;
282 
283  return referenceList.CheckAnnotation( aErrorHandler );
284 }
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:219
int CheckAnnotate(ANNOTATION_ERROR_HANDLER aErrorHandler, bool aOneSheetOnly=false)
Check for annotation errors.
void SortByYCoordinate()
Sort the list of references by Y position.
void UpdateNetHighlightStatus()
void mapExistingAnnotation(std::map< wxString, wxString > &aMap)
Fills a map of uuid -> reference from the currently loaded schematic.
void GetSymbols(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanComponents=false) const
Add a SCH_REFERENCE object to aReferences for each component in the list of sheets.
void GetMultiUnitSymbols(SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, bool aIncludePowerSymbols=true) const
Add a SCH_REFERENCE_LIST object to aRefList for each same-reference set of multi-unit parts in the li...
This file is part of the common library.
const SCH_SHEET_PATH & GetSheetPath() const
ANNOTATE_ORDER_T
Schematic annotation order options.
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
void AnnotateComponents(bool aAnnotateSchematic, ANNOTATE_ORDER_T aSortOption, ANNOTATE_OPTION_T aAlgoOption, int aStartNumber, bool aResetAnnotation, bool aRepairTimestamps, bool aLockUnits, REPORTER &aReporter)
Annotate the components in the schematic that are not currently annotated.
virtual REPORTER & ReportTail(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Places the report at the end of the list, for objects that support report ordering.
Definition: reporter.h:93
int GetUnitCount() const
Return the number of units per package of the symbol.
Definition: sch_symbol.cpp:355
Annotate incrementally using the first free reference number.
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:64
void UpdateAllScreenReferences()
Update all the symbol references for this sheet path.
void DeleteAnnotation(bool aCurrentSheetOnly, bool *appendUndo)
Clear the current component annotation.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
void GetMultiUnitComponents(SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, bool aIncludePowerSymbols=true) const
Add a SCH_REFERENCE_LIST object to aRefList for each same-reference set of multi-unit parts in the sh...
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
int GetUnit() const
Definition: sch_symbol.h:237
const wxString GetValue(const SCH_SHEET_PATH *sheet, bool aResolve) const
Definition: sch_symbol.cpp:587
void SortByXCoordinate()
Sort the list of references by X position.
void SyncView()
Mark all items for refresh.
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void Annotate()
Update the annotation of the symbol according the the current object state.
SCHEMATIC & Schematic() const
ANNOTATE_OPTION_T
Schematic annotation type options.
void Annotate(bool aUseSheetNum, int aSheetIntervalId, int aStartNumber, SCH_MULTI_UNIT_REFERENCE_MAP aLockedUnitMap)
Set the reference designators in the list that have not been annotated.
bool IsAnnotated(const SCH_SHEET_PATH *aSheet)
Checks if the component has a valid annotation (reference) for the given sheet path.
Definition: sch_symbol.cpp:531
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
ERCE_T
ERC error codes.
Definition: erc_settings.h:36
std::map< wxString, SCH_REFERENCE_LIST > SCH_MULTI_UNIT_REFERENCE_MAP
Container to map reference designators for multi-unit parts.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
SCH_COMPONENT * GetSymbol() const
const KIID m_Uuid
Definition: eda_item.h:524
Annotate by Y position from top to bottom.
unsigned GetCount() const
Annotate using the first free reference number starting at the sheet number * 100.
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:111
int CheckAnnotation(ANNOTATION_ERROR_HANDLER aErrorHandler)
Check for annotations errors.
SCH_SCREEN * LastScreen()
void SetSheetNumberAndCount()
Set the m_ScreenNumber and m_NumberOfScreens members for screens.
void SplitReferences()
Attempt to split all reference designators into a name (U) and number (1).
void SaveCopyInUndoList(SCH_SCREEN *aScreen, SCH_ITEM *aItemToCopy, UNDO_REDO aTypeCommand, bool aAppend)
Create a copy of the current schematic item, and put it in the undo list.
#define _(s)
Definition: 3d_actions.cpp:33
std::function< void(ERCE_T aType, const wxString &aMsg, SCH_REFERENCE *aItemA, SCH_REFERENCE *aItemB)> ANNOTATION_ERROR_HANDLER
Define a standard error handler for annotation errors.
wxString AsString() const
Definition: kiid.cpp:245
EE_RTREE & Items()
Definition: sch_screen.h:162
Annotate by X position from left to right.
Annotate using the first free reference number starting at the sheet number * 1000.
static wxString SubReference(int aUnit, bool aAddSeparator=true)
Definition: lib_symbol.cpp:440
Schematic symbol object.
Definition: sch_symbol.h:79
SCH_SHEET_PATH & GetCurrentSheet() const
int ReplaceDuplicateTimeStamps()
Test all sheet and component objects in the schematic for duplicate time stamps and replaces them as ...
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current screen and u...
Definition for part library class.
void ClearAnnotation(const SCH_SHEET_PATH *aSheetPath)
Clear exiting component annotation.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:196
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Definition: sch_symbol.cpp:545
A helper to define a symbol's reference designator in a schematic.
void GetSymbols(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanComponents=false) const
Adds SCH_REFERENCE object to aReferences for each component in the sheet.
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:534
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:426