kicad-developers team mailing list archive
-
kicad-developers team
-
Mailing list archive
-
Message #17446
Re: [PATCH] Option in eeschema to annotate keeping multi-unit parts grouped
Here is a fixed version of the patch. It handled perfectly any complex
hierarchies I could throw at it. Got anything worse to torture it with?
Chris
On Sat, Mar 21, 2015 at 04:44:43PM +0100, jp charras wrote:
Le 14/03/2015 00:11, Chris Pavlina a écrit :
Hello,
Here is a patch for eeschema that adds "Reset existing annotation, but
do not swap any units" to eeschema. This first compiles a list of
multi-unit parts and all of the components that comprise them, and then
on annotation, annotates all of them as a group. For example, if
components were originally R3B and R3C, they can be annotated to R5B and
R5C, but never R5B and R6C, or R5A and R5D.
I wanted this feature so that I could re-annotate a project to tidy up
the references, while not losing symbol->footprint mappings that already
exist in a routed PCB.
Perhaps, I'll follow up in a few days with a patch to follow through the
annotations to the other files in the project. (Currently I'm using a
hacked-together Python script for this...)
Chris
Thank for your contribution.
This is a very interesting feature.
I tested it on different schematic projects.
It works fine only for simple hierarchies.
Unfortunately, it does not work on complex hierarchies.
These hierarchies uses more than once a given sheet: there is one file,
one schematic, and several instances.
the sheet which is used more than once stores only one drawing, but n
different references when it is used n times.
For instance demos/complex_hierarchy project.
Be *extremely" careful with complex hierarchies.
Complex hierarchies are always a very tricky case, and are never easy to
handle.
--
Jean-Pierre CHARRAS
_______________________________________________
Mailing list: https://launchpad.net/~kicad-developers
Post to : kicad-developers@xxxxxxxxxxxxxxxxxxx
Unsubscribe : https://launchpad.net/~kicad-developers
More help : https://help.launchpad.net/ListHelp
diff --git a/eeschema/annotate.cpp b/eeschema/annotate.cpp
index 3fccb8e..f041fe3 100644
--- a/eeschema/annotate.cpp
+++ b/eeschema/annotate.cpp
@@ -38,6 +38,7 @@
#include <sch_component.h>
#include <lib_pin.h>
+#include <boost/foreach.hpp>
void SCH_EDIT_FRAME::DeleteAnnotation( bool aCurrentSheetOnly )
{
@@ -62,7 +63,8 @@ void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic,
ANNOTATE_ORDER_T aSortOption,
ANNOTATE_OPTION_T aAlgoOption,
bool aResetAnnotation,
- bool aRepairTimestamps )
+ bool aRepairTimestamps,
+ bool aLockUnits )
{
SCH_REFERENCE_LIST references;
@@ -73,6 +75,9 @@ void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic,
// Build the sheet list.
SCH_SHEET_LIST sheets;
+ // Map of locked components
+ SCH_MULTI_UNIT_REFERENCE_MAP lockedComponents;
+
// Test for and replace duplicate time stamps in components and sheets. Duplicate
// time stamps can happen with old schematics, schematic conversions, or manual
// editing of files.
@@ -88,6 +93,19 @@ void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic,
}
}
+ // If units must be locked, collect all the sets that must be annotated together.
+ if( aLockUnits )
+ {
+ if( aAnnotateSchematic )
+ {
+ sheets.GetMultiUnitComponents( Prj().SchLibs(), lockedComponents );
+ }
+ else
+ {
+ m_CurrentSheet->GetMultiUnitComponents( Prj().SchLibs(), lockedComponents );
+ }
+ }
+
// If it is an annotation for all the components, reset previous annotation.
if( aResetAnnotation )
DeleteAnnotation( !aAnnotateSchematic );
@@ -141,7 +159,7 @@ void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic,
}
// Recalculate and update reference numbers in schematic
- references.Annotate( useSheetNum, idStep );
+ references.Annotate( useSheetNum, idStep, lockedComponents );
references.UpdateAnnotation();
wxArrayString errors;
diff --git a/eeschema/component_references_lister.cpp b/eeschema/component_references_lister.cpp
index 15eb9e6..6796ef3 100644
--- a/eeschema/component_references_lister.cpp
+++ b/eeschema/component_references_lister.cpp
@@ -39,6 +39,8 @@
#include <sch_reference_list.h>
#include <sch_component.h>
+#include <boost/foreach.hpp>
+
//#define USE_OLD_ALGO
@@ -283,7 +285,8 @@ int SCH_REFERENCE_LIST::CreateFirstFreeRefId( std::vector<int>& aIdList, int aFi
}
-void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId )
+void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId,
+ SCH_MULTI_UNIT_REFERENCE_MAP aLockedUnitMap )
{
if ( componentFlatList.size() == 0 )
return;
@@ -327,6 +330,24 @@ void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId )
if( componentFlatList[ii].m_Flag )
continue;
+ // Check whether this component is in aLockedUnitMap.
+ SCH_REFERENCE_LIST* lockedList = NULL;
+ BOOST_FOREACH( SCH_MULTI_UNIT_REFERENCE_MAP::value_type& pair, aLockedUnitMap )
+ {
+ unsigned n_refs = pair.second.GetCount();
+ for( unsigned thisRefI = 0; thisRefI < n_refs; ++thisRefI )
+ {
+ SCH_REFERENCE &thisRef = pair.second[thisRefI];
+
+ if( thisRef.IsSameInstance( componentFlatList[ii] ) )
+ {
+ lockedList = &pair.second;
+ break;
+ }
+ }
+ if( lockedList != NULL ) break;
+ }
+
if( ( componentFlatList[first].CompareRef( componentFlatList[ii] ) != 0 )
|| ( aUseSheetNum && ( componentFlatList[first].m_SheetNum != componentFlatList[ii].m_SheetNum ) ) )
{
@@ -388,47 +409,80 @@ void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId )
componentFlatList[ii].m_Flag = 1;
}
- /* search for others units of this component.
- * we search for others parts that have the same value and the same
- * reference prefix (ref without ref number)
- */
- for( Unit = 1; Unit <= NumberOfUnits; Unit++ )
+ // If this component is in aLockedUnitMap, copy the annotation to all
+ // components that are not it
+ if( lockedList != NULL )
{
- if( componentFlatList[ii].m_Unit == Unit )
- continue;
+ unsigned n_refs = lockedList->GetCount();
+ for( unsigned thisRefI = 0; thisRefI < n_refs; ++thisRefI )
+ {
+ SCH_REFERENCE &thisRef = (*lockedList)[thisRefI];
+ if( thisRef.IsSameInstance( componentFlatList[ii] ) )
+ {
+ // This is the component we're currently annotating. Hold the unit!
+ componentFlatList[ii].m_Unit = thisRef.m_Unit;
+ }
- int found = FindUnit( ii, Unit );
+ if( thisRef.CompareValue( componentFlatList[ii] ) != 0 ) continue;
+ if( thisRef.CompareLibName( componentFlatList[ii] ) != 0 ) continue;
- if( found >= 0 )
- continue; // this unit exists for this reference (unit already annotated)
+ // Find the matching component
+ for( unsigned jj = ii + 1; jj < componentFlatList.size(); jj++ )
+ {
+ if( ! thisRef.IsSameInstance( componentFlatList[jj] ) ) continue;
+ componentFlatList[jj].m_NumRef = componentFlatList[ii].m_NumRef;
+ componentFlatList[jj].m_Unit = thisRef.m_Unit;
+ componentFlatList[jj].m_IsNew = false;
+ componentFlatList[jj].m_Flag = 1;
+ break;
+ }
+ }
+ }
- // Search a component to annotate ( same prefix, same value, not annotated)
- for( unsigned jj = ii + 1; jj < componentFlatList.size(); jj++ )
+ else
+ {
+ /* search for others units of this component.
+ * we search for others parts that have the same value and the same
+ * reference prefix (ref without ref number)
+ */
+ for( Unit = 1; Unit <= NumberOfUnits; Unit++ )
{
- if( componentFlatList[jj].m_Flag ) // already tested
- continue;
-
- if( componentFlatList[ii].CompareRef( componentFlatList[jj] ) != 0 )
+ if( componentFlatList[ii].m_Unit == Unit )
continue;
- if( componentFlatList[jj].CompareValue( componentFlatList[ii] ) != 0 )
- continue;
+ int found = FindUnit( ii, Unit );
- if( componentFlatList[jj].CompareLibName( componentFlatList[ii] ) != 0 )
- continue;
+ if( found >= 0 )
+ continue; // this unit exists for this reference (unit already annotated)
- if( !componentFlatList[jj].m_IsNew )
- continue;
-
- // Component without reference number found, annotate it if possible
- if( !componentFlatList[jj].IsUnitsLocked()
- || ( componentFlatList[jj].m_Unit == Unit ) )
+ // Search a component to annotate ( same prefix, same value, not annotated)
+ for( unsigned jj = ii + 1; jj < componentFlatList.size(); jj++ )
{
- componentFlatList[jj].m_NumRef = componentFlatList[ii].m_NumRef;
- componentFlatList[jj].m_Unit = Unit;
- componentFlatList[jj].m_Flag = 1;
- componentFlatList[jj].m_IsNew = false;
- break;
+ if( componentFlatList[jj].m_Flag ) // already tested
+ continue;
+
+ if( componentFlatList[ii].CompareRef( componentFlatList[jj] ) != 0 )
+ continue;
+
+ if( componentFlatList[jj].CompareValue( componentFlatList[ii] ) != 0 )
+ continue;
+
+ if( componentFlatList[jj].CompareLibName( componentFlatList[ii] ) != 0 )
+ continue;
+
+ if( !componentFlatList[jj].m_IsNew )
+ continue;
+
+ // Component without reference number found, annotate it if possible
+ if( !componentFlatList[jj].IsUnitsLocked()
+ || ( componentFlatList[jj].m_Unit == Unit ) )
+ {
+ componentFlatList[jj].m_NumRef = componentFlatList[ii].m_NumRef;
+ componentFlatList[jj].m_Unit = Unit;
+ componentFlatList[jj].m_Flag = 1;
+ componentFlatList[jj].m_IsNew = false;
+ break;
+ }
}
}
}
diff --git a/eeschema/dialogs/dialog_annotate.cpp b/eeschema/dialogs/dialog_annotate.cpp
index 8cf2c1d..55ab3a4 100644
--- a/eeschema/dialogs/dialog_annotate.cpp
+++ b/eeschema/dialogs/dialog_annotate.cpp
@@ -67,6 +67,7 @@ private:
// User functions:
bool GetLevel();
bool GetResetItems();
+ bool GetLockUnits();
/**
* Function GetSortOrder
@@ -212,7 +213,7 @@ void DIALOG_ANNOTATE::OnApplyClick( wxCommandEvent& event )
m_Parent->AnnotateComponents( GetLevel(), (ANNOTATE_ORDER_T) GetSortOrder(),
(ANNOTATE_OPTION_T) GetAnnotateAlgo(),
- GetResetItems() , true );
+ GetResetItems() , true, GetLockUnits() );
m_Parent->GetCanvas()->Refresh();
m_btnClear->Enable();
@@ -273,9 +274,13 @@ bool DIALOG_ANNOTATE::GetLevel()
bool DIALOG_ANNOTATE::GetResetItems()
{
- return m_rbResetAnnotation->GetValue();
+ return m_rbResetAnnotation->GetValue() || m_rbResetButLock->GetValue();
}
+bool DIALOG_ANNOTATE::GetLockUnits()
+{
+ return m_rbResetButLock->GetValue();
+}
int DIALOG_ANNOTATE::GetSortOrder()
{
diff --git a/eeschema/dialogs/dialog_annotate_base.cpp b/eeschema/dialogs/dialog_annotate_base.cpp
index 83fb59b..a911ca7 100644
--- a/eeschema/dialogs/dialog_annotate_base.cpp
+++ b/eeschema/dialogs/dialog_annotate_base.cpp
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Jun 6 2014)
+// C++ code generated with wxFormBuilder (version Mar 13 2015)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
@@ -43,6 +43,9 @@ DIALOG_ANNOTATE_BASE::DIALOG_ANNOTATE_BASE( wxWindow* parent, wxWindowID id, con
m_rbResetAnnotation = new wxRadioButton( this, ID_RESET_ANNOTATION, _("&Reset existing annotation"), wxDefaultPosition, wxDefaultSize, 0 );
bscopeOptSizer->Add( m_rbResetAnnotation, 0, wxALL, 3 );
+ m_rbResetButLock = new wxRadioButton( this, ID_RESET_BUT_LOCK, _("R&eset existing annotation, but do not swap any units"), wxDefaultPosition, wxDefaultSize, 0 );
+ bscopeOptSizer->Add( m_rbResetButLock, 0, wxALL, 3 );
+
bupperSizer->Add( bscopeOptSizer, 0, wxEXPAND|wxLEFT|wxALIGN_RIGHT, 25 );
diff --git a/eeschema/dialogs/dialog_annotate_base.fbp b/eeschema/dialogs/dialog_annotate_base.fbp
index ebf4f0f..f99d1a1 100644
--- a/eeschema/dialogs/dialog_annotate_base.fbp
+++ b/eeschema/dialogs/dialog_annotate_base.fbp
@@ -627,6 +627,94 @@
<event name="OnUpdateUI"></event>
</object>
</object>
+ <object class="sizeritem" expanded="1">
+ <property name="border">3</property>
+ <property name="flag">wxALL</property>
+ <property name="proportion">0</property>
+ <object class="wxRadioButton" expanded="1">
+ <property name="BottomDockable">1</property>
+ <property name="LeftDockable">1</property>
+ <property name="RightDockable">1</property>
+ <property name="TopDockable">1</property>
+ <property name="aui_layer"></property>
+ <property name="aui_name"></property>
+ <property name="aui_position"></property>
+ <property name="aui_row"></property>
+ <property name="best_size"></property>
+ <property name="bg"></property>
+ <property name="caption"></property>
+ <property name="caption_visible">1</property>
+ <property name="center_pane">0</property>
+ <property name="close_button">1</property>
+ <property name="context_help"></property>
+ <property name="context_menu">1</property>
+ <property name="default_pane">0</property>
+ <property name="dock">Dock</property>
+ <property name="dock_fixed">0</property>
+ <property name="docking">Left</property>
+ <property name="enabled">1</property>
+ <property name="fg"></property>
+ <property name="floatable">1</property>
+ <property name="font"></property>
+ <property name="gripper">0</property>
+ <property name="hidden">0</property>
+ <property name="id">ID_RESET_BUT_LOCK</property>
+ <property name="label">R&eset existing annotation, but do not swap any units</property>
+ <property name="max_size"></property>
+ <property name="maximize_button">0</property>
+ <property name="maximum_size"></property>
+ <property name="min_size"></property>
+ <property name="minimize_button">0</property>
+ <property name="minimum_size"></property>
+ <property name="moveable">1</property>
+ <property name="name">m_rbResetButLock</property>
+ <property name="pane_border">1</property>
+ <property name="pane_position"></property>
+ <property name="pane_size"></property>
+ <property name="permission">protected</property>
+ <property name="pin_button">1</property>
+ <property name="pos"></property>
+ <property name="resize">Resizable</property>
+ <property name="show">1</property>
+ <property name="size"></property>
+ <property name="style"></property>
+ <property name="subclass"></property>
+ <property name="toolbar_pane">0</property>
+ <property name="tooltip"></property>
+ <property name="validator_data_type"></property>
+ <property name="validator_style">wxFILTER_NONE</property>
+ <property name="validator_type">wxDefaultValidator</property>
+ <property name="validator_variable"></property>
+ <property name="value">0</property>
+ <property name="window_extra_style"></property>
+ <property name="window_name"></property>
+ <property name="window_style"></property>
+ <event name="OnChar"></event>
+ <event name="OnEnterWindow"></event>
+ <event name="OnEraseBackground"></event>
+ <event name="OnKeyDown"></event>
+ <event name="OnKeyUp"></event>
+ <event name="OnKillFocus"></event>
+ <event name="OnLeaveWindow"></event>
+ <event name="OnLeftDClick"></event>
+ <event name="OnLeftDown"></event>
+ <event name="OnLeftUp"></event>
+ <event name="OnMiddleDClick"></event>
+ <event name="OnMiddleDown"></event>
+ <event name="OnMiddleUp"></event>
+ <event name="OnMotion"></event>
+ <event name="OnMouseEvents"></event>
+ <event name="OnMouseWheel"></event>
+ <event name="OnPaint"></event>
+ <event name="OnRadioButton"></event>
+ <event name="OnRightDClick"></event>
+ <event name="OnRightDown"></event>
+ <event name="OnRightUp"></event>
+ <event name="OnSetFocus"></event>
+ <event name="OnSize"></event>
+ <event name="OnUpdateUI"></event>
+ </object>
+ </object>
</object>
</object>
<object class="sizeritem" expanded="1">
diff --git a/eeschema/dialogs/dialog_annotate_base.h b/eeschema/dialogs/dialog_annotate_base.h
index a6161ee..3fce47b 100644
--- a/eeschema/dialogs/dialog_annotate_base.h
+++ b/eeschema/dialogs/dialog_annotate_base.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Jun 6 2014)
+// C++ code generated with wxFormBuilder (version Mar 13 2015)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
@@ -37,9 +37,10 @@ class DIALOG_SHIM;
#define ID_CURRENT_PAGE 1001
#define ID_KEEP_ANNOTATION 1002
#define ID_RESET_ANNOTATION 1003
-#define ID_SORT_BY_X_POSITION 1004
-#define ID_SORT_BY_Y_POSITION 1005
-#define ID_CLEAR_ANNOTATION_CMP 1006
+#define ID_RESET_BUT_LOCK 1004
+#define ID_SORT_BY_X_POSITION 1005
+#define ID_SORT_BY_Y_POSITION 1006
+#define ID_CLEAR_ANNOTATION_CMP 1007
///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_ANNOTATE_BASE
@@ -55,6 +56,7 @@ class DIALOG_ANNOTATE_BASE : public DIALOG_SHIM
wxStaticLine* m_staticline1;
wxRadioButton* m_rbKeepAnnotation;
wxRadioButton* m_rbResetAnnotation;
+ wxRadioButton* m_rbResetButLock;
wxStaticLine* m_staticline2;
wxStaticText* m_staticTextOrder;
wxRadioButton* m_rbSortBy_X_Position;
diff --git a/eeschema/sch_reference_list.h b/eeschema/sch_reference_list.h
index 7133d4b..31e8157 100644
--- a/eeschema/sch_reference_list.h
+++ b/eeschema/sch_reference_list.h
@@ -39,6 +39,10 @@
#include <sch_component.h>
#include <sch_text.h>
+#include <map>
+
+class SCH_REFERENCE;
+class SCH_REFERENCE_LIST;
/**
* Class SCH_REFERENCE
@@ -136,6 +140,17 @@ public:
return m_Ref.c_str();
}
+ /**
+ * Function GetRefAndPath
+ * a SCH_REFERENCE_AND_PATH pair is used to identify a complete component
+ * instance, including reference designator and sheet path.
+ */
+ SCH_REFERENCE_AND_PATH GetRefAndPath() const
+ {
+ SCH_REFERENCE_AND_PATH refAndPath( GetRef(), GetSheetPath().Path() );
+ return refAndPath;
+ }
+
int CompareValue( const SCH_REFERENCE& item ) const
{
return Cmp_KEEPCASE( m_Value->GetText(), item.m_Value->GetText() );
@@ -151,6 +166,16 @@ public:
return Cmp_KEEPCASE( m_RootCmp->GetPartName(), item.m_RootCmp->GetPartName() );
}
+ /**
+ * Function IsSameInstance
+ * returns whether this reference refers to the same component instance
+ * (component and sheet) as another.
+ */
+ bool IsSameInstance( const SCH_REFERENCE& other ) const
+ {
+ return GetComp() == other.GetComp() && GetSheetPath().Path() == other.GetSheetPath().Path();
+ }
+
bool IsUnitsLocked()
{
return m_Entry->UnitsLocked();
@@ -272,6 +297,9 @@ public:
* @param aUseSheetNum Set to true to start annotation for each sheet at the sheet number
* times \a aSheetIntervalId. Otherwise annotate incrementally.
* @param aSheetIntervalId The per sheet reference designator multiplier.
+ * @param aLockedUnitMap A SCH_MULTI_UNIT_REFERENCE_MAP of reference designator wxStrings
+ * to SCH_REFERENCE_LISTs. May be an empty map. If not empty, any multi-unit parts
+ * found in this map will be annotated as a group rather than individually.
* <p>
* If a the sheet number is 2 and \a aSheetIntervalId is 100, then the first reference
* designator would be 201 and the last reference designator would be 299 when no overlap
@@ -279,7 +307,7 @@ public:
* referenced U201 to U351, and items in sheet 3 start from U352
* </p>
*/
- void Annotate( bool aUseSheetNum, int aSheetIntervalId );
+ void Annotate( bool aUseSheetNum, int aSheetIntervalId, SCH_MULTI_UNIT_REFERENCE_MAP aLockedUnitMap );
/**
* Function CheckAnnotation
@@ -449,5 +477,4 @@ private:
int CreateFirstFreeRefId( std::vector<int>& aIdList, int aFirstValue );
};
-
#endif // _SCH_REFERENCE_LIST_H_
diff --git a/eeschema/sch_sheet_path.cpp b/eeschema/sch_sheet_path.cpp
index 28900e4..d719ad5 100644
--- a/eeschema/sch_sheet_path.cpp
+++ b/eeschema/sch_sheet_path.cpp
@@ -44,6 +44,8 @@
#include <dialogs/dialog_schematic_find.h>
+#include <boost/foreach.hpp>
+
SCH_SHEET_PATH::SCH_SHEET_PATH()
{
@@ -299,11 +301,12 @@ void SCH_SHEET_PATH::GetComponents( PART_LIBS* aLibs, SCH_REFERENCE_LIST& aRefer
SCH_COMPONENT* component = (SCH_COMPONENT*) item;
// Skip pseudo components, which have a reference starting with #. This mainly
- // effects power symbols.
+ // affects power symbols.
if( !aIncludePowerSymbols && component->GetRef( this )[0] == wxT( '#' ) )
continue;
- if( LIB_PART* part = aLibs->FindLibPart( component->GetPartName() ) )
+ LIB_PART* part = aLibs->FindLibPart( component->GetPartName() );
+ if( part )
{
SCH_REFERENCE reference = SCH_REFERENCE( component, part, *this );
reference.SetSheetNumber( sheetnumber );
@@ -313,6 +316,40 @@ void SCH_SHEET_PATH::GetComponents( PART_LIBS* aLibs, SCH_REFERENCE_LIST& aRefer
}
}
+void SCH_SHEET_PATH::GetMultiUnitComponents( PART_LIBS* aLibs, SCH_MULTI_UNIT_REFERENCE_MAP &aRefList,
+ bool aIncludePowerSymbols )
+{
+ // Find sheet path number
+ int sheetnumber = 1; // 1 = root
+
+ SCH_SHEET_LIST sheetList;
+
+ for( SCH_SHEET_PATH* path = sheetList.GetFirst(); path; path = sheetList.GetNext(), sheetnumber++ )
+ {
+ if( Cmp( *path ) == 0 )
+ break;
+ }
+
+ for( SCH_ITEM* item = LastDrawList(); item; item = item->Next() )
+ {
+ if( item->Type() != SCH_COMPONENT_T ) continue;
+ SCH_COMPONENT* component = (SCH_COMPONENT*) item;
+
+ // Skip pseudo components, which have a reference starting with #. This mainly
+ // affects power symbols.
+ if( !aIncludePowerSymbols && component->GetRef( this )[0] == wxT( '#' ) )
+ continue;
+
+ LIB_PART* part = aLibs->FindLibPart( component->GetPartName() );
+ if( part && part->GetUnitCount() > 1 )
+ {
+ SCH_REFERENCE reference = SCH_REFERENCE( component, part, *this );
+ reference.SetSheetNumber( sheetnumber );
+ aRefList[reference.GetRefAndPath()].AddItem( reference );
+ }
+ }
+}
+
SCH_ITEM* SCH_SHEET_PATH::FindNextItem( KICAD_T aType, SCH_ITEM* aLastItem, bool aWrap ) const
{
@@ -606,6 +643,25 @@ void SCH_SHEET_LIST::GetComponents( PART_LIBS* aLibs, SCH_REFERENCE_LIST& aRefer
path->GetComponents( aLibs, aReferences, aIncludePowerSymbols );
}
+void SCH_SHEET_LIST::GetMultiUnitComponents( PART_LIBS* aLibs,
+ SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, bool aIncludePowerSymbols )
+{
+ for( SCH_SHEET_PATH* path = GetFirst(); path; path = GetNext() )
+ {
+ SCH_MULTI_UNIT_REFERENCE_MAP tempMap;
+ path->GetMultiUnitComponents( aLibs, tempMap );
+ BOOST_FOREACH( SCH_MULTI_UNIT_REFERENCE_MAP::value_type& pair, tempMap )
+ {
+ // Merge this list into the main one
+ unsigned n_refs = pair.second.GetCount();
+ for( unsigned thisRef = 0; thisRef < n_refs; ++thisRef )
+ {
+ aRefList[pair.first].AddItem( pair.second[thisRef] );
+ }
+ }
+ }
+}
+
SCH_ITEM* SCH_SHEET_LIST::FindNextItem( KICAD_T aType, SCH_SHEET_PATH** aSheetFoundIn,
SCH_ITEM* aLastItem, bool aWrap )
diff --git a/eeschema/sch_sheet_path.h b/eeschema/sch_sheet_path.h
index d5bb231..23d6164 100644
--- a/eeschema/sch_sheet_path.h
+++ b/eeschema/sch_sheet_path.h
@@ -85,6 +85,18 @@ class SCH_ITEM;
class SCH_REFERENCE_LIST;
class PART_LIBS;
+/**
+ * Type SCH_REFERENCE_AND_PATH
+ * holds a pair of wxStrings to identify a component instance including
+ * reference designator and sheet path.
+ */
+typedef std::pair<wxString, wxString> SCH_REFERENCE_AND_PATH;
+
+/**
+ * Type SCH_MULTI_UNIT_REFERENCE_MAP
+ * is used to create a map of reference designators for multi-unit parts.
+ */
+typedef std::map<SCH_REFERENCE_AND_PATH, SCH_REFERENCE_LIST> SCH_MULTI_UNIT_REFERENCE_MAP;
/**
* Class SCH_SHEET_PATH
@@ -230,6 +242,18 @@ public:
bool aIncludePowerSymbols = true );
/**
+ * Function GetMultiUnitComponents
+ * adds a SCH_REFERENCE_LIST object to \a aRefList for each same-reference set of
+ * multi-unit parts in the sheet. The map key for each element will be the
+ * reference designator.
+ * @param aLibs the library list to use
+ * @param aRefList Map of reference designators to reference lists
+ * @param aIncludePowerSymbols : false to only get normal components.
+ */
+ void GetMultiUnitComponents( PART_LIBS* aLibs, SCH_MULTI_UNIT_REFERENCE_MAP &aRefList,
+ bool aIncludePowerSymbols = true );
+
+ /**
* Function SetFootprintField
* searches last sheet in the path for a component with \a aReference and set the footprint
* field to \a aFootPrint if found.
@@ -415,6 +439,18 @@ public:
void GetComponents( PART_LIBS* aLibs, SCH_REFERENCE_LIST& aReferences, bool aIncludePowerSymbols = true );
/**
+ * Function GetMultiUnitComponents
+ * adds a SCH_REFERENCE_LIST object to \a aRefList for each same-reference set of
+ * multi-unit parts in the list of sheets. The map key for each element will be the
+ * reference designator.
+ * @param aLibs the library list to use
+ * @param aRefList Map of reference designators to reference lists
+ * @param aIncludePowerSymbols Set to false to only get normal components.
+ */
+ void GetMultiUnitComponents( PART_LIBS* aLibs, SCH_MULTI_UNIT_REFERENCE_MAP &aRefList,
+ bool aIncludePowerSymbols = true );
+
+ /**
* Function FindNextItem
* searches the entire schematic for the next schematic object.
*
diff --git a/eeschema/schframe.h b/eeschema/schframe.h
index c09f0c3..d1702e0 100644
--- a/eeschema/schframe.h
+++ b/eeschema/schframe.h
@@ -30,7 +30,6 @@
#ifndef WX_EESCHEMA_STRUCT_H
#define WX_EESCHEMA_STRUCT_H
-
#include <sch_base_frame.h>
#include <config_params.h>
#include <class_undoredo_container.h>
@@ -522,8 +521,8 @@ public:
/**
* Function DeleteAnnotation
* clears the current component annotation.
- * @param aCurrentSheetOnly Clear the entire schematic annotation if true. Otherwise
- * only clear the annotation for the current sheet.
+ * @param aCurrentSheetOnly Clear only the annotation for the current sheet if true.
+ * Otherwise clear the entire schematic annotation.
*/
void DeleteAnnotation( bool aCurrentSheetOnly );
@@ -542,6 +541,14 @@ public:
* Otherwise, keep the existing time stamps. This option
* could change previous annotation because time stamps are
* used to handle annotation in complex hierarchies.
+ * @param aLockUnits When both aLockUnits and aResetAnnotation are true, all unit
+ * associations should be kept when reannotating. That is, if
+ * two components were R8A and R8B, they may become R3A and R3B,
+ * but not R3A and R3C or R3C and R4D.
+ * When aResetAnnotation is true but aLockUnits is false, the
+ * usual behavior of annotating each part individually is
+ * performed.
+ * When aResetAnnotation is false, this option has no effect.
*
* When the sheet number is used in annotation, each sheet annotation starts from sheet
* number * 100. In other words the first sheet uses 100 to 199, the second sheet uses
@@ -549,7 +556,7 @@ public:
*/
void AnnotateComponents( bool aAnnotateSchematic, ANNOTATE_ORDER_T aSortOption,
ANNOTATE_OPTION_T aAlgoOption, bool aResetAnnotation,
- bool aRepairTimestamps );
+ bool aRepairTimestamps, bool aLockUnits );
/**
* Function CheckAnnotate
Follow ups
References