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>
29#include <string_utils.h>
30#include <tool/tool_manager.h>
31#include <tools/pcb_actions.h>
32#include <zone.h>
33#include "search_handlers.h"
34
35
37{
38 std::vector<long> item = { aItemRow };
39 SelectItems( item );
40
42}
43
44
45void PCB_SEARCH_HANDLER::Sort( int aCol, bool aAscending, std::vector<long>* aSelection )
46{
47 std::vector<BOARD_ITEM*> selection;
48
49 for( long i = 0; i < (long) m_hitlist.size(); ++i )
50 {
51 if( alg::contains( *aSelection, i ) )
52 selection.push_back( m_hitlist[i] );
53 }
54
55 int col = std::max( 0, aCol ); // Provide a stable order by sorting on first column if no
56 // sort column provided.
57
58 std::sort( m_hitlist.begin(), m_hitlist.end(),
59 [&]( BOARD_ITEM* a, BOARD_ITEM* b ) -> bool
60 {
61 // N.B. To meet the iterator sort conditions, we cannot simply invert the truth
62 // to get the opposite sort. i.e. ~(a<b) != (a>b)
63 if( aAscending )
64 return StrNumCmp( getResultCell( a, col ), getResultCell( b, col ), true ) < 0;
65 else
66 return StrNumCmp( getResultCell( b, col ), getResultCell( a, col ), true ) < 0;
67 } );
68
69
70 aSelection->clear();
71
72 for( long i = 0; i < (long) m_hitlist.size(); ++i )
73 {
74 if( alg::contains( selection, m_hitlist[i] ) )
75 aSelection->push_back( i );
76 }
77}
78
79
80void PCB_SEARCH_HANDLER::SelectItems( std::vector<long>& aItemRows )
81{
82 std::vector<EDA_ITEM*> selectedItems;
83
84 for( long row : aItemRows )
85 {
86 if( row >= 0 && row < (long) m_hitlist.size() )
87 selectedItems.push_back( m_hitlist[row] );
88 }
89
91
92 if( selectedItems.size() )
94
95 m_frame->GetCanvas()->Refresh( false );
96}
97
98
100 PCB_SEARCH_HANDLER( _HKI( "Footprints" ), aFrame )
101{
102 m_columns.emplace_back( _HKI( "Reference" ), 2, wxLIST_FORMAT_LEFT );
103 m_columns.emplace_back( _HKI( "Value" ), 8, wxLIST_FORMAT_LEFT );
104 m_columns.emplace_back( _HKI( "Layer" ), 3, wxLIST_FORMAT_CENTER );
105 m_columns.emplace_back( wxT( "X" ), 3, wxLIST_FORMAT_CENTER );
106 m_columns.emplace_back( wxT( "Y" ), 3, wxLIST_FORMAT_CENTER );
107}
108
109
110int FOOTPRINT_SEARCH_HANDLER::Search( const wxString& aQuery )
111{
112 m_hitlist.clear();
113 BOARD* board = m_frame->GetBoard();
114
115 if( board == nullptr )
116 return 0;
117
118 EDA_SEARCH_DATA frp;
119 frp.findString = aQuery;
120
121 // Try to handle whatever the user throws at us (substring, wildcards, regex, etc.)
122 frp.matchMode = EDA_SEARCH_MATCH_MODE::PERMISSIVE;
123
124 for( FOOTPRINT* fp : board->Footprints() )
125 {
126 if( aQuery.IsEmpty()
127 || fp->Reference().Matches( frp, nullptr )
128 || fp->Value().Matches( frp, nullptr ) )
129 {
130 m_hitlist.push_back( fp );
131 }
132 }
133
134 return (int) m_hitlist.size();
135}
136
137
139{
140 FOOTPRINT* fp = static_cast<FOOTPRINT*>( aItem );
141
142 if( aCol == 0 )
143 return fp->GetReference();
144 else if( aCol == 1 )
145 return UnescapeString( fp->GetValue() );
146 else if( aCol == 2 )
147 return fp->GetLayerName();
148 else if( aCol == 3 )
150 else if( aCol == 4 )
152
153 return wxEmptyString;
154}
155
156
158 PCB_SEARCH_HANDLER( _HKI( "Zones" ), aFrame )
159{
160 m_columns.emplace_back( _HKI( "Name" ), 6, wxLIST_FORMAT_LEFT );
161 m_columns.emplace_back( _HKI( "Net" ), 6, wxLIST_FORMAT_LEFT);
162 m_columns.emplace_back( _HKI( "Layer" ), 3, wxLIST_FORMAT_CENTER );
163 m_columns.emplace_back( _HKI( "Priority" ), 2, wxLIST_FORMAT_CENTER );
164 m_columns.emplace_back( wxT( "X" ), 3, wxLIST_FORMAT_CENTER );
165 m_columns.emplace_back( wxT( "Y" ), 3, wxLIST_FORMAT_CENTER );
166}
167
168
169int ZONE_SEARCH_HANDLER::Search( const wxString& aQuery )
170{
171 m_hitlist.clear();
172 BOARD* board = m_frame->GetBoard();
173
174 EDA_SEARCH_DATA frp;
175 frp.findString = aQuery;
176
177 // Try to handle whatever the user throws at us (substring, wildcards, regex, etc.)
178 frp.matchMode = EDA_SEARCH_MATCH_MODE::PERMISSIVE;
179
180 for( BOARD_ITEM* item : board->Zones() )
181 {
182 ZONE* zoneItem = dynamic_cast<ZONE*>( item );
183
184 if( zoneItem && ( aQuery.IsEmpty() || zoneItem->Matches( frp, nullptr ) ) )
185 m_hitlist.push_back( zoneItem );
186 }
187
188 return (int) m_hitlist.size();
189}
190
191
193{
194 ZONE* zone = static_cast<ZONE*>( aItem );
195
196 if( aCol == 0 )
197 return zone->GetZoneName();
198 else if( aCol == 1 )
199 return UnescapeString( zone->GetNetname() );
200 else if( aCol == 2 )
201 {
202 wxArrayString layers;
203 BOARD* board = m_frame->GetBoard();
204
205 for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
206 layers.Add( board->GetLayerName( layer ) );
207
208 return wxJoin( layers, ',' );
209 }
210 else if( aCol == 3 )
211 return wxString::Format( "%d", zone->GetAssignedPriority() );
212 else if( aCol == 4 )
214 else if( aCol == 5 )
216
217
218 return wxEmptyString;
219}
220
221
223 PCB_SEARCH_HANDLER( _HKI( "Text" ), aFrame )
224{
225 m_columns.emplace_back( _HKI( "Type" ), 2, wxLIST_FORMAT_LEFT );
226 m_columns.emplace_back( _HKI( "Text" ), 12, wxLIST_FORMAT_LEFT );
227 m_columns.emplace_back( _HKI( "Layer" ), 3, wxLIST_FORMAT_CENTER );
228 m_columns.emplace_back( wxT( "X" ), 3, wxLIST_FORMAT_CENTER );
229 m_columns.emplace_back( wxT( "Y" ), 3, wxLIST_FORMAT_CENTER );
230}
231
232
233int TEXT_SEARCH_HANDLER::Search( const wxString& aQuery )
234{
235 m_hitlist.clear();
236 BOARD* board = m_frame->GetBoard();
237
238 EDA_SEARCH_DATA frp;
239 frp.findString = aQuery;
240
241 // Try to handle whatever the user throws at us (substring, wildcards, regex, etc.)
242 frp.matchMode = EDA_SEARCH_MATCH_MODE::PERMISSIVE;
243
244 for( BOARD_ITEM* item : board->Drawings() )
245 {
246 PCB_TEXT* textItem = dynamic_cast<PCB_TEXT*>( item );
247 PCB_TEXTBOX* textBoxItem = dynamic_cast<PCB_TEXTBOX*>( item );
248
249 if( textItem && ( aQuery.IsEmpty() || textItem->Matches( frp, nullptr ) ) )
250 m_hitlist.push_back( textItem );
251 else if( textBoxItem && ( aQuery.IsEmpty() || textBoxItem->Matches( frp, nullptr ) ) )
252 m_hitlist.push_back( textBoxItem );
253 }
254
255 return (int) m_hitlist.size();
256}
257
258
260{
261 if( aCol == 0 )
262 {
263 if( PCB_TEXT::ClassOf( aItem ) )
264 return _( "Text" );
265 else if( PCB_TEXTBOX::ClassOf( aItem ) )
266 return _( "Textbox" );
267 else if( dynamic_cast<PCB_DIMENSION_BASE*>( aItem ) )
268 return _( "Dimension" );
269 }
270 else if( aCol == 1 )
271 {
272 if( PCB_TEXT::ClassOf( aItem ) )
273 return UnescapeString( static_cast<PCB_TEXT*>( aItem )->GetText() );
274 else if( PCB_TEXTBOX::ClassOf( aItem ) )
275 return UnescapeString( static_cast<PCB_TEXTBOX*>( aItem )->GetText() );
276 else if( PCB_DIMENSION_BASE* dimension = dynamic_cast<PCB_DIMENSION_BASE*>( aItem ) )
277 return UnescapeString( dimension->GetText() );
278 }
279 else if( aCol == 2 )
280 return aItem->GetLayerName();
281 else if( aCol == 3 )
282 return m_frame->MessageTextFromCoord( aItem->GetX(), ORIGIN_TRANSFORMS::ABS_X_COORD );
283 else if( aCol == 4 )
284 return m_frame->MessageTextFromCoord( aItem->GetY(), ORIGIN_TRANSFORMS::ABS_Y_COORD );
285
286 return wxEmptyString;
287}
288
289
291 PCB_SEARCH_HANDLER( _HKI( "Nets" ), aFrame )
292{
293 m_columns.emplace_back( _HKI( "Name" ), 6, wxLIST_FORMAT_LEFT );
294 m_columns.emplace_back( _HKI( "Class" ), 6, wxLIST_FORMAT_LEFT );
295}
296
297
298int NETS_SEARCH_HANDLER::Search( const wxString& aQuery )
299{
300 m_hitlist.clear();
301
302 EDA_SEARCH_DATA frp;
303 frp.findString = aQuery;
304
305 // Try to handle whatever the user throws at us (substring, wildcards, regex, etc.)
306 frp.matchMode = EDA_SEARCH_MATCH_MODE::PERMISSIVE;
307
308 BOARD* board = m_frame->GetBoard();
309
310 for( NETINFO_ITEM* net : board->GetNetInfo() )
311 {
312 if( net && ( aQuery.IsEmpty() || net->Matches( frp, nullptr ) ) )
313 m_hitlist.push_back( net );
314 }
315
316 return (int) m_hitlist.size();
317}
318
319
321{
322 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aItem );
323
324 if( net->GetNetCode() == 0 )
325 {
326 if( aCol == 0 )
327 return _( "No Net" );
328 else if( aCol == 1 )
329 return wxT( "" );
330 }
331
332 if( aCol == 0 )
333 return UnescapeString( net->GetNetname() );
334 else if( aCol == 1 )
335 return net->GetNetClass()->GetName();
336
337 return wxEmptyString;
338}
339
340
341void NETS_SEARCH_HANDLER::SelectItems( std::vector<long>& aItemRows )
342{
344 ps->SetHighlight( false );
345
346 std::vector<NETINFO_ITEM*> selectedItems;
347
348 for( long row : aItemRows )
349 {
350 if( row >= 0 && row < (long) m_hitlist.size() )
351 {
352 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( m_hitlist[row] );
353
354 ps->SetHighlight( true, net->GetNetCode(), true );
355 }
356 }
357
360}
361
362
364{
365 m_frame->ShowBoardSetupDialog( _( "Net Classes" ) );
366}
367
368
370 PCB_SEARCH_HANDLER( _HKI( "Ratsnest" ), aFrame )
371{
372 m_columns.emplace_back( _HKI( "Name" ), 6, wxLIST_FORMAT_LEFT );
373 m_columns.emplace_back( _HKI( "Class" ), 6, wxLIST_FORMAT_LEFT );
374}
375
376
377int RATSNEST_SEARCH_HANDLER::Search( const wxString& aQuery )
378{
379 m_hitlist.clear();
380
381 EDA_SEARCH_DATA frp;
382 frp.findString = aQuery;
383
384 // Try to handle whatever the user throws at us (substring, wildcards, regex, etc.)
385 frp.matchMode = EDA_SEARCH_MATCH_MODE::PERMISSIVE;
386
387 BOARD* board = m_frame->GetBoard();
388
389 for( NETINFO_ITEM* net : board->GetNetInfo() )
390 {
391 if( net == nullptr || !net->Matches( frp, nullptr ) )
392 continue;
393
394 RN_NET* rn = board->GetConnectivity()->GetRatsnestForNet( net->GetNetCode() );
395
396 if( rn && !rn->GetEdges().empty() )
397 m_hitlist.push_back( net );
398 }
399
400 return (int) m_hitlist.size();
401}
402
403
405{
406 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aItem );
407
408 if( net->GetNetCode() == 0 )
409 {
410 if( aCol == 0 )
411 return _( "No Net" );
412 else if( aCol == 1 )
413 return wxT( "" );
414 }
415
416 if( aCol == 0 )
417 return UnescapeString( net->GetNetname() );
418 else if( aCol == 1 )
419 return net->GetNetClass()->GetName();
420
421 return wxEmptyString;
422}
423
424
425void RATSNEST_SEARCH_HANDLER::SelectItems( std::vector<long>& aItemRows )
426{
428 ps->SetHighlight( false );
429
430 std::vector<NETINFO_ITEM*> selectedItems;
431
432 for( long row : aItemRows )
433 {
434 if( row >= 0 && row < (long) m_hitlist.size() )
435 {
436 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( m_hitlist[row] );
437
438 ps->SetHighlight( true, net->GetNetCode(), true );
439 }
440 }
441
444}
445
446
448{
449 m_frame->ShowBoardSetupDialog( _( "Net Classes" ) );
450}
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:77
int GetY() const
Definition: board_item.h:101
int GetX() const
Definition: board_item.h:95
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Definition: board_item.cpp:103
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:282
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:853
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: board.cpp:882
const ZONES & Zones() const
Definition: board.h:327
const FOOTPRINTS & Footprints() const
Definition: board.h:323
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:564
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:460
const DRAWINGS & Drawings() const
Definition: board.h:325
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:610
const wxString & GetReference() const
Definition: footprint.h:588
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:766
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:215
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:418
const wxString GetName() const
Definition: netclass.h:62
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:176
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:221
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:53
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:72
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: zone.h:134
const wxString & GetZoneName() const
Definition: zone.h:131
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:129
unsigned GetAssignedPriority() const
Definition: zone.h:119
#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