More performant (and more correct) deletion of DRC markers.

Fixes https://gitlab.com/kicad/code/kicad/issues/5057
This commit is contained in:
Jeff Young 2020-08-04 01:41:56 +01:00
parent 5982626a80
commit 9c9fdb2569
10 changed files with 116 additions and 31 deletions

View File

@ -387,17 +387,16 @@ void RC_TREE_MODEL::ValueChanged( RC_TREE_NODE* aNode )
void RC_TREE_MODEL::DeleteCurrentItem( bool aDeep ) void RC_TREE_MODEL::DeleteCurrentItem( bool aDeep )
{ {
DeleteItems( true, false, false, aDeep ); DeleteItems( true, false, aDeep );
} }
void RC_TREE_MODEL::DeleteItems( bool aCurrent, bool aWarningsAndErrors, bool aExclusions, void RC_TREE_MODEL::DeleteItems( bool aCurrentOnly, bool aIncludeExclusions, bool aDeep )
bool aDeep )
{ {
RC_TREE_NODE* current_node = ToNode( m_view->GetCurrentItem() ); RC_TREE_NODE* current_node = ToNode( m_view->GetCurrentItem() );
const RC_ITEM* current_item = current_node ? current_node->m_RcItem : nullptr; const RC_ITEM* current_item = current_node ? current_node->m_RcItem : nullptr;
if( !current_item && !aWarningsAndErrors && !aExclusions ) if( aCurrentOnly && !current_item )
{ {
wxBell(); wxBell();
return; return;
@ -407,33 +406,42 @@ void RC_TREE_MODEL::DeleteItems( bool aCurrent, bool aWarningsAndErrors, bool aE
{ {
RC_ITEM* rcItem = m_rcItemsProvider->GetItem( i ); RC_ITEM* rcItem = m_rcItemsProvider->GetItem( i );
MARKER_BASE* marker = rcItem->GetParent(); MARKER_BASE* marker = rcItem->GetParent();
bool excluded = marker ? marker->IsExcluded() : false;
if( ( aCurrent && rcItem == current_item ) if( aCurrentOnly && rcItem != current_item )
|| ( aWarningsAndErrors && marker && !marker->IsExcluded() ) continue;
|| ( aExclusions && marker && marker->IsExcluded() ) )
if( excluded && !aIncludeExclusions )
continue;
wxDataViewItem markerItem = ToItem( m_tree[i] );
wxDataViewItemArray childItems;
wxDataViewItem parentItem = ToItem( m_tree[i]->m_Parent );
for( RC_TREE_NODE* child : m_tree[i]->m_Children )
{ {
wxDataViewItem markerItem = ToItem( m_tree[i] ); childItems.push_back( ToItem( child ) );
wxDataViewItemArray childItems; delete child;
wxDataViewItem parentItem = ToItem( m_tree[i]->m_Parent );
for( RC_TREE_NODE* child : m_tree[i]->m_Children )
{
childItems.push_back( ToItem( child ) );
delete child;
}
m_tree[i]->m_Children.clear();
ItemsDeleted( markerItem, childItems );
delete m_tree[i];
m_tree.erase( m_tree.begin() + i );
ItemDeleted( parentItem, markerItem );
m_rcItemsProvider->DeleteItem( i, aDeep );
if( !aWarningsAndErrors && !aExclusions )
break;
} }
m_tree[i]->m_Children.clear();
ItemsDeleted( markerItem, childItems );
delete m_tree[i];
m_tree.erase( m_tree.begin() + i );
ItemDeleted( parentItem, markerItem );
// Only deep delete the current item here; others will be done through the
// DeleteAllItems() call below, which is more efficient.
m_rcItemsProvider->DeleteItem( i, aDeep && aCurrentOnly );
if( aCurrentOnly )
break;
}
if( !aCurrentOnly )
{
m_rcItemsProvider->DeleteAllItems( aIncludeExclusions, aDeep );
} }
} }

View File

@ -59,6 +59,8 @@ public:
*/ */
virtual void DeleteItem( int aIndex, bool aDeep ) = 0; virtual void DeleteItem( int aIndex, bool aDeep ) = 0;
virtual void DeleteAllItems( bool aIncludeExclusions, bool aDeep ) = 0;
virtual ~RC_ITEMS_PROVIDER() { } virtual ~RC_ITEMS_PROVIDER() { }
}; };
@ -272,7 +274,12 @@ public:
void ValueChanged( RC_TREE_NODE* aNode ); void ValueChanged( RC_TREE_NODE* aNode );
void DeleteCurrentItem( bool aDeep ); void DeleteCurrentItem( bool aDeep );
void DeleteItems( bool aCurrent, bool aWarningsAndErrors, bool aExclusions, bool aDeep );
/**
* Deletes the current item or all items. If all, \a aIncludeExclusions determines
* whether or not exclusions are also deleted.
*/
void DeleteItems( bool aCurrentOnly, bool aIncludeExclusions, bool aDeep );
private: private:
void rebuildModel( RC_ITEMS_PROVIDER* aProvider, int aSeverities ); void rebuildModel( RC_ITEMS_PROVIDER* aProvider, int aSeverities );

View File

@ -582,7 +582,7 @@ void DIALOG_ERC::deleteAllMarkers( bool aIncludeExclusions )
// Clear current selection list to avoid selection of deleted items // Clear current selection list to avoid selection of deleted items
m_parent->GetToolManager()->RunAction( EE_ACTIONS::clearSelection, true ); m_parent->GetToolManager()->RunAction( EE_ACTIONS::clearSelection, true );
m_markerTreeModel->DeleteItems( false, true, aIncludeExclusions, true ); m_markerTreeModel->DeleteItems( false, true, aIncludeExclusions );
} }

View File

@ -315,3 +315,15 @@ void SHEETLIST_ERC_ITEMS_PROVIDER::DeleteItem( int aIndex, bool aDeep )
screens.DeleteMarker( marker ); screens.DeleteMarker( marker );
} }
} }
void SHEETLIST_ERC_ITEMS_PROVIDER::DeleteAllItems( bool aIncludeExclusions, bool aDeep )
{
// Filtered list was already handled through DeleteItem() by the tree control
if( aDeep )
{
SCH_SCREENS screens( m_schematic->Root() );
screens.DeleteAllMarkers( MARKER_BASE::MARKER_ERC, aIncludeExclusions );
}
}

View File

@ -190,6 +190,8 @@ public:
ERC_ITEM* GetItem( int aIndex ) override; ERC_ITEM* GetItem( int aIndex ) override;
void DeleteItem( int aIndex, bool aDeep ) override; void DeleteItem( int aIndex, bool aDeep ) override;
void DeleteAllItems( bool aIncludeExclusions, bool aDeep ) override;
}; };

View File

@ -715,6 +715,28 @@ void BOARD::DeleteMARKERs()
} }
void BOARD::DeleteMARKERs( bool aWarningsAndErrors, bool aExclusions )
{
// Deleting lots of items from a vector can be very slow. Copy remaining items instead.
MARKERS remaining;
for( MARKER_PCB* marker : m_markers )
{
if( ( marker->IsExcluded() && aExclusions )
|| ( !marker->IsExcluded() && aWarningsAndErrors ) )
{
delete marker;
}
else
{
remaining.push_back( marker );
}
}
m_markers = remaining;
}
void BOARD::DeleteZONEOutlines() void BOARD::DeleteZONEOutlines()
{ {
// the vector does not know how to delete the ZONE Outlines, it holds pointers // the vector does not know how to delete the ZONE Outlines, it holds pointers

View File

@ -367,6 +367,8 @@ public:
*/ */
void DeleteMARKERs(); void DeleteMARKERs();
void DeleteMARKERs( bool aWarningsAndErrors, bool aExclusions );
/** /**
* Function DeleteZONEOutlines * Function DeleteZONEOutlines
* deletes ALL zone outlines from the board. * deletes ALL zone outlines from the board.

View File

@ -106,6 +106,17 @@ public:
m_sourceVector->erase( m_sourceVector->begin() + aIndex ); m_sourceVector->erase( m_sourceVector->begin() + aIndex );
} }
} }
void DeleteAllItems( bool aIncludeExclusions, bool aDeep ) override
{
if( aDeep )
{
for( CLEANUP_ITEM* item : *m_sourceVector )
delete item;
m_sourceVector->clear();
}
}
}; };

View File

@ -513,7 +513,7 @@ void DIALOG_DRC::deleteAllMarkers( bool aIncludeExclusions )
// Clear current selection list to avoid selection of deleted items // Clear current selection list to avoid selection of deleted items
m_brdEditor->GetToolManager()->RunAction( PCB_ACTIONS::selectionClear, true ); m_brdEditor->GetToolManager()->RunAction( PCB_ACTIONS::selectionClear, true );
m_markerTreeModel->DeleteItems( false, true, aIncludeExclusions, true ); m_markerTreeModel->DeleteItems( false, true, aIncludeExclusions );
} }

View File

@ -159,6 +159,14 @@ public:
if( aDeep ) if( aDeep )
m_board->Delete( marker ); m_board->Delete( marker );
} }
void DeleteAllItems( bool aIncludeExclusions, bool aDeep ) override
{
// Filtered list was already handled through DeleteItem() by the tree control
if( aDeep )
m_board->DeleteMARKERs( true, aIncludeExclusions );
}
}; };
@ -246,6 +254,19 @@ public:
} }
} }
} }
void DeleteAllItems( bool aIncludeExclusions, bool aDeep ) override
{
if( aDeep )
{
for( DRC_ITEM* item : *m_sourceVector )
delete item;
m_sourceVector->clear();
}
m_filteredVector.clear(); // no ownership of DRC_ITEM pointers
}
}; };