From d9ff3c448510f29ac1c2e905e029669e16fbe7a6 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sat, 11 May 2024 16:20:09 +0100 Subject: [PATCH] Maintain selection when sorting. Fixes https://gitlab.com/kicad/code/kicad/-/issues/17983 --- common/widgets/search_pane_tab.cpp | 21 ++++++++++++++++++--- eeschema/widgets/search_handlers.cpp | 18 +++++++++++++++++- eeschema/widgets/search_handlers.h | 2 +- include/widgets/search_pane.h | 2 +- include/widgets/search_pane_tab.h | 2 +- pcbnew/widgets/search_handlers.cpp | 26 +++++++++++++++++++++++--- pcbnew/widgets/search_handlers.h | 2 +- 7 files changed, 62 insertions(+), 11 deletions(-) diff --git a/common/widgets/search_pane_tab.cpp b/common/widgets/search_pane_tab.cpp index 57481e63f6..0c08a88224 100644 --- a/common/widgets/search_pane_tab.cpp +++ b/common/widgets/search_pane_tab.cpp @@ -23,6 +23,7 @@ #include #include #include +#include SEARCH_PANE_LISTVIEW::SEARCH_PANE_LISTVIEW( SEARCH_HANDLER* handler, wxWindow* parent, wxWindowID winid, const wxPoint& pos, @@ -134,7 +135,16 @@ void SEARCH_PANE_LISTVIEW::OnColClicked( wxListEvent& aEvent ) ShowSortIndicator( m_sortCol, m_sortAscending ); - Sort(); + std::vector selection = Sort(); + + for( long row = 0; row < GetItemCount(); row++ ) + { + if( alg::contains( selection, row ) ) + SetItemState( row, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED ); + else + SetItemState( row, 0, wxLIST_STATE_SELECTED ); + } + Refresh(); } @@ -177,9 +187,14 @@ void SEARCH_PANE_LISTVIEW::OnChar( wxKeyEvent& aEvent ) } -void SEARCH_PANE_LISTVIEW::Sort() +std::vector SEARCH_PANE_LISTVIEW::Sort() { - m_handler->Sort( m_sortCol, m_sortAscending ); + std::vector selection; + GetSelectRowsList( selection ); + + m_handler->Sort( m_sortCol, m_sortAscending, &selection ); + + return selection; } diff --git a/eeschema/widgets/search_handlers.cpp b/eeschema/widgets/search_handlers.cpp index dda47e060b..eb3bfc196a 100644 --- a/eeschema/widgets/search_handlers.cpp +++ b/eeschema/widgets/search_handlers.cpp @@ -65,8 +65,16 @@ void SCH_SEARCH_HANDLER::FindAll( const std::function* aSelection ) { + std::vector selection; + + for( long i = 0; i < (long) m_hitlist.size(); ++i ) + { + if( alg::contains( *aSelection, i ) ) + selection.push_back( m_hitlist[i].item ); + } + int col = std::max( 0, aCol ); // Provide a stable order by sorting on first column if no // sort column provided. @@ -80,6 +88,14 @@ void SCH_SEARCH_HANDLER::Sort( int aCol, bool aAscending ) else return StrNumCmp( getResultCell( b, col ), getResultCell( a, col ), true ) < 0; } ); + + aSelection->clear(); + + for( long i = 0; i < (long) m_hitlist.size(); ++i ) + { + if( alg::contains( selection, m_hitlist[i].item ) ) + aSelection->push_back( i ); + } } diff --git a/eeschema/widgets/search_handlers.h b/eeschema/widgets/search_handlers.h index a89a86a2af..85325d8446 100644 --- a/eeschema/widgets/search_handlers.h +++ b/eeschema/widgets/search_handlers.h @@ -60,7 +60,7 @@ public: } void FindAll( const std::function& aCollector ); - void Sort( int aCol, bool aAscending ) override; + void Sort( int aCol, bool aAscending, std::vector* aSelection ) override; void SelectItems( std::vector& aItemRows ) override; protected: diff --git a/include/widgets/search_pane.h b/include/widgets/search_pane.h index 4101ea0a6a..a2d65098a9 100644 --- a/include/widgets/search_pane.h +++ b/include/widgets/search_pane.h @@ -43,7 +43,7 @@ public: virtual int Search( const wxString& string ) = 0; virtual wxString GetResultCell( int row, int col ) = 0; - virtual void Sort( int aCol, bool aAscending ) = 0; + virtual void Sort( int aCol, bool aAscending, std::vector* aSelection ) = 0; virtual void SelectItems( std::vector& aItemRows ) {} virtual void ActivateItem( long aItemRow ) {} diff --git a/include/widgets/search_pane_tab.h b/include/widgets/search_pane_tab.h index 68150251e7..35849de49a 100644 --- a/include/widgets/search_pane_tab.h +++ b/include/widgets/search_pane_tab.h @@ -40,7 +40,7 @@ public: void RefreshColumnNames(); - void Sort(); + std::vector Sort(); protected: wxString OnGetItemText( long item, long column ) const override; diff --git a/pcbnew/widgets/search_handlers.cpp b/pcbnew/widgets/search_handlers.cpp index eccf3e5bc0..262a256a4b 100644 --- a/pcbnew/widgets/search_handlers.cpp +++ b/pcbnew/widgets/search_handlers.cpp @@ -42,18 +42,38 @@ void PCB_SEARCH_HANDLER::ActivateItem( long aItemRow ) } -void PCB_SEARCH_HANDLER::Sort( int aCol, bool aAscending ) +void PCB_SEARCH_HANDLER::Sort( int aCol, bool aAscending, std::vector* aSelection ) { + std::vector selection; + + for( long i = 0; i < (long) m_hitlist.size(); ++i ) + { + if( alg::contains( *aSelection, i ) ) + selection.push_back( m_hitlist[i] ); + } + + int col = std::max( 0, aCol ); // Provide a stable order by sorting on first column if no + // sort column provided. + std::sort( m_hitlist.begin(), m_hitlist.end(), [&]( BOARD_ITEM* a, BOARD_ITEM* b ) -> bool { // N.B. To meet the iterator sort conditions, we cannot simply invert the truth // to get the opposite sort. i.e. ~(ab) if( aAscending ) - return StrNumCmp( getResultCell( a, aCol ), getResultCell( b, aCol ), true ) < 0; + return StrNumCmp( getResultCell( a, col ), getResultCell( b, col ), true ) < 0; else - return StrNumCmp( getResultCell( b, aCol ), getResultCell( a, aCol ), true ) < 0; + return StrNumCmp( getResultCell( b, col ), getResultCell( a, col ), true ) < 0; } ); + + + aSelection->clear(); + + for( long i = 0; i < (long) m_hitlist.size(); ++i ) + { + if( alg::contains( selection, m_hitlist[i] ) ) + aSelection->push_back( i ); + } } diff --git a/pcbnew/widgets/search_handlers.h b/pcbnew/widgets/search_handlers.h index 49ac0c99ba..2bd2d46dab 100644 --- a/pcbnew/widgets/search_handlers.h +++ b/pcbnew/widgets/search_handlers.h @@ -50,7 +50,7 @@ public: return getResultCell( item, aCol ); } - void Sort( int aCol, bool aAscending ) override; + void Sort( int aCol, bool aAscending, std::vector* aSelection ) override; void SelectItems( std::vector& aItemRows ) override; void ActivateItem( long aItemRow ) override;