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 The 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" ), 6, wxLIST_FORMAT_LEFT );
120 m_columns.emplace_back( _HKI( "Layer" ), 2, 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 m_columns.emplace_back( _HKI( "Library Link" ), 8, wxLIST_FORMAT_LEFT );
124 m_columns.emplace_back( _HKI( "Library Description" ), 10, wxLIST_FORMAT_LEFT );
125}
126
127
128int FOOTPRINT_SEARCH_HANDLER::Search( const wxString& aQuery )
129{
130 m_hitlist.clear();
131 BOARD* board = m_frame->GetBoard();
132
133 if( board == nullptr )
134 return 0;
135
137 EDA_SEARCH_DATA frp;
138
140 frp.searchMetadata = settings.search_metadata;
141 frp.findString = aQuery;
142
143 // Try to handle whatever the user throws at us (substring, wildcards, regex, etc.)
144 frp.matchMode = EDA_SEARCH_MATCH_MODE::PERMISSIVE;
145
146 for( FOOTPRINT* fp : board->Footprints() )
147 {
148 bool found = false;
149
150 if( frp.findString.IsEmpty() )
151 found = true;
152
153 if( !found && fp->Matches( frp, nullptr ) )
154 found = true;
155
156 if( !found )
157 {
158 for( PCB_FIELD* field : fp->GetFields() )
159 {
160 if( field->Matches( frp, nullptr ) )
161 {
162 found = true;
163 break;
164 }
165 }
166 }
167
168 if( found )
169 m_hitlist.push_back( fp );
170 }
171
172 return (int) m_hitlist.size();
173}
174
175
177{
178 FOOTPRINT* fp = static_cast<FOOTPRINT*>( aItem );
179
180 if( aCol == 0 )
181 return fp->GetReference();
182 else if( aCol == 1 )
183 return UnescapeString( fp->GetValue() );
184 else if( aCol == 2 )
185 return fp->GetLayerName();
186 else if( aCol == 3 )
188 else if( aCol == 4 )
190 else if( aCol == 5 )
191 return fp->GetFPID().Format();
192 else if( aCol == 6 )
193 return fp->GetLibDescription();
194
195 return wxEmptyString;
196}
197
198
200 PCB_SEARCH_HANDLER( _HKI( "Zones" ), aFrame )
201{
202 m_columns.emplace_back( _HKI( "Name" ), 6, wxLIST_FORMAT_LEFT );
203 m_columns.emplace_back( _HKI( "Net" ), 6, wxLIST_FORMAT_LEFT);
204 m_columns.emplace_back( _HKI( "Layer" ), 3, wxLIST_FORMAT_CENTER );
205 m_columns.emplace_back( _HKI( "Priority" ), 2, wxLIST_FORMAT_CENTER );
206 m_columns.emplace_back( wxT( "X" ), 3, wxLIST_FORMAT_CENTER );
207 m_columns.emplace_back( wxT( "Y" ), 3, wxLIST_FORMAT_CENTER );
208}
209
210
211int ZONE_SEARCH_HANDLER::Search( const wxString& aQuery )
212{
213 m_hitlist.clear();
214 BOARD* board = m_frame->GetBoard();
215
217 EDA_SEARCH_DATA frp;
218
220 frp.searchMetadata = settings.search_metadata;
221 frp.findString = aQuery;
222
223 // Try to handle whatever the user throws at us (substring, wildcards, regex, etc.)
224 frp.matchMode = EDA_SEARCH_MATCH_MODE::PERMISSIVE;
225
226 for( BOARD_ITEM* item : board->Zones() )
227 {
228 if( frp.findString.IsEmpty() || item->Matches( frp, nullptr ) )
229 m_hitlist.push_back( item );
230 }
231
232 return (int) m_hitlist.size();
233}
234
235
237{
238 ZONE* zone = static_cast<ZONE*>( aItem );
239
240 if( aCol == 0 )
241 return zone->GetZoneName();
242 else if( aCol == 1 )
243 return UnescapeString( zone->GetNetname() );
244 else if( aCol == 2 )
245 {
246 wxArrayString layers;
247 BOARD* board = m_frame->GetBoard();
248
249 for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
250 layers.Add( board->GetLayerName( layer ) );
251
252 return wxJoin( layers, ',' );
253 }
254 else if( aCol == 3 )
255 return wxString::Format( "%d", zone->GetAssignedPriority() );
256 else if( aCol == 4 )
258 else if( aCol == 5 )
260
261
262 return wxEmptyString;
263}
264
265
267 PCB_SEARCH_HANDLER( _HKI( "Text" ), aFrame )
268{
269 m_columns.emplace_back( _HKI( "Type" ), 2, wxLIST_FORMAT_LEFT );
270 m_columns.emplace_back( _HKI( "Text" ), 12, wxLIST_FORMAT_LEFT );
271 m_columns.emplace_back( _HKI( "Layer" ), 3, wxLIST_FORMAT_CENTER );
272 m_columns.emplace_back( wxT( "X" ), 3, wxLIST_FORMAT_CENTER );
273 m_columns.emplace_back( wxT( "Y" ), 3, wxLIST_FORMAT_CENTER );
274}
275
276
277int TEXT_SEARCH_HANDLER::Search( const wxString& aQuery )
278{
279 m_hitlist.clear();
280 BOARD* board = m_frame->GetBoard();
281
283 EDA_SEARCH_DATA frp;
284
286 frp.searchMetadata = settings.search_metadata;
287 frp.findString = aQuery;
288
289 // Try to handle whatever the user throws at us (substring, wildcards, regex, etc.)
290 frp.matchMode = EDA_SEARCH_MATCH_MODE::PERMISSIVE;
291
292 for( BOARD_ITEM* item : board->Drawings() )
293 {
294 if( item->Type() == PCB_TEXT_T
295 || BaseType( item->Type() ) == PCB_DIMENSION_T
296 || item->Type() == PCB_TEXTBOX_T
297 || item->Type() == PCB_TABLECELL_T )
298 {
299 if( frp.findString.IsEmpty() || item->Matches( frp, nullptr ) )
300 m_hitlist.push_back( item );
301 }
302 }
303
304 return (int) m_hitlist.size();
305}
306
307
309{
310 if( aCol == 0 )
311 {
312 if( PCB_TEXT::ClassOf( aItem ) )
313 return _( "Text" );
314 else if( PCB_TEXTBOX::ClassOf( aItem ) )
315 return _( "Textbox" );
316 else if( dynamic_cast<PCB_DIMENSION_BASE*>( aItem ) )
317 return _( "Dimension" );
318 }
319 else if( aCol == 1 )
320 {
321 if( PCB_TEXT::ClassOf( aItem ) )
322 return UnescapeString( static_cast<PCB_TEXT*>( aItem )->GetText() );
323 else if( PCB_TEXTBOX::ClassOf( aItem ) )
324 return UnescapeString( static_cast<PCB_TEXTBOX*>( aItem )->GetText() );
325 else if( PCB_DIMENSION_BASE* dimension = dynamic_cast<PCB_DIMENSION_BASE*>( aItem ) )
326 return UnescapeString( dimension->GetText() );
327 }
328 else if( aCol == 2 )
329 return aItem->GetLayerName();
330 else if( aCol == 3 )
331 return m_frame->MessageTextFromCoord( aItem->GetX(), ORIGIN_TRANSFORMS::ABS_X_COORD );
332 else if( aCol == 4 )
333 return m_frame->MessageTextFromCoord( aItem->GetY(), ORIGIN_TRANSFORMS::ABS_Y_COORD );
334
335 return wxEmptyString;
336}
337
338
340 PCB_SEARCH_HANDLER( _HKI( "Nets" ), aFrame )
341{
342 m_columns.emplace_back( _HKI( "Name" ), 6, wxLIST_FORMAT_LEFT );
343 m_columns.emplace_back( _HKI( "Class" ), 6, wxLIST_FORMAT_LEFT );
344}
345
346
347int NETS_SEARCH_HANDLER::Search( const wxString& aQuery )
348{
349 m_hitlist.clear();
350
352 EDA_SEARCH_DATA frp;
353
355 frp.searchMetadata = settings.search_metadata;
356 frp.findString = aQuery;
357
358 // Try to handle whatever the user throws at us (substring, wildcards, regex, etc.)
359 frp.matchMode = EDA_SEARCH_MATCH_MODE::PERMISSIVE;
360
361 BOARD* board = m_frame->GetBoard();
362
363 for( NETINFO_ITEM* net : board->GetNetInfo() )
364 {
365 if( net && ( aQuery.IsEmpty() || net->Matches( frp, nullptr ) ) )
366 m_hitlist.push_back( net );
367 }
368
369 return (int) m_hitlist.size();
370}
371
372
374{
375 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aItem );
376
377 if( net->GetNetCode() == 0 )
378 {
379 if( aCol == 0 )
380 return _( "No Net" );
381 else if( aCol == 1 )
382 return wxT( "" );
383 }
384
385 if( aCol == 0 )
386 return UnescapeString( net->GetNetname() );
387 else if( aCol == 1 )
388 return net->GetNetClass()->GetName();
389
390 return wxEmptyString;
391}
392
393
394void NETS_SEARCH_HANDLER::SelectItems( std::vector<long>& aItemRows )
395{
397 ps->SetHighlight( false );
398
399 std::vector<NETINFO_ITEM*> selectedItems;
400
401 for( long row : aItemRows )
402 {
403 if( row >= 0 && row < (long) m_hitlist.size() )
404 {
405 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( m_hitlist[row] );
406
407 ps->SetHighlight( true, net->GetNetCode(), true );
408 }
409 }
410
413}
414
415
417{
418 m_frame->ShowBoardSetupDialog( _( "Net Classes" ) );
419}
420
421
423 PCB_SEARCH_HANDLER( _HKI( "Ratsnest" ), aFrame )
424{
425 m_columns.emplace_back( _HKI( "Name" ), 6, wxLIST_FORMAT_LEFT );
426 m_columns.emplace_back( _HKI( "Class" ), 6, wxLIST_FORMAT_LEFT );
427}
428
429
430int RATSNEST_SEARCH_HANDLER::Search( const wxString& aQuery )
431{
432 m_hitlist.clear();
433
435 EDA_SEARCH_DATA frp;
436
438 frp.searchMetadata = settings.search_metadata;
439 frp.findString = aQuery;
440
441 // Try to handle whatever the user throws at us (substring, wildcards, regex, etc.)
442 frp.matchMode = EDA_SEARCH_MATCH_MODE::PERMISSIVE;
443
444 BOARD* board = m_frame->GetBoard();
445
446 for( NETINFO_ITEM* net : board->GetNetInfo() )
447 {
448 if( net == nullptr || !net->Matches( frp, nullptr ) )
449 continue;
450
451 RN_NET* rn = board->GetConnectivity()->GetRatsnestForNet( net->GetNetCode() );
452
453 if( rn && !rn->GetEdges().empty() )
454 m_hitlist.push_back( net );
455 }
456
457 return (int) m_hitlist.size();
458}
459
460
462{
463 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aItem );
464
465 if( net->GetNetCode() == 0 )
466 {
467 if( aCol == 0 )
468 return _( "No Net" );
469 else if( aCol == 1 )
470 return wxT( "" );
471 }
472
473 if( aCol == 0 )
474 return UnescapeString( net->GetNetname() );
475 else if( aCol == 1 )
476 return net->GetNetClass()->GetName();
477
478 return wxEmptyString;
479}
480
481
482void RATSNEST_SEARCH_HANDLER::SelectItems( std::vector<long>& aItemRows )
483{
485 ps->SetHighlight( false );
486
487 std::vector<NETINFO_ITEM*> selectedItems;
488
489 for( long row : aItemRows )
490 {
491 if( row >= 0 && row < (long) m_hitlist.size() )
492 {
493 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( m_hitlist[row] );
494
495 ps->SetHighlight( true, net->GetNetCode(), true );
496 }
497 }
498
501}
502
503
505{
506 m_frame->ShowBoardSetupDialog( _( "Net Classes" ) );
507}
static TOOL_ACTION zoomFitSelection
Definition: actions.h:143
static TOOL_ACTION centerSelection
Definition: actions.h:149
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: actions.h:220
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Definition: actions.h:228
SEARCH_PANE m_SearchPane
Definition: app_settings.h:209
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:78
int GetY() const
Definition: board_item.h:98
int GetX() const
Definition: board_item.h:92
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Definition: board_item.cpp:140
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:297
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:897
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: board.cpp:1060
const ZONES & Zones() const
Definition: board.h:342
const FOOTPRINTS & Footprints() const
Definition: board.h:338
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:614
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:495
const DRAWINGS & Drawings() const
Definition: board.h:340
virtual APP_SETTINGS_BASE * config() const
Return 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
wxString GetLibDescription() const
Definition: footprint.h:262
const LIB_ID & GetFPID() const
Definition: footprint.h:253
const wxString & GetValue() const
Definition: footprint.h:643
const wxString & GetReference() const
Definition: footprint.h:621
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:765
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:216
UTF8 Format() const
Definition: lib_id.cpp:119
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:297
const wxString GetName() const
Gets the name of this (maybe aggregate) netclass in a format for internal usage or for export to exte...
Definition: netclass.cpp:316
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:163
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
static bool ClassOf(const EDA_ITEM *aItem)
Definition: pcb_textbox.h:48
static bool ClassOf(const EDA_ITEM *aItem)
Definition: pcb_text.h:51
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:61
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:74
const wxString & GetZoneName() const
Definition: zone.h:163
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:136
unsigned GetAssignedPriority() const
Definition: zone.h:126
#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
constexpr KICAD_T BaseType(const KICAD_T aType)
Return the underlying type of the given type.
Definition: typeinfo.h:250
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:93
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
Definition: typeinfo.h:95
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
Definition: typeinfo.h:100