KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_base_frame.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 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <algorithm>
26#include <advanced_config.h>
27#include <base_units.h>
28#include <kiplatform/io.h>
31#include <kiway.h>
33#include <pgm_base.h>
34#include <eda_list_dialog.h>
37#include <eeschema_settings.h>
41#include <sch_draw_panel.h>
43#include <sch_group.h>
44#include <sch_view.h>
45#include <sch_painter.h>
46#include <sch_shape.h>
49#include <widgets/wx_infobar.h>
50#include <string_utils.h>
51#include <confirm.h>
53#include <project_sch.h>
56#include <sch_base_frame.h>
58#include <design_block.h>
59#include <thread_pool.h>
60#include <tool/actions.h>
61#include <tool/action_toolbar.h>
62#include <tool/tool_manager.h>
65#include <trace_helpers.h>
66#include <view/view_controls.h>
67#include <widgets/kistatusbar.h>
68#include <wx/choicdlg.h>
69#include <wx/evtloop.h>
70#include <wx/fswatcher.h>
71#include <wx/log.h>
72#include <wx/msgdlg.h>
73#include <trace_helpers.h>
74
75#if defined(__linux__) || defined(__FreeBSD__)
77#else
79#include <wx/fdrepdlg.h>
80#endif
81
82
84 LEGACY_SYMBOL_LIB* aCacheLib, wxWindow* aParent, bool aShowErrorMsg )
85{
86 wxCHECK_MSG( aLibMgr, nullptr, wxS( "Invalid symbol library manager adapter." ) );
87
88 LIB_SYMBOL* symbol = nullptr;
89
90 try
91 {
92 symbol = aLibMgr->LoadSymbol( aLibId );
93
94 if( !symbol && aCacheLib )
95 {
96 wxCHECK_MSG( aCacheLib->IsCache(), nullptr, wxS( "Invalid cache library." ) );
97
98 wxString cacheName = aLibId.GetLibNickname().wx_str();
99 cacheName << "_" << aLibId.GetLibItemName();
100 symbol = aCacheLib->FindSymbol( cacheName );
101 }
102 }
103 catch( const IO_ERROR& ioe )
104 {
105 if( aShowErrorMsg )
106 {
107 wxString msg = wxString::Format( _( "Error loading symbol %s from library '%s'." ),
108 aLibId.GetLibItemName().wx_str(),
109 aLibId.GetLibNickname().wx_str() );
110 DisplayErrorMessage( aParent, msg, ioe.What() );
111 }
112 }
113
114 return symbol;
115}
116
117
118SCH_BASE_FRAME::SCH_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aWindowType,
119 const wxString& aTitle, const wxPoint& aPosition,
120 const wxSize& aSize, long aStyle, const wxString& aFrameName ) :
121 EDA_DRAW_FRAME( aKiway, aParent, aWindowType, aTitle, aPosition, aSize, aStyle,
122 aFrameName, schIUScale ),
123 m_selectionFilterPanel( nullptr ),
124 m_findReplaceDialog( nullptr ),
125 m_base_frame_defaults( nullptr, "base_Frame_defaults" ),
127 m_watcherIsDir( false ),
129{
130 m_findReplaceData = std::make_unique<SCH_SEARCH_DATA>();
131
132 if( ( aStyle & wxFRAME_NO_TASKBAR ) == 0 )
133 createCanvas();
134
135 Bind( wxEVT_IDLE,
136 [this]( wxIdleEvent& aEvent )
137 {
138 // Handle cursor adjustments. While we can get motion and key events through
139 // wxWidgets, we can't get modifier-key-up events.
140 if( m_toolManager )
141 {
143
144 if( selTool )
145 selTool->OnIdle( aEvent );
146 }
147 } );
148
149 Pgm().GetBackgroundJobMonitor().RegisterStatusBar( static_cast<KISTATUSBAR*>( GetStatusBar() ) );
150
152}
153
154
157{
158 Pgm().GetBackgroundJobMonitor().UnregisterStatusBar( static_cast<KISTATUSBAR*>( GetStatusBar() ) );
159}
160
161
163{
164 GetCanvas()->SetEvtHandlerEnabled( false );
166
167 // Shutdown all running tools
168 if( m_toolManager )
169 m_toolManager->ShutdownAllTools();
170
171 // Close the find dialog and preserve its setting if it is displayed.
173 {
175 m_replaceStringHistoryList = m_findReplaceDialog->GetReplaceEntries();
176
177 m_findReplaceDialog->Destroy();
178 m_findReplaceDialog = nullptr;
179 }
180
181 // This class is pure virtual. Derived class will finish shutdown and Destroy().
182}
183
184
189
190
192{
193 return dynamic_cast<EESCHEMA_SETTINGS*>( config() );
194}
195
196
201
202
204{
205 switch( GetFrameType() )
206 {
207 case FRAME_SCH:
208 default:
209 return GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" );
210
212 case FRAME_SCH_VIEWER:
214 return GetAppSettings<SYMBOL_EDITOR_SETTINGS>( "symbol_editor" );
215 }
216}
217
218
219void SCH_BASE_FRAME::SetPageSettings( const PAGE_INFO& aPageSettings )
220{
221 GetScreen()->SetPageSettings( aPageSettings );
222}
223
224
226{
227 return GetScreen()->GetPageSettings();
228}
229
230
232{
233 // GetSizeIU is compile time dependent:
234 return GetScreen()->GetPageSettings().GetSizeIU( schIUScale.IU_PER_MILS );
235}
236
237
239{
240 wxASSERT( GetScreen() );
241 return GetScreen()->GetTitleBlock();
242}
243
244
246{
247 wxASSERT( GetScreen() );
248 GetScreen()->SetTitleBlock( aTitleBlock );
249}
250
251
253{
254 wxString line;
255 BASE_SCREEN* screen = GetScreen();
256
257 if( !screen )
258 return;
259
261
262 // Display absolute and relative coordinates
264 VECTOR2D d = cursorPos - screen->m_LocalOrigin;
265
266 line.Printf( wxS( "X %s Y %s" ),
267 MessageTextFromValue( cursorPos.x, false ),
268 MessageTextFromValue( cursorPos.y, false ) );
269 SetStatusText( line, 2 );
270
271 line.Printf( wxS( "dx %s dy %s dist %s" ),
272 MessageTextFromValue( d.x, false ),
273 MessageTextFromValue( d.y, false ),
274 MessageTextFromValue( hypot( d.x, d.y ), false ) );
275 SetStatusText( line, 3 );
276
279}
280
281
282LIB_SYMBOL* SCH_BASE_FRAME::GetLibSymbol( const LIB_ID& aLibId, bool aUseCacheLib,
283 bool aShowErrorMsg )
284{
285 LEGACY_SYMBOL_LIB* cache =
286 ( aUseCacheLib ) ? PROJECT_SCH::LegacySchLibs( &Prj() )->GetCacheLibrary() : nullptr;
287
288 return SchGetLibSymbol( aLibId, PROJECT_SCH::SymbolLibAdapter( &Prj() ), cache, this,
289 aShowErrorMsg );
290}
291
292
293void SCH_BASE_FRAME::RedrawScreen( const VECTOR2I& aCenterPoint, bool aWarpPointer )
294{
295 GetCanvas()->GetView()->SetCenter( aCenterPoint );
296
297 if( aWarpPointer )
299
300 GetCanvas()->Refresh();
301}
302
303
305{
306 if( GetCanvas() && GetCanvas()->GetView() )
307 {
310 }
311}
312
313
318
319
321{
322 if( GetCanvas() && GetCanvas()->GetView() )
323 {
324 if( KIGFX::PAINTER* painter = GetCanvas()->GetView()->GetPainter() )
325 return static_cast<SCH_RENDER_SETTINGS*>( painter->GetSettings() );
326 }
327
328 return nullptr;
329}
330
331
333{
335
336 SetCanvas( new SCH_DRAW_PANEL( this, wxID_ANY, wxPoint( 0, 0 ), m_frameSize,
339}
340
341
343{
345
346 try
347 {
348 if( !m_spaceMouse )
349 {
350#if defined(__linux__) || defined(__FreeBSD__)
351 m_spaceMouse = std::make_unique<SPNAV_2D_PLUGIN>( GetCanvas() );
352 m_spaceMouse->SetScale( schIUScale.IU_PER_MILS / pcbIUScale.IU_PER_MILS );
353#else
354 m_spaceMouse = std::make_unique<NL_SCHEMATIC_PLUGIN>();
355#endif
356 }
357
358 m_spaceMouse->SetCanvas( GetCanvas() );
359 }
360 catch( const std::system_error& e )
361 {
362 wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() );
363 }
364}
365
366
367void SCH_BASE_FRAME::UpdateItem( EDA_ITEM* aItem, bool isAddOrDelete, bool aUpdateRtree )
368{
369 EDA_ITEM* parent = aItem->GetParent();
370
371 if( aItem->Type() == SCH_SHEET_PIN_T )
372 {
373 // Sheet pins aren't in the view. Refresh their parent.
374 if( parent )
375 GetCanvas()->GetView()->Update( parent );
376 }
377 else
378 {
379 if( aItem->Type() == SCH_SHAPE_T )
380 static_cast<SCH_SHAPE*>( aItem )->UpdateHatching();
381
382 if( !isAddOrDelete )
383 GetCanvas()->GetView()->Update( aItem );
384
385 // Some children are drawn from their parents. Mark them for re-paint.
386 if( parent && ( parent->Type() == SCH_SYMBOL_T
387 || parent->Type() == SCH_SHEET_T
388 || parent->Type() == SCH_LABEL_LOCATE_ANY_T
389 || parent->Type() == SCH_TABLE_T ) )
390 {
391 GetCanvas()->GetView()->Update( parent, KIGFX::REPAINT );
392 }
393 }
394
395 /*
396 * Be careful when calling this. Update will invalidate RTree iterators, so you cannot
397 * call this while doing things like `for( SCH_ITEM* item : screen->Items() )`
398 */
399 if( aUpdateRtree && dynamic_cast<SCH_ITEM*>( aItem ) )
400 {
401 GetScreen()->Update( static_cast<SCH_ITEM*>( aItem ) );
402
403 /*
404 * If we are updating the group, we also need to update all the children otherwise
405 * their positions will remain stale in the RTree
406 */
407 if( SCH_GROUP* group = dynamic_cast<SCH_GROUP*>( aItem ) )
408 {
409 group->RunOnChildren(
410 [&]( SCH_ITEM* item )
411 {
412 GetScreen()->Update( item );
413 },
415 }
416 }
417
418 // Calling Refresh() here introduces a bi-stable state: when doing operations on a
419 // large number of items if at some point the refresh timer times out and does a
420 // refresh it will take long enough that the next item will also time out, and the
421 // next, and the next, etc.
422 // GetCanvas()->Refresh();
423}
424
425
427{
428 // We currently have two zoom-dependent renderings: text, which is rendered as bitmap text
429 // when too small to see the difference, and selection shadows.
430 //
431 // Because non-selected text is cached by OpenGL, we only apply the bitmap performance hack
432 // to selected text items.
433 //
434 // Thus, as it currently stands, all zoom-dependent items can be found in the list of selected
435 // items.
436 if( m_toolManager )
437 {
438 SCH_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<SCH_SELECTION_TOOL>();
439 SELECTION& selection = selectionTool->GetSelection();
440 KIGFX::SCH_VIEW* view = GetCanvas()->GetView();
441
442 for( EDA_ITEM* item : selection )
443 {
444 if( item->RenderAsBitmap( view->GetGAL()->GetWorldScale() ) != item->IsShownAsBitmap()
446 {
447 view->Update( item, KIGFX::REPAINT );
448
449 EDA_ITEM* parent = item->GetParent();
450
451 // Symbol children are drawn from their parents. Mark them for re-paint.
452 if( parent && parent->Type() == SCH_SYMBOL_T )
453 GetCanvas()->GetView()->Update( parent, KIGFX::REPAINT );
454 }
455 }
456 }
457}
458
459
461{
462 // Null pointers will cause boost::ptr_vector to raise a boost::bad_pointer exception which
463 // will be unhandled. There is no valid reason to pass an invalid EDA_ITEM pointer to the
464 // screen append function.
465 wxCHECK( aItem, /* void */ );
466
467 SCH_SCREEN* screen = aScreen;
468
469 if( aScreen == nullptr )
470 screen = GetScreen();
471
472 if( aItem->Type() != SCH_TABLECELL_T )
473 screen->Append( (SCH_ITEM*) aItem );
474
475 if( screen == GetScreen() )
476 {
477 GetCanvas()->GetView()->Add( aItem );
478 UpdateItem( aItem, true ); // handle any additional parent semantics
479 }
480}
481
482
484{
485 auto screen = aScreen;
486
487 if( aScreen == nullptr )
488 screen = GetScreen();
489
490 if( screen == GetScreen() )
491 GetCanvas()->GetView()->Remove( aItem );
492
493 if( aItem->Type() != SCH_TABLECELL_T )
494 screen->Remove( (SCH_ITEM*) aItem );
495
496 if( screen == GetScreen() )
497 UpdateItem( aItem, true ); // handle any additional parent semantics
498}
499
500
502{
503 // Let tools add things to the view if necessary
504 if( m_toolManager )
506
508}
509
510
515
516
518{
519 wxString findString;
520
521 SCH_SELECTION& selection = m_toolManager->GetTool<SCH_SELECTION_TOOL>()->GetSelection();
522
523 if( selection.Size() == 1 )
524 {
525 EDA_ITEM* front = selection.Front();
526
527 switch( front->Type() )
528 {
529 case SCH_SYMBOL_T:
530 {
531 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( front );
532 findString = UnescapeString( symbol->GetField( FIELD_T::VALUE )->GetText() );
533 break;
534 }
535
536 case SCH_FIELD_T:
537 findString = UnescapeString( static_cast<SCH_FIELD*>( front )->GetText() );
538 break;
539
540 case SCH_LABEL_T:
542 case SCH_HIER_LABEL_T:
543 case SCH_SHEET_PIN_T:
544 findString = UnescapeString( static_cast<SCH_LABEL_BASE*>( front )->GetText() );
545 break;
546
547 case SCH_TEXT_T:
548 findString = UnescapeString( static_cast<SCH_TEXT*>( front )->GetText() );
549
550 if( findString.Contains( wxT( "\n" ) ) )
551 findString = findString.Before( '\n' );
552
553 break;
554
555 default:
556 break;
557 }
558 }
559
561 m_findReplaceDialog->Destroy();
562
563 m_findReplaceDialog = new DIALOG_SCH_FIND( this, static_cast<SCH_SEARCH_DATA*>( m_findReplaceData.get() ),
564 wxDefaultPosition, wxDefaultSize, aReplace ? wxFR_REPLACEDIALOG : 0 );
565
566 m_findReplaceDialog->SetFindEntries( m_findStringHistoryList, findString );
568 m_findReplaceDialog->Show( true );
569}
570
571
572void SCH_BASE_FRAME::ShowFindReplaceStatus( const wxString& aMsg, int aStatusTime )
573{
574 // Prepare the infobar, since we don't know its state
575 m_infoBar->RemoveAllButtons();
576 m_infoBar->AddCloseButton();
577
578 m_infoBar->ShowMessageFor( aMsg, aStatusTime, wxICON_INFORMATION );
579}
580
581
583{
584 m_infoBar->Dismiss();
585}
586
587
589{
591 m_replaceStringHistoryList = m_findReplaceDialog->GetReplaceEntries();
592
593 m_findReplaceDialog->Destroy();
594 m_findReplaceDialog = nullptr;
595
597}
598
599
613
614
616{
617 if( !m_colorSettings || aForceRefresh )
618 {
620 wxString colorTheme = cfg ? cfg->m_ColorTheme : wxString( "" );
621
623 {
624 if( SYMBOL_EDITOR_SETTINGS* sym_edit_cfg = GetAppSettings<SYMBOL_EDITOR_SETTINGS>( "symbol_editor" ) )
625 {
626 if( !sym_edit_cfg->m_UseEeschemaColorSettings )
627 colorTheme = sym_edit_cfg->m_ColorTheme;
628 }
629 }
630
631 const_cast<SCH_BASE_FRAME*>( this )->m_colorSettings = ::GetColorSettings( colorTheme );
632 }
633
634 return m_colorSettings;
635}
636
637
642
643
644void SCH_BASE_FRAME::handleActivateEvent( wxActivateEvent& aEvent )
645{
647
648 if( m_spaceMouse )
649 m_spaceMouse->SetFocus( aEvent.GetActive() );
650}
651
652
653void SCH_BASE_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent )
654{
656
657 if( m_spaceMouse )
658 m_spaceMouse->SetFocus( false );
659}
660
661
663 std::vector<wxArrayString>& aItemsToDisplay )
664{
665 aHeaders.Add( _( "Library" ) );
666 aHeaders.Add( _( "Description" ) );
667
671 std::vector<wxString> libNicknames = adapter->GetLibraryNames();
672 std::vector<wxArrayString> unpinned;
673
674 for( const wxString& nickname : libNicknames )
675 {
676 wxArrayString item;
677 wxString description = adapter->GetLibraryDescription( nickname ).value_or( wxEmptyString );
678
679 if( alg::contains( project.m_PinnedSymbolLibs, nickname )
680 || alg::contains( cfg->m_Session.pinned_symbol_libs, nickname ) )
681 {
682 item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
683 item.Add( description );
684 aItemsToDisplay.push_back( item );
685 }
686 else
687 {
688 item.Add( nickname );
689 item.Add( description );
690 unpinned.push_back( item );
691 }
692 }
693
694 std::sort( aItemsToDisplay.begin(), aItemsToDisplay.end(),
695 []( const wxArrayString& a, const wxArrayString& b )
696 {
697 return StrNumCmp( a[0], b[0], true ) < 0;
698 } );
699
700 std::sort( unpinned.begin(), unpinned.end(),
701 []( const wxArrayString& a, const wxArrayString& b )
702 {
703 return StrNumCmp( a[0], b[0], true ) < 0;
704 } );
705
706 std::ranges::copy( unpinned, std::back_inserter( aItemsToDisplay ) );
707}
708
709
710wxString SCH_BASE_FRAME::SelectLibrary( const wxString& aDialogTitle, const wxString& aListLabel,
711 const std::vector<std::pair<wxString, bool*>>& aExtraCheckboxes )
712{
713 static const int ID_MAKE_NEW_LIBRARY = wxID_HIGHEST;
714
715 // Keep asking the user for a new name until they give a valid one or cancel the operation
716 while( true )
717 {
718 wxArrayString headers;
719 std::vector<wxArrayString> itemsToDisplay;
720
721 GetLibraryItemsForListDialog( headers, itemsToDisplay );
722
723 wxString libraryName = Prj().GetRString( PROJECT::SCH_LIB_SELECT );
724
725 EDA_LIST_DIALOG dlg( this, aDialogTitle, headers, itemsToDisplay, libraryName, false );
726 dlg.SetListLabel( aListLabel );
727
728 for( const auto& [label, val] : aExtraCheckboxes )
729 dlg.AddExtraCheckbox( label, val );
730
731 wxButton* newLibraryButton = new wxButton( &dlg, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
732 dlg.m_ButtonsSizer->Prepend( 80, 20 );
733 dlg.m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
734
735 newLibraryButton->Bind( wxEVT_BUTTON,
736 [&dlg]( wxCommandEvent& )
737 {
738 dlg.EndModal( ID_MAKE_NEW_LIBRARY );
740
741 dlg.Layout();
742 dlg.GetSizer()->Fit( &dlg );
743
744 int ret = dlg.ShowModal();
745
746 switch( ret )
747 {
748 case wxID_CANCEL:
749 return wxEmptyString;
750
751 case wxID_OK:
752 libraryName = dlg.GetTextSelection();
753 Prj().SetRString( PROJECT::SCH_LIB_SELECT, libraryName );
755 return libraryName;
756
758 {
759 SYMBOL_LIBRARY_MANAGER mgr( *this );
760 wxFileName fn( Prj().GetRString( PROJECT::SCH_LIB_PATH ) );
761 bool useGlobalTable = false;
762 FILEDLG_HOOK_NEW_LIBRARY tableChooser( useGlobalTable );
763
764 if( !LibraryFileBrowser( _( "Create New Library" ), false, fn, FILEEXT::KiCadSymbolLibFileWildcard(),
765 FILEEXT::KiCadSymbolLibFileExtension, false, &tableChooser ) )
766 {
767 break;
768 }
769
770 libraryName = fn.GetName();
771 Prj().SetRString( PROJECT::SCH_LIB_PATH, fn.GetPath() );
772
776
777 if( adapter->HasLibrary( libraryName, false ) )
778 {
779 DisplayError( this, wxString::Format( _( "Library '%s' already exists." ), libraryName ) );
780 break;
781 }
782
783 if( !mgr.CreateLibrary( fn.GetFullPath(), scope ) )
784 DisplayError( this, wxString::Format( _( "Could not add library '%s'." ), libraryName ) );
785
786 break;
787 }
788
789 default:
790 break;
791 }
792 }
793}
794
795
797{
798 Unbind( wxEVT_FSWATCHER, &SCH_BASE_FRAME::OnSymChange, this );
799
800 if( m_watcher )
801 {
802 wxLogTrace( traceLibWatch, "Remove watch" );
803 m_watcher->RemoveAll();
804 m_watcher->SetOwner( nullptr );
805 m_watcher.reset();
806 }
807
808 if( !aID )
809 return;
810
812 std::optional<wxString> uri = manager.GetFullURI( LIBRARY_TABLE_TYPE::SYMBOL,
813 aID->GetLibNickname() );
814
815 if( !uri )
816 {
817 wxLogTrace( traceLibWatch, "Could not get URI for library %s",
818 wxString( aID->GetLibNickname().c_str() ) );
819 return;
820 }
821
822 wxString tmp = ExpandEnvVarSubstitutions( *uri, &Prj() );
823
824 wxLogTrace( traceLibWatch, "Setting up watcher for %s", tmp );
825
826 if( wxFileName::DirExists( tmp ) )
827 {
828 m_watcherFileName.AssignDir( tmp );
829 m_watcherIsDir = true;
831 m_watcherFileName.GetPath(),
832 wxS( "*." ) + wxString( FILEEXT::KiCadSymbolLibFileExtension ) );
833 }
834 else
835 {
836 m_watcherFileName.Assign( tmp );
837 m_watcherIsDir = false;
838
839 if( !m_watcherFileName.FileExists() )
840 return;
841
842 wxLogNull silence;
843 m_watcherTimestamp = m_watcherFileName.GetModificationTime().GetValue().GetValue();
844 }
845
846 // File system watcher requires an active event loop. If we're being called during
847 // library enumeration before the main event loop is running, skip watcher creation.
848 if( !wxEventLoopBase::GetActive() )
849 return;
850
851 Bind( wxEVT_FSWATCHER, &SCH_BASE_FRAME::OnSymChange, this );
852 m_watcher = std::make_unique<wxFileSystemWatcher>();
853 m_watcher->SetOwner( this );
854
855 wxFileName fn;
856 fn.AssignDir( m_watcherFileName.GetPath() );
857 fn.DontFollowLink();
858
859 {
860 // Silence OS errors that come from the watcher
861 wxLogNull silence;
862 m_watcher->Add( fn );
863 }
864}
865
866
867void SCH_BASE_FRAME::OnSymChange( wxFileSystemWatcherEvent& aEvent )
868{
869 wxLogTrace( traceLibWatch, "OnSymChange: %s, watcher file: %s",
870 aEvent.GetPath().GetFullPath(), m_watcherFileName.GetFullPath() );
871
872 if( !m_watcher || !m_watcher.get() || m_watcherFileName.GetPath().IsEmpty() )
873 return;
874
875 if( m_watcherIsDir )
876 {
877 // For directory-based libraries, accept events for any file within the directory
878 wxString eventPath = aEvent.GetPath().GetFullPath();
879 wxString dirPath = m_watcherFileName.GetPath();
880
881 if( !eventPath.StartsWith( dirPath ) )
882 return;
883 }
884 else
885 {
886 if( aEvent.GetPath() != m_watcherFileName )
887 return;
888 }
889
890 // Start the debounce timer (set to 1 second)
891 if( !m_watcherDebounceTimer.StartOnce( 1000 ) )
892 {
893 wxLogTrace( traceLibWatch, "Failed to start the debounce timer" );
894 return;
895 }
896}
897
898
900{
901 if( aEvent.GetId() != m_watcherDebounceTimer.GetId() )
902 {
903 aEvent.Skip();
904 return;
905 }
906
908 {
909 wxLogTrace( traceLibWatch, "Restarting debounce timer" );
910 m_watcherDebounceTimer.StartOnce( 3000 );
911 return;
912 }
913
914 // If the frame is currently disabled then a quasi-modal/modal dialog is open on top
915 // of it (for example the symbol properties dialog). Reloading the library now would
916 // delete the LIB_SYMBOL the dialog is editing and crash on dialog close. Defer the
917 // reload until the dialog is dismissed.
918 if( !IsEnabled() )
919 {
920 wxLogTrace( traceLibWatch, "Frame disabled (dialog open); restarting debounce timer" );
921 m_watcherDebounceTimer.StartOnce( 1000 );
922 return;
923 }
924
925 wxLogTrace( traceLibWatch, "OnSymChangeDebounceTimer" );
926
927 long long currentTimestamp = 0;
928
929 if( m_watcherIsDir )
930 {
931 currentTimestamp = KIPLATFORM::IO::TimestampDir(
932 m_watcherFileName.GetPath(),
933 wxS( "*." ) + wxString( FILEEXT::KiCadSymbolLibFileExtension ) );
934 }
935 else
936 {
937 wxLogNull silence;
938 wxDateTime lastModified = m_watcherFileName.GetModificationTime();
939
940 if( !lastModified.IsValid() )
941 return;
942
943 currentTimestamp = lastModified.GetValue().GetValue();
944 }
945
946 if( currentTimestamp == m_watcherTimestamp )
947 return;
948
949 m_watcherTimestamp = currentTimestamp;
950
952
954 || IsOK( this, _( "The library containing the current symbol has changed.\n"
955 "Do you want to reload the library?" ) ) )
956 {
957 wxLogTrace( traceLibWatch, "Sending refresh symbol mail" );
958
959 // For directory libraries, GetFullPath() appends a trailing separator which
960 // won't match the library table URI. Use GetPath() for directories instead.
961 std::string libName = m_watcherIsDir
962 ? m_watcherFileName.GetPath().ToStdString()
963 : m_watcherFileName.GetFullPath().ToStdString();
964
967 }
968
970}
971
972
974{
975 if( m_toolManager )
976 return m_toolManager->GetTool<SCH_SELECTION_TOOL>();
977
978 return nullptr;
979}
980
981
983{
984 SCH_SELECTION_FILTER_EVENT evt( aOptions );
985 wxPostEvent( this, evt );
986}
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:127
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:125
static TOOL_ACTION updateFind
Definition actions.h:124
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
wxString m_ColorTheme
Active color theme name.
void UnregisterStatusBar(KISTATUSBAR *aStatusBar)
Removes status bar from handling.
void RegisterStatusBar(KISTATUSBAR *aStatusBar)
Add a status bar for handling.
Handles how to draw a screen (a board, a schematic ...)
Definition base_screen.h:41
VECTOR2D m_LocalOrigin
Relative Screen cursor coordinate (on grid) in user units.
Definition base_screen.h:90
Color settings are a bit different than most of the settings objects in that there can be more than o...
COLOR4D GetColor(int aLayer) const
int ShowModal() override
FRAME_T GetFrameType() const
virtual APP_SETTINGS_BASE * config() const
Return the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
virtual void handleIconizeEvent(wxIconizeEvent &aEvent)
Handle a window iconize event.
WX_INFOBAR * m_infoBar
virtual bool IsContentModified() const
Get if the contents of the frame have been modified since the last save.
bool IsType(FRAME_T aType) const
wxArrayString m_replaceStringHistoryList
virtual void ActivateGalCanvas()
Use to start up the GAL drawing canvas.
COLOR_SETTINGS * m_colorSettings
EDA_DRAW_PANEL_GAL::GAL_TYPE m_canvasType
The current canvas type.
virtual BASE_SCREEN * GetScreen() const
Return a pointer to a BASE_SCREEN or one of its derivatives.
void DisplayUnitsMsg()
Display current unit pane in the status bar.
GAL_DISPLAY_OPTIONS_IMPL & GetGalDisplayOptions()
Return a reference to the gal rendering options used by GAL for rendering.
void SetCanvas(EDA_DRAW_PANEL_GAL *aPanel)
EDA_DRAW_FRAME(KIWAY *aKiway, wxWindow *aParent, FRAME_T aFrameType, const wxString &aTitle, const wxPoint &aPos, const wxSize &aSize, long aStyle, const wxString &aFrameName, const EDA_IU_SCALE &aIuScale)
bool LibraryFileBrowser(const wxString &aTitle, bool doOpen, wxFileName &aFilename, const wxString &wildcard, const wxString &ext, bool isDirectory, FILEDLG_HOOK_NEW_LIBRARY *aFileDlgHook=nullptr)
virtual void handleActivateEvent(wxActivateEvent &aEvent)
Handle a window activation event.
void UpdateStatusBar() override
Update the status bar information.
virtual EDA_DRAW_PANEL_GAL * GetCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
virtual void DisplayGridMsg()
Display current grid size in the status bar.
EDA_DRAW_PANEL_GAL::GAL_TYPE loadCanvasTypeSetting()
Return the canvas type stored in the application settings.
wxArrayString m_findStringHistoryList
std::unique_ptr< EDA_SEARCH_DATA > m_findReplaceData
void CommonSettingsChanged(int aFlags) override
Notification event that some of the common (suite-wide) settings have changed.
void StopDrawing()
Prevent the GAL canvas from further drawing until it is recreated or StartDrawing() is called.
KIGFX::VIEW_CONTROLS * GetViewControls() const
Return a pointer to the #VIEW_CONTROLS instance used in the panel.
void ForceRefresh()
Force a redraw.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
KIGFX::GAL * GetGAL() const
Return a pointer to the GAL instance used in the panel.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:100
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:112
EDA_ITEM * GetParent() const
Definition eda_item.h:114
A dialog which shows:
wxString GetTextSelection(int aColumn=0)
Return the selected text from aColumn in the wxListCtrl in the dialog.
void SetListLabel(const wxString &aLabel)
void AddExtraCheckbox(const wxString &aLabel, bool *aValuePtr)
Add a checkbox value to the dialog.
void GetExtraCheckboxValues()
Fills in the value pointers from the checkboxes after the dialog has run.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:105
void SetAxesColor(const COLOR4D &aAxesColor)
Set the axes color.
double GetWorldScale() const
Get the world scale.
Contains all the knowledge about how to draw graphical object onto any particular output device.
Definition painter.h:59
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
virtual void LoadColors(const COLOR_SETTINGS *aSettings)
static std::vector< KICAD_T > g_ScaledSelectionTypes
void Update(const KIGFX::VIEW_ITEM *aItem, int aUpdateFlags) const override
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition sch_view.cpp:77
virtual void CenterOnCursor()=0
Set the viewport center to the current cursor position and warps the cursor to the screen center.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition view.cpp:304
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition view.cpp:408
GAL * GetGAL() const
Return the GAL this view is using to draw graphical primitives.
Definition view.h:211
void RecacheAllItems()
Rebuild GAL display lists.
Definition view.cpp:1551
void UpdateAllItems(int aUpdateFlags)
Update all items in the view according to the given flags.
Definition view.cpp:1685
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition view.h:229
void SetCenter(const VECTOR2D &aCenter)
Set the center point of the VIEW (i.e.
Definition view.cpp:667
void MarkTargetDirty(int aTarget)
Set or clear target 'dirty' flag.
Definition view.h:661
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition kiway.h:315
virtual void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string &aPayload, wxWindow *aSource=nullptr, bool aFromOtherThread=false)
Send aPayload to aDestination from aSource.
Definition kiway.cpp:500
Object used to load, save, search, and otherwise manipulate symbol library files.
LIB_SYMBOL * FindSymbol(const wxString &aName) const
Find LIB_SYMBOL by aName.
std::optional< wxString > GetLibraryDescription(const wxString &aNickname) const
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library tables.
std::vector< wxString > GetLibraryNames() const
Returns a list of library nicknames that are available (skips any that failed to load)
std::optional< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, bool aSubstituted=false)
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:49
const UTF8 & GetLibItemName() const
Definition lib_id.h:102
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition lib_id.h:87
Define a library symbol object.
Definition lib_symbol.h:83
static const wxString GetPinningSymbol()
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition page_info.h:79
const VECTOR2D GetSizeIU(double aIUScale) const
Gets the page size in internal units.
Definition page_info.h:177
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition pgm_base.cpp:541
virtual BACKGROUND_JOBS_MONITOR & GetBackgroundJobMonitor() const
Definition pgm_base.h:136
virtual LIBRARY_MANAGER & GetLibraryManager() const
Definition pgm_base.h:132
The backing store for a PROJECT, in JSON format.
static SYMBOL_LIBRARY_ADAPTER * SymbolLibAdapter(PROJECT *aProject)
Accessor for project symbol library manager adapter.
static LEGACY_SYMBOL_LIBS * LegacySchLibs(PROJECT *aProject)
Returns the list of symbol libraries from a legacy (pre-5.x) design This is only used from the remapp...
@ SCH_LIB_SELECT
Definition project.h:221
@ SCH_LIB_PATH
Definition project.h:220
virtual PROJECT_FILE & GetProjectFile() const
Definition project.h:204
virtual void SetRString(RSTRING_T aStringId, const wxString &aString)
Store a "retained string", which is any session and project specific string identified in enum RSTRIN...
Definition project.cpp:359
virtual const wxString & GetRString(RSTRING_T aStringId)
Return a "retained string", which is any session and project specific string identified in enum RSTRI...
Definition project.cpp:370
virtual void RedrawScreen(const VECTOR2I &aCenterPoint, bool aWarpPointer)
SCH_BASE_FRAME(KIWAY *aKiway, wxWindow *aParent, FRAME_T aWindowType, const wxString &aTitle, const wxPoint &aPosition, const wxSize &aSize, long aStyle, const wxString &aFrameName)
void UpdateStatusBar() override
Update the status bar information.
void RemoveFromScreen(EDA_ITEM *aItem, SCH_SCREEN *aScreen) override
Remove an item from the screen (and view) aScreen is the screen the item is located on,...
SCH_RENDER_SETTINGS * GetRenderSettings()
void doCloseWindow() override
void ActivateGalCanvas() override
Use to start up the GAL drawing canvas.
const VECTOR2I GetPageSizeIU() const override
Works off of GetPageSettings() to return the size of the paper page in the internal units of this par...
void SetPageSettings(const PAGE_INFO &aPageSettings) override
void handleIconizeEvent(wxIconizeEvent &aEvent) override
Handle a window iconize event.
void OnSymChange(wxFileSystemWatcherEvent &aEvent)
Handler for Symbol change events.
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
SYMBOL_EDITOR_SETTINGS * libeditconfig() const
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
APP_SETTINGS_BASE * GetViewerSettingsBase() const
void HighlightSelectionFilter(const SCH_SELECTION_FILTER_OPTIONS &aOptions)
void HardRedraw() override
Rebuild the GAL and redraws the screen.
DIALOG_SCH_FIND * m_findReplaceDialog
SCHEMATIC_SETTINGS m_base_frame_defaults
Only used by symbol_editor. Eeschema should be using the one inside the SCHEMATIC.
wxTimer m_watcherDebounceTimer
void CommonSettingsChanged(int aFlags) override
Notification event that some of the common (suite-wide) settings have changed.
void ShowFindReplaceDialog(bool aReplace)
Run the Find or Find & Replace dialog.
SCH_SELECTION_TOOL * GetSelectionTool() override
void SyncView()
Mark all items for refresh.
std::unique_ptr< NL_SCHEMATIC_PLUGIN > m_spaceMouse
void GetLibraryItemsForListDialog(wxArrayString &aHeaders, std::vector< wxArrayString > &aItemsToDisplay)
std::unique_ptr< wxFileSystemWatcher > m_watcher
These are file watchers for the symbol library tables.
wxString SelectLibrary(const wxString &aDialogTitle, const wxString &aListLabel, const std::vector< std::pair< wxString, bool * > > &aExtraCheckboxes={})
Display a list of loaded libraries and allows the user to select a library.
virtual ~SCH_BASE_FRAME()
Needs to be in the cpp file to encode the sizeof() for std::unique_ptr.
const TITLE_BLOCK & GetTitleBlock() const override
void RefreshZoomDependentItems()
Mark selected items for refresh.
EESCHEMA_SETTINGS * eeconfig() const
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock) override
PANEL_SCH_SELECTION_FILTER * m_selectionFilterPanel
LIB_SYMBOL * GetLibSymbol(const LIB_ID &aLibId, bool aUseCacheLib=false, bool aShowErrorMsg=false)
Load symbol from symbol library table.
virtual void UpdateItem(EDA_ITEM *aItem, bool isAddOrDelete=false, bool aUpdateRtree=false)
Mark an item for refresh.
void handleActivateEvent(wxActivateEvent &aEvent) override
Handle a window activation event.
COLOR_SETTINGS * GetColorSettings(bool aForceRefresh=false) const override
Returns a pointer to the active color theme settings.
void OnFindDialogClose()
Notification that the Find dialog has closed.
wxFileName m_watcherFileName
void setSymWatcher(const LIB_ID *aSymbol)
Creates (or removes) a watcher on the specified symbol library.
void AddToScreen(EDA_ITEM *aItem, SCH_SCREEN *aScreen=nullptr) override
Add an item to the screen (and view) aScreen is the screen the item is located on,...
const PAGE_INFO & GetPageSettings() const override
void ShowFindReplaceStatus(const wxString &aMsg, int aStatusTime)
COLOR4D GetDrawBgColor() const override
void OnSymChangeDebounceTimer(wxTimerEvent &aEvent)
Handler for the filesystem watcher debounce timer.
long long m_watcherTimestamp
void ClearFindReplaceStatus()
COLOR4D GetLayerColor(SCH_LAYER_ID aLayer)
Helper to retrieve a layer color from the global color settings.
KIGFX::SCH_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:132
A set of SCH_ITEMs (i.e., without duplicates).
Definition sch_group.h:52
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:166
const PAGE_INFO & GetPageSettings() const
Definition sch_screen.h:141
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
Definition sch_screen.h:168
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition sch_screen.h:142
TITLE_BLOCK & GetTitleBlock()
Definition sch_screen.h:165
void Update(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Update aItem's bounding box in the tree.
SCH_SELECTION & GetSelection()
void OnIdle(wxIdleEvent &aEvent)
Zoom the screen to fit the bounding box for cross probing/selection sync.
Schematic symbol object.
Definition sch_symbol.h:73
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
EDA_ITEM * Front() const
Definition selection.h:177
int Size() const
Returns the number of selected parts.
Definition selection.h:121
An interface to the global shared library manager that is schematic-specific and linked to one projec...
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
Class to handle modifications to the symbol libraries.
bool CreateLibrary(const wxString &aFilePath, LIBRARY_TABLE_SCOPE aScope)
Create an empty library and adds it to the library table.
Hold the information shown in the lower right corner of a plot, printout, or editing view.
Definition title_block.h:41
TOOL_MANAGER * m_toolManager
@ MODEL_RELOAD
Model changes (the sheet for a schematic)
Definition tool_base.h:80
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
const char * c_str() const
Definition utf8.h:108
wxString wx_str() const
Definition utf8.cpp:45
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition common.cpp:708
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:278
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:221
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:196
This file is part of the common library.
#define _(s)
@ RECURSE
Definition eda_item.h:53
FRAME_T
The set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
Definition frame_type.h:33
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:35
@ FRAME_SCH_VIEWER
Definition frame_type.h:36
@ FRAME_SCH
Definition frame_type.h:34
@ FRAME_SYMBOL_CHOOSER
Definition frame_type.h:37
static const std::string KiCadSymbolLibFileExtension
static wxString KiCadSymbolLibFileWildcard()
const wxChar *const traceLibWatch
Flag to enable debug output for library file watch refreshes.
SCH_LAYER_ID
Eeschema drawing layers.
Definition layer_ids.h:451
@ LAYER_SCHEMATIC_GRID_AXES
Definition layer_ids.h:489
@ LAYER_SCHEMATIC_BACKGROUND
Definition layer_ids.h:490
LIBRARY_TABLE_SCOPE
@ MAIL_REFRESH_SYMBOL
Definition mail_type.h:60
@ REPAINT
Item needs to be redrawn.
Definition view_item.h:58
@ ALL
All except INITIAL_ADD.
Definition view_item.h:59
@ TARGET_NONCACHED
Auxiliary rendering target (noncached)
Definition definitions.h:38
long long TimestampDir(const wxString &aDirPath, const wxString &aFilespec)
Computes a hash of modification times and sizes for files matching a pattern.
Definition unix/io.cpp:123
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:100
Declaration of the NL_SCHEMATIC_PLUGIN class.
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
LIB_SYMBOL * SchGetLibSymbol(const LIB_ID &aLibId, SYMBOL_LIBRARY_ADAPTER *aLibMgr, LEGACY_SYMBOL_LIB *aCacheLib, wxWindow *aParent, bool aShowErrorMsg)
Load symbol from symbol library table.
LIB_SYMBOL * SchGetLibSymbol(const LIB_ID &aLibId, SYMBOL_LIBRARY_ADAPTER *aLibMgr, LEGACY_SYMBOL_LIB *aCacheLib=nullptr, wxWindow *aParent=nullptr, bool aShowErrorMsg=false)
Load symbol from symbol library table.
Class to handle a set of SCH_ITEMs.
T * GetAppSettings(const char *aFilename)
KIWAY Kiway(KFCTL_STANDALONE)
wxString UnescapeString(const wxString &aSource)
std::vector< wxString > pinned_symbol_libs
@ ID_MAKE_NEW_LIBRARY
@ VALUE
Field Value of part, i.e. "3.3K".
wxLogTrace helper definitions.
@ SCH_TABLE_T
Definition typeinfo.h:166
@ SCH_SYMBOL_T
Definition typeinfo.h:173
@ SCH_TABLECELL_T
Definition typeinfo.h:167
@ SCH_FIELD_T
Definition typeinfo.h:151
@ SCH_LABEL_T
Definition typeinfo.h:168
@ SCH_SHEET_T
Definition typeinfo.h:176
@ SCH_SHAPE_T
Definition typeinfo.h:150
@ SCH_HIER_LABEL_T
Definition typeinfo.h:170
@ SCH_LABEL_LOCATE_ANY_T
Definition typeinfo.h:192
@ SCH_SHEET_PIN_T
Definition typeinfo.h:175
@ SCH_TEXT_T
Definition typeinfo.h:152
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:169
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687
VECTOR2< double > VECTOR2D
Definition vector2d.h:686
Definition of file extensions used in Kicad.