KiCad PCB EDA Suite
Loading...
Searching...
No Matches
kicad_manager_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) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2013 CERN (www.cern.ch)
6 * Copyright (C) 2004-2023, 2024 KiCad Developers, see change_log.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 "kicad_id.h"
27#include "pcm.h"
28#include "pgm_kicad.h"
29#include "project_tree_pane.h"
31
32#include <advanced_config.h>
34#include <bitmaps.h>
35#include <build_version.h>
36#include <confirm.h>
39#include <dialogs/panel_jobs.h>
40#include <eda_base_frame.h>
41#include <executable_names.h>
42#include <file_history.h>
43#include <policy_keys.h>
44#include <gestfich.h>
45#include <kiplatform/app.h>
46#include <kiplatform/policy.h>
47#include <build_version.h>
48#include <kiway.h>
49#include <kiway_express.h>
50#include <launch_ext.h>
52#include <reporter.h>
54#include <sch_file_versions.h>
56#include <tool/action_manager.h>
57#include <tool/action_toolbar.h>
58#include <tool/common_control.h>
60#include <tool/tool_manager.h>
65#include <widgets/kistatusbar.h>
66#include <wx/ffile.h>
67#include <wx/filedlg.h>
68#include <wx/dnd.h>
69#include <wx/process.h>
70#include <atomic>
71#include <update_manager.h>
72#include <jobs/jobset.h>
73
74#include <../pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h> // for SEXPR_BOARD_FILE_VERSION def
75
76
77#ifdef __WXMAC__
78#include <MacTypes.h>
79#include <ApplicationServices/ApplicationServices.h>
80#endif
81
82#include "kicad_manager_frame.h"
84
85
86#define SEP() wxFileName::GetPathSeparator()
87
88
89// Menubar and toolbar event table
90BEGIN_EVENT_TABLE( KICAD_MANAGER_FRAME, EDA_BASE_FRAME )
91 // Window events
94
95 // Menu events
96 EVT_MENU( wxID_EXIT, KICAD_MANAGER_FRAME::OnExit )
105
106 // Range menu events
108 KICAD_MANAGER_FRAME::language_change )
109
111 EVT_MENU( ID_FILE_LIST_CLEAR, KICAD_MANAGER_FRAME::OnClearFileHistory )
112
113 // Special functions
114 EVT_MENU( ID_INIT_WATCHED_PATHS, KICAD_MANAGER_FRAME::OnChangeWatchedPaths )
115
116 // Drop files event
117 EVT_DROP_FILES( KICAD_MANAGER_FRAME::OnDropFiles )
118
119END_EVENT_TABLE()
120
121// See below the purpose of this include
122#include <wx/xml/xml.h>
123
124KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent, const wxString& title,
125 const wxPoint& pos, const wxSize& size ) :
128 m_leftWin( nullptr ),
129 m_launcher( nullptr ),
130 m_mainToolBar( nullptr ),
131 m_lastToolbarIconSize( 0 )
132{
133 const int defaultLeftWinWidth = FromDIP( 250 );
134
135 m_active_project = false;
136 m_leftWinWidth = defaultLeftWinWidth; // Default value
137 m_aboutTitle = "KiCad";
138
139 // JPC: A very ugly hack to fix an issue on Linux: if the wxbase315u_xml_gcc_custom.so is
140 // used **only** in PCM, it is not found in some cases at run time.
141 // So just use it in the main module to avoid a not found issue
142 // wxbase315u_xml_gcc_custom shared object when launching Kicad
143 wxXmlDocument dummy;
144
145 // Create the status line (bottom of the frame). Left half is for project name; right half
146 // is for Reporter (currently used by archiver/unarchiver and PCM).
147 // Note: this is a KISTATUSBAR status bar. Therefore the specified number of fields
148 // is the extra number of fields, not the full field count.
149 // We need here 2 fields: the extra fiels to display the project name, and another field
150 // to display a info (specific to Windows) using the FIELD_OFFSET_BGJOB_TEXT id offset (=1)
151 // So the extra field count is 1
152 CreateStatusBar( 1 );
155 GetStatusBar()->SetFont( KIUI::GetStatusFont( this ) );
156
157 // Give an icon
158 wxIcon icon;
159 wxIconBundle icon_bundle;
160
161 if( IsNightlyVersion())
162 {
163 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly, 48 ) );
164 icon_bundle.AddIcon( icon );
165 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly, 128 ) );
166 icon_bundle.AddIcon( icon );
167 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly, 256 ) );
168 icon_bundle.AddIcon( icon );
169 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly_32 ) );
170 icon_bundle.AddIcon( icon );
171 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly_16 ) );
172 icon_bundle.AddIcon( icon );
173 }
174 else
175 {
176 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad, 48 ) );
177 icon_bundle.AddIcon( icon );
178 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad, 128 ) );
179 icon_bundle.AddIcon( icon );
180 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad, 256 ) );
181 icon_bundle.AddIcon( icon );
182 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_32 ) );
183 icon_bundle.AddIcon( icon );
184 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_16 ) );
185 icon_bundle.AddIcon( icon );
186 }
187
188 SetIcons( icon_bundle );
189
190 // Load the settings
191 LoadSettings( config() );
192
193 m_pcmButton = nullptr;
194 m_pcmUpdateCount = 0;
195
196 // Left window: is the box which display tree project
197 m_leftWin = new PROJECT_TREE_PANE( this );
198
199 setupTools();
200 setupUIConditions();
201
202 RecreateBaseLeftToolbar();
203 ReCreateMenuBar();
204
205 m_auimgr.SetManagedWindow( this );
206 m_auimgr.SetFlags( wxAUI_MGR_LIVE_RESIZE );
207
208 m_auimgr.AddPane( m_mainToolBar, EDA_PANE().VToolbar().Name( "MainToolbar" ).Left()
209 .Layer( 2 ) );
210
211 // BestSize() does not always set the actual pane size of m_leftWin to the required value.
212 // It happens when m_leftWin is too large (roughly > 1/3 of the kicad manager frame width.
213 // (Well, BestSize() sets the best size... not the window size)
214 // A trick is to use MinSize() to set the required pane width,
215 // and after give a reasonable MinSize value
216 m_auimgr.AddPane( m_leftWin, EDA_PANE().Palette().Name( "ProjectTree" ).Left().Layer( 1 )
217 .Caption( _( "Project Files" ) ).PaneBorder( false )
218 .MinSize( m_leftWinWidth, -1 ).BestSize( m_leftWinWidth, -1 ) );
219
220 wxSize client_size = GetClientSize();
221 m_notebook = new wxAuiNotebook( this, wxID_ANY, wxPoint( client_size.x, client_size.y ),
222 FromDIP( wxSize( 610, 590 ) ),
223 wxAUI_NB_TOP | wxAUI_NB_CLOSE_ON_ALL_TABS | wxAUI_NB_TAB_MOVE
224 | wxAUI_NB_SCROLL_BUTTONS | wxNO_BORDER );
225
226 m_notebook->Connect(
227 wxEVT_AUINOTEBOOK_PAGE_CLOSE,
228 wxAuiNotebookEventHandler( KICAD_MANAGER_FRAME::onNotebookPageCloseRequest ), nullptr,
229 this );
230 m_launcher = new PANEL_KICAD_LAUNCHER( m_notebook );
231
232 m_notebook->Freeze();
233 m_launcher->SetClosable( false );
234 m_notebook->AddPage( m_launcher, "Editors", false );
235 m_notebook->Thaw();
236
237 m_auimgr.AddPane( m_notebook, EDA_PANE()
238 .Canvas()
239 .Name( "Editors" )
240 .Center()
241 .Caption( _( "Editors" ) )
242 .PaneBorder( false )
243 .MinSize( m_notebook->GetBestSize() ) );
244
245 m_auimgr.Update();
246
247 // Now the actual m_leftWin size is set, give it a reasonable min width
248 m_auimgr.GetPane( m_leftWin ).MinSize( defaultLeftWinWidth, -1 );
249
250 wxSizer* mainSizer = GetSizer();
251
252 // Only fit the initial window size the first time KiCad is run.
253 if( mainSizer && config()->m_Window.state.size_x == 0 && config()->m_Window.state.size_y == 0 )
254 {
255 Layout();
256 mainSizer->Fit( this );
257 Center();
258 }
259
260 if( ADVANCED_CFG::GetCfg().m_HideVersionFromTitle )
261 SetTitle( wxT( "KiCad" ) );
262 else
263 SetTitle( wxString( "KiCad " ) + GetMajorMinorVersion() );
264
265 // Do not let the messages window have initial focus
266 m_leftWin->SetFocus();
267
268 // Init for dropping files
271
272 // Gerber files
273 // Note that all gerber files are aliased as GerberFileExtension
277
278 DragAcceptFiles( true );
279
280 // Ensure the window is on top
281 Raise();
282}
283
284
286{
288 Unbind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
289
290 m_notebook->Disconnect(
291 wxEVT_AUINOTEBOOK_PAGE_CLOSE,
292 wxAuiNotebookEventHandler( KICAD_MANAGER_FRAME::onNotebookPageCloseRequest ), nullptr,
293 this );
294
297
298 // Shutdown all running tools
299 if( m_toolManager )
301
302 if( m_pcm )
303 m_pcm->StopBackgroundUpdate();
304
305 delete m_actions;
306 delete m_toolManager;
307 delete m_toolDispatcher;
308
309 m_auimgr.UnInit();
310}
311
312
314{
315 wxAuiNotebook* ctrl = (wxAuiNotebook*) evt.GetEventObject();
316
317 wxWindow* pageWindow = ctrl->GetPage( evt.GetSelection() );
318
319 PANEL_NOTEBOOK_BASE* panel = dynamic_cast<PANEL_NOTEBOOK_BASE*>( pageWindow );
320
321 if( panel )
322 {
323 if( panel->GetClosable() )
324 {
325 if( !panel->GetCanClose() )
326 {
327 evt.Veto();
328 }
329 }
330 else
331 {
332 evt.Veto();
333 }
334 }
335}
336
337
338wxStatusBar* KICAD_MANAGER_FRAME::OnCreateStatusBar( int number, long style, wxWindowID id,
339 const wxString& name )
340{
341 return new KISTATUSBAR( number, this, id );
342}
343
344
346{
347 // creates the PLUGIN_CONTENT_MANAGER, if not exists
348 if( m_pcm )
349 return;
350
351 m_pcm = std::make_shared<PLUGIN_CONTENT_MANAGER>(
352 [this]( int aUpdateCount )
353 {
354 m_pcmUpdateCount = aUpdateCount;
355
356 if( aUpdateCount > 0 )
357 {
359 wxS( "pcm" ),
360 _( "PCM Updates Available" ),
361 wxString::Format( _( "%d package update(s) avaliable" ), aUpdateCount ),
362 wxT( "" ) );
363 }
364 else
365 {
366 Pgm().GetNotificationsManager().Remove( wxS( "pcm" ) );
367 }
368
369 CallAfter(
370 [this]()
371 {
373 } );
374 });
375
376 m_pcm->SetRepositoryList( kicadSettings()->m_PcmRepositories );
377}
378
379
381{
382 // Create the manager
384 m_toolManager->SetEnvironment( nullptr, nullptr, nullptr, config(), this );
386
388
389 // Attach the events to the tool dispatcher
391 Bind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
392
393 // Register tools
397}
398
399
401{
403
405
406 wxASSERT( manager );
407
408 auto activeProject =
409 [this] ( const SELECTION& )
410 {
411 return m_active_project;
412 };
413
414#define ENABLE( x ) ACTION_CONDITIONS().Enable( x )
415
416 ACTION_CONDITIONS activeProjectCond;
417 activeProjectCond.Enable( activeProject );
418
419 manager->SetConditions( ACTIONS::saveAs, activeProjectCond );
420 manager->SetConditions( KICAD_MANAGER_ACTIONS::closeProject, activeProjectCond );
421
422 // These are just here for text boxes, search boxes, etc. in places such as the standard
423 // file dialogs.
427
428 // TODO: Switch this to an action
430
431#undef ENABLE
432}
433
434
436{
437 return m_leftWin;
438}
439
440
442{
444 wxASSERT( ret );
445 return ret;
446}
447
448
450{
451 KICAD_SETTINGS* ret = dynamic_cast<KICAD_SETTINGS*>( config() );
452 wxASSERT( ret );
453 return ret;
454}
455
456
458{
460 wxString( wxEmptyString );
461}
462
463
465{
466 wxFileName fn( GetProjectFileName() );
467
469 return fn.GetFullPath();
470}
471
472
474{
475 wxFileName fn( GetProjectFileName() );
476
478 return fn.GetFullPath();
479}
480
481
483{
484 wxFileName fn( GetProjectFileName() );
485
486 fn.SetExt( FILEEXT::PcbFileExtension );
487 return fn.GetFullPath();
488}
489
490
492{
493 wxFileName fn( GetProjectFileName() );
494
496 return fn.GetFullPath();
497}
498
499
501{
503}
504
505
507{
508 return PgmTop().SysSearch();
509}
510
511
513{
514 return PgmTop().GetHelpFileName();
515}
516
517
518void KICAD_MANAGER_FRAME::OnSize( wxSizeEvent& event )
519{
520 if( m_auimgr.GetManagedWindow() )
521 m_auimgr.Update();
522
523 PrintPrjInfo();
524
525#if defined( _WIN32 )
526 KISTATUSBAR* statusBar = static_cast<KISTATUSBAR*>( GetStatusBar() );
528#endif
529
530 event.Skip();
531}
532
533
535{
536 // All fileNames are now in m_AcceptedFiles vector.
537 // Check if contains a project file name and load project.
538 // If not, open files in dedicated app.
539 for( const wxFileName& fileName : m_AcceptedFiles )
540 {
541 wxString ext = fileName.GetExt();
542
544 {
545 wxString fn = fileName.GetFullPath();
546 m_toolManager->RunAction<wxString*>( *m_acceptedExts.at( fileName.GetExt() ), &fn );
547
548 return;
549 }
550 }
551
552 // Then stock gerber files in gerberFiles and run action for other files.
553 wxString gerberFiles;
554
555 // Gerbview editor should be able to open Gerber and drill files
556 for( const wxFileName& fileName : m_AcceptedFiles )
557 {
558 wxString ext = fileName.GetExt();
559
562 {
563 gerberFiles += wxT( '\"' );
564 gerberFiles += fileName.GetFullPath() + wxT( '\"' );
565 gerberFiles = gerberFiles.Pad( 1 );
566 }
567 else
568 {
569 wxString fn = fileName.GetFullPath();
570 m_toolManager->RunAction<wxString*>( *m_acceptedExts.at( fileName.GetExt() ), &fn );
571 }
572 }
573
574 // Execute Gerbviewer
575 if( !gerberFiles.IsEmpty() )
576 {
577 wxString fullEditorName = FindKicadFile( GERBVIEW_EXE );
578
579 if( wxFileExists( fullEditorName ) )
580 {
581 wxString command = fullEditorName + " " + gerberFiles;
583 &command );
584 }
585 }
586}
587
588
589bool KICAD_MANAGER_FRAME::canCloseWindow( wxCloseEvent& aEvent )
590{
591 KICAD_SETTINGS* settings = kicadSettings();
593
594 for( size_t i = 0; i < m_notebook->GetPageCount(); i++ )
595 {
596 wxWindow* page = m_notebook->GetPage( i );
597
598 PANEL_NOTEBOOK_BASE* panel = dynamic_cast<PANEL_NOTEBOOK_BASE*>( page );
599 if( panel )
600 {
601 if( !panel->GetCanClose() )
602 return false;
603 }
604 }
605
606 // CloseProject will recursively ask all the open editors if they need to save changes.
607 // If any of them cancel then we need to cancel closing the KICAD_MANAGER_FRAME.
608 if( CloseProject( true ) )
609 {
610 // Don't propagate event to frames which have already been closed
611 aEvent.StopPropagation();
612
613 return true;
614 }
615 else
616 {
617 if( aEvent.CanVeto() )
618 aEvent.Veto();
619
620 return false;
621 }
622}
623
624
626{
627#ifdef _WINDOWS_
628 // For some obscure reason, on Windows, when killing Kicad from the Windows task manager
629 // if a editor frame (schematic, library, board editor or fp editor) is open and has
630 // some edition to save, OnCloseWindow is run twice *at the same time*, creating race
631 // conditions between OnCloseWindow() code.
632 // Therefore I added (JPC) a ugly hack to discard the second call (unwanted) during
633 // execution of the first call (only one call is right).
634 // Note also if there is no change made in editors, this behavior does not happen.
635 static std::atomic<unsigned int> lock_close_event( 0 );
636
637 if( ++lock_close_event > 1 ) // Skip extra calls
638 {
639 return;
640 }
641#endif
642
643 for( size_t i = 0; i < m_notebook->GetPageCount(); i++ )
644 {
645 wxWindow* page = m_notebook->GetPage( i );
646
647 PANEL_NOTEBOOK_BASE* panel = dynamic_cast<PANEL_NOTEBOOK_BASE*>( page );
648 if( panel )
649 {
650 m_notebook->DeletePage( i );
651 }
652 }
653
654 m_leftWin->Show( false );
655 Pgm().m_Quitting = true;
656
657 Destroy();
658
659#ifdef _WINDOWS_
660 lock_close_event = 0; // Reenable event management
661#endif
662}
663
664
665void KICAD_MANAGER_FRAME::OnExit( wxCommandEvent& event )
666{
667 Close( true );
668}
669
670
672{
673 if( !Kiway().PlayersClose( false ) )
674 return false;
675
676 // Save the project file for the currently loaded project.
677 if( m_active_project )
678 {
680
682
683 if( aSave )
684 mgr.SaveProject();
685
686 m_active_project = false;
687 mgr.UnloadProject( &Prj() );
688 }
689
690 SetStatusText( "" );
691
692 for( size_t i = 0; i < m_notebook->GetPageCount(); i++ )
693 {
694 wxWindow* page = m_notebook->GetPage( i );
695
696 PANEL_NOTEBOOK_BASE* panel = dynamic_cast<PANEL_NOTEBOOK_BASE*>( page );
697 if( panel )
698 {
699 if( panel->GetProjectTied() )
700 {
701 m_notebook->DeletePage( i );
702 }
703 }
704 }
705
707
708 return true;
709}
710
711
712void KICAD_MANAGER_FRAME::OpenJobsFile( const wxFileName& aFileName, bool aCreate )
713{
714 if( !ADVANCED_CFG::GetCfg().m_EnableJobset )
715 {
716 return;
717 }
718
719 for( size_t i = 0; i < m_notebook->GetPageCount(); i++ )
720 {
721 wxWindow* page = m_notebook->GetPage( i );
722
723 PANEL_JOBS* panel = dynamic_cast<PANEL_JOBS*>( page );
724 if( panel )
725 {
726 if( aFileName.GetFullPath() == panel->GetFilePath() )
727 {
728 m_notebook->SetSelection( i );
729 return;
730 }
731 }
732 }
733
734 try
735 {
736 std::unique_ptr<JOBSET> jobsFile =
737 std::make_unique<JOBSET>( aFileName.GetFullPath().ToStdString() );
738
739 jobsFile->LoadFromFile();
740
741 PANEL_JOBS* jobPanel = new PANEL_JOBS( m_notebook, this, std::move( jobsFile ) );
742 jobPanel->SetProjectTied( true );
743 jobPanel->SetClosable( true );
744 m_notebook->AddPage( jobPanel, aFileName.GetFullName(),
745 true );
746 }
747 catch( ... )
748 {
749 DisplayErrorMessage( this, _( "Error opening jobs file" ) );
750 }
751}
752
753
754void KICAD_MANAGER_FRAME::LoadProject( const wxFileName& aProjectFileName )
755{
756 // The project file should be valid by the time we get here or something has gone wrong.
757 if( !aProjectFileName.Exists() )
758 return;
759
760 // Any open KIFACE's must be closed if they are not part of the new project.
761 // (We never want a KIWAY_PLAYER open on a KIWAY that isn't in the same project.)
762 // User is prompted here to close those KIWAY_PLAYERs:
763 if( !CloseProject( true ) )
764 return;
765
766 m_active_project = true;
767
768 Pgm().GetSettingsManager().LoadProject( aProjectFileName.GetFullPath() );
769
770 LoadWindowState( aProjectFileName.GetFullName() );
771
772 if( aProjectFileName.IsDirWritable() )
773 SetMruPath( Prj().GetProjectPath() ); // Only set MRU path if we have write access. Why?
774
775 // Save history & window state to disk now. Don't wait around for a crash.
776 KICAD_SETTINGS* settings = kicadSettings();
777 SaveSettings( settings );
778 settings->SaveToFile( Pgm().GetSettingsManager().GetPathForSettingsFile( settings ) );
779
781
782 // Rebuild the list of watched paths.
783 // however this is possible only when the main loop event handler is running,
784 // so we use it to run the rebuild function.
785 wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED, ID_INIT_WATCHED_PATHS );
786
787 wxPostEvent( this, cmd );
788
789 PrintPrjInfo();
790
791 KIPLATFORM::APP::RegisterApplicationRestart( aProjectFileName.GetFullPath() );
792 m_openSavedWindows = true;
793}
794
795
796void KICAD_MANAGER_FRAME::CreateNewProject( const wxFileName& aProjectFileName,
797 bool aCreateStubFiles )
798{
799 wxCHECK_RET( aProjectFileName.DirExists() && aProjectFileName.IsDirWritable(),
800 "Project folder must exist and be writable to create a new project." );
801
802 // If the project is legacy, convert it
803 if( !aProjectFileName.FileExists() )
804 {
805 wxFileName legacyPro( aProjectFileName );
806 legacyPro.SetExt( FILEEXT::LegacyProjectFileExtension );
807
808 if( legacyPro.FileExists() )
809 {
810 GetSettingsManager()->LoadProject( legacyPro.GetFullPath() );
812
813 wxRemoveFile( legacyPro.GetFullPath() );
814 }
815 else
816 {
817 // Copy template project file from template folder.
818 wxString srcFileName = sys_search().FindValidPath( "kicad.kicad_pro" );
819
820 wxFileName destFileName( aProjectFileName );
821 destFileName.SetExt( FILEEXT::ProjectFileExtension );
822
823 // Create a minimal project file if the template project file could not be copied
824 if( !wxFileName::FileExists( srcFileName )
825 || !wxCopyFile( srcFileName, destFileName.GetFullPath() ) )
826 {
827 wxFFile file( destFileName.GetFullPath(), "wb" );
828
829 if( file.IsOpened() )
830 file.Write( wxT( "{\n}\n") );
831
832 // wxFFile dtor will close the file
833 }
834 }
835 }
836
837 // Create a "stub" for a schematic root sheet and a board if requested.
838 // It will avoid messages from the schematic editor or the board editor to create a new file
839 // And forces the user to create main files under the right name for the project manager
840 if( aCreateStubFiles )
841 {
842 wxFileName fn( aProjectFileName.GetFullPath() );
844
845 // If a <project>.kicad_sch file does not exist, create a "stub" file ( minimal schematic
846 // file ).
847 if( !fn.FileExists() )
848 {
849 wxFFile file( fn.GetFullPath(), "wb" );
850
851 if( file.IsOpened() )
852 file.Write( wxString::Format( "(kicad_sch (version %d) (generator \"eeschema\") (generator_version \"%s\")\n"
853 " (paper \"A4\")\n (lib_symbols)\n"
854 " (symbol_instances)\n)\n",
856
857 // wxFFile dtor will close the file
858 }
859
860 // If a <project>.kicad_pcb or <project>.brd file does not exist,
861 // create a .kicad_pcb "stub" file
863 wxFileName leg_fn( fn );
864 leg_fn.SetExt( FILEEXT::LegacyPcbFileExtension );
865
866 if( !fn.FileExists() && !leg_fn.FileExists() )
867 {
868 wxFFile file( fn.GetFullPath(), "wb" );
869
870 if( file.IsOpened() )
871 // Create a small dummy file as a stub for pcbnew:
872 file.Write( wxString::Format( "(kicad_pcb (version %d) (generator \"pcbnew\") (generator_version \"%s\")\n)",
874
875 // wxFFile dtor will close the file
876 }
877 }
878
879 // Save history & window state to disk now. Don't wait around for a crash.
880 KICAD_SETTINGS* settings = kicadSettings();
881 SaveSettings( settings );
882 settings->SaveToFile( Pgm().GetSettingsManager().GetPathForSettingsFile( settings ) );
883
884 m_openSavedWindows = true;
885}
886
887
889{
890 // show all files in file dialog (in Kicad all files are editable texts):
891 wxString wildcard = FILEEXT::AllFilesWildcard();
892
893 wxString default_dir = Prj().GetProjectPath();
894
895 wxFileDialog dlg( this, _( "Edit File in Text Editor" ), default_dir, wxEmptyString, wildcard,
896 wxFD_OPEN );
897
898 if( dlg.ShowModal() == wxID_CANCEL )
899 return;
900
901 wxString filename = dlg.GetPath();
902
903 if( !dlg.GetPath().IsEmpty() && !Pgm().GetTextEditor().IsEmpty() )
905}
906
907
909{
910 // open project directory in host OS's file explorer
911 LaunchExternal( Prj().GetProjectPath() );
912}
913
914
916{
918}
919
920
921void KICAD_MANAGER_FRAME::language_change( wxCommandEvent& event )
922{
923 int id = event.GetId();
924 Kiway().SetLanguage( id );
925}
926
927
929{
930 // call my base class
932
933 // tooltips in toolbars
936
937 PrintPrjInfo();
938}
939
940
941void KICAD_MANAGER_FRAME::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged )
942{
943 EDA_BASE_FRAME::CommonSettingsChanged( aEnvVarsChanged, aTextVarsChanged );
944
945 if( m_pcm && aEnvVarsChanged )
946 {
947 m_pcm->ReadEnvVar();
948 }
949
950 COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
951
952 if( m_lastToolbarIconSize == 0
954 {
957 }
958}
959
960
962{
963 wxString file = GetProjectFileName();
964 wxString title;
965
966 if( !file.IsEmpty() )
967 {
968 wxFileName fn( file );
969
970 title = fn.GetName();
971
972 if( !fn.IsDirWritable() )
973 title += wxS( " " ) + _( "[Read Only]" );
974 }
975 else
976 {
977 title = _( "[no project loaded]" );
978 }
979
980 if( ADVANCED_CFG::GetCfg().m_HideVersionFromTitle )
981 title += wxT( " \u2014 " ) + wxString( wxS( "KiCad" ) );
982 else
983 title += wxT( " \u2014 " ) + wxString( wxS( "KiCad " ) ) + GetMajorMinorVersion();
984
985 SetTitle( title );
986}
987
988
990{
992
993 auto settings = dynamic_cast<KICAD_SETTINGS*>( aCfg );
994
995 wxCHECK( settings, /*void*/ );
996
997 m_leftWinWidth = settings->m_LeftWinWidth;
998}
999
1000
1002{
1004
1005 auto settings = dynamic_cast<KICAD_SETTINGS*>( aCfg );
1006
1007 wxCHECK( settings, /*void*/);
1008
1009 settings->m_LeftWinWidth = m_leftWin->GetSize().x;
1010
1011 if( !m_isClosing )
1012 settings->m_OpenProjects = GetSettingsManager()->GetOpenProjects();
1013}
1014
1015
1017{
1018 // wxStatusBar's wxELLIPSIZE_MIDDLE flag doesn't work (at least on Mac).
1019
1020 wxString status = wxString::Format( _( "Project: %s" ), Prj().GetProjectFullName() );
1021 KISTATUSBAR* statusBar = static_cast<KISTATUSBAR*>( GetStatusBar() );
1022 statusBar->SetEllipsedTextField( status, 0 );
1023}
1024
1025
1027{
1028 return m_active_project;
1029}
1030
1031
1032void KICAD_MANAGER_FRAME::OnIdle( wxIdleEvent& aEvent )
1033{
1039 if( !m_openSavedWindows )
1040 return;
1041
1042 m_openSavedWindows = false;
1043
1044 if( Pgm().GetCommonSettings()->m_Session.remember_open_files )
1045 {
1046 int previousOpenCount =
1047 std::count_if( Prj().GetLocalSettings().m_files.begin(),
1048 Prj().GetLocalSettings().m_files.end(),
1049 [&]( const PROJECT_FILE_STATE& f )
1050 {
1051 return !f.fileName.EndsWith( FILEEXT::ProjectFileExtension ) && f.open;
1052 } );
1053
1054 if( previousOpenCount > 0 )
1055 {
1056 APP_PROGRESS_DIALOG progressReporter( _( "Restoring session" ), wxEmptyString,
1057 previousOpenCount, this );
1058
1059 // We don't currently support opening more than one view per file
1060 std::set<wxString> openedFiles;
1061
1062 int i = 0;
1063
1064 for( const PROJECT_FILE_STATE& file : Prj().GetLocalSettings().m_files )
1065 {
1066 if( file.open && !openedFiles.count( file.fileName ) )
1067 {
1068 progressReporter.Update( i++,
1069 wxString::Format( _( "Restoring '%s'" ), file.fileName ) );
1070
1071 openedFiles.insert( file.fileName );
1072 wxFileName fn( file.fileName );
1073
1074 if( fn.GetExt() == FILEEXT::LegacySchematicFileExtension
1075 || fn.GetExt() == FILEEXT::KiCadSchematicFileExtension )
1076 {
1078 }
1079 else if( fn.GetExt() == FILEEXT::LegacyPcbFileExtension
1080 || fn.GetExt() == FILEEXT::KiCadPcbFileExtension )
1081 {
1083 }
1084 }
1085
1086 wxYield();
1087 }
1088 }
1089 }
1090
1091 // clear file states regardless if we opened windows or not due to setting
1093
1094 KICAD_SETTINGS* settings = kicadSettings();
1095
1096 if( !Pgm().GetCommonSettings()->m_DoNotShowAgain.update_check_prompt )
1097 {
1098 auto prompt = new DIALOG_UPDATE_CHECK_PROMPT( this );
1099 prompt->ShowModal();
1100
1102 }
1103
1105 && settings->m_PcmUpdateCheck )
1106 {
1107 if( !m_pcm )
1108 CreatePCM();
1109
1110 m_pcm->RunBackgroundUpdate();
1111 }
1112
1113#ifdef KICAD_UPDATE_CHECK
1114 if( !m_updateManager && settings->m_KiCadUpdateCheck )
1115 {
1116 m_updateManager = std::make_unique<UPDATE_MANAGER>();
1117 m_updateManager->CheckForUpdate( this );
1118 }
1119#endif
1120}
1121
1122
1124{
1125 m_pcmButton = aButton;
1126
1128}
1129
1130
1132{
1133 if( m_pcmButton )
1134 {
1135 if( m_pcmUpdateCount > 0 )
1136 {
1137 m_pcmButton->SetShowBadge( true );
1138 m_pcmButton->SetBadgeText( wxString::Format( "%d", m_pcmUpdateCount ) );
1139 }
1140 else
1141 {
1142 m_pcmButton->SetShowBadge( false );
1143 }
1144
1145 m_pcmButton->Refresh();
1146 }
1147}
1148
1149
1151{
1152 // No idea why, but the same mechanism used in EDA_DRAW_FRAME doesn't work here
1153 // the only thing that seems to work is to blow it all up and start from scratch.
1154 m_auimgr.DetachPane( m_mainToolBar );
1155 delete m_mainToolBar;
1156 m_mainToolBar = nullptr;
1158 m_auimgr.AddPane( m_mainToolBar, EDA_PANE().HToolbar().Name( "MainToolbar" ).Left()
1159 .Layer( 2 ) );
1160}
const char * name
Definition: DXF_plotter.cpp:57
constexpr EDA_IU_SCALE unityScale
Definition: base_units.h:111
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:104
@ icon_kicad_16
@ icon_kicad_nightly
@ icon_kicad_32
@ icon_kicad_nightly_32
@ icon_kicad_nightly_16
wxString GetMajorMinorVersion()
Get only the major and minor version in a string major.minor.
bool IsNightlyVersion()
Check if the build is meant to be nightly.
static TOOL_ACTION paste
Definition: actions.h:73
static TOOL_ACTION saveAs
Definition: actions.h:52
static TOOL_ACTION copy
Definition: actions.h:71
static TOOL_ACTION cut
Definition: actions.h:70
Manage TOOL_ACTION objects.
void SetConditions(const TOOL_ACTION &aAction, const ACTION_CONDITIONS &aConditions)
Set the conditions the UI elements for activating a specific tool action should use for determining t...
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
wxProgressDialog with the option to also update the application progress on the taskbar
virtual bool Update(int aValue, const wxString &aNewMsg=wxEmptyString, bool *aSkip=nullptr) override
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
Definition: app_settings.h:92
void UnregisterStatusBar(KISTATUSBAR *aStatusBar)
Removes status bar from handling.
void RegisterStatusBar(KISTATUSBAR *aStatusBar)
Add a status bar for handling.
A bitmap button widget that behaves like an AUI toolbar item's button when it is drawn.
Definition: bitmap_button.h:42
void SetBadgeText(const wxString &aText)
void SetShowBadge(bool aShowBadge)
Handle actions that are shared between different applications.
APPEARANCE m_Appearance
DO_NOT_SHOW_AGAIN m_DoNotShowAgain
The base frame for deriving all KiCad main window classes.
void LoadWindowState(const wxString &aFileName)
void ShowChangedLanguage() override
Redraw the menus and what not in current language.
virtual void setupUIConditions()
Setup the UI conditions for the various actions and their controls in this frame.
std::vector< wxFileName > m_AcceptedFiles
SETTINGS_MANAGER * GetSettingsManager() const
wxAuiManager m_auimgr
virtual void LoadSettings(APP_SETTINGS_BASE *aCfg)
Load common frame parameters from a configuration file.
void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged) override
Notification event that some of the common (suite-wide) settings have changed.
std::map< const wxString, TOOL_ACTION * > m_acceptedExts
Associates files extensions with action to execute.
virtual void SaveSettings(APP_SETTINGS_BASE *aCfg)
Save common frame parameters to a configuration data file.
void SetMruPath(const wxString &aPath)
virtual void RegisterUIUpdateHandler(int aID, const ACTION_CONDITIONS &aConditions) override
Register a UI update handler for the control with ID aID.
bool m_isClosing
Set by NonUserClose() to indicate that the user did not request the current close.
Specialization of the wxAuiPaneInfo class for KiCad panels.
virtual bool SaveToFile(const wxString &aDirectory="", bool aForce=false)
Calls Store() and then writes the contents of the JSON document to a file.
static TOOL_ACTION viewDroppedGerbers
static TOOL_ACTION editPCB
static TOOL_ACTION loadProject
static TOOL_ACTION editSchematic
static TOOL_ACTION openTextEditor
static TOOL_ACTION closeProject
Handle actions in the kicad manager frame.
The main KiCad project manager frame.
std::shared_ptr< PLUGIN_CONTENT_MANAGER > m_pcm
void language_change(wxCommandEvent &event)
void SetPcmButton(BITMAP_BUTTON *aButton)
void doCloseWindow() override
void CreateNewProject(const wxFileName &aProjectFileName, bool aCreateStubFiles=true)
Creates a new project by setting up and initial project, schematic, and board files.
void OnUnarchiveFiles(wxCommandEvent &event)
const SEARCH_STACK & sys_search() override
Return a SEARCH_STACK pertaining to entire program.
void OnImportEasyEdaProFiles(wxCommandEvent &event)
Open dialog to import EasyEDA Pro schematic and board files.
void ProjectChanged() override
Notification event that the project has changed.
void ShowChangedLanguage() override
Redraw the menus and what not in current language.
const wxString SchLegacyFileName()
void OpenJobsFile(const wxFileName &aFileName, bool aCreate=false)
void RecreateBaseLeftToolbar()
(Re)Create the left vertical toolbar
wxWindow * GetToolCanvas() const override
Canvas access.
void OnImportEasyEdaFiles(wxCommandEvent &event)
Open dialog to import EasyEDA Std schematic and board files.
PROJECT_TREE_PANE * m_leftWin
const wxString GetProjectFileName() const
void OnBrowseInFileExplorer(wxCommandEvent &event)
KICAD_SETTINGS * kicadSettings() const
const wxString SchFileName()
void OnImportEagleFiles(wxCommandEvent &event)
Open dialog to import Eagle schematic and board files.
wxStatusBar * OnCreateStatusBar(int number, long style, wxWindowID id, const wxString &name) override
Create the status line (like a wxStatusBar).
void OnExit(wxCommandEvent &event)
void LoadProject(const wxFileName &aProjectFileName)
bool canCloseWindow(wxCloseEvent &aCloseEvent) override
void OnSize(wxSizeEvent &event) override
virtual void setupUIConditions() override
Setup the UI conditions for the various actions and their controls in this frame.
void DoWithAcceptedFiles() override
Execute action on accepted dropped file.
void OnOpenFileInTextEditor(wxCommandEvent &event)
APP_SETTINGS_BASE * config() const override
Returns the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
const wxString PcbLegacyFileName()
KICAD_MANAGER_FRAME(wxWindow *parent, const wxString &title, const wxPoint &pos, const wxSize &size)
bool CloseProject(bool aSave)
Closes the project, and saves it if aSave is true;.
void onNotebookPageCloseRequest(wxAuiNotebookEvent &evt)
void LoadSettings(APP_SETTINGS_BASE *aCfg) override
Load common frame parameters from a configuration file.
void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged) override
Notification event that some of the common (suite-wide) settings have changed.
void OnIdle(wxIdleEvent &event)
void PrintPrjInfo()
Prints the current working directory name and the project name on the text panel.
ACTION_TOOLBAR * m_mainToolBar
void OnArchiveFiles(wxCommandEvent &event)
void OnImportCadstarArchiveFiles(wxCommandEvent &event)
Open dialog to import CADSTAR Schematic and PCB Archive files.
void SaveSettings(APP_SETTINGS_BASE *aCfg) override
Save common frame parameters to a configuration data file.
BITMAP_BUTTON * m_pcmButton
PANEL_KICAD_LAUNCHER * m_launcher
wxString help_name() override
const wxString PcbFileName()
std::unique_ptr< UPDATE_MANAGER > m_updateManager
wxAuiNotebook * m_notebook
std::vector< wxString > m_OpenProjects
std::vector< std::pair< wxString, wxString > > m_PcmRepositories
KISTATUSBAR is a wxStatusBar suitable for Kicad manager.
Definition: kistatusbar.h:45
void SetEllipsedTextField(const wxString &aText, int aFieldId)
Set the text in a field using wxELLIPSIZE_MIDDLE option to adjust the text size to the field size (un...
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:55
virtual void SetLanguage(int aLanguage)
Change the language and then calls ShowChangedLanguage() on all #KIWAY_PLAYERs.
Definition: kiway.cpp:543
void RegisterStatusBar(KISTATUSBAR *aStatusBar)
Add a status bar for handling.
void CreateOrUpdate(const wxString &aKey, const wxString &aTitle, const wxString &aDescription, const wxString &aHref=wxEmptyString)
Creates a notification with the given parameters or updates an existing one with the same key.
void Remove(const wxString &aKey)
Remove a notification by key.
void UnregisterStatusBar(KISTATUSBAR *aStatusBar)
Removes status bar from handling.
static REPORTER & GetInstance()
Definition: reporter.cpp:115
wxString GetFilePath() const
Definition: panel_jobs.cpp:761
void SetClosable(bool aYes)
virtual bool GetCanClose()
void SetProjectTied(bool aYes)
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition: pgm_base.cpp:679
virtual BACKGROUND_JOBS_MONITOR & GetBackgroundJobMonitor() const
Definition: pgm_base.h:146
bool m_Quitting
Definition: pgm_base.h:390
virtual NOTIFICATIONS_MANAGER & GetNotificationsManager() const
Definition: pgm_base.h:148
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:142
wxString GetHelpFileName()
Definition: pgm_kicad.h:63
SEARCH_STACK & SysSearch()
Definition: pgm_kicad.h:61
APP_SETTINGS_BASE * PgmSettings()
Definition: pgm_kicad.h:59
PROJECT_TREE_PANE Window to display the tree files.
void EmptyTreePrj()
Delete all m_TreeProject entries.
void ReCreateTreePrj()
Create or modify the tree showing project file names.
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition: project.cpp:129
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:135
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition: project.h:206
Look for files in a number of paths.
Definition: search_stack.h:43
static bool ShowNever(const SELECTION &aSelection)
Always returns false.
bool SaveProject(const wxString &aFullPath=wxEmptyString, PROJECT *aProject=nullptr)
Saves a loaded project.
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Loads a project or sets up a new project with a specified path.
bool IsProjectOpen() const
Helper for checking if we have a project open TODO: This should be deprecated along with Prj() once w...
bool UnloadProject(PROJECT *aProject, bool aSave=true)
Saves, unloads and unregisters the given PROJECT.
std::vector< wxString > GetOpenProjects() const
bool TriggerBackupIfNeeded(REPORTER &aReporter) const
Calls BackupProject if a new backup is needed according to the current backup policy.
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:167
TOOL_DISPATCHER * m_toolDispatcher
Definition: tools_holder.h:169
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
ACTIONS * m_actions
Definition: tools_holder.h:168
virtual void DispatchWxEvent(wxEvent &aEvent)
Process wxEvents (mostly UI events), translate them to TOOL_EVENTs, and make tools handle those.
Master controller class:
Definition: tool_manager.h:62
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
ACTION_MANAGER * GetActionManager() const
Definition: tool_manager.h:302
void RegisterTool(TOOL_BASE *aTool)
Add a tool to the manager set and sets it up.
void SetEnvironment(EDA_ITEM *aModel, KIGFX::VIEW *aView, KIGFX::VIEW_CONTROLS *aViewControls, APP_SETTINGS_BASE *aSettings, TOOLS_HOLDER *aFrame)
Set the work environment (model, view, view controls and the parent window).
void InitTools()
Initializes all registered tools.
void ShutdownAllTools()
Shutdown all tools with a currently registered event loop in this tool manager by waking them up with...
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:195
This file is part of the common library.
#define ENABLE(x)
#define _(s)
Base window classes and related definitions.
#define KICAD_DEFAULT_DRAWFRAME_STYLE
#define KICAD_MANAGER_FRAME_NAME
KiCad executable names.
const wxString GERBVIEW_EXE
@ KICAD_MAIN_FRAME_T
Definition: frame_type.h:68
wxString FindKicadFile(const wxString &shortname)
Search the executable file shortname in KiCad binary path and return full file name if found or short...
Definition: gestfich.cpp:58
static const std::string LegacySchematicFileExtension
static const std::string GerberJobFileExtension
static const std::string GerberFileExtension
static const std::string ProjectFileExtension
static const std::string LegacyPcbFileExtension
static const std::string LegacyProjectFileExtension
static const std::string KiCadSchematicFileExtension
static const std::string DrillFileExtension
static const std::string KiCadPcbFileExtension
static wxString AllFilesWildcard()
static bool IsGerberFileExtension(const wxString &ext)
@ ID_FILE_LIST_CLEAR
Definition: id.h:86
@ ID_LANGUAGE_CHOICE
Definition: id.h:104
@ ID_FILEMAX
Definition: id.h:84
@ ID_LANGUAGE_CHOICE_END
Definition: id.h:141
@ ID_FILE1
Definition: id.h:83
PGM_KICAD & PgmTop()
Definition: kicad.cpp:80
IDs used in KiCad main frame foe menuitems and tools.
@ ID_IMPORT_EAGLE_PROJECT
Definition: kicad_id.h:72
@ ID_IMPORT_EASYEDAPRO_PROJECT
Definition: kicad_id.h:74
@ ID_READ_ZIP_ARCHIVE
Definition: kicad_id.h:69
@ ID_SAVE_AND_ZIP_FILES
Definition: kicad_id.h:68
@ ID_INIT_WATCHED_PATHS
Definition: kicad_id.h:70
@ ID_IMPORT_CADSTAR_ARCHIVE_PROJECT
Definition: kicad_id.h:71
@ ID_EDIT_LOCAL_FILE_IN_TEXT_EDITOR
Definition: kicad_id.h:66
@ ID_IMPORT_EASYEDA_PROJECT
Definition: kicad_id.h:73
@ ID_BROWSE_IN_FILE_EXPLORER
Definition: kicad_id.h:67
EVT_MENU_RANGE(ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, KICAD_MANAGER_FRAME::language_change) KICAD_MANAGER_FRAME
bool LaunchExternal(const wxString &aPath)
Launches the given file or folder in the host OS.
Definition: launch_ext.cpp:25
bool RegisterApplicationRestart(const wxString &aCommandLine)
Registers the application for restart with the OS with the given command line string to pass as args.
Definition: unix/app.cpp:65
PBOOL GetPolicyBool(const wxString &aKey)
Definition: unix/policy.cpp:26
KICOMMON_API wxFont GetStatusFont(wxWindow *aWindow)
Definition: ui_common.cpp:130
#define SEXPR_BOARD_FILE_VERSION
Current s-expression file format version. 2 was the last legacy format version.
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1060
#define POLICY_KEY_PCM
Definition: policy_keys.h:31
#define SEXPR_SCHEMATIC_FILE_VERSION
Schematic file version.
KIWAY Kiway(KFCTL_STANDALONE)
std::vector< FAB_LAYER_COLOR > dummy
Functors that can be used to figure out how the action controls should be displayed in the UI and if ...
ACTION_CONDITIONS & Enable(const SELECTION_CONDITION &aCondition)
Definition of file extensions used in Kicad.