KiCad PCB EDA Suite
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 <symbol_library.h>
33 #include <tools/ee_selection.h>
35 #include <tool/tool_manager.h>
36 
37 
38 void SCH_EDIT_FRAME::mapExistingAnnotation( std::map<wxString, wxString>& aMap )
39 {
40  SCH_REFERENCE_LIST references;
41 
42  Schematic().GetSheets().GetSymbols( references );
43 
44  for( size_t i = 0; i < references.GetCount(); i++ )
45  {
46  SCH_SYMBOL* symbol = references[ i ].GetSymbol();
47  SCH_SHEET_PATH* curr_sheetpath = &references[ i ].GetSheetPath();
48  KIID_PATH curr_full_uuid = curr_sheetpath->Path();
49 
50  curr_full_uuid.push_back( symbol->m_Uuid );
51 
52  wxString ref = symbol->GetRef( curr_sheetpath );
53 
54  if( symbol->GetUnitCount() > 1 )
55  ref << LIB_SYMBOL::SubReference( symbol->GetUnitSelection( curr_sheetpath ) );
56 
57  if( symbol->IsAnnotated( curr_sheetpath ) )
58  aMap[ curr_full_uuid.AsString() ] = ref;
59  }
60 }
61 
62 
63 void SCH_EDIT_FRAME::DeleteAnnotation( ANNOTATE_SCOPE_T aAnnotateScope, bool* aAppendUndo )
64 {
65  auto clearSymbolAnnotation =
66  [&]( EDA_ITEM* aItem, SCH_SCREEN* aScreen, SCH_SHEET_PATH* aSheet )
67  {
68  SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( aItem );
69 
70  SaveCopyInUndoList( aScreen, symbol, UNDO_REDO::CHANGED, *aAppendUndo );
71  *aAppendUndo = true;
72  symbol->ClearAnnotation( aSheet );
73  };
74 
75  auto clearSheetAnnotation =
76  [&]( SCH_SCREEN* aScreen, SCH_SHEET_PATH* aSheet )
77  {
78  for( SCH_ITEM* item : aScreen->Items().OfType( SCH_SYMBOL_T ) )
79  clearSymbolAnnotation( item, aScreen, aSheet );
80  };
81 
82  SCH_SCREEN* screen = GetScreen();
83  SCH_SHEET_PATH currentSheet = GetCurrentSheet();
84 
85  switch( aAnnotateScope )
86  {
87  case ANNOTATE_ALL:
88  {
89  for( const SCH_SHEET_PATH& sheet : Schematic().GetSheets() )
90  clearSheetAnnotation( sheet.LastScreen(), nullptr );
91 
92  break;
93  }
95  {
96  clearSheetAnnotation( screen, &currentSheet );
97  break;
98  }
99 
100  case ANNOTATE_SELECTION:
101  {
103  EE_SELECTION& selection = selTool->RequestSelection();
104 
105  for( EDA_ITEM* item : selection.Items() )
106  {
107  if( item->Type() == SCH_SYMBOL_T )
108  clearSymbolAnnotation( item, screen, &currentSheet );
109  }
110  break;
111  }
112  }
113 
114  // Update the references for the sheet that is currently being displayed.
116 
117  SyncView();
118  GetCanvas()->Refresh();
119  OnModify();
120 
121  // Must go after OnModify() so the connectivity graph has been updated
123 }
124 
125 
127  ANNOTATE_ORDER_T aSortOption,
128  ANNOTATE_ALGO_T aAlgoOption,
129  int aStartNumber,
130  bool aResetAnnotation,
131  bool aRepairTimestamps,
132  REPORTER& aReporter )
133 {
135  EE_SELECTION& selection = selTool->RequestSelection();
136 
137  SCH_REFERENCE_LIST references;
138  SCH_SCREENS screens( Schematic().Root() );
139  SCH_SHEET_LIST sheets = Schematic().GetSheets();
140  SCH_SHEET_PATH currentSheet = GetCurrentSheet();
141  bool appendUndo = false;
142 
143  // Map of locked symbols
144  SCH_MULTI_UNIT_REFERENCE_MAP lockedSymbols;
145 
146  // Map of previous annotation for building info messages
147  std::map<wxString, wxString> previousAnnotation;
148 
149  // Test for and replace duplicate time stamps in symbols and sheets. Duplicate
150  // time stamps can happen with old schematics, schematic conversions, or manual
151  // editing of files.
152  if( aRepairTimestamps )
153  {
154  int count = screens.ReplaceDuplicateTimeStamps();
155 
156  if( count )
157  {
158  wxString msg;
159  msg.Printf( _( "%d duplicate time stamps were found and replaced." ), count );
160  aReporter.ReportTail( msg, RPT_SEVERITY_WARNING );
161  }
162  }
163 
164  // Collect all the sets that must be annotated together.
165  switch( aAnnotateScope )
166  {
167  case ANNOTATE_ALL:
168  sheets.GetMultiUnitSymbols( lockedSymbols );
169  break;
170 
172  currentSheet.GetMultiUnitSymbols( lockedSymbols );
173  break;
174 
175  case ANNOTATE_SELECTION:
176  selection.GetMultiUnitSymbols( lockedSymbols, currentSheet );
177  break;
178  }
179 
180  // Store previous annotations for building info messages
181  mapExistingAnnotation( previousAnnotation );
182 
183  // If it is an annotation for all the symbols, reset previous annotation.
184  if( aResetAnnotation )
185  DeleteAnnotation( aAnnotateScope, &appendUndo );
186 
187  // Set sheet number and number of sheets.
189 
190  // Build symbol list
191  switch( aAnnotateScope )
192  {
193  case ANNOTATE_ALL:
194  sheets.GetSymbols( references );
195  break;
196 
198  GetCurrentSheet().GetSymbols( references );
199  break;
200 
201  case ANNOTATE_SELECTION:
202  selection.GetSymbols( references, currentSheet );
203  break;
204  }
205 
206  // Build additional list of references to be used during reannotation
207  // to avoid duplicate designators (no additional references when annotating
208  // the full schematic)
209  SCH_REFERENCE_LIST additionalRefs;
210 
211  if( aAnnotateScope != ANNOTATE_ALL )
212  {
213  SCH_REFERENCE_LIST allRefs;
214  sheets.GetSymbols( allRefs );
215 
216  for( size_t i = 0; i < allRefs.GetCount(); i++ )
217  {
218  if( !references.Contains( allRefs[i] ) )
219  additionalRefs.AddItem( allRefs[i] );
220  }
221  }
222 
223  // Break full symbol reference into name (prefix) and number:
224  // example: IC1 become IC, and 1
225  references.SplitReferences();
226 
227  switch( aSortOption )
228  {
229  default:
230  case SORT_BY_X_POSITION: references.SortByXCoordinate(); break;
231  case SORT_BY_Y_POSITION: references.SortByYCoordinate(); break;
232  }
233 
234  bool useSheetNum = false;
235  int idStep = 100;
236 
237  switch( aAlgoOption )
238  {
239  default:
240  case INCREMENTAL_BY_REF:
241  break;
242 
243  case SHEET_NUMBER_X_100:
244  useSheetNum = true;
245  break;
246 
247  case SHEET_NUMBER_X_1000:
248  useSheetNum = true;
249  idStep = 1000;
250  break;
251  }
252 
253  // Recalculate and update reference numbers in schematic
254  references.Annotate( useSheetNum, idStep, aStartNumber, lockedSymbols, additionalRefs );
255 
256  for( size_t i = 0; i < references.GetCount(); i++ )
257  {
258  SCH_REFERENCE& ref = references[i];
259  SCH_SYMBOL* symbol = ref.GetSymbol();
260  SCH_SHEET_PATH* sheet = &ref.GetSheetPath();
261 
262  SaveCopyInUndoList( sheet->LastScreen(), symbol, UNDO_REDO::CHANGED, appendUndo );
263  appendUndo = true;
264  ref.Annotate();
265 
266  KIID_PATH full_uuid = sheet->Path();
267  full_uuid.push_back( symbol->m_Uuid );
268 
269  wxString prevRef = previousAnnotation[ full_uuid.AsString() ];
270  wxString newRef = symbol->GetRef( sheet );
271 
272  if( symbol->GetUnitCount() > 1 )
273  newRef << LIB_SYMBOL::SubReference( symbol->GetUnitSelection( sheet ) );
274 
275  wxString msg;
276 
277  if( prevRef.Length() )
278  {
279  if( newRef == prevRef )
280  continue;
281 
282  if( symbol->GetUnitCount() > 1 )
283  {
284  msg.Printf( _( "Updated %s (unit %s) from %s to %s." ),
285  symbol->GetValue( sheet, true ),
286  LIB_SYMBOL::SubReference( symbol->GetUnit(), false ),
287  prevRef,
288  newRef );
289  }
290  else
291  {
292  msg.Printf( _( "Updated %s from %s to %s." ),
293  symbol->GetValue( sheet, true ),
294  prevRef,
295  newRef );
296  }
297  }
298  else
299  {
300  if( symbol->GetUnitCount() > 1 )
301  {
302  msg.Printf( _( "Annotated %s (unit %s) as %s." ),
303  symbol->GetValue( sheet, true ),
304  LIB_SYMBOL::SubReference( symbol->GetUnit(), false ),
305  newRef );
306  }
307  else
308  {
309  msg.Printf( _( "Annotated %s as %s." ),
310  symbol->GetValue( sheet, true ),
311  newRef );
312  }
313  }
314 
315  aReporter.Report( msg, RPT_SEVERITY_ACTION );
316  }
317 
318  // Final control (just in case ... ).
319  if( !CheckAnnotate(
320  [ &aReporter ]( ERCE_T , const wxString& aMsg, SCH_REFERENCE* , SCH_REFERENCE* )
321  {
322  aReporter.Report( aMsg, RPT_SEVERITY_ERROR );
323  },
324  aAnnotateScope ) )
325  {
326  aReporter.ReportTail( _( "Annotation complete." ), RPT_SEVERITY_ACTION );
327  }
328 
329  // Update on screen references, that can be modified by previous calculations:
332 
333  SyncView();
334  GetCanvas()->Refresh();
335  OnModify();
336 
337  // Must go after OnModify() so the connectivity graph has been updated
339 }
340 
341 
343  ANNOTATE_SCOPE_T aAnnotateScope )
344 {
345  SCH_REFERENCE_LIST referenceList;
346  constexpr bool includePowerSymbols = false;
347 
348  // Build the list of symbols
349  switch( aAnnotateScope )
350  {
351  case ANNOTATE_ALL:
352  Schematic().GetSheets().GetSymbols( referenceList );
353  break;
354 
356  GetCurrentSheet().GetSymbols( referenceList, includePowerSymbols );
357  break;
358 
359  case ANNOTATE_SELECTION:
361  EE_SELECTION& selection = selTool->RequestSelection();
362  selection.GetSymbols( referenceList, GetCurrentSheet(), includePowerSymbols );
363  break;
364  }
365 
366  // Empty schematic does not need annotation
367  if( referenceList.GetCount() == 0 )
368  return 0;
369 
370  return referenceList.CheckAnnotation( aErrorHandler );
371 }
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:216
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 sh...
void SortByYCoordinate()
Sort the list of references by Y position.
void UpdateNetHighlightStatus()
Annotate the selection.
void mapExistingAnnotation(std::map< wxString, wxString > &aMap)
Fill a map of uuid -> reference from the currently loaded schematic.
Definition: annotate.cpp:38
Annotate the full schematic.
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...
void GetSymbols(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets.
This file is part of the common library.
const SCH_SHEET_PATH & GetSheetPath() const
ANNOTATE_ORDER_T
Schematic annotation order options.
int GetUnitCount() const
Return the number of units per package of the symbol.
Definition: sch_symbol.cpp:361
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
void ClearAnnotation(const SCH_SHEET_PATH *aSheetPath)
Clear exiting symbol annotation.
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
void DeleteAnnotation(ANNOTATE_SCOPE_T aAnnotateScope, bool *appendUndo)
Clear the current symbol annotation.
Definition: annotate.cpp:63
void AnnotateSymbols(ANNOTATE_SCOPE_T aAnnotateScope, ANNOTATE_ORDER_T aSortOption, ANNOTATE_ALGO_T aAlgoOption, int aStartNumber, bool aResetAnnotation, bool aRepairTimestamps, REPORTER &aReporter)
Annotate the symbols in the schematic that are not currently annotated.
Definition: annotate.cpp:126
void AddItem(const SCH_REFERENCE &aItem)
static wxString SubReference(int aUnit, bool aAddSeparator=true)
Definition: lib_symbol.cpp:445
SCH_SYMBOL * GetSymbol() const
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:432
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.
int CheckAnnotate(ANNOTATION_ERROR_HANDLER aErrorHandler, ANNOTATE_SCOPE_T aAnnotateScope=ANNOTATE_ALL)
Check for annotation errors.
Definition: annotate.cpp:342
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
EE_SELECTION & RequestSelection(const KICAD_T *aFilterList=EE_COLLECTOR::AllItems)
Return either an existing selection (filtered), or the selection at the current cursor if the existin...
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
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.
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
Definition: sch_symbol.cpp:522
void Annotate()
Update the annotation of the symbol according the current object state.
Annotate using the first free reference number starting at the sheet number * 100.
SCHEMATIC & Schematic() const
size_t GetCount() const
Definition for symbol library class.
ANNOTATE_SCOPE_T
Schematic annotation scope options.
#define _(s)
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
bool Contains(const SCH_REFERENCE &aItem)
Return true if aItem exists in this list.
const wxString GetValue(const SCH_SHEET_PATH *sheet, bool aResolve) const
Return the instance-specific value for the given sheet path.
Definition: sch_symbol.cpp:564
std::map< wxString, SCH_REFERENCE_LIST > SCH_MULTI_UNIT_REFERENCE_MAP
Container to map reference designators for multi-unit parts.
const KIID m_Uuid
Definition: eda_item.h:475
bool IsAnnotated(const SCH_SHEET_PATH *aSheet)
Check if the symbol has a valid annotation (reference) for the given sheet path.
Definition: sch_symbol.cpp:508
Annotate by Y position from top to bottom.
Annotate incrementally using the first free reference number.
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:87
int CheckAnnotation(ANNOTATION_ERROR_HANDLER aErrorHandler)
Check for annotations errors.
void Annotate(bool aUseSheetNum, int aSheetIntervalId, int aStartNumber, SCH_MULTI_UNIT_REFERENCE_MAP aLockedUnitMap, const SCH_REFERENCE_LIST &aAdditionalRefs, bool aStartAtCurrent=false)
Set the reference designators in the list that have not been annotated.
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:158
Schematic symbol object.
Definition: sch_symbol.h:78
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.
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:277
ANNOTATE_ALGO_T
Schematic annotation type options.
EE_RTREE & Items()
Definition: sch_screen.h:102
void GetSymbols(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Adds SCH_REFERENCE object to aReferences for each symbol in the sheet.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
Annotate by X position from left to right.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:100
Annotate using the first free reference number starting at the sheet number * 1000.
SCH_SHEET_PATH & GetCurrentSheet() const
int ReplaceDuplicateTimeStamps()
Test all sheet and symbol objects in the schematic for duplicate time stamps and replaces them as nec...
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current screen and u...
Annotate the current sheet.
int GetUnit() const
Definition: sch_symbol.h:195
void GetSymbols(SCH_REFERENCE_LIST &aReferences, const SCH_SHEET_PATH &aSelectionPath, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false)
Adds SCH_REFERENCE object to aReferences for each symbol in the selection.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:197
A helper to define a symbol's reference designator in a schematic.
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:551