Do not update schematic connectivity for irrelevant property changes.

Prior to this change, the schematic connectivity was updated any time a
change was made to a connectable object.  Now the connectivity is only
updated when an object change actually affects the connectivity.  Other
properties like line width, fill type, custom fonts, etc. will not cause
the connectivity graph to be rebuilt.

The SCH_COMMIT flag SKIP_CONNECTIVITY has been removed.  All schematic
objects can test if they are connectable and if there have been changes
to any connection properties that require a connectivity rebuild.

Remove duplicate rebuild connectivity calls from editor control tool.
This was causing the tangling end test to get called four times on every
undo and redo action because the dangling end test is already called in
the connectivity graph calculation code.

Update connectivity when changing label names which fixes an unreported
connectivity bug.

(cherry picked from commit c5a02fc266)
This commit is contained in:
Wayne Stambaugh 2024-03-09 08:50:26 -05:00
parent dcd304c5d8
commit e904731e28
32 changed files with 408 additions and 107 deletions

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2019-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -594,7 +594,7 @@ bool DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::TransferDataFromWindow()
if( !commit.Empty() )
{
commit.Push( _( "Edit Text and Graphics" ), SKIP_CONNECTIVITY );
commit.Push( _( "Edit Text and Graphics" ) );
m_parent->HardRedraw();
}

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2018-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -72,7 +72,7 @@ bool DIALOG_IMAGE_PROPERTIES::TransferDataFromWindow()
m_bitmap->SetPosition( VECTOR2I( m_posX.GetValue(), m_posY.GetValue() ) );
if( !commit.Empty() )
commit.Push( _( "Image Properties" ), SKIP_CONNECTIVITY );
commit.Push( _( "Image Properties" ) );
return true;
}

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2020-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@ -110,8 +110,7 @@ bool DIALOG_JUNCTION_PROPS::TransferDataFromWindow()
m_frame->GetCanvas()->GetView()->Update( junction );
}
commit.Push( m_junctions.size() == 1 ? _( "Edit Junction" ) : _( "Edit Junctions" ),
SKIP_CONNECTIVITY );
commit.Push( m_junctions.size() == 1 ? _( "Edit Junction" ) : _( "Edit Junctions" ) );
return true;
}

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2013 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -599,7 +599,7 @@ bool DIALOG_LABEL_PROPERTIES::TransferDataFromWindow()
m_currentLabel->AutoAutoplaceFields( m_Parent->GetScreen() );
if( !commit.Empty() )
commit.Push( _( "Edit Label" ), SKIP_CONNECTIVITY );
commit.Push( _( "Edit Label Properties" ) );
return true;
}

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 Seth Hillbrand <hillbrand@ucdavis.edu>
* Copyright (C) 2014-2023 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2014-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -149,6 +149,6 @@ bool DIALOG_LINE_PROPERTIES::TransferDataFromWindow()
line->SetLineColor( m_colorSwatch->GetSwatchColor() );
}
commit.Push( m_lines.size() == 1 ? _( "Edit Line" ) : _( "Edit Lines" ), SKIP_CONNECTIVITY );
commit.Push( m_lines.size() == 1 ? _( "Edit Line" ) : _( "Edit Lines" ) );
return true;
}

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2021-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -166,8 +166,7 @@ bool DIALOG_SHAPE_PROPERTIES::TransferDataFromWindow()
if( !commit.Empty() )
{
commit.Push( wxString::Format( _( "Edit %s" ), m_shape->EDA_SHAPE::GetFriendlyName() ),
SKIP_CONNECTIVITY );
commit.Push( wxString::Format( _( "Edit %s" ), m_shape->EDA_SHAPE::GetFriendlyName() ) );
}
return true;

View File

@ -536,7 +536,7 @@ bool DIALOG_TEXT_PROPERTIES::TransferDataFromWindow()
}
if( !commit.Empty() )
commit.Push( _( "Edit Text" ), SKIP_CONNECTIVITY );
commit.Push( _( "Edit Text Properties" ) );
return true;
}

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2004 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2004-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2004-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -424,6 +424,25 @@ std::vector<VECTOR2I> SCH_BUS_ENTRY_BASE::GetConnectionPoints() const
}
bool SCH_BUS_ENTRY_BASE::HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance ) const
{
// Do not compare to ourself.
if( aItem == this )
return false;
const SCH_BUS_ENTRY_BASE* busEntry = dynamic_cast<const SCH_BUS_ENTRY_BASE*>( aItem );
// Don't compare against a different SCH_ITEM.
wxCHECK( busEntry, false );
if( GetPosition() != busEntry->GetPosition() )
return true;
return GetEnd() != busEntry->GetEnd();
}
wxString SCH_BUS_WIRE_ENTRY::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
{
return wxString( _( "Bus to Wire Entry" ) );

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 2004-2021 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2004-2024 KiCad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -108,6 +108,9 @@ public:
bool IsConnectable() const override { return true; }
bool HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance = nullptr ) const override;
std::vector<VECTOR2I> GetConnectionPoints() const override;
VECTOR2I GetPosition() const override { return m_pos; }

View File

@ -211,23 +211,28 @@ void SCH_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
if( schItem->IsSelected() )
selectedModified = true;
if( !( aCommitFlags & SKIP_CONNECTIVITY ) && schItem->IsConnectable() )
auto updateConnectivityFlag = [&, this]()
{
dirtyConnectivity = true;
if( schItem->IsConnectable() )
{
dirtyConnectivity = true;
// Do a local clean up if there are any connectable objects in the commit.
if( connectivityCleanUp == NO_CLEANUP )
connectivityCleanUp = LOCAL_CLEANUP;
// Do a local clean up if there are any connectable objects in the commit.
if( connectivityCleanUp == NO_CLEANUP )
connectivityCleanUp = LOCAL_CLEANUP;
// Do a full rebauild of the connectivity if there is a sheet in the commit.
if( schItem->Type() == SCH_SHEET_T )
connectivityCleanUp = GLOBAL_CLEANUP;
}
// Do a full rebauild of the connectivity if there is a sheet in the commit.
if( schItem->Type() == SCH_SHEET_T )
connectivityCleanUp = GLOBAL_CLEANUP;
}
};
switch( changeType )
{
case CHT_ADD:
{
updateConnectivityFlag();
if( !( aCommitFlags & SKIP_UNDO ) )
undoList.PushItem( ITEM_PICKER( screen, schItem, UNDO_REDO::NEWITEM ) );
@ -250,6 +255,8 @@ void SCH_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
case CHT_REMOVE:
{
updateConnectivityFlag();
if( !( aCommitFlags & SKIP_UNDO ) )
undoList.PushItem( ITEM_PICKER( screen, schItem, UNDO_REDO::DELETED ) );
@ -290,6 +297,19 @@ void SCH_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
ITEM_PICKER itemWrapper( screen, schItem, UNDO_REDO::CHANGED );
wxASSERT( ent.m_copy );
itemWrapper.SetLink( ent.m_copy );
const SCH_ITEM* itemCopy = static_cast<const SCH_ITEM*>( ent.m_copy );
wxCHECK2( itemCopy, continue );
SCH_SHEET_PATH currentSheet;
if( frame )
currentSheet = frame->GetCurrentSheet();
if( itemCopy->HasConnectivityChanges( schItem, &currentSheet ) )
updateConnectivityFlag();
undoList.PushItem( itemWrapper );
ent.m_copy = nullptr; // We've transferred ownership to the undo list
}
@ -339,7 +359,12 @@ void SCH_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
frame->SaveCopyInUndoList( undoList, UNDO_REDO::UNSPECIFIED, false, dirtyConnectivity );
if( dirtyConnectivity )
{
wxLogTrace( wxS( "CONN_PROFILE" ),
wxS( "SCH_COMMIT::pushSchEdit() %s clean up connectivity rebuild." ),
( connectivityCleanUp == LOCAL_CLEANUP ) ? wxS( "local" ) : wxS( "global" ) );
frame->RecalculateConnections( this, connectivityCleanUp );
}
}
}

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 CERN
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors.
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
@ -40,7 +40,6 @@ class EE_TOOL_BASE;
#define SKIP_UNDO 0x0001
#define APPEND_UNDO 0x0002
#define SKIP_SET_DIRTY 0x0004
#define SKIP_CONNECTIVITY 0x0008
class SCH_COMMIT : public COMMIT
{

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 2004-2023 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2004-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -454,6 +454,27 @@ public:
void SetConnectivityDirty( bool aDirty = true ) { m_connectivity_dirty = aDirty; }
/**
* Check if \a aItem has connectivity changes against this object.
*
* This provides granular per object connectivity change testing to prevent the need
* to rebuild the #CONNECTION_GRAPH when object properties that have nothing to do with
* the schematic connectivity changes i.e. color, thickness, fill type. etc.
*
* @note Developers should override this method for all objects that are connectable.
*
* @param aItem is the item to test for connectivity changes.
* @param aInstance is the instance to test for connectivity changes. This parameter is
* only meaningful for #SCH_SYMBOL objects.
*
* @return true if there are connectivity changes otherwise false.
*/
virtual bool HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance = nullptr ) const
{
return false;
}
/// Updates the connection graph for all connections in this item
void SetConnectionGraph( CONNECTION_GRAPH* aGraph );

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2009 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -231,6 +231,22 @@ bool SCH_JUNCTION::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy )
}
bool SCH_JUNCTION::HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance ) const
{
// Do not compare to ourself.
if( aItem == this )
return false;
const SCH_JUNCTION* junction = dynamic_cast<const SCH_JUNCTION*>( aItem );
// Don't compare against a different SCH_ITEM.
wxCHECK( junction, false );
return GetPosition() != junction->GetPosition();
}
bool SCH_JUNCTION::doIsConnected( const VECTOR2I& aPosition ) const
{
return m_pos == aPosition;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -84,6 +84,9 @@ public:
bool IsConnectable() const override { return true; }
bool HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance = nullptr ) const override;
std::vector<VECTOR2I> GetConnectionPoints() const override;
bool CanConnect( const SCH_ITEM* aItem ) const override

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2015 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -407,6 +407,7 @@ VECTOR2I SCH_LABEL_BASE::GetSchematicTextOffset( const RENDER_SETTINGS* aSetting
return text_offset;
}
void SCH_LABEL_BASE::SetPosition( const VECTOR2I& aPosition )
{
VECTOR2I offset = aPosition - GetTextPos();
@ -1207,6 +1208,25 @@ bool SCH_LABEL_BASE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemL
}
bool SCH_LABEL_BASE::HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance ) const
{
// Do not compare to ourself.
if( aItem == this || !IsConnectable() )
return false;
const SCH_LABEL_BASE* label = dynamic_cast<const SCH_LABEL_BASE*>( aItem );
// Don't compare against a different SCH_ITEM.
wxCHECK( label, false );
if( GetPosition() != label->GetPosition() )
return true;
return GetShownText( aInstance ) != label->GetShownText( aInstance );
}
void SCH_LABEL_BASE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
{
wxString msg;
@ -1336,7 +1356,8 @@ void SCH_LABEL_BASE::Plot( PLOTTER* aPlotter, bool aBackground,
properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), _( "Net" ),
connection->Name() ) );
properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), _( "Resolved netclass" ),
properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
_( "Resolved netclass" ),
GetEffectiveNetClass()->GetName() ) );
}
@ -1405,16 +1426,19 @@ void SCH_LABEL_BASE::Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aO
field.Print( aSettings, aOffset );
}
bool SCH_LABEL_BASE::AutoRotateOnPlacement() const
{
return m_autoRotateOnPlacement;
}
void SCH_LABEL_BASE::SetAutoRotateOnPlacement( bool autoRotate )
{
m_autoRotateOnPlacement = autoRotate;
}
SCH_LABEL::SCH_LABEL( const VECTOR2I& pos, const wxString& text ) :
SCH_LABEL_BASE( pos, text, SCH_LABEL_T )
{
@ -1615,6 +1639,7 @@ void SCH_DIRECTIVE_LABEL::CreateGraphicShape( const RENDER_SETTINGS* aRenderSett
aPoints.emplace_back( VECTOR2I( 0, 0 ) );
aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) );
aPoints.emplace_back( VECTOR2I( 0, m_pinLength ) );
// These points are just used to bulk out the bounding box
aPoints.emplace_back( VECTOR2I( -m_symbolSize, m_pinLength ) );
aPoints.emplace_back( VECTOR2I( 0, m_pinLength ) );
@ -2187,8 +2212,10 @@ static struct SCH_DIRECTIVE_LABEL_DESC
propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Thickness" ) );
propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Italic" ) );
propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Bold" ) );
propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Horizontal Justification" ) );
propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Vertical Justification" ) );
propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ),
_HKI( "Horizontal Justification" ) );
propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ),
_HKI( "Vertical Justification" ) );
}
} _SCH_DIRECTIVE_LABEL_DESC;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -164,6 +164,9 @@ public:
}
}
bool HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance = nullptr ) const override;
LABEL_FLAG_SHAPE GetShape() const { return m_shape; }
void SetShape( LABEL_FLAG_SHAPE aShape ) { m_shape = aShape; }
@ -472,7 +475,8 @@ private:
class SCH_GLOBALLABEL : public SCH_LABEL_BASE
{
public:
SCH_GLOBALLABEL( const VECTOR2I& aPos = VECTOR2I( 0, 0 ), const wxString& aText = wxEmptyString );
SCH_GLOBALLABEL( const VECTOR2I& aPos = VECTOR2I( 0, 0 ),
const wxString& aText = wxEmptyString );
SCH_GLOBALLABEL( const SCH_GLOBALLABEL& aGlobalLabel );

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -117,7 +117,8 @@ wxString SCH_LINE::FindWireSegmentNetNameRecursive( SCH_LINE *line,
{
if( connected->Type() == SCH_LINE_T )
{
if( std::find(checkedLines.begin(), checkedLines.end(), connected ) == checkedLines.end() )
if( std::find(checkedLines.begin(), checkedLines.end(),
connected ) == checkedLines.end() )
{
SCH_LINE* connectedLine = static_cast<SCH_LINE*>( connected );
checkedLines.push_back( connectedLine );
@ -715,6 +716,25 @@ bool SCH_LINE::CanConnect( const SCH_ITEM* aItem ) const
}
bool SCH_LINE::HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance ) const
{
// Do not compare to ourself.
if( aItem == this || !IsConnectable() )
return false;
const SCH_LINE* line = dynamic_cast<const SCH_LINE*>( aItem );
// Don't compare against a different SCH_ITEM.
wxCHECK( line, false );
if( GetStartPoint() != line->GetStartPoint() )
return true;
return GetEndPoint() != line->GetEndPoint();
}
std::vector<VECTOR2I> SCH_LINE::GetConnectionPoints() const
{
return { m_start, m_end };

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -264,6 +264,9 @@ public:
bool IsConnectable() const override;
bool HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance = nullptr ) const override;
std::vector<VECTOR2I> GetConnectionPoints() const override;
bool ConnectionPropagatesTo( const EDA_ITEM* aItem ) const override;

View File

@ -134,6 +134,22 @@ void SCH_NO_CONNECT::Rotate( const VECTOR2I& aCenter )
}
bool SCH_NO_CONNECT::HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance ) const
{
// Do not compare to ourself.
if( aItem == this )
return false;
const SCH_NO_CONNECT* noConnect = dynamic_cast<const SCH_NO_CONNECT*>( aItem );
// Don't compare against a different SCH_ITEM.
wxCHECK( noConnect, false );
return GetPosition() != noConnect->GetPosition();
}
std::vector<VECTOR2I> SCH_NO_CONNECT::GetConnectionPoints() const
{
return { m_pos };
@ -226,4 +242,4 @@ double SCH_NO_CONNECT::Similarity( const SCH_ITEM& aOther ) const
return 0.0;
return 1.0;
}
}

View File

@ -84,6 +84,9 @@ public:
bool IsConnectable() const override { return true; }
bool HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance = nullptr ) const override;
bool CanConnect( const SCH_ITEM* aItem ) const override
{
return ( aItem->Type() == SCH_LINE_T && aItem->GetLayer() == LAYER_WIRE ) ||

View File

@ -465,6 +465,25 @@ EDA_ITEM* SCH_PIN::Clone() const
}
bool SCH_PIN::HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance ) const
{
// Do not compare to ourself.
if( aItem == this )
return false;
const SCH_PIN* pin = dynamic_cast<const SCH_PIN*>( aItem );
// Don't compare against a different SCH_ITEM.
wxCHECK( pin, false );
if( GetPosition() != pin->GetPosition() )
return true;
return GetNumber() != pin->GetNumber();
}
bool SCH_PIN::ConnectionPropagatesTo( const EDA_ITEM* aItem ) const
{
wxCHECK( m_libPin, false );

View File

@ -100,6 +100,9 @@ public:
bool IsConnectable() const override { return true; }
bool HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance = nullptr ) const override;
bool IsDangling() const override
{
if( GetType() == ELECTRICAL_PINTYPE::PT_NC || GetType() == ELECTRICAL_PINTYPE::PT_NIC )
@ -168,6 +171,8 @@ public:
bool operator==( const SCH_ITEM& aItem ) const override;
bool operator!=( const SCH_PIN& aRhs ) const { return !( *this == aRhs ); }
#if defined(DEBUG)
void Show( int nestLevel, std::ostream& os ) const override {}
#endif

View File

@ -1013,6 +1013,40 @@ bool SCH_SHEET::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListBy
}
bool SCH_SHEET::HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance ) const
{
// Do not compare to ourself.
if( aItem == this )
return false;
const SCH_SHEET* sheet = dynamic_cast<const SCH_SHEET*>( aItem );
// Don't compare against a different SCH_ITEM.
wxCHECK( sheet, false );
if( GetPosition() != sheet->GetPosition() )
return true;
// Technically this cannot happen because undo/redo does not support reloading sheet
// file association changes. This was just added so that it doesn't get missed should
// we ever fix the undo/redo issue.
if( ( GetFileName() != sheet->GetFileName() ) || ( GetName() != sheet->GetName() ) )
return true;
if( m_pins.size() != sheet->m_pins.size() )
return true;
for( size_t i = 0; i < m_pins.size(); i++ )
{
if( m_pins[i]->HasConnectivityChanges( sheet->m_pins[i] ) )
return true;
}
return false;
}
std::vector<VECTOR2I> SCH_SHEET::GetConnectionPoints() const
{
std::vector<VECTOR2I> retval;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -58,7 +58,7 @@ class SCH_SHEET : public SCH_ITEM
public:
SCH_SHEET( EDA_ITEM* aParent = nullptr, const VECTOR2I& aPos = VECTOR2I( 0, 0 ),
VECTOR2I aSize = VECTOR2I( schIUScale.MilsToIU( MIN_SHEET_WIDTH ),
schIUScale.MilsToIU( MIN_SHEET_HEIGHT ) ),
schIUScale.MilsToIU( MIN_SHEET_HEIGHT ) ),
FIELDS_AUTOPLACED aAutoplaceFields = FIELDS_AUTOPLACED_AUTO );
/**
@ -347,6 +347,9 @@ public:
bool IsConnectable() const override { return true; }
bool HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance = nullptr ) const override;
bool CanConnect( const SCH_ITEM* aItem ) const override
{
return ( aItem->Type() == SCH_LINE_T && aItem->GetLayer() == LAYER_WIRE )

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2006 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -389,6 +389,25 @@ double SCH_SHEET_PIN::Similarity( const SCH_ITEM& aOther ) const
}
bool SCH_SHEET_PIN::HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance ) const
{
// Do not compare to ourself.
if( aItem == this )
return false;
const SCH_SHEET_PIN* pin = dynamic_cast<const SCH_SHEET_PIN*>( aItem );
// Don't compare against a different SCH_ITEM.
wxCHECK( pin, false );
if( GetPosition() != pin->GetPosition() )
return true;
return GetText() != pin->GetText();
}
#if defined(DEBUG)
void SCH_SHEET_PIN::Show( int nestLevel, std::ostream& os ) const

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -83,6 +83,7 @@ public:
}
bool operator ==( const SCH_SHEET_PIN* aPin ) const;
bool operator!=( const SCH_SHEET_PIN* aRhs ) const { return !( this == aRhs ); }
static SHEET_SIDE GetOppositeSide( SHEET_SIDE aSide )
{
@ -182,6 +183,9 @@ public:
bool IsConnectable() const override { return true; }
bool HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance = nullptr ) const override;
wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const override;
BITMAPS GetMenuImage() const override;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -2160,6 +2160,48 @@ VECTOR2I SCH_SYMBOL::GetPinPhysicalPosition( const LIB_PIN* Pin ) const
}
bool SCH_SYMBOL::HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance ) const
{
// Do not compare to ourself.
if( aItem == this )
return false;
const SCH_SYMBOL* symbol = dynamic_cast<const SCH_SYMBOL*>( aItem );
// Don't compare against a different SCH_ITEM.
wxCHECK( symbol, false );
if( GetPosition() != symbol->GetPosition() )
return true;
if( GetLibId() != symbol->GetLibId() )
return true;
if( GetUnitSelection( aInstance ) != symbol->GetUnitSelection( aInstance ) )
return true;
if( GetRef( aInstance ) != symbol->GetRef( aInstance ) )
return true;
// Power symbol value field changes are connectivity changes.
if( IsPower()
&& ( GetValueFieldText( true, aInstance, false ) != symbol->GetValueFieldText( true, aInstance, false ) ) )
return true;
if( m_pins.size() != symbol->m_pins.size() )
return true;
for( size_t i = 0; i < m_pins.size(); i++ )
{
if( m_pins[i]->HasConnectivityChanges( symbol->m_pins[i].get() ) )
return true;
}
return false;
}
std::vector<VECTOR2I> SCH_SYMBOL::GetConnectionPoints() const
{
std::vector<VECTOR2I> retval;

View File

@ -5,7 +5,7 @@
* Copyright (C) 2014 Dick Hollenbeck, dick@softplc.com
* Copyright (C) 2015 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 2022 CERN
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -766,6 +766,9 @@ public:
bool IsConnectable() const override { return true; }
bool HasConnectivityChanges( const SCH_ITEM* aItem,
const SCH_SHEET_PATH* aInstance = nullptr ) const override;
bool CanConnect( const SCH_ITEM* aItem ) const override
{
return ( aItem->Type() == SCH_LINE_T && aItem->GetLayer() == LAYER_WIRE ) ||

View File

@ -289,43 +289,48 @@ void SCH_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( eda_item );
// Set connectable object connectivity status.
if( schItem && schItem->IsConnectable() )
auto updateConnectivityFlag = [&, this]()
{
schItem->SetConnectivityDirty();
if( schItem->Type() == SCH_SYMBOL_T )
if( schItem && schItem->IsConnectable() )
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( schItem );
schItem->SetConnectivityDirty();
wxCHECK2( symbol, continue );
if( schItem->Type() == SCH_SYMBOL_T )
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( schItem );
for( SCH_PIN* pin : symbol->GetPins() )
pin->SetConnectivityDirty();
wxCHECK( symbol, /* void */ );
for( SCH_PIN* pin : symbol->GetPins() )
pin->SetConnectivityDirty();
}
else if( schItem->Type() == SCH_SHEET_T )
{
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( schItem );
wxCHECK( sheet, /* void */ );
for( SCH_SHEET_PIN* pin : sheet->GetPins() )
pin->SetConnectivityDirty();
}
m_highlightedConnChanged = true;
dirtyConnectivity = true;
// Do a local clean up if there are any connectable objects in the commit.
if( connectivityCleanUp == NO_CLEANUP )
connectivityCleanUp = LOCAL_CLEANUP;
// Do a full rebauild of the connectivity if there is a sheet in the commit.
if( schItem->Type() == SCH_SHEET_T )
connectivityCleanUp = GLOBAL_CLEANUP;
}
else if( schItem->Type() == SCH_SHEET_T )
{
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( schItem );
wxCHECK2( sheet, continue );
for( SCH_SHEET_PIN* pin : sheet->GetPins() )
pin->SetConnectivityDirty();
}
m_highlightedConnChanged = true;
dirtyConnectivity = true;
// Do a local clean up if there are any connectable objects in the commit.
if( connectivityCleanUp == NO_CLEANUP )
connectivityCleanUp = LOCAL_CLEANUP;
// Do a full rebauild of the connectivity if there is a sheet in the commit.
if( schItem->Type() == SCH_SHEET_T )
connectivityCleanUp = GLOBAL_CLEANUP;
}
};
if( status == UNDO_REDO::NEWITEM )
{
updateConnectivityFlag();
// If we are removing the current sheet, get out first
if( eda_item->Type() == SCH_SHEET_T )
{
@ -340,6 +345,8 @@ void SCH_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
}
else if( status == UNDO_REDO::DELETED )
{
updateConnectivityFlag();
// deleted items are re-inserted on undo
AddToScreen( eda_item, screen );
aList->SetPickedItemStatus( UNDO_REDO::NEWITEM, ii );
@ -362,28 +369,32 @@ void SCH_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
item->Restore( this );
*item = std::move( alt_item );
}
else if( SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( eda_item ) )
else if( schItem )
{
// everything else is modified in place
SCH_ITEM* alt_item = static_cast<SCH_ITEM*>( aList->GetPickedItemLink( ii ) );
SCH_ITEM* itemCopy = dynamic_cast<SCH_ITEM*>( aList->GetPickedItemLink( ii ) );
wxCHECK2( itemCopy, continue );
if( schItem->HasConnectivityChanges( itemCopy, &GetCurrentSheet() ) )
updateConnectivityFlag();
// The root sheet is a pseudo object that owns the root screen object but is not on
// the root screen so do not attempt to remove it from the screen it owns.
if( item != &Schematic().Root() )
RemoveFromScreen( item, screen );
if( schItem != &Schematic().Root() )
RemoveFromScreen( schItem, screen );
switch( status )
{
case UNDO_REDO::CHANGED:
item->SwapData( alt_item );
bulkChangedItems.emplace_back( item );
schItem->SwapData( itemCopy );
bulkChangedItems.emplace_back( schItem );
// Special cases for items which have instance data
if( item->GetParent() && item->GetParent()->Type() == SCH_SYMBOL_T
&& item->Type() == SCH_FIELD_T )
if( schItem->GetParent() && schItem->GetParent()->Type() == SCH_SYMBOL_T
&& schItem->Type() == SCH_FIELD_T )
{
SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item->GetParent() );
SCH_FIELD* field = static_cast<SCH_FIELD*>( schItem );
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( schItem->GetParent() );
if( field->GetId() == REFERENCE_FIELD )
{
@ -402,14 +413,14 @@ void SCH_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
break;
}
if( item->Type() == SCH_SYMBOL_T )
if( schItem->Type() == SCH_SYMBOL_T )
{
SCH_SYMBOL* sym = static_cast<SCH_SYMBOL*>( item );
SCH_SYMBOL* sym = static_cast<SCH_SYMBOL*>( schItem );
sym->UpdatePins();
}
if( item != &Schematic().Root() )
AddToScreen( item, screen );
if( schItem != &Schematic().Root() )
AddToScreen( schItem, screen );
}
}
@ -427,6 +438,10 @@ void SCH_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
if( dirtyConnectivity )
{
wxLogTrace( wxS( "CONN_PROFILE" ),
wxS( "Undo/redo %s clean up connectivity rebuild." ),
( connectivityCleanUp == LOCAL_CLEANUP ) ? wxS( "local" ) : wxS( "global" ) );
SCH_COMMIT localCommit( m_toolManager );
RecalculateConnections( &localCommit, connectivityCleanUp );

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019-2023 CERN
* Copyright (C) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2019-2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View File

@ -1547,7 +1547,7 @@ void SCH_EDIT_TOOL::editFieldText( SCH_FIELD* aField )
static_cast<SCH_ITEM*>( aField->GetParent() )->AutoAutoplaceFields( m_frame->GetScreen() );
if( !commit.Empty() )
commit.Push( caption, SKIP_CONNECTIVITY );
commit.Push( caption );
}

View File

@ -1257,14 +1257,14 @@ int SCH_EDITOR_CONTROL::Undo( const TOOL_EVENT& aEvent )
m_frame->PutDataInPreviousState( undo_list );
// Only rebuild the hierarchy navigator if there are sheet changes.
if( undo_list->ContainsItemType( SCH_SHEET_T ) )
{
m_frame->SetSheetNumberAndCount();
m_frame->UpdateHierarchyNavigator();
}
// if( undo_list->ContainsItemType( SCH_SHEET_T ) )
// {
// m_frame->SetSheetNumberAndCount();
// m_frame->UpdateHierarchyNavigator();
// }
m_frame->RecalculateConnections( nullptr, NO_CLEANUP );
m_frame->TestDanglingEnds();
// m_frame->RecalculateConnections( nullptr, NO_CLEANUP );
// m_frame->TestDanglingEnds();
// Now push the old command to the RedoList
undo_list->ReversePickersListOrder();
@ -1302,14 +1302,14 @@ int SCH_EDITOR_CONTROL::Redo( const TOOL_EVENT& aEvent )
m_frame->PushCommandToUndoList( list );
// Only rebuild the hierarchy navigator if there are sheet changes.
if( list->ContainsItemType( SCH_SHEET_T ) )
{
m_frame->SetSheetNumberAndCount();
m_frame->UpdateHierarchyNavigator();
}
// if( list->ContainsItemType( SCH_SHEET_T ) )
// {
// m_frame->SetSheetNumberAndCount();
// m_frame->UpdateHierarchyNavigator();
// }
m_frame->RecalculateConnections( nullptr, NO_CLEANUP );
m_frame->TestDanglingEnds();
// m_frame->RecalculateConnections( nullptr, NO_CLEANUP );
// m_frame->TestDanglingEnds();
m_toolMgr->GetTool<EE_SELECTION_TOOL>()->RebuildSelection();