KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_find.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) 2012 Marco Mattila <[email protected]>
5 * Copyright (C) 2018 Jean-Pierre Charras jp.charras at wanadoo.fr
6 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <pcb_edit_frame.h> // Keep this include at top to avoid compil issue on MSYS2
27#include <board.h>
28#include <pcb_marker.h>
29#include <footprint.h>
30#include <pcb_text.h>
31#include <zone.h>
32#include <dialog_find.h>
33#include <string_utils.h>
34#include <hotkeys_basic.h>
35#include <string>
36#include <tool/tool_manager.h>
37#include <tools/pcb_actions.h>
38#include <wx/fdrepdlg.h>
39
40
41//Defined as global because these values have to survive the destructor
42
43bool g_FindOptionCase = false;
44bool g_FindOptionWords = false;
46bool g_FindOptionWrap = true;
47
54
55
57 DIALOG_FIND_BASE( aFrame, wxID_ANY, _( "Find" ) ),
58 m_frame( aFrame )
59{
60 GetSizer()->SetSizeHints( this );
61
63
64 while( m_searchCombo->GetCount() > 10 )
65 {
66 m_frame->GetFindHistoryList().pop_back();
67 m_searchCombo->Delete( 9 );
68 }
69
70 if( m_searchCombo->GetCount() )
71 {
72 m_searchCombo->SetSelection( 0 );
73 m_searchCombo->SelectAll();
74 }
75
76 m_matchCase->SetValue( g_FindOptionCase );
79 m_wrap->SetValue( g_FindOptionWrap );
80
87
88 m_status->SetLabel( wxEmptyString);
89 m_upToDate = false;
90
91 m_hitList.clear();
92 m_it = m_hitList.begin();
93
94 if( int hotkey = ACTIONS::showSearch.GetHotKey() )
95 {
96 wxString hotkeyHint = wxString::Format( wxT( " (%s)" ), KeyNameFromKeyCode( hotkey ) );
97 m_searchPanelLink->SetLabel( m_searchPanelLink->GetLabel() + hotkeyHint );
98 }
99
100 m_findNext->SetDefault();
102
103 Center();
104}
105
106
107void DIALOG_FIND::Preload( const wxString& aFindString )
108{
109 if( !aFindString.IsEmpty() )
110 {
111 m_searchCombo->SetValue( aFindString );
112 m_searchCombo->SelectAll();
113 }
114}
115
116
117void DIALOG_FIND::onTextEnter( wxCommandEvent& aEvent )
118{
119 search( true );
120}
121
122
123void DIALOG_FIND::onFindNextClick( wxCommandEvent& aEvent )
124{
125 search( true );
126}
127
128
129void DIALOG_FIND::onFindPreviousClick( wxCommandEvent& aEvent )
130{
131 search( false );
132}
133
134
135void DIALOG_FIND::onSearchAgainClick( wxCommandEvent& aEvent )
136{
137 m_upToDate = false;
138 search( true );
139}
140
141
142void DIALOG_FIND::onShowSearchPanel( wxHyperlinkEvent& event )
143{
145 {
146 EndModal( wxID_CANCEL );
147
148 CallAfter(
149 []()
150 {
151 if( wxWindow* frame = wxWindow::FindWindowByName( PCB_EDIT_FRAME_NAME ) )
152 static_cast<PCB_EDIT_FRAME*>( frame )->FocusSearch();
153 } );
154 }
155 else
156 {
158 }
159}
160
161
162void DIALOG_FIND::search( bool aDirection )
163{
164 PCB_SCREEN* screen = m_frame->GetScreen();
165 int index;
166 wxString msg;
167 wxString searchString;
168 bool endIsReached = false;
169 bool isFirstSearch = false;
170
171 searchString = m_searchCombo->GetValue();
172
173 if( searchString.IsEmpty() )
174 {
175 Show();
176 return;
177 }
178
179 // Add/move the search string to the top of the list if it isn't already there
180 index = m_searchCombo->FindString( searchString, true );
181
182 if( index == wxNOT_FOUND )
183 {
184 m_searchCombo->Insert( searchString, 0 );
185 m_searchCombo->SetSelection( 0 );
186 m_upToDate = false;
187 m_frame->GetFindHistoryList().Insert( searchString, 0 );
188
189 if( m_searchCombo->GetCount() > 10 )
190 {
191 m_frame->GetFindHistoryList().pop_back();
192 m_searchCombo->Delete( 10 );
193 }
194 }
195 else if( index != 0 )
196 {
197 m_searchCombo->Delete( index );
198 m_searchCombo->Insert( searchString, 0 );
199 m_searchCombo->SetSelection( 0 );
200 m_upToDate = false;
201
202 if( m_frame->GetFindHistoryList().Index( searchString ) )
203 m_frame->GetFindHistoryList().Remove( searchString );
204
205 m_frame->GetFindHistoryList().Insert( searchString, 0 );
206 }
207
208 if( g_FindOptionCase != m_matchCase->GetValue() )
209 {
210 g_FindOptionCase = m_matchCase->GetValue();
211 m_upToDate = false;
212 }
213
214 if( g_FindOptionWords != m_matchWords->GetValue() )
215 {
216 g_FindOptionWords = m_matchWords->GetValue();
217 m_upToDate = false;
218 }
219
220 if( g_FindOptionWildcards != m_wildcards->GetValue() )
221 {
223 m_upToDate = false;
224 }
225
226 g_FindOptionWrap = m_wrap->GetValue();
227
228 if( g_FindIncludeTexts != m_includeTexts->GetValue() )
229 {
231 m_upToDate = false;
232 }
233
234 if( g_FindIncludeValues != m_includeValues->GetValue() )
235 {
237 m_upToDate = false;
238 }
239
241 {
243 m_upToDate = false;
244 }
245
247 {
249 m_upToDate = false;
250 }
251
252 if( g_FindIncludeMarkers != m_includeMarkers->GetValue() )
253 {
255 m_upToDate = false;
256 }
257
258 if( g_FindIncludeNets != m_includeNets->GetValue() )
259 {
260 g_FindIncludeNets = m_includeNets->GetValue();
261 m_upToDate = false;
262 }
263
265
266 if( g_FindOptionCase )
267 frd.matchCase = true;
268
270 frd.matchMode = EDA_SEARCH_MATCH_MODE::WHOLEWORD;
271 else if( g_FindOptionWildcards )
272 frd.matchMode = EDA_SEARCH_MATCH_MODE::WILDCARD;
273 else
274 frd.matchMode = EDA_SEARCH_MATCH_MODE::PLAIN;
275
277
278 // Search parameters
279 frd.findString = searchString;
280
282 m_frame->GetCanvas()->GetViewStart( &screen->m_StartVisu.x, &screen->m_StartVisu.y );
283
284 BOARD* board = m_frame->GetBoard();
285
286 // Refresh the list of results
287 if( !m_upToDate )
288 {
289 m_status->SetLabel( _( "Searching..." ) );
290 m_hitList.clear();
291
293 {
294 for( FOOTPRINT* fp : board->Footprints() )
295 {
296 bool found = false;
297
298 if( g_FindIncludeReferences && fp->Reference().Matches( frd, nullptr ) )
299 found = true;
300
301 if( !found && g_FindIncludeValues && fp->Value().Matches( frd, nullptr ) )
302 found = true;
303
304 if( !found && m_includeTexts->GetValue() )
305 {
306 for( BOARD_ITEM* item : fp->GraphicalItems() )
307 {
308 if( item->Type() == PCB_TEXT_T )
309 {
310 PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
311
312 if( text->Matches( frd, nullptr ) )
313 {
314 found = true;
315 break;
316 }
317 }
318 }
319 }
320
321 if( !found && m_includeTexts->GetValue() )
322 {
323 for( PCB_FIELD* field : fp->GetFields() )
324 {
325 if( field->Matches( frd, nullptr ) )
326 {
327 found = true;
328 break;
329 }
330 }
331 }
332
333 if( found )
334 m_hitList.push_back( fp );
335 }
336
338 {
339 for( BOARD_ITEM* item : board->Drawings() )
340 {
341 if( item->Type() == PCB_TEXT_T )
342 {
343 PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
344
345 if( text && text->Matches( frd, nullptr ) )
346 m_hitList.push_back( text );
347 }
348 }
349
350 for( BOARD_ITEM* item : board->Zones() )
351 {
352 ZONE* zone = static_cast<ZONE*>( item );
353
354 if( zone->Matches( frd, nullptr ) )
355 m_hitList.push_back( zone );
356 }
357 }
358 }
359
361 {
362 for( PCB_MARKER* marker : board->Markers() )
363 {
364 if( marker->Matches( frd, nullptr ) )
365 m_hitList.push_back( marker );
366 }
367 }
368
370 {
371 for( NETINFO_ITEM* net : board->GetNetInfo() )
372 {
373 if( net && net->Matches( frd, nullptr ) )
374 m_hitList.push_back( net );
375 }
376 }
377
378 m_upToDate = true;
379 isFirstSearch = true;
380
381 if( aDirection )
382 m_it = m_hitList.begin();
383 else
384 m_it = m_hitList.end();
385 }
386
387 // Do we want a sorting algorithm ? If so, implement it here.
388
389 // Get the item to display
390 if( m_hitList.empty() )
391 {
392 m_frame->SetStatusText( wxEmptyString );
393 }
394 else
395 {
396 if( aDirection )
397 {
398 if( m_it != m_hitList.end() && !isFirstSearch )
399 m_it++;
400
401 if( m_it == m_hitList.end() )
402 {
403 if( m_wrap->GetValue() )
404 {
405 m_it = m_hitList.begin();
406 }
407 else
408 {
409 endIsReached = true;
410 m_it--; // point to the last REAL result
411 }
412 }
413 }
414 else
415 {
416 if( m_it == m_hitList.begin() )
417 {
418 if( m_wrap->GetValue() )
419 m_it = m_hitList.end();
420 else
421 endIsReached = true;
422 }
423
424 if( m_it != m_hitList.begin() )
425 m_it--;
426 }
427 }
428
429 // Display the item
430 if( m_hitList.empty() )
431 {
432 m_frame->SetStatusText( wxEmptyString );
433 msg.Printf( _( "'%s' not found" ), searchString );
434 m_frame->ShowInfoBarMsg( msg );
435
436 m_status->SetLabel( msg );
437 }
438 else if( endIsReached || m_it == m_hitList.end() )
439 {
440 m_frame->SetStatusText( wxEmptyString );
441 m_frame->ShowInfoBarMsg( _( "No more items to show" ) );
442
443 m_status->SetLabel( _( "No hits" ) );
444 }
445 else
446 {
448
449 msg.Printf( _( "'%s' found" ), searchString );
450 m_frame->SetStatusText( msg );
451
452 msg.Printf( _( "Hit(s): %d / %zu" ),
453 (int)std::distance( m_hitList.begin(), m_it ) + 1,
454 m_hitList.size() );
455 m_status->SetLabel( msg );
456 }
457
460}
461
462
463void DIALOG_FIND::OnCloseButtonClick( wxCommandEvent& aEvent )
464{
465 wxCloseEvent tmp;
466
467 OnClose( tmp );
468
469 aEvent.Skip();
470}
471
472bool DIALOG_FIND::Show( bool show )
473{
474 bool ret = DIALOG_FIND_BASE::Show( show );
475
476 if( show )
477 m_searchCombo->SetFocus();
478
479 return ret;
480}
481
482
483void DIALOG_FIND::OnClose( wxCloseEvent& aEvent )
484{
485 g_FindOptionCase = m_matchCase->GetValue();
486 g_FindOptionWords = m_matchWords->GetValue();
488 g_FindOptionWrap = m_wrap->GetValue();
489
494 g_FindIncludeNets = m_includeNets->GetValue();
495
496 aEvent.Skip();
497}
static TOOL_ACTION selectItem
Select an item (specified as the event parameter).
Definition: actions.h:220
static TOOL_ACTION showSearch
Definition: actions.h:115
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: actions.h:217
VECTOR2I m_StartVisu
Coordinates in drawing units of the current view position (upper left corner of device)
Definition: base_screen.h:93
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:317
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:932
const ZONES & Zones() const
Definition: board.h:362
const MARKERS & Markers() const
Definition: board.h:370
const FOOTPRINTS & Footprints() const
Definition: board.h:358
const DRAWINGS & Drawings() const
Definition: board.h:360
Class DIALOG_FIND_BASE.
wxCheckBox * m_checkAllFields
wxCheckBox * m_matchCase
wxCheckBox * m_includeTexts
wxCheckBox * m_includeValues
wxHyperlinkCtrl * m_searchPanelLink
wxButton * m_findNext
wxComboBox * m_searchCombo
wxCheckBox * m_includeReferences
wxCheckBox * m_matchWords
wxCheckBox * m_includeNets
wxStaticText * m_status
wxCheckBox * m_includeMarkers
wxCheckBox * m_wildcards
wxCheckBox * m_wrap
PCB_EDIT_FRAME * m_frame
Definition: dialog_find.h:95
void onTextEnter(wxCommandEvent &event) override
DIALOG_FIND(PCB_EDIT_FRAME *aParent)
Definition: dialog_find.cpp:56
bool Show(bool show=true) override
The Show method is overridden to make the search combobox focused by default.
std::deque< BOARD_ITEM * >::iterator m_it
Definition: dialog_find.h:97
void Preload(const wxString &aFindString)
void onFindNextClick(wxCommandEvent &event) override
void search(bool direction)
bool m_upToDate
Definition: dialog_find.h:98
void onSearchAgainClick(wxCommandEvent &event) override
BOARD_ITEM * GetItem() const
Return the currently found item or nullptr in the case of no items found.
Definition: dialog_find.h:50
void onShowSearchPanel(wxHyperlinkEvent &event) override
void onFindPreviousClick(wxCommandEvent &event) override
void OnClose(wxCloseEvent &event) override
std::function< void(BOARD_ITEM *)> m_highlightCallback
Definition: dialog_find.h:100
void OnCloseButtonClick(wxCommandEvent &aEvent) override
std::deque< BOARD_ITEM * > m_hitList
Definition: dialog_find.h:96
bool Show(bool show) override
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:66
void ShowInfoBarMsg(const wxString &aMsg, bool aShowCloseButton=false)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an info icon on the left of...
wxArrayString & GetFindHistoryList()
EDA_SEARCH_DATA & GetFindReplaceData()
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:97
Handle the data for a net.
Definition: netinfo.h:56
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
BOARD * GetBoard() const
The main frame for Pcbnew.
bool IsSearchPaneShown()
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
Handle a list of polygons defining a copper zone.
Definition: zone.h:74
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: zone.h:166
bool g_FindOptionWrap
Definition: dialog_find.cpp:46
bool g_FindIncludeTexts
Definition: dialog_find.cpp:48
bool g_FindIncludeValues
Definition: dialog_find.cpp:49
bool g_FindIncludeHiddenFields
Definition: dialog_find.cpp:51
bool g_FindIncludeMarkers
Definition: dialog_find.cpp:52
bool g_FindIncludeReferences
Definition: dialog_find.cpp:50
bool g_FindOptionWords
Definition: dialog_find.cpp:44
bool g_FindIncludeNets
Definition: dialog_find.cpp:53
bool g_FindOptionWildcards
Definition: dialog_find.cpp:45
bool g_FindOptionCase
Definition: dialog_find.cpp:43
#define _(s)
#define PCB_EDIT_FRAME_NAME
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Return the key name from the key code.
EDA_SEARCH_MATCH_MODE matchMode
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92