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 <fctsys.h>
27 #include <sch_draw_panel.h>
28 #include <confirm.h>
29 #include <reporter.h>
30 #include <sch_edit_frame.h>
31 #include <schematic.h>
32 
33 #include <sch_reference_list.h>
34 #include <class_library.h>
35 
36 
37 void SCH_EDIT_FRAME::mapExistingAnnotation( std::map<wxString, wxString>& aMap )
38 {
39  SCH_REFERENCE_LIST references;
40 
41  Schematic().GetSheets().GetComponents( references );
42 
43  for( size_t i = 0; i < references.GetCount(); i++ )
44  {
45  SCH_COMPONENT* comp = references[ i ].GetComp();
46  SCH_SHEET_PATH* curr_sheetpath = &references[ i ].GetSheetPath();
47  KIID_PATH curr_full_uuid = curr_sheetpath->Path();
48  curr_full_uuid.push_back( comp->m_Uuid );
49 
50  wxString ref = comp->GetRef( curr_sheetpath );
51 
52  if( comp->GetUnitCount() > 1 )
53  ref << LIB_PART::SubReference( comp->GetUnitSelection( curr_sheetpath ) );
54 
55  if( comp->IsAnnotated( curr_sheetpath ) )
56  aMap[ curr_full_uuid.AsString() ] = ref;
57  }
58 }
59 
60 
61 void SCH_EDIT_FRAME::DeleteAnnotation( bool aCurrentSheetOnly, bool* aAppendUndo )
62 {
63  auto clearAnnotation =
64  [&]( SCH_SCREEN* aScreen, SCH_SHEET_PATH* aSheet )
65  {
66  for( SCH_ITEM* item : aScreen->Items().OfType( SCH_COMPONENT_T ) )
67  {
68  SCH_COMPONENT* component = static_cast<SCH_COMPONENT*>( item );
69 
70  SaveCopyInUndoList( aScreen, component, UR_CHANGED, *aAppendUndo );
71  *aAppendUndo = true;
72  component->ClearAnnotation( aSheet );
73 
74  // Clear the modified component flag set by component->ClearAnnotation
75  // because we do not use it here and we should not leave this flag set,
76  // when an editing is finished:
77  component->ClearFlags();
78  }
79  };
80 
81  if( aCurrentSheetOnly )
82  {
83  clearAnnotation( GetScreen(), &GetCurrentSheet() );
84  }
85  else
86  {
87  for( const SCH_SHEET_PATH& sheet : Schematic().GetSheets() )
88  clearAnnotation( sheet.LastScreen(), nullptr );
89  }
90 
91  // Update the references for the sheet that is currently being displayed.
93 
94  SyncView();
95  GetCanvas()->Refresh();
96  OnModify();
97 }
98 
99 
100 void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic,
101  ANNOTATE_ORDER_T aSortOption,
102  ANNOTATE_OPTION_T aAlgoOption,
103  int aStartNumber,
104  bool aResetAnnotation,
105  bool aRepairTimestamps,
106  bool aLockUnits,
107  REPORTER& aReporter )
108 {
109  SCH_REFERENCE_LIST references;
110  SCH_SCREENS screens( Schematic().Root() );
111  SCH_SHEET_LIST sheets = Schematic().GetSheets();
112  bool appendUndo = false;
113 
114  // Map of locked components
115  SCH_MULTI_UNIT_REFERENCE_MAP lockedComponents;
116 
117  // Map of previous annotation for building info messages
118  std::map<wxString, wxString> previousAnnotation;
119 
120  // Test for and replace duplicate time stamps in components and sheets. Duplicate
121  // time stamps can happen with old schematics, schematic conversions, or manual
122  // editing of files.
123  if( aRepairTimestamps )
124  {
125  int count = screens.ReplaceDuplicateTimeStamps();
126 
127  if( count )
128  {
129  wxString msg;
130  msg.Printf( _( "%d duplicate time stamps were found and replaced." ), count );
131  aReporter.ReportTail( msg, RPT_SEVERITY_WARNING );
132  }
133  }
134 
135  // If units must be locked, collect all the sets that must be annotated together.
136  if( aLockUnits )
137  {
138  if( aAnnotateSchematic )
139  sheets.GetMultiUnitComponents( lockedComponents );
140  else
141  GetCurrentSheet().GetMultiUnitComponents( lockedComponents );
142  }
143 
144  // Store previous annotations for building info messages
145  mapExistingAnnotation( previousAnnotation );
146 
147  // If it is an annotation for all the components, reset previous annotation.
148  if( aResetAnnotation )
149  DeleteAnnotation( !aAnnotateSchematic, &appendUndo );
150 
151  // Set sheet number and number of sheets.
153 
154  // Build component list
155  if( aAnnotateSchematic )
156  sheets.GetComponents( references );
157  else
158  GetCurrentSheet().GetComponents( references );
159 
160  // Break full components reference in name (prefix) and number:
161  // example: IC1 become IC, and 1
162  references.SplitReferences();
163 
164  switch( aSortOption )
165  {
166  default:
167  case SORT_BY_X_POSITION: references.SortByXCoordinate(); break;
168  case SORT_BY_Y_POSITION: references.SortByYCoordinate(); break;
169  }
170 
171  bool useSheetNum = false;
172  int idStep = 100;
173 
174  switch( aAlgoOption )
175  {
176  default:
177  case INCREMENTAL_BY_REF:
178  break;
179 
180  case SHEET_NUMBER_X_100:
181  useSheetNum = true;
182  break;
183 
184  case SHEET_NUMBER_X_1000:
185  useSheetNum = true;
186  idStep = 1000;
187  break;
188  }
189 
190  // Recalculate and update reference numbers in schematic
191  references.Annotate( useSheetNum, idStep, aStartNumber, lockedComponents );
192 
193  for( size_t i = 0; i < references.GetCount(); i++ )
194  {
195  SCH_REFERENCE& ref = references[i];
196  SCH_COMPONENT* comp = ref.GetComp();
197  SCH_SHEET_PATH* sheet = &ref.GetSheetPath();
198 
199  SaveCopyInUndoList( sheet->LastScreen(), comp, UR_CHANGED, appendUndo );
200  appendUndo = true;
201  ref.Annotate();
202 
203  KIID_PATH full_uuid = sheet->Path();
204  full_uuid.push_back( comp->m_Uuid );
205 
206  wxString prevRef = previousAnnotation[ full_uuid.AsString() ];
207  wxString newRef = comp->GetRef( sheet );
208 
209  if( comp->GetUnitCount() > 1 )
210  newRef << LIB_PART::SubReference( comp->GetUnitSelection( sheet ) );
211 
212  wxString msg;
213 
214  if( prevRef.Length() )
215  {
216  if( newRef == prevRef )
217  continue;
218 
219  if( comp->GetUnitCount() > 1 )
220  msg.Printf( _( "Updated %s (unit %s) from %s to %s" ),
221  comp->GetField( VALUE )->GetShownText(),
222  LIB_PART::SubReference( comp->GetUnit(), false ),
223  prevRef,
224  newRef );
225  else
226  msg.Printf( _( "Updated %s from %s to %s" ),
227  comp->GetField( VALUE )->GetShownText(),
228  prevRef,
229  newRef );
230  }
231  else
232  {
233  if( comp->GetUnitCount() > 1 )
234  msg.Printf( _( "Annotated %s (unit %s) as %s" ),
235  comp->GetField( VALUE )->GetShownText(),
236  LIB_PART::SubReference( comp->GetUnit(), false ),
237  newRef );
238  else
239  msg.Printf( _( "Annotated %s as %s" ),
240  comp->GetField( VALUE )->GetShownText(),
241  newRef );
242  }
243 
244  aReporter.Report( msg, RPT_SEVERITY_ACTION );
245  }
246 
247  // Final control (just in case ... ).
248  if( !CheckAnnotate( aReporter, !aAnnotateSchematic ) )
249  aReporter.ReportTail( _( "Annotation complete." ), RPT_SEVERITY_ACTION );
250 
251  // Update on screen references, that can be modified by previous calculations:
254 
255  SyncView();
256  GetCanvas()->Refresh();
257  OnModify();
258 }
259 
260 
261 int SCH_EDIT_FRAME::CheckAnnotate( REPORTER& aReporter, bool aOneSheetOnly )
262 {
263  SCH_REFERENCE_LIST componentsList;
264 
265  // Build the list of components
266  if( !aOneSheetOnly )
267  Schematic().GetSheets().GetComponents( componentsList );
268  else
269  GetCurrentSheet().GetComponents( componentsList );
270 
271  // Empty schematic does not need annotation
272  if( componentsList.GetCount() == 0 )
273  return 0;
274 
275  return componentsList.CheckAnnotation( aReporter );
276 }
SCH_SHEET_LIST.
void SortByYCoordinate()
Function sortByYCoordinate sorts the list of references by Y position.
void GetComponents(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanComponents=false) const
Function GetComponents adds a 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:92
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.
REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:64
void UpdateAllScreenReferences()
Function UpdateAllScreenReferences updates the reference and the m_Multi parameter (part selection) f...
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.
wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: sch_field.cpp:102
void GetMultiUnitComponents(SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, bool aIncludePowerSymbols=true) const
Function GetMultiUnitComponents adds a SCH_REFERENCE_LIST object to aRefList for each same-reference ...
void GetMultiUnitComponents(SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, bool aIncludePowerSymbols=true) const
Function GetMultiUnitComponents adds a SCH_REFERENCE_LIST object to aRefList for each same-reference ...
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
Function GetComponents adds a SCH_REFERENCE() object to aReferences for each component in the list of...
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
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.
SCH_SHEET_PATH.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false)
Return the reference for the given sheet path.
void ClearAnnotation(SCH_SHEET_PATH *aSheetPath)
Clear exiting component annotation.
std::map< wxString, SCH_REFERENCE_LIST > SCH_MULTI_UNIT_REFERENCE_MAP
Type SCH_MULTI_UNIT_REFERENCE_MAP is used to create a map of reference designators for multi-unit par...
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: base_struct.h:162
Annotate by Y position from top to bottom.
unsigned GetCount() const
Function GetCount.
SCH_FIELD * GetField(int aFieldNdx)
Returns a field in this symbol.
Field Value of part, i.e. "3.3K".
Annotate using the first free reference number starting at the sheet number * 100.
SCH_SCREEN * LastScreen()
Function 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
void SaveCopyInUndoList(SCH_SCREEN *aScreen, SCH_ITEM *aItemToCopy, UNDO_REDO_T aTypeCommand, bool aAppend, const wxPoint &aTransformPoint=wxPoint(0, 0))
Create a copy of the current schematic item, and put it in the undo list.
wxString AsString() const
Definition: common.h:137
EE_RTREE & Items()
Definition: sch_screen.h:158
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:88
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:233
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.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:187
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:528