Don't use std::set_difference which assumes sorted lists.

Fixes https://gitlab.com/kicad/code/kicad/issues/4968
This commit is contained in:
Jeff Young 2020-08-01 22:15:30 +01:00
parent 07085345e9
commit dae40d5c9f

View File

@ -356,45 +356,48 @@ PCBNEW_SELECTION& SELECTION_TOOL::RequestSelection( CLIENT_SELECTION_FILTER aCli
if( aClientFilter ) if( aClientFilter )
{ {
GENERAL_COLLECTOR collector; enum DISPOSITION { BEFORE = 1, AFTER, BOTH };
for( auto item : m_selection ) std::map<EDA_ITEM*, DISPOSITION> itemDispositions;
GENERAL_COLLECTOR collector;
for( EDA_ITEM* item : m_selection )
{
collector.Append( item ); collector.Append( item );
itemDispositions[ item ] = BEFORE;
}
aClientFilter( VECTOR2I(), collector ); aClientFilter( VECTOR2I(), collector );
/* for( EDA_ITEM* item : collector )
* The first step is to find the items that may have been added by the client filter
* This can happen if the locked pads select the module instead
*/
std::vector<EDA_ITEM*> new_items;
std::set_difference( collector.begin(), collector.end(),
m_selection.begin(), m_selection.end(),
std::back_inserter( new_items ) );
/**
* The second step is to find the items that were removed by the client filter
*/
std::vector<EDA_ITEM*> diff;
std::set_difference( m_selection.begin(), m_selection.end(),
collector.begin(), collector.end(),
std::back_inserter( diff ) );
if( aFiltered )
{ {
for( auto item : diff ) if( itemDispositions.count( item ) )
aFiltered->push_back( static_cast<BOARD_ITEM*>( item ) ); itemDispositions[ item ] = BOTH;
else
itemDispositions[ item ] = AFTER;
} }
/** for( std::pair<EDA_ITEM* const, DISPOSITION> itemDisposition : itemDispositions )
* Once we find the adjustments to m_selection that are required by the client filter, we {
* apply them both BOARD_ITEM* item = static_cast<BOARD_ITEM*>( itemDisposition.first );
*/ DISPOSITION disposition = itemDisposition.second;
for( auto item : diff )
unhighlight( static_cast<BOARD_ITEM*>( item ), SELECTED, &m_selection );
for( auto item : new_items ) if( disposition == BEFORE )
highlight( static_cast<BOARD_ITEM*>( item ), SELECTED, &m_selection ); {
if( aFiltered )
aFiltered->push_back( item );
unhighlight( item, SELECTED, &m_selection );
}
else if( disposition == AFTER )
{
highlight( item, SELECTED, &m_selection );
}
else if( disposition == BOTH )
{
// nothing to do
}
}
m_frame->GetCanvas()->ForceRefresh(); m_frame->GetCanvas()->ForceRefresh();
} }