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-2020 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 <sch_draw_panel.h>
27 #include <confirm.h>
28 #include <reporter.h>
29 #include <sch_edit_frame.h>
30 #include <schematic.h>
31 
32 #include <sch_reference_list.h>
33 #include <class_library.h>
34 
35 
36 void SCH_EDIT_FRAME::mapExistingAnnotation( std::map<wxString, wxString>& aMap )
37 {
38  SCH_REFERENCE_LIST references;
39 
40  Schematic().GetSheets().GetComponents( references );
41 
42  for( size_t i = 0; i < references.GetCount(); i++ )
43  {
44  SCH_COMPONENT* comp = references[ i ].GetComp();
45  SCH_SHEET_PATH* curr_sheetpath = &references[ i ].GetSheetPath();
46  KIID_PATH curr_full_uuid = curr_sheetpath->Path();
47  curr_full_uuid.push_back( comp->m_Uuid );
48 
49  wxString ref = comp->GetRef( curr_sheetpath );
50 
51  if( comp->GetUnitCount() > 1 )
52  ref << LIB_PART::SubReference( comp->GetUnitSelection( curr_sheetpath ) );
53 
54  if( comp->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.GetMultiUnitComponents( 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.GetComponents( references );
154  else
155  GetCurrentSheet().GetComponents( 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* comp = ref.GetComp();
194  SCH_SHEET_PATH* sheet = &ref.GetSheetPath();
195 
196  SaveCopyInUndoList( sheet->LastScreen(), comp, UNDO_REDO::CHANGED, appendUndo );
197  appendUndo = true;
198  ref.Annotate();
199 
200  KIID_PATH full_uuid = sheet->Path();
201  full_uuid.push_back( comp->m_Uuid );
202 
203  wxString prevRef = previousAnnotation[ full_uuid.AsString() ];
204  wxString newRef = comp->GetRef( sheet );
205 
206  if( comp->GetUnitCount() > 1 )
207  newRef << LIB_PART::SubReference( comp->GetUnitSelection( sheet ) );
208 
209  wxString msg;
210 
211  if( prevRef.Length() )
212  {
213  if( newRef == prevRef )
214  continue;
215 
216  if( comp->GetUnitCount() > 1 )
217  msg.Printf( _( "Updated %s (unit %s) from %s to %s" ),
218  comp->GetValue( sheet ),
219  LIB_PART::SubReference( comp->GetUnit(), false ),
220  prevRef,
221  newRef );
222  else
223  msg.Printf( _( "Updated %s from %s to %s" ),
224  comp->GetValue( sheet ),
225  prevRef,
226  newRef );
227  }
228  else
229  {
230  if( comp->GetUnitCount() > 1 )
231  msg.Printf( _( "Annotated %s (unit %s) as %s" ),
232  comp->GetValue( sheet ),
233  LIB_PART::SubReference( comp->GetUnit(), false ),
234  newRef );
235  else
236  msg.Printf( _( "Annotated %s as %s" ),
237  comp->GetValue( sheet ),
238  newRef );
239  }
240 
241  aReporter.Report( msg, RPT_SEVERITY_ACTION );
242  }
243 
244  // Final control (just in case ... ).
245  if( !CheckAnnotate( aReporter, !aAnnotateSchematic ) )
246  aReporter.ReportTail( _( "Annotation complete." ), RPT_SEVERITY_ACTION );
247 
248  // Update on screen references, that can be modified by previous calculations:
251 
252  SyncView();
253  GetCanvas()->Refresh();
254  OnModify();
255 
256  // Must go after OnModify() so the connectivity graph has been updated
258 }
259 
260 
261 int SCH_EDIT_FRAME::CheckAnnotate( REPORTER& aReporter, bool aOneSheetOnly )
262 {
263  SCH_REFERENCE_LIST componentsList;
264  constexpr bool includePowerSymbols = false;
265 
266  // Build the list of components
267  if( !aOneSheetOnly )
268  Schematic().GetSheets().GetComponents( componentsList, includePowerSymbols );
269  else
270  GetCurrentSheet().GetComponents( componentsList );
271 
272  // Empty schematic does not need annotation
273  if( componentsList.GetCount() == 0 )
274  return 0;
275 
276  return componentsList.CheckAnnotation( aReporter );
277 }
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
void SortByYCoordinate()
Function sortByYCoordinate sorts the list of references by Y position.
void UpdateNetHighlightStatus()
void GetComponents(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanComponents=false) const
Adds SCH_REFERENCE object to aReferences for each component in the sheet.
void mapExistingAnnotation(std::map< wxString, wxString > &aMap)
Fills a map of uuid -> reference from the currently loaded schematic.
SCH_SHEET_LIST GetSheets() const
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:91
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.
SCH_COMPONENT * GetComp() const
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.
EE_TYPE OfType(KICAD_T aType)
Definition: sch_rtree.h:219
virtual REPORTER & ReportTail(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Function ReportTail Places the report at the end of the list, for objects that support report orderin...
Definition: reporter.h:94
int GetUnitCount() const
Return the number of units per package of the symbol.
Annotate incrementally using the first free reference number.
const wxString GetValue(const SCH_SHEET_PATH *sheet) const
REPORTER is 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
Function Report is a pure virtual function to override in the derived object.
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...
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 li...
SCH_REFERENCE_LIST is used to create a flattened list of components because in a complex hierarchy,...
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
int GetUnit() const
void SortByXCoordinate()
Function sortByXCoordinate sorts the list of references by X position.
void GetComponents(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 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()
Function Annotate updates the annotation of the component according the the current object state.
SCHEMATIC & Schematic() const
void SaveCopyInUndoList(SCH_SCREEN *aScreen, SCH_ITEM *aItemToCopy, UNDO_REDO aTypeCommand, bool aAppend, const wxPoint &aTransformPoint=wxPoint(0, 0))
Create a copy of the current schematic item, and put it in the undo list.
ANNOTATE_OPTION_T
Schematic annotation type options.
void Annotate(bool aUseSheetNum, int aSheetIntervalId, int aStartNumber, SCH_MULTI_UNIT_REFERENCE_MAP aLockedUnitMap)
Function Annotate 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.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
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...
int CheckAnnotate(REPORTER &aReporter, bool aOneSheetOnly)
Check for annotation errors.
const KIID m_Uuid
Definition: eda_item.h:151
Annotate by Y position from top to bottom.
unsigned GetCount() const
Function GetCount.
Annotate using the first free reference number starting at the sheet number * 100.
SCH_SCREEN * LastScreen()
void SetSheetNumberAndCount()
Set the m_ScreenNumber and m_NumberOfScreens members for screens.
void SplitReferences()
Function SplitReferences attempts to split all reference designators into a name (U) and number (1).
#define _(s)
Definition: 3d_actions.cpp:33
wxString AsString() const
Definition: kiid.cpp:206
EE_RTREE & Items()
Definition: sch_screen.h:159
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)
Schematic symbol object.
Definition: sch_component.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.
int CheckAnnotation(REPORTER &aReporter)
Function CheckAnnotation check for annotations errors.
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:194
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
SCH_REFERENCE is used as a helper to define a component's reference designator in a schematic.
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:521
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.