KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcbnew/widgets/search_handlers.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2023 CERN
5 * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <footprint.h>
22#include <pcb_edit_frame.h>
23#include <pcb_marker.h>
24#include <pcb_painter.h>
25#include <pcb_textbox.h>
26#include <pcb_text.h>
27#include <pcb_dimension.h>
28#include <pcbnew_settings.h>
30#include <string_utils.h>
31#include <tool/tool_manager.h>
32#include <tools/pcb_actions.h>
33#include <zone.h>
34#include "search_handlers.h"
35
36
38{
39 std::vector<long> item = { aItemRow };
40 SelectItems( item );
41
43}
44
45
46void PCB_SEARCH_HANDLER::Sort( int aCol, bool aAscending, std::vector<long>* aSelection )
47{
48 std::vector<BOARD_ITEM*> selection;
49
50 for( long i = 0; i < (long) m_hitlist.size(); ++i )
51 {
52 if( alg::contains( *aSelection, i ) )
53 selection.push_back( m_hitlist[i] );
54 }
55
56 int col = std::max( 0, aCol ); // Provide a stable order by sorting on first column if no
57 // sort column provided.
58
59 std::sort( m_hitlist.begin(), m_hitlist.end(),
60 [&]( BOARD_ITEM* a, BOARD_ITEM* b ) -> bool
61 {
62 // N.B. To meet the iterator sort conditions, we cannot simply invert the truth
63 // to get the opposite sort. i.e. ~(a<b) != (a>b)
64 if( aAscending )
65 return StrNumCmp( getResultCell( a, col ), getResultCell( b, col ), true ) < 0;
66 else
67 return StrNumCmp( getResultCell( b, col ), getResultCell( a, col ), true ) < 0;
68 } );
69
70
71 aSelection->clear();
72
73 for( long i = 0; i < (long) m_hitlist.size(); ++i )
74 {
75 if( alg::contains( selection, m_hitlist[i] ) )
76 aSelection->push_back( i );
77 }
78}
79
80
81void PCB_SEARCH_HANDLER::SelectItems( std::vector<long>& aItemRows )
82{
84 std::vector<EDA_ITEM*> selectedItems;
85
86 for( long row : aItemRows )
87 {
88 if( row >= 0 && row < (long) m_hitlist.size() )
89 selectedItems.push_back( m_hitlist[row] );
90 }
91
93
94 if( selectedItems.size() )
95 {
97
98 switch( settings.selection_zoom )
99 {
102 break;
105 break;
107 break;
108 }
109 }
110
111 m_frame->GetCanvas()->Refresh( false );
112}
113
114
116 PCB_SEARCH_HANDLER( _HKI( "Footprints" ), aFrame )
117{
118 m_columns.emplace_back( _HKI( "Reference" ), 2, wxLIST_FORMAT_LEFT );
119 m_columns.emplace_back( _HKI( "Value" ), 8, wxLIST_FORMAT_LEFT );
120 m_columns.emplace_back( _HKI( "Layer" ), 3, wxLIST_FORMAT_CENTER );
121 m_columns.emplace_back( wxT( "X" ), 3, wxLIST_FORMAT_CENTER );
122 m_columns.emplace_back( wxT( "Y" ), 3, wxLIST_FORMAT_CENTER );
123}
124
125
126int FOOTPRINT_SEARCH_HANDLER::Search( const wxString& aQuery )
127{
128 m_hitlist.clear();
129 BOARD* board = m_frame->GetBoard();
130
131 if( board == nullptr )
132 return 0;
133
134 EDA_SEARCH_DATA frp;
135 frp.findString = aQuery;
136
137 // Try to handle whatever the user throws at us (substring, wildcards, regex, etc.)
138 frp.matchMode = EDA_SEARCH_MATCH_MODE::PERMISSIVE;
139
140 for( FOOTPRINT* fp : board->Footprints() )
141 {
142 if( aQuery.IsEmpty()
143 || fp->Reference().Matches( frp, nullptr )
144 || fp->Value().Matches( frp, nullptr ) )
145 {
146 m_hitlist.push_back( fp );
147 }
148 }
149
150 return (int) m_hitlist.size();
151}
152
153
155{
156 FOOTPRINT* fp = static_cast<FOOTPRINT*>( aItem );
157
158 if( aCol == 0 )
159 return fp->GetReference();
160 else if( aCol == 1 )
161 return UnescapeString( fp->GetValue() );
162 else if( aCol == 2 )
163 return fp->GetLayerName();
164 else if( aCol == 3 )
166 else if( aCol == 4 )
168
169 return wxEmptyString;
170}
171
172
174 PCB_SEARCH_HANDLER( _HKI( "Zones" ), aFrame )
175{
176 m_columns.emplace_back( _HKI( "Name" ), 6, wxLIST_FORMAT_LEFT );
177 m_columns.emplace_back( _HKI( "Net" ), 6, wxLIST_FORMAT_LEFT);
178 m_columns.emplace_back( _HKI( "Layer" ), 3, wxLIST_FORMAT_CENTER );
179 m_columns.emplace_back( _HKI( "Priority" ), 2, wxLIST_FORMAT_CENTER );
180 m_columns.emplace_back( wxT( "X" ), 3, wxLIST_FORMAT_CENTER );
181 m_columns.emplace_back( wxT( "Y" ), 3, wxLIST_FORMAT_CENTER );
182}
183
184
185int ZONE_SEARCH_HANDLER::Search( const wxString& aQuery )
186{
187 m_hitlist.clear();
188 BOARD* board = m_frame->GetBoard();
189
190 EDA_SEARCH_DATA frp;
191 frp.findString = aQuery;
192
193 // Try to handle whatever the user throws at us (substring, wildcards, regex, etc.)
194 frp.matchMode = EDA_SEARCH_MATCH_MODE::PERMISSIVE;
195
196 for( BOARD_ITEM* item : board->Zones() )
197 {
198 ZONE* zoneItem = dynamic_cast<ZONE*>( item );
199
200 if( zoneItem && ( aQuery.IsEmpty() || zoneItem->Matches( frp, nullptr ) ) )
201 m_hitlist.push_back( zoneItem );
202 }
203
204 return (int) m_hitlist.size();
205}
206
207
209{
210 ZONE* zone = static_cast<ZONE*>( aItem );
211
212 if( aCol == 0 )
213 return zone->GetZoneName();
214 else if( aCol == 1 )
215 return UnescapeString( zone->GetNetname() );
216 else if( aCol == 2 )
217 {
218 wxArrayString layers;
219 BOARD* board = m_frame->GetBoard();
220
221 for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
222 layers.Add( board->GetLayerName( layer ) );
223
224 return wxJoin( layers, ',' );
225 }
226 else if( aCol == 3 )
227 return wxString::Format( "%d", zone->GetAssignedPriority() );
228 else if( aCol == 4 )
230 else if( aCol == 5 )
232
233
234 return wxEmptyString;
235}
236
237
239 PCB_SEARCH_HANDLER( _HKI( "Text" ), aFrame )
240{
241 m_columns.emplace_back( _HKI( "Type" ), 2, wxLIST_FORMAT_LEFT );
242 m_columns.emplace_back( _HKI( "Text" ), 12, wxLIST_FORMAT_LEFT );
243 m_columns.emplace_back( _HKI( "Layer" ), 3, wxLIST_FORMAT_CENTER );
244 m_columns.emplace_back( wxT( "X" ), 3, wxLIST_FORMAT_CENTER );
245 m_columns.emplace_back( wxT( "Y" ), 3, wxLIST_FORMAT_CENTER );
246}
247
248
249int TEXT_SEARCH_HANDLER::Search( const wxString& aQuery )
250{
251 m_hitlist.clear();
252 BOARD* board = m_frame->GetBoard();
253
254 EDA_SEARCH_DATA frp;
255 frp.findString = aQuery;
256
257 // Try to handle whatever the user throws at us (substring, wildcards, regex, etc.)
258 frp.matchMode = EDA_SEARCH_MATCH_MODE::PERMISSIVE;
259
260 for( BOARD_ITEM* item : board->Drawings() )
261 {
262 PCB_TEXT* textItem = dynamic_cast<PCB_TEXT*>( item );
263 PCB_TEXTBOX* textBoxItem = dynamic_cast<PCB_TEXTBOX*>( item );
264
265 if( textItem && ( aQuery.IsEmpty() || textItem->Matches( frp, nullptr ) ) )
266 m_hitlist.push_back( textItem );
267 else if( textBoxItem && ( aQuery.IsEmpty() || textBoxItem->Matches( frp, nullptr ) ) )
268 m_hitlist.push_back( textBoxItem );
269 }
270
271 return (int) m_hitlist.size();
272}
273
274
276{
277 if( aCol == 0 )
278 {
279 if( PCB_TEXT::ClassOf( aItem ) )
280 return _( "Text" );
281 else if( PCB_TEXTBOX::ClassOf( aItem ) )
282 return _( "Textbox" );
283 else if( dynamic_cast<PCB_DIMENSION_BASE*>( aItem ) )
284 return _( "Dimension" );
285 }
286 else if( aCol == 1 )
287 {
288 if( PCB_TEXT::ClassOf( aItem ) )
289 return UnescapeString( static_cast<PCB_TEXT*>( aItem )->GetText() );
290 else if( PCB_TEXTBOX::ClassOf( aItem ) )
291 return UnescapeString( static_cast<PCB_TEXTBOX*>( aItem )->GetText() );
292 else if( PCB_DIMENSION_BASE* dimension = dynamic_cast<PCB_DIMENSION_BASE*>( aItem ) )
293 return UnescapeString( dimension->GetText() );
294 }
295 else if( aCol == 2 )
296 return aItem->GetLayerName();
297 else if( aCol == 3 )
298 return m_frame->MessageTextFromCoord( aItem->GetX(), ORIGIN_TRANSFORMS::ABS_X_COORD );
299 else if( aCol == 4 )
300 return m_frame->MessageTextFromCoord( aItem->GetY(), ORIGIN_TRANSFORMS::ABS_Y_COORD );
301
302 return wxEmptyString;
303}
304
305
307 PCB_SEARCH_HANDLER( _HKI( "Nets" ), aFrame )
308{
309 m_columns.emplace_back( _HKI( "Name" ), 6, wxLIST_FORMAT_LEFT );
310 m_columns.emplace_back( _HKI( "Class" ), 6, wxLIST_FORMAT_LEFT );
311}
312
313
314int NETS_SEARCH_HANDLER::Search( const wxString& aQuery )
315{
316 m_hitlist.clear();
317
318 EDA_SEARCH_DATA frp;
319 frp.findString = aQuery;
320
321 // Try to handle whatever the user throws at us (substring, wildcards, regex, etc.)
322 frp.matchMode = EDA_SEARCH_MATCH_MODE::PERMISSIVE;
323
324 BOARD* board = m_frame->GetBoard();
325
326 for( NETINFO_ITEM* net : board->GetNetInfo() )
327 {
328 if( net && ( aQuery.IsEmpty() || net->Matches( frp, nullptr ) ) )
329 m_hitlist.push_back( net );
330 }
331
332 return (int) m_hitlist.size();
333}
334
335
337{
338 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aItem );
339
340 if( net->GetNetCode() == 0 )
341 {
342 if( aCol == 0 )
343 return _( "No Net" );
344 else if( aCol == 1 )
345 return wxT( "" );
346 }
347
348 if( aCol == 0 )
349 return UnescapeString( net->GetNetname() );
350 else if( aCol == 1 )
351 return net->GetNetClass()->GetName();
352
353 return wxEmptyString;
354}
355
356
357void NETS_SEARCH_HANDLER::SelectItems( std::vector<long>& aItemRows )
358{
360 ps->SetHighlight( false );
361
362 std::vector<NETINFO_ITEM*> selectedItems;
363
364 for( long row : aItemRows )
365 {
366 if( row >= 0 && row < (long) m_hitlist.size() )
367 {
368 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( m_hitlist[row] );
369
370 ps->SetHighlight( true, net->GetNetCode(), true );
371 }
372 }
373
376}
377
378
380{
381 m_frame->ShowBoardSetupDialog( _( "Net Classes" ) );
382}
383
384
386 PCB_SEARCH_HANDLER( _HKI( "Ratsnest" ), aFrame )
387{
388 m_columns.emplace_back( _HKI( "Name" ), 6, wxLIST_FORMAT_LEFT );
389 m_columns.emplace_back( _HKI( "Class" ), 6, wxLIST_FORMAT_LEFT );
390}
391
392
393int RATSNEST_SEARCH_HANDLER::Search( const wxString& aQuery )
394{
395 m_hitlist.clear();
396
397 EDA_SEARCH_DATA frp;
398 frp.findString = aQuery;
399
400 // Try to handle whatever the user throws at us (substring, wildcards, regex, etc.)
401 frp.matchMode = EDA_SEARCH_MATCH_MODE::PERMISSIVE;
402
403 BOARD* board = m_frame->GetBoard();
404
405 for( NETINFO_ITEM* net : board->GetNetInfo() )
406 {
407 if( net == nullptr || !net->Matches( frp, nullptr ) )
408 continue;
409
410 RN_NET* rn = board->GetConnectivity()->GetRatsnestForNet( net->GetNetCode() );
411
412 if( rn && !rn->GetEdges().empty() )
413 m_hitlist.push_back( net );
414 }
415
416 return (int) m_hitlist.size();
417}
418
419
421{
422 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aItem );
423
424 if( net->GetNetCode() == 0 )
425 {
426 if( aCol == 0 )
427 return _( "No Net" );
428 else if( aCol == 1 )
429 return wxT( "" );
430 }
431
432 if( aCol == 0 )
433 return UnescapeString( net->GetNetname() );
434 else if( aCol == 1 )
435 return net->GetNetClass()->GetName();
436
437 return wxEmptyString;
438}
439
440
441void RATSNEST_SEARCH_HANDLER::SelectItems( std::vector<long>& aItemRows )
442{
444 ps->SetHighlight( false );
445
446 std::vector<NETINFO_ITEM*> selectedItems;
447
448 for( long row : aItemRows )
449 {
450 if( row >= 0 && row < (long) m_hitlist.size() )
451 {
452 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( m_hitlist[row] );
453
454 ps->SetHighlight( true, net->GetNetCode(), true );
455 }
456 }
457
460}
461
462
464{
465 m_frame->ShowBoardSetupDialog( _( "Net Classes" ) );
466}
static TOOL_ACTION zoomFitSelection
Definition: actions.h:136
static TOOL_ACTION centerSelection
Definition: actions.h:142
SEARCH_PANE m_SearchPane
Definition: app_settings.h:182
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
int GetY() const
Definition: board_item.h:100
int GetX() const
Definition: board_item.h:94
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Definition: board_item.cpp:139
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:290
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:871
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: board.cpp:1000
const ZONES & Zones() const
Definition: board.h:335
const FOOTPRINTS & Footprints() const
Definition: board.h:331
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:579
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:475
const DRAWINGS & Drawings() const
Definition: board.h:333
virtual APP_SETTINGS_BASE * config() const
Returns the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
FOOTPRINT_SEARCH_HANDLER(PCB_EDIT_FRAME *aFrame)
int Search(const wxString &aQuery) override
wxString getResultCell(BOARD_ITEM *aItem, int aCol) override
const wxString & GetValue() const
Definition: footprint.h:624
const wxString & GetReference() const
Definition: footprint.h:602
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
void SetHighlight(bool aEnabled, int aNetcode=-1, bool aMulti=false)
Turns on/off highlighting.
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
Definition: view.cpp:804
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:221
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:410
const wxString GetName() const
Gets the consolidated name of this netclass (which may be an aggregate)
Definition: netclass.cpp:151
Handle the data for a net.
Definition: netinfo.h:56
const wxString & GetNetname() const
Definition: netinfo.h:114
NETCLASS * GetNetClass()
Definition: netinfo.h:101
int GetNetCode() const
Definition: netinfo.h:108
void ActivateItem(long aItemRow) override
int Search(const wxString &aQuery) override
NETS_SEARCH_HANDLER(PCB_EDIT_FRAME *aFrame)
wxString getResultCell(BOARD_ITEM *aItem, int aCol) override
void SelectItems(std::vector< long > &aItemRows) override
static TOOL_ACTION properties
Activation of the edit tool.
Definition: pcb_actions.h:180
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:68
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Definition: pcb_actions.h:76
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
BOARD * GetBoard() const
wxString MessageTextFromCoord(int aValue, ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType) const
Abstract dimension API.
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
The main frame for Pcbnew.
void ShowBoardSetupDialog(const wxString &aInitialPage=wxEmptyString)
void ActivateItem(long aItemRow) override
void Sort(int aCol, bool aAscending, std::vector< long > *aSelection) override
void SelectItems(std::vector< long > &aItemRows) override
std::vector< BOARD_ITEM * > m_hitlist
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
static bool ClassOf(const EDA_ITEM *aItem)
Definition: pcb_textbox.h:46
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: pcb_text.cpp:222
static bool ClassOf(const EDA_ITEM *aItem)
Definition: pcb_text.h:49
wxString getResultCell(BOARD_ITEM *aItem, int aCol) override
RATSNEST_SEARCH_HANDLER(PCB_EDIT_FRAME *aFrame)
int Search(const wxString &aQuery) override
void SelectItems(std::vector< long > &aItemRows) override
void ActivateItem(long aItemRow) override
Describe ratsnest for a single net.
Definition: ratsnest_data.h:63
const std::vector< CN_EDGE > & GetEdges() const
Definition: ratsnest_data.h:96
std::vector< SCH_SEARCH_HIT > m_hitlist
std::vector< std::tuple< wxString, int, wxListColumnFormat > > m_columns
Definition: search_pane.h:57
TEXT_SEARCH_HANDLER(SCH_EDIT_FRAME *aFrame)
int Search(const wxString &aQuery) override
wxString getResultCell(const SCH_SEARCH_HIT &hit, int aCol) override
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:150
ZONE_SEARCH_HANDLER(PCB_EDIT_FRAME *aFrame)
wxString getResultCell(BOARD_ITEM *aItem, int aCol) override
int Search(const wxString &aQuery) override
Handle a list of polygons defining a copper zone.
Definition: zone.h:73
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: zone.h:135
const wxString & GetZoneName() const
Definition: zone.h:132
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:130
unsigned GetAssignedPriority() const
Definition: zone.h:120
#define _HKI(x)
#define _(s)
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:100
Class that computes missing connections on a PCB.
wxString UnescapeString(const wxString &aSource)
EDA_SEARCH_MATCH_MODE matchMode