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 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 "kicad_id.h"
27#include "pcm.h"
28#include "pgm_kicad.h"
29#include "project_tree_pane.h"
30#include "local_history_pane.h"
32
33#include <advanced_config.h>
35#include <bitmaps.h>
36#include <build_version.h>
37#include <confirm.h>
41#include <local_history.h>
42#include <wx/msgdlg.h>
43#include <eda_base_frame.h>
44#include <executable_names.h>
45#include <file_history.h>
46#include <local_history.h>
47#include <policy_keys.h>
48#include <gestfich.h>
49#include <kiplatform/app.h>
51#include <kiplatform/ui.h>
52#include <kiplatform/policy.h>
53#include <build_version.h>
54#include <kiway.h>
55#include <kiway_express.h>
56#include <launch_ext.h>
57#include <lockfile.h>
59#include <reporter.h>
61#include <sch_file_versions.h>
63#include <tool/action_manager.h>
64#include <tool/action_toolbar.h>
65#include <tool/common_control.h>
67#include <tool/tool_manager.h>
73#include <widgets/kistatusbar.h>
74#include <wx/ffile.h>
75#include <wx/filedlg.h>
76#include <wx/dnd.h>
77#include <wx/process.h>
78#include <wx/snglinst.h>
79#include <atomic>
80#include <update_manager.h>
81#include <jobs/jobset.h>
82
83#include <../pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h> // for SEXPR_BOARD_FILE_VERSION def
84
85
86#ifdef __WXMAC__
87#include <MacTypes.h>
88#include <ApplicationServices/ApplicationServices.h>
89#endif
90
91#include "kicad_manager_frame.h"
93
95
96
97#define EDITORS_CAPTION _( "Editors" )
98#define PROJECT_FILES_CAPTION _( "Project Files" )
99
100#define ID_INIT_WATCHED_PATHS 52913
101
102#define SEP() wxFileName::GetPathSeparator()
103
104
105// Menubar and toolbar event table
106BEGIN_EVENT_TABLE( KICAD_MANAGER_FRAME, EDA_BASE_FRAME )
107 // Window events
110
111 // Menu events
112 EVT_MENU( wxID_EXIT, KICAD_MANAGER_FRAME::OnExit )
120
121 // Range menu events
123 KICAD_MANAGER_FRAME::language_change )
124
126 EVT_MENU( ID_FILE_LIST_CLEAR, KICAD_MANAGER_FRAME::OnClearFileHistory )
127
128 // Special functions
129 EVT_MENU( ID_INIT_WATCHED_PATHS, KICAD_MANAGER_FRAME::OnChangeWatchedPaths )
130
131 // Drop files event
132 EVT_DROP_FILES( KICAD_MANAGER_FRAME::OnDropFiles )
133
134END_EVENT_TABLE()
135
136// See below the purpose of this include
137#include <wx/xml/xml.h>
139
140KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent, const wxString& title,
141 const wxPoint& pos, const wxSize& size ) :
144 m_openSavedWindows( false ),
145 m_restoredFromHistory( false ),
146 m_active_project( false ),
147 m_showHistoryPanel( false ),
148 m_leftWin( nullptr ),
149 m_historyPane( nullptr ),
150 m_launcher( nullptr ),
151 m_lastToolbarIconSize( 0 ),
152 m_pcmButton( nullptr ),
153 m_pcmUpdateCount( 0 )
154{
155 const int defaultLeftWinWidth = FromDIP( 250 );
156
157 m_leftWinWidth = defaultLeftWinWidth; // Default value
158 m_aboutTitle = "KiCad";
159
160 // JPC: A very ugly hack to fix an issue on Linux: if the wxbase315u_xml_gcc_custom.so is
161 // used **only** in PCM, it is not found in some cases at run time.
162 // So just use it in the main module to avoid a not found issue
163 // wxbase315u_xml_gcc_custom shared object when launching Kicad
164 wxXmlDocument dummy;
165
166 // Create the status line (bottom of the frame). Left half is for project name; right half
167 // is for Reporter (currently used by archiver/unarchiver and PCM).
168 // Note: this is a KISTATUSBAR status bar. Therefore the specified number of fields
169 // is the extra number of fields, not the full field count.
170 // We need here 2 fields: the extra fiels to display the project name, and another field
171 // to display a info (specific to Windows) using the FIELD_OFFSET_BGJOB_TEXT id offset (=1)
172 // So the extra field count is 1
173 CreateStatusBar( 2 );
176 Pgm().RegisterLibraryLoadStatusBar( (KISTATUSBAR*) GetStatusBar() );
177 GetStatusBar()->SetFont( KIUI::GetStatusFont( this ) );
178
179 // Give an icon
180 wxIcon icon;
181 wxIconBundle icon_bundle;
182
183 if( IsNightlyVersion())
184 {
185 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly, 48 ) );
186 icon_bundle.AddIcon( icon );
187 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly, 128 ) );
188 icon_bundle.AddIcon( icon );
189 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly, 256 ) );
190 icon_bundle.AddIcon( icon );
191 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly_32 ) );
192 icon_bundle.AddIcon( icon );
193 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly_16 ) );
194 icon_bundle.AddIcon( icon );
195 }
196 else
197 {
198 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad, 48 ) );
199 icon_bundle.AddIcon( icon );
200 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad, 128 ) );
201 icon_bundle.AddIcon( icon );
202 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad, 256 ) );
203 icon_bundle.AddIcon( icon );
204 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_32 ) );
205 icon_bundle.AddIcon( icon );
206 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_16 ) );
207 icon_bundle.AddIcon( icon );
208 }
209
210 SetIcons( icon_bundle );
211
212 // Load the settings
213 LoadSettings( config() );
214
215 // Left window: is the box which display tree project
216 m_leftWin = new PROJECT_TREE_PANE( this );
217
218 setupTools();
219 setupUIConditions();
220
221 m_toolbarSettings = GetToolbarSettings<KICAD_MANAGER_TOOLBAR_SETTINGS>( "kicad-toolbars" );
222 configureToolbars();
223 RecreateToolbars();
224 ReCreateMenuBar();
225
226 m_auimgr.SetManagedWindow( this );
227 m_auimgr.SetFlags( wxAUI_MGR_LIVE_RESIZE );
228
229 m_auimgr.AddPane( m_tbLeft, EDA_PANE().VToolbar().Name( "TopMainToolbar" ).Left().Layer( 2 ) );
230
231 // BestSize() does not always set the actual pane size of m_leftWin to the required value.
232 // It happens when m_leftWin is too large (roughly > 1/3 of the kicad manager frame width.
233 // (Well, BestSize() sets the best size... not the window size)
234 // A trick is to use MinSize() to set the required pane width,
235 // and after give a reasonable MinSize value
236 m_auimgr.AddPane( m_leftWin, EDA_PANE().Palette().Name( "ProjectTree" ).Left().Layer( 1 )
237 .Caption( PROJECT_FILES_CAPTION ).PaneBorder( false )
238 .MinSize( m_leftWinWidth, -1 ).BestSize( m_leftWinWidth, -1 ) );
239
240 m_historyPane = new LOCAL_HISTORY_PANE( this );
241 m_auimgr.AddPane( m_historyPane,
242 EDA_PANE().Palette().Name( "LocalHistory" ).Left().Layer( 1 ).Position( 1 )
243 .Caption( _( "Local History" ) ).PaneBorder( false )
244 .Floatable( false ).Movable( false ).CloseButton( true ).Hide() );
245
246 if( m_showHistoryPanel )
247 m_auimgr.GetPane( m_historyPane ).Show();
248
249 wxSize client_size = GetClientSize();
250 m_notebook = new wxAuiNotebook( this, wxID_ANY, wxPoint( client_size.x, client_size.y ),
251 FromDIP( wxSize( 700, 590 ) ),
252 wxAUI_NB_TOP | wxAUI_NB_CLOSE_ON_ALL_TABS | wxAUI_NB_TAB_MOVE
253 | wxAUI_NB_SCROLL_BUTTONS | wxNO_BORDER );
254
255 m_notebook->SetArtProvider( new WX_AUI_TAB_ART() );
256
257 m_notebook->Bind( wxEVT_AUINOTEBOOK_PAGE_CLOSE, &KICAD_MANAGER_FRAME::onNotebookPageCloseRequest, this );
258 m_notebook->Bind( wxEVT_AUINOTEBOOK_PAGE_CLOSED, &KICAD_MANAGER_FRAME::onNotebookPageCountChanged, this );
259 m_launcher = new PANEL_KICAD_LAUNCHER( m_notebook );
260
261 m_notebook->Freeze();
262 m_launcher->SetClosable( false );
263 m_notebook->AddPage( m_launcher, EDITORS_CAPTION, false );
264 m_notebook->SetTabCtrlHeight( 0 );
265 m_notebook->Thaw();
266
267 m_auimgr.AddPane( m_notebook, EDA_PANE().Canvas().Name( "Editors" ).Center().Caption( EDITORS_CAPTION )
268 .PaneBorder( false ).MinSize( m_notebook->GetBestSize() ) );
269
270 m_auimgr.Update();
271
272 // Now the actual m_leftWin size is set, give it a reasonable min width
273 m_auimgr.GetPane( m_leftWin ).MinSize( defaultLeftWinWidth, -1 );
274
275
276 wxSizer* mainSizer = GetSizer();
277
278 // Only fit the initial window size the first time KiCad is run.
279 if( mainSizer && config()->m_Window.state.size_x == 0 && config()->m_Window.state.size_y == 0 )
280 {
281 Layout();
282 mainSizer->Fit( this );
283 Center();
284 }
285
286 if( ADVANCED_CFG::GetCfg().m_HideVersionFromTitle )
287 SetTitle( wxT( "KiCad" ) );
288 else
289 SetTitle( wxString( "KiCad " ) + GetMajorMinorVersion() );
290
291 // Do not let the messages window have initial focus
292 m_leftWin->SetFocus();
293
294 // Init for dropping files
297
298 // Gerber files
299 // Note that all gerber files are aliased as GerberFileExtension
303
304 DragAcceptFiles( true );
305
306 // Ensure the window is on top
307 Raise();
308}
309
310
312{
314 Unbind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
315
316 m_notebook->Unbind( wxEVT_AUINOTEBOOK_PAGE_CLOSE, &KICAD_MANAGER_FRAME::onNotebookPageCloseRequest, this );
317 m_notebook->Unbind( wxEVT_AUINOTEBOOK_PAGE_CLOSED, &KICAD_MANAGER_FRAME::onNotebookPageCountChanged, this );
318
321 Pgm().UnregisterLibraryLoadStatusBar( (KISTATUSBAR*) GetStatusBar() );
322
323 // Shutdown all running tools
324 if( m_toolManager )
325 m_toolManager->ShutdownAllTools();
326
327 if( m_pcm )
328 m_pcm->StopBackgroundUpdate();
329
330 delete m_actions;
331 delete m_toolManager;
332 delete m_toolDispatcher;
333
334 m_auimgr.UnInit();
335}
336
338{
339 if( m_notebook->GetPageCount() == 1 )
340 m_notebook->SetTabCtrlHeight( 0 );
341 else
342 m_notebook->SetTabCtrlHeight( -1 );
343}
344
345
347{
349}
350
351
353{
354 wxAuiNotebook* notebook = (wxAuiNotebook*) evt.GetEventObject();
355 wxWindow* page = notebook->GetPage( evt.GetSelection() );
356
357 if( PANEL_NOTEBOOK_BASE* panel = dynamic_cast<PANEL_NOTEBOOK_BASE*>( page ) )
358 {
359 if( panel->GetClosable() )
360 {
361 if( !panel->GetCanClose() )
362 evt.Veto();
363
364 CallAfter(
365 [this]()
366 {
368 } );
369 }
370 else
371 {
372 evt.Veto();
373 }
374 }
375}
376
377
378wxStatusBar* KICAD_MANAGER_FRAME::OnCreateStatusBar( int number, long style, wxWindowID id,
379 const wxString& name )
380{
381 return new KISTATUSBAR( number, this, id,
382 static_cast<KISTATUSBAR::STYLE_FLAGS>(
385}
386
387
389{
390 // creates the PLUGIN_CONTENT_MANAGER, if not exists
391 if( m_pcm )
392 return;
393
394 m_pcm = std::make_shared<PLUGIN_CONTENT_MANAGER>(
395 [this]( int aUpdateCount )
396 {
397 m_pcmUpdateCount = aUpdateCount;
398
399 if( aUpdateCount > 0 )
400 {
402 wxS( "pcm" ),
403 _( "PCM Updates Available" ),
404 wxString::Format( _( "%d package update(s) available" ), aUpdateCount ),
405 wxT( "" ) );
406 }
407 else
408 {
409 Pgm().GetNotificationsManager().Remove( wxS( "pcm" ) );
410 }
411
412 CallAfter(
413 [this]()
414 {
416 } );
417 });
418
419 m_pcm->SetRepositoryList( kicadSettings()->m_PcmRepositories );
420}
421
422
424{
425 // Create the manager
427 m_toolManager->SetEnvironment( nullptr, nullptr, nullptr, config(), this );
429
431
432 // Attach the events to the tool dispatcher
434 Bind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
435
436 // Register tools
437 m_toolManager->RegisterTool( new COMMON_CONTROL );
438 m_toolManager->RegisterTool( new KICAD_MANAGER_CONTROL );
439 m_toolManager->InitTools();
440}
441
442
444{
446
447 ACTION_MANAGER* manager = m_toolManager->GetActionManager();
448
449 wxASSERT( manager );
450
451 auto activeProject =
452 [this] ( const SELECTION& )
453 {
454 return m_active_project;
455 };
456
457#define ENABLE( x ) ACTION_CONDITIONS().Enable( x )
458
459 ACTION_CONDITIONS activeProjectCond;
460 activeProjectCond.Enable( activeProject );
461
462 manager->SetConditions( ACTIONS::saveAs, activeProjectCond );
463 manager->SetConditions( KICAD_MANAGER_ACTIONS::closeProject, activeProjectCond );
464 manager->SetConditions( KICAD_MANAGER_ACTIONS::archiveProject, activeProjectCond );
465 manager->SetConditions( KICAD_MANAGER_ACTIONS::newJobsetFile, activeProjectCond );
466 manager->SetConditions( KICAD_MANAGER_ACTIONS::openJobsetFile, activeProjectCond );
467
468 auto historyCond =
469 [this]( const SELECTION& )
470 {
471 return HistoryPanelShown();
472 };
473
475 ACTION_CONDITIONS().Check( historyCond ) );
476
477 // These are just here for text boxes, search boxes, etc. in places such as the standard
478 // file dialogs.
482
483#undef ENABLE
484}
485
486
488{
489 return m_leftWin;
490}
491
492
494{
496 wxASSERT( ret );
497 return ret;
498}
499
500
502{
503 KICAD_SETTINGS* ret = dynamic_cast<KICAD_SETTINGS*>( config() );
504 wxASSERT( ret );
505 return ret;
506}
507
508
510{
512 : wxString( wxEmptyString );
513}
514
515
517{
518 wxFileName fn( GetProjectFileName() );
519
521 return fn.GetFullPath();
522}
523
524
526{
527 wxFileName fn( GetProjectFileName() );
528
530 return fn.GetFullPath();
531}
532
533
535{
536 wxFileName fn( GetProjectFileName() );
537
538 fn.SetExt( FILEEXT::PcbFileExtension );
539 return fn.GetFullPath();
540}
541
542
544{
545 wxFileName fn( GetProjectFileName() );
546
548 return fn.GetFullPath();
549}
550
551
553{
554 m_leftWin->ReCreateTreePrj();
555}
556
557
562
563
565{
566 return PgmTop().GetHelpFileName();
567}
568
569
570void KICAD_MANAGER_FRAME::OnSize( wxSizeEvent& event )
571{
572 if( m_auimgr.GetManagedWindow() )
573 m_auimgr.Update();
574
575 PrintPrjInfo();
576
577#if defined( _WIN32 )
578 KISTATUSBAR* statusBar = static_cast<KISTATUSBAR*>( GetStatusBar() );
580#endif
581
582 event.Skip();
583}
584
585
587{
588 // All fileNames are now in m_AcceptedFiles vector.
589 // Check if contains a project file name and load project.
590 // If not, open files in dedicated app.
591 for( const wxFileName& fileName : m_AcceptedFiles )
592 {
593 wxString ext = fileName.GetExt();
594
596 {
597 wxString fn = fileName.GetFullPath();
598 m_toolManager->RunAction<wxString*>( *m_acceptedExts.at( fileName.GetExt() ), &fn );
599
600 return;
601 }
602 }
603
604 // Then stock gerber files in gerberFiles and run action for other files.
605 wxString gerberFiles;
606
607 // Gerbview editor should be able to open Gerber and drill files
608 for( const wxFileName& fileName : m_AcceptedFiles )
609 {
610 wxString ext = fileName.GetExt();
611
614 {
615 gerberFiles += wxT( '\"' );
616 gerberFiles += fileName.GetFullPath() + wxT( '\"' );
617 gerberFiles = gerberFiles.Pad( 1 );
618 }
619 else
620 {
621 wxString fn = fileName.GetFullPath();
622 m_toolManager->RunAction<wxString*>( *m_acceptedExts.at( fileName.GetExt() ), &fn );
623 }
624 }
625
626 // Execute Gerbviewer
627 if( !gerberFiles.IsEmpty() )
628 {
629 wxString fullEditorName = FindKicadFile( GERBVIEW_EXE );
630
631 if( wxFileExists( fullEditorName ) )
632 {
633 wxString command = fullEditorName + " " + gerberFiles;
634 m_toolManager->RunAction<wxString*>( *m_acceptedExts.at( FILEEXT::GerberFileExtension ), &command );
635 }
636 }
637}
638
639
640bool KICAD_MANAGER_FRAME::canCloseWindow( wxCloseEvent& aEvent )
641{
642 KICAD_SETTINGS* settings = kicadSettings();
644
645 for( size_t i = 0; i < m_notebook->GetPageCount(); i++ )
646 {
647 wxWindow* page = m_notebook->GetPage( i );
648
649 if( PANEL_NOTEBOOK_BASE* panel = dynamic_cast<PANEL_NOTEBOOK_BASE*>( page ) )
650 {
651 if( !panel->GetCanClose() )
652 return false;
653 }
654 }
655
656 // CloseProject will recursively ask all the open editors if they need to save changes.
657 // If any of them cancel then we need to cancel closing the KICAD_MANAGER_FRAME.
658 if( CloseProject( true ) )
659 {
660 // Don't propagate event to frames which have already been closed
661 aEvent.StopPropagation();
662
663 return true;
664 }
665 else
666 {
667 if( aEvent.CanVeto() )
668 aEvent.Veto();
669
670 return false;
671 }
672}
673
674
676{
677#ifdef _WINDOWS_
678 // For some obscure reason, on Windows, when killing Kicad from the Windows task manager
679 // if a editor frame (schematic, library, board editor or fp editor) is open and has
680 // some edition to save, OnCloseWindow is run twice *at the same time*, creating race
681 // conditions between OnCloseWindow() code.
682 // Therefore I added (JPC) a ugly hack to discard the second call (unwanted) during
683 // execution of the first call (only one call is right).
684 // Note also if there is no change made in editors, this behavior does not happen.
685 static std::atomic<unsigned int> lock_close_event( 0 );
686
687 if( ++lock_close_event > 1 ) // Skip extra calls
688 {
689 return;
690 }
691#endif
692
693 m_leftWin->Show( false );
694 Pgm().m_Quitting = true;
695
696 Destroy();
697
698#ifdef _WINDOWS_
699 lock_close_event = 0; // Reenable event management
700#endif
701}
702
703
705{
707
708 if( !aIsExplicitUserSave && !cfg.ShouldAutoSave() )
709 return;
710
711 cfg.m_OpenJobSets.clear();
712
713 for( size_t i = 0; i < m_notebook->GetPageCount(); i++ )
714 {
715 if( PANEL_JOBSET* jobset = dynamic_cast<PANEL_JOBSET*>( m_notebook->GetPage( i ) ) )
716 {
717 wxFileName jobsetFn( jobset->GetFilePath() );
718 jobsetFn.MakeRelativeTo( Prj().GetProjectPath() );
719 cfg.m_OpenJobSets.emplace_back( jobsetFn.GetFullPath() );
720 }
721 }
722
723 cfg.SaveToFile( Prj().GetProjectPath() );
724}
725
726
727void KICAD_MANAGER_FRAME::OnExit( wxCommandEvent& event )
728{
729 Close( true );
730}
731
732
734{
735 if( !Kiway().PlayersClose( false ) )
736 return false;
737
738 // Abort any in-progress background load, since the threads depend on the project not changing
739 KIFACE *schface = Kiway().KiFACE( KIWAY::FACE_SCH );
740 schface->CancelPreload();
741
742 KIFACE *pcbface = Kiway().KiFACE( KIWAY::FACE_PCB );
743 pcbface->CancelPreload();
744
745 // Save the project file for the currently loaded project.
746 if( m_active_project )
747 {
749
750 if( Prj().GetLocalSettings().ShouldAutoSave() && Prj().GetProjectFile().ShouldAutoSave() )
751 {
753
754 if( aSave )
755 mgr.SaveProject();
756 }
757
758 // Ensure the Last_Save tag is at HEAD before closing. This handles the case where
759 // autosave commits were made after the last explicit save - without this, the next
760 // project load would offer to restore the autosave state, which is incorrect after
761 // a clean close.
762 wxString projPath = Prj().GetProjectPath();
763
764 if( !projPath.IsEmpty() && Kiway().LocalHistory().HistoryExists( projPath ) )
765 {
766 if( Kiway().LocalHistory().HeadNewerThanLastSave( projPath ) )
767 {
768 // Commit the current on-disk state and tag it so Last_Save matches HEAD
769 if( Kiway().LocalHistory().CommitFullProjectSnapshot( projPath, wxS( "Close" ) ) )
770 {
771 Kiway().LocalHistory().TagSave( projPath, wxS( "project" ) );
772 }
773 }
774 }
775
776 m_active_project = false;
777 // Enforce local history size limit (if enabled) once all pending saves/backups are done.
778 if( Pgm().GetCommonSettings() && Pgm().GetCommonSettings()->m_Backup.enabled )
779 {
781
782 if( limit > 0 )
783 Kiway().LocalHistory().EnforceSizeLimit( Prj().GetProjectPath(), (size_t) limit );
784 }
785
786 // Unregister the project saver before unloading the project to prevent
787 // dangling references
789
790 mgr.UnloadProject( &Prj() );
791 }
792
793 SetStatusText( "" );
794
795 // Traverse pages in reverse order so deleting them doesn't mess up our iterator.
796 for( int i = (int) m_notebook->GetPageCount() - 1; i >= 0; i-- )
797 {
798 wxWindow* page = m_notebook->GetPage( i );
799
800 if( PANEL_NOTEBOOK_BASE* panel = dynamic_cast<PANEL_NOTEBOOK_BASE*>( page ) )
801 {
802 if( panel->GetProjectTied() )
803 m_notebook->DeletePage( i );
804 }
805 }
806
807 m_leftWin->EmptyTreePrj();
809
810 return true;
811}
812
813
814void KICAD_MANAGER_FRAME::OpenJobsFile( const wxFileName& aFileName, bool aCreate,
815 bool aResaveProjectPreferences )
816{
817 for( size_t i = 0; i < m_notebook->GetPageCount(); i++ )
818 {
819 if( PANEL_JOBSET* panel = dynamic_cast<PANEL_JOBSET*>( m_notebook->GetPage( i ) ) )
820 {
821 if( aFileName.GetFullPath() == panel->GetFilePath() )
822 {
823 m_notebook->SetSelection( i );
824 return;
825 }
826 }
827 }
828
829 try
830 {
831 std::unique_ptr<JOBSET> jobsFile = std::make_unique<JOBSET>( aFileName.GetFullPath().ToStdString() );
832
833 jobsFile->LoadFromFile();
834
835 if( aCreate && !aFileName.FileExists() )
836 {
837 JOBSET_DESTINATION* dest = jobsFile->AddNewDestination( JOBSET_DESTINATION_T::FOLDER );
838 dest->m_outputHandler->SetOutputPath( aFileName.GetName() );
839 jobsFile->SaveToFile( wxEmptyString, true );
840 }
841
842 PANEL_JOBSET* jobPanel = new PANEL_JOBSET( m_notebook, this, std::move( jobsFile ) );
843 jobPanel->SetProjectTied( true );
844 jobPanel->SetClosable( true );
845 m_notebook->AddPage( jobPanel, aFileName.GetFullName(), true );
847
848 if( aResaveProjectPreferences )
850 }
851 catch( ... )
852 {
853 DisplayErrorMessage( this, _( "Error opening jobs file" ) );
854 }
855}
856
857
858void KICAD_MANAGER_FRAME::LoadProject( const wxFileName& aProjectFileName )
859{
860 // The project file should be valid by the time we get here or something has gone wrong.
861 if( !aProjectFileName.Exists() )
862 return;
863
864 wxString fullPath = aProjectFileName.GetFullPath();
865
866 // Check if a lock file already exists BEFORE we try to acquire it. We only want to warn
867 // the user if the lock file pre-existed, not if we're about to create it ourselves.
868 // The actual lock acquisition happens in SETTINGS_MANAGER::LoadProject().
869 wxFileName lockFn( fullPath );
870 lockFn.SetName( FILEEXT::LockFilePrefix + lockFn.GetName() );
871 lockFn.SetExt( lockFn.GetExt() + wxS( "." ) + FILEEXT::LockFileExtension );
872 bool lockFilePreExisted = lockFn.FileExists();
873
874 bool lockOverrideGranted = false;
875
876 if( lockFilePreExisted )
877 {
878 // A lock file exists. Create a LOCKFILE to read who owns it and decide what to do.
879 LOCKFILE lockFile( fullPath );
880
881 if( !lockFile.Valid() && lockFile.IsLockedByMe() )
882 {
883 // If we cannot acquire the lock but we appear to be the one who locked it, check to
884 // see if there is another KiCad instance running. If not, then we can override the
885 // lock. This could happen if KiCad crashed or was interrupted.
886 if( !Pgm().SingleInstance()->IsAnotherRunning() )
887 lockFile.OverrideLock();
888 }
889
890 if( !lockFile.Valid() )
891 {
892 wxString msg;
893 msg.Printf( _( "Project '%s' is already open by '%s' at '%s'." ),
894 fullPath, lockFile.GetUsername(), lockFile.GetHostname() );
895
896 if( !AskOverrideLock( this, msg ) )
897 return; // User clicked Cancel - abort project loading entirely
898
899 lockFile.OverrideLock();
900 lockOverrideGranted = true;
901 }
902
903 // The LOCKFILE goes out of scope here and releases/removes the lock file.
904 // SETTINGS_MANAGER::LoadProject() will create the actual persistent lock.
905 }
906
907 // Any open KIFACE's must be closed if they are not part of the new project.
908 // (We never want a KIWAY_PLAYER open on a KIWAY that isn't in the same project.)
909 // User is prompted here to close those KIWAY_PLAYERs:
910 if( !CloseProject( true ) )
911 return;
912
913 m_active_project = true;
914
915 // NB: when loading a legacy project SETTINGS_MANAGER::LoadProject() will convert it to
916 // current extension. Be very careful with aProjectFileName vs. Prj().GetProjectPath()
917 // from here on out.
918
919 Pgm().GetSettingsManager().LoadProject( fullPath );
920
921 // Propagate lock override decision to the loaded project
922 if( lockOverrideGranted )
923 Prj().SetLockOverrideGranted( true );
924
925 LoadWindowState( aProjectFileName.GetFullName() );
926
927 if( aProjectFileName.IsDirWritable() )
928 SetMruPath( Prj().GetProjectPath() );
929
930 Kiway().LocalHistory().Init( Prj().GetProjectPath() );
931
932 if( Kiway().LocalHistory().HeadNewerThanLastSave( Prj().GetProjectPath() ) )
933 {
934 wxString head = Kiway().LocalHistory().GetHeadHash( Prj().GetProjectPath() );
935
936 KICAD_MESSAGE_DIALOG dlg( this,
937 _( "KiCad found unsaved changes from your last session that are newer than "
938 "the saved project files." ),
939 _( "Recover Unsaved Changes" ),
940 wxYES_NO | wxICON_QUESTION );
941
942 dlg.SetExtendedMessage(
943 _( "This can happen if your previous session ended unexpectedly.\n\n"
944 "Choose 'Restore' to recover those changes, or 'Discard' to keep the "
945 "currently saved files." ) );
946
947 dlg.SetYesNoLabels( _( "Restore" ), _( "Discard" ) );
948
949 if( dlg.ShowModal() == wxID_YES )
950 {
951 Kiway().LocalHistory().RestoreCommit( Prj().GetProjectPath(), head, this );
952 }
953 else
954 {
955 // User declined to restore - commit the current on-disk state and tag it
956 // so we don't prompt again on next load
957 if( Kiway().LocalHistory().CommitFullProjectSnapshot( Prj().GetProjectPath(),
958 wxS( "Declined restore" ) ) )
959 {
960 Kiway().LocalHistory().TagSave( Prj().GetProjectPath(), wxS( "project" ) );
961 }
962 }
963 }
964
965 // Save history & window state to disk now. Don't wait around for a crash.
966 KICAD_SETTINGS* settings = kicadSettings();
967 SaveSettings( settings );
968 settings->SaveToFile( Pgm().GetSettingsManager().GetPathForSettingsFile( settings ) );
969
970 m_leftWin->ReCreateTreePrj();
971 m_historyPane->RefreshHistory( Prj().GetProjectPath() );
972
973 for( const wxString& jobset : Prj().GetLocalSettings().m_OpenJobSets )
974 {
975 wxFileName jobsetFn( jobset );
976 jobsetFn.MakeAbsolute( Prj().GetProjectPath() );
977
978 if( jobsetFn.Exists() )
979 OpenJobsFile( jobsetFn.GetFullPath(), false, false );
980 }
981
982 // Always start with the apps page
983 m_notebook->SetSelection( 0 );
984
985 // Rebuild the list of watched paths.
986 // however this is possible only when the main loop event handler is running,
987 // so we use it to run the rebuild function.
988 wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED, ID_INIT_WATCHED_PATHS );
989
990 wxPostEvent( this, cmd );
991
992 PrintPrjInfo();
993
994 KIPLATFORM::APP::RegisterApplicationRestart( aProjectFileName.GetFullPath() );
995 m_openSavedWindows = true;
996
997 KIPLATFORM::ENV::AddToRecentDocs( aProjectFileName.GetFullPath() );
998
999 // Now that we have a new project, trigger a library preload, which will load in any
1000 // project-specific symbol and footprint libraries into the manager
1001 CallAfter( [&]()
1002 {
1003 KIFACE *schface = Kiway().KiFACE( KIWAY::FACE_SCH );
1004 schface->PreloadLibraries( &Kiway() );
1005
1006 KIFACE *pcbface = Kiway().KiFACE( KIWAY::FACE_PCB );
1007 pcbface->PreloadLibraries( &Kiway() );
1008
1010 } );
1011}
1012
1013
1014void KICAD_MANAGER_FRAME::CreateNewProject( const wxFileName& aProjectFileName, bool aCreateStubFiles )
1015{
1016 wxCHECK_RET( aProjectFileName.DirExists() && aProjectFileName.IsDirWritable(),
1017 "Project folder must exist and be writable to create a new project." );
1018
1019 // If the project is legacy, convert it
1020 if( !aProjectFileName.FileExists() )
1021 {
1022 wxFileName legacyPro( aProjectFileName );
1023 legacyPro.SetExt( FILEEXT::LegacyProjectFileExtension );
1024
1025 if( legacyPro.FileExists() )
1026 {
1027 GetSettingsManager()->LoadProject( legacyPro.GetFullPath() );
1029
1030 wxRemoveFile( legacyPro.GetFullPath() );
1031 }
1032 else
1033 {
1034 // Copy template project file from template folder.
1035 wxString srcFileName = sys_search().FindValidPath( "kicad.kicad_pro" );
1036
1037 wxFileName destFileName( aProjectFileName );
1038 destFileName.SetExt( FILEEXT::ProjectFileExtension );
1039
1040 // Create a minimal project file if the template project file could not be copied
1041 if( !wxFileName::FileExists( srcFileName )
1042 || !wxCopyFile( srcFileName, destFileName.GetFullPath() ) )
1043 {
1044 wxFFile file( destFileName.GetFullPath(), "wb" );
1045
1046 if( file.IsOpened() )
1047 file.Write( wxT( "{\n}\n") );
1048
1049 // wxFFile dtor will close the file
1050 }
1051 }
1052 }
1053
1054 // Create a "stub" for a schematic root sheet and a board if requested.
1055 // It will avoid messages from the schematic editor or the board editor to create a new file
1056 // And forces the user to create main files under the right name for the project manager
1057 if( aCreateStubFiles )
1058 {
1059 wxFileName fn( aProjectFileName.GetFullPath() );
1061
1062 // If a <project>.kicad_sch file does not exist, create a "stub" file ( minimal schematic
1063 // file ).
1064 if( !fn.FileExists() )
1065 {
1066 wxFFile file( fn.GetFullPath(), "wb" );
1067
1068 if( file.IsOpened() )
1069 {
1070 file.Write( wxString::Format( "(kicad_sch\n"
1071 "\t(version %d)\n"
1072 "\t(generator \"eeschema\")\n"
1073 "\t(generator_version \"%s\")\n"
1074 "\t(uuid %s)\n"
1075 "\t(paper \"A4\")\n"
1076 "\t(lib_symbols)\n"
1077 "\t(sheet_instances\n"
1078 "\t\t(path \"/\"\n"
1079 "\t\t\t(page \"1\")\n"
1080 "\t\t)\n"
1081 "\t)\n"
1082 "\t(embedded_fonts no)\n"
1083 ")",
1085 KIID().AsString() ) );
1086 }
1087
1088 // wxFFile dtor will close the file
1089 }
1090
1091 // If a <project>.kicad_pcb or <project>.brd file does not exist,
1092 // create a .kicad_pcb "stub" file
1093 fn.SetExt( FILEEXT::KiCadPcbFileExtension );
1094 wxFileName leg_fn( fn );
1095 leg_fn.SetExt( FILEEXT::LegacyPcbFileExtension );
1096
1097 if( !fn.FileExists() && !leg_fn.FileExists() )
1098 {
1099 wxFFile file( fn.GetFullPath(), "wb" );
1100
1101 if( file.IsOpened() )
1102 {
1103 // Create a small dummy file as a stub for pcbnew:
1104 file.Write( wxString::Format( "(kicad_pcb (version %d) (generator \"pcbnew\") (generator_version \"%s\")\n)",
1106 }
1107
1108 // wxFFile dtor will close the file
1109 }
1110 }
1111
1112 // Save history & window state to disk now. Don't wait around for a crash.
1113 KICAD_SETTINGS* settings = kicadSettings();
1114 SaveSettings( settings );
1115 settings->SaveToFile( Pgm().GetSettingsManager().GetPathForSettingsFile( settings ) );
1116
1117 m_openSavedWindows = true;
1118}
1119
1120
1122{
1123 // show all files in file dialog (in Kicad all files are editable texts):
1124 wxString wildcard = FILEEXT::AllFilesWildcard();
1125
1126 wxString default_dir = Prj().GetProjectPath();
1127
1128 wxFileDialog dlg( this, _( "Edit File in Text Editor" ), default_dir, wxEmptyString, wildcard,
1129 wxFD_OPEN );
1130
1132
1133 if( dlg.ShowModal() == wxID_CANCEL )
1134 return;
1135
1136 wxString filename = dlg.GetPath();
1137
1138 if( !dlg.GetPath().IsEmpty() && !Pgm().GetTextEditor().IsEmpty() )
1139 m_toolManager->RunAction<wxString*>( KICAD_MANAGER_ACTIONS::openTextEditor, &filename );
1140}
1141
1142
1143void KICAD_MANAGER_FRAME::OnEditAdvancedCfg( wxCommandEvent& WXUNUSED( event ) )
1144{
1145 DIALOG_EDIT_CFG dlg( this );
1146 dlg.ShowModal();
1147}
1148
1149
1151{
1152 m_leftWin->ReCreateTreePrj();
1153}
1154
1155
1156void KICAD_MANAGER_FRAME::language_change( wxCommandEvent& event )
1157{
1158 int id = event.GetId();
1159 Kiway().SetLanguage( id );
1160}
1161
1162
1164{
1165 // call my base class
1167
1168 // tooltips in toolbars
1170 m_launcher->CreateLaunchers();
1171
1172 // update captions
1173 int pageId = m_notebook->FindPage( m_launcher );
1174
1175 if( pageId != wxNOT_FOUND )
1176 m_notebook->SetPageText( pageId, EDITORS_CAPTION );
1177
1178 m_auimgr.GetPane( m_leftWin ).Caption( PROJECT_FILES_CAPTION );
1179 m_auimgr.Update();
1180
1181 m_leftWin->FileWatcherReset();
1182
1183 PrintPrjInfo();
1184}
1185
1186
1188{
1190
1191 if( m_pcm && ( aFlags & ENVVARS_CHANGED ) )
1192 m_pcm->ReadEnvVar();
1193
1194 COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
1195
1196 if( m_lastToolbarIconSize == 0
1198 {
1201 }
1202
1203 m_leftWin->ReCreateTreePrj();
1204}
1205
1206
1208{
1209 wxString file = GetProjectFileName();
1210
1211 // empty file string means no project loaded
1212 if( !Prj().IsNullProject() &&
1213 Prj().GetProjectLock() == nullptr )
1214 {
1215 LOCKFILE lockFile( file );
1216
1217 if( !lockFile.Valid() && lockFile.IsLockedByMe() )
1218 {
1219 // If we cannot acquire the lock but we appear to be the one who
1220 // locked it, check to see if there is another KiCad instance running.
1221 // If there is not, then we can override the lock. This could happen if
1222 // KiCad crashed or was interrupted
1223 if( !Pgm().SingleInstance()->IsAnotherRunning() )
1224 {
1225 lockFile.OverrideLock();
1226 }
1227 }
1228
1229 if( !lockFile.Valid() )
1230 {
1231 wxString msg;
1232 msg.Printf( _( "Project '%s' is already open by '%s' at '%s'." ), file, lockFile.GetUsername(),
1233 lockFile.GetHostname() );
1234
1235 if( AskOverrideLock( this, msg ) )
1236 {
1237 lockFile.OverrideLock();
1238 }
1239 }
1240
1241 Prj().SetReadOnly( !lockFile.Valid() || Prj().GetProjectFile().IsReadOnly() );
1242 Prj().SetProjectLock( new LOCKFILE( std::move( lockFile ) ) );
1243 }
1244
1245 wxString title;
1246
1247 if( !file.IsEmpty() )
1248 {
1249 wxFileName fn( file );
1250
1251 title = fn.GetName();
1252
1253 if( Prj().IsReadOnly() )
1254 title += wxS( " " ) + _( "[Read Only]" );
1255 }
1256 else
1257 {
1258 title = _( "[no project loaded]" );
1259 }
1260
1261 if( ADVANCED_CFG::GetCfg().m_HideVersionFromTitle )
1262 title += wxT( " \u2014 " ) + wxString( wxS( "KiCad" ) );
1263 else
1264 title += wxT( " \u2014 " ) + wxString( wxS( "KiCad " ) ) + GetMajorMinorVersion();
1265
1266 SetTitle( title );
1267
1268 // Register project file saver. Ensures project file participates in
1269 // autosave history commits without affecting dirty state.
1271 [this]( const wxString& aProjectPath, std::vector<wxString>& aFiles )
1272 {
1273 Prj().SaveToHistory( aProjectPath, aFiles );
1274 } );
1275}
1276
1277
1279{
1281
1282 auto settings = dynamic_cast<KICAD_SETTINGS*>( aCfg );
1283
1284 wxCHECK( settings, /*void*/ );
1285
1286 m_leftWinWidth = settings->m_LeftWinWidth;
1287 m_showHistoryPanel = settings->m_ShowHistoryPanel;
1288}
1289
1290
1292{
1294
1295 auto settings = dynamic_cast<KICAD_SETTINGS*>( aCfg );
1296
1297 wxCHECK( settings, /*void*/);
1298
1299 settings->m_LeftWinWidth = m_leftWin->GetSize().x;
1300 settings->m_ShowHistoryPanel = m_historyPane &&
1301 m_auimgr.GetPane( m_historyPane ).IsShown();
1302
1303 if( !m_isClosing )
1304 settings->m_OpenProjects = GetSettingsManager()->GetOpenProjects();
1305}
1306
1307
1309{
1310 // wxStatusBar's wxELLIPSIZE_MIDDLE flag doesn't work (at least on Mac).
1311
1312 wxString status = wxString::Format( _( "Project: %s" ), Prj().GetProjectFullName() );
1313 KISTATUSBAR* statusBar = static_cast<KISTATUSBAR*>( GetStatusBar() );
1314 statusBar->SetEllipsedTextField( status, 0 );
1315}
1316
1317
1322
1323
1324void KICAD_MANAGER_FRAME::OnIdle( wxIdleEvent& aEvent )
1325{
1331 if( !m_openSavedWindows )
1332 return;
1333
1334 m_openSavedWindows = false;
1335
1336 if( Pgm().GetCommonSettings()->m_Session.remember_open_files )
1337 {
1338 int previousOpenCount =
1339 std::count_if( Prj().GetLocalSettings().m_files.begin(),
1340 Prj().GetLocalSettings().m_files.end(),
1341 [&]( const PROJECT_FILE_STATE& f )
1342 {
1343 return !f.fileName.EndsWith( FILEEXT::ProjectFileExtension ) && f.open;
1344 } );
1345
1346 if( previousOpenCount > 0 )
1347 {
1348 APP_PROGRESS_DIALOG progressReporter( _( "Restoring session" ), wxEmptyString,
1349 previousOpenCount, this );
1350
1351 // We don't currently support opening more than one view per file
1352 std::set<wxString> openedFiles;
1353
1354 int i = 0;
1355
1356 for( const PROJECT_FILE_STATE& file : Prj().GetLocalSettings().m_files )
1357 {
1358 if( file.open && !openedFiles.count( file.fileName ) )
1359 {
1360 progressReporter.Update( i++, wxString::Format( _( "Restoring '%s'" ), file.fileName ) );
1361
1362 openedFiles.insert( file.fileName );
1363 wxFileName fn( file.fileName );
1364
1365 if( fn.GetExt() == FILEEXT::LegacySchematicFileExtension
1366 || fn.GetExt() == FILEEXT::KiCadSchematicFileExtension )
1367 {
1369 }
1370 else if( fn.GetExt() == FILEEXT::LegacyPcbFileExtension
1371 || fn.GetExt() == FILEEXT::KiCadPcbFileExtension )
1372 {
1374 }
1375 }
1376
1377 wxYield();
1378 }
1379 }
1380 }
1381
1382 // clear file states regardless if we opened windows or not due to setting
1384
1385 // After restore from history, mark open editors as dirty so user is prompted to save
1387 {
1388 m_restoredFromHistory = false;
1389
1390 // Mark schematic editor as dirty if open
1391 if( KIWAY_PLAYER* schFrame = Kiway().Player( FRAME_SCH, false ) )
1392 schFrame->OnModify();
1393
1394 // Mark PCB editor as dirty if open
1395 if( KIWAY_PLAYER* pcbFrame = Kiway().Player( FRAME_PCB_EDITOR, false ) )
1396 pcbFrame->OnModify();
1397 }
1398
1399 KICAD_SETTINGS* settings = kicadSettings();
1400
1402 && settings->m_PcmUpdateCheck )
1403 {
1404 if( !m_pcm )
1405 CreatePCM();
1406
1407 m_pcm->RunBackgroundUpdate();
1408 }
1409
1410#ifdef KICAD_UPDATE_CHECK
1411 if( !m_updateManager && settings->m_KiCadUpdateCheck )
1412 {
1413 m_updateManager = std::make_unique<UPDATE_MANAGER>();
1414 m_updateManager->CheckForUpdate( this );
1415 }
1416#endif
1417
1418 // This little diddy is needed to get the window put into the Mac dock icon's context menu.
1419 Raise();
1420}
1421
1422
1424{
1425 m_pcmButton = aButton;
1426
1428}
1429
1430
1432{
1433 if( m_pcmButton )
1434 {
1435 if( m_pcmUpdateCount > 0 )
1436 {
1437 m_pcmButton->SetShowBadge( true );
1438 m_pcmButton->SetBadgeText( wxString::Format( "%d", m_pcmUpdateCount ) );
1439 }
1440 else
1441 {
1442 m_pcmButton->SetShowBadge( false );
1443 }
1444
1445 m_pcmButton->Refresh();
1446 }
1447}
1448
1449
1451{
1452 // No idea why, but the same mechanism used in EDA_DRAW_FRAME doesn't work here
1453 // the only thing that seems to work is to blow it all up and start from scratch.
1454 m_auimgr.DetachPane( m_tbLeft );
1455 delete m_tbLeft;
1456 m_tbLeft = nullptr;
1458 m_auimgr.AddPane( m_tbLeft, EDA_PANE().HToolbar().Name( "TopMainToolbar" ).Left()
1459 .Layer( 2 ) );
1460
1461 m_auimgr.Update();
1462}
1463
1464
1466{
1467 wxAuiPaneInfo& pane = m_auimgr.GetPane( m_historyPane );
1468 bool show = !pane.IsShown();
1469 pane.Show( show );
1470
1471 if( show )
1472 m_historyPane->RefreshHistory( Prj().GetProjectPath() );
1473
1474 m_auimgr.Update();
1475}
1476
1477
1479{
1480 if( !Kiway().PlayersClose( true ) )
1481 return;
1482
1483 if( Kiway().LocalHistory().RestoreCommit( Prj().GetProjectPath(), aHash, this ) )
1484 {
1485 m_restoredFromHistory = true; // Mark editors dirty when they reopen
1486 }
1487
1488 m_leftWin->ReCreateTreePrj();
1489 m_openSavedWindows = true;
1490 m_historyPane->RefreshHistory( Prj().GetProjectPath() );
1491}
1492
1493
1495{
1496 return m_historyPane && m_auimgr.GetPane( m_historyPane ).IsShown();
1497}
const char * name
constexpr EDA_IU_SCALE unityScale
Definition base_units.h:115
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_nightly
@ 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:80
static TOOL_ACTION saveAs
Definition actions.h:59
static TOOL_ACTION copy
Definition actions.h:78
static TOOL_ACTION cut
Definition actions.h:77
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.
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.
Handle actions that are shared between different applications.
APPEARANCE m_Appearance
AUTO_BACKUP m_Backup
The base frame for deriving all KiCad main window classes.
void LoadWindowState(const wxString &aFileName)
void CommonSettingsChanged(int aFlags) override
Notification event that some of the common (suite-wide) settings have changed.
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 RecreateToolbars()
virtual void LoadSettings(APP_SETTINGS_BASE *aCfg)
Load common frame parameters from a configuration file.
ACTION_TOOLBAR * m_tbLeft
std::map< const wxString, TOOL_ACTION * > m_acceptedExts
Associate file 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)
bool m_isClosing
Set by the close window event handler after frames are asked if they can close.
Specialization of the wxAuiPaneInfo class for KiCad panels.
void SetOutputPath(const wxString &aPath)
Definition jobs_output.h:56
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 loadProject
static TOOL_ACTION showLocalHistory
static TOOL_ACTION editSchematic
static TOOL_ACTION openTextEditor
static TOOL_ACTION archiveProject
static TOOL_ACTION closeProject
static TOOL_ACTION openJobsetFile
static TOOL_ACTION newJobsetFile
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 CreateNewProject(const wxFileName &aProjectFileName, bool aCreateStubFiles=true)
Creates a new project by setting up and initial project, schematic, and board files.
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()
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
void OnImportAltiumProjectFiles(wxCommandEvent &event)
Open dialog to import Altium project files.
const wxString GetProjectFileName() const
KICAD_SETTINGS * kicadSettings() const
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 OpenJobsFile(const wxFileName &aFileName, bool aCreate=false, bool aResaveProjectPreferences=true)
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 RestoreCommitFromHistory(const wxString &aHash)
void DoWithAcceptedFiles() override
Execute action on accepted dropped file.
void OnOpenFileInTextEditor(wxCommandEvent &event)
APP_SETTINGS_BASE * config() const override
Return the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
const wxString PcbLegacyFileName()
void OnEditAdvancedCfg(wxCommandEvent &event)
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 CommonSettingsChanged(int aFlags) override
Notification event that some of the common (suite-wide) settings have changed.
void LoadSettings(APP_SETTINGS_BASE *aCfg) override
Load common frame parameters from a configuration file.
void OnIdle(wxIdleEvent &event)
void PrintPrjInfo()
Prints the current working directory name and the project name on the text panel.
void SaveOpenJobSetsToLocalSettings(bool aIsExplicitUserSave=false)
bool m_restoredFromHistory
Set after restore to mark editors dirty.
void onNotebookPageCountChanged(wxAuiNotebookEvent &evt)
LOCAL_HISTORY_PANE * m_historyPane
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
void HideTabsIfNeeded()
Hides the tabs for Editor notebook if there is only 1 page.
wxString help_name() override
std::unique_ptr< UPDATE_MANAGER > m_updateManager
std::vector< wxString > m_OpenProjects
Definition kiid.h:49
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.
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.
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
virtual void SetLanguage(int aLanguage)
Change the language and then calls ShowChangedLanguage() on all #KIWAY_PLAYERs.
Definition kiway.cpp:526
virtual KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
Definition kiway.cpp:206
@ FACE_SCH
eeschema DSO
Definition kiway.h:301
@ FACE_PCB
pcbnew DSO
Definition kiway.h:302
LOCAL_HISTORY & LocalHistory()
Return the LOCAL_HISTORY associated with this KIWAY.
Definition kiway.h:406
bool TagSave(const wxString &aProjectPath, const wxString &aFileType)
Tag a manual save in the local history repository.
wxString GetHeadHash(const wxString &aProjectPath)
Return the current head commit hash.
bool RestoreCommit(const wxString &aProjectPath, const wxString &aHash, wxWindow *aParent=nullptr)
Restore the project files to the state recorded by the given commit hash.
bool EnforceSizeLimit(const wxString &aProjectPath, size_t aMaxBytes)
Enforce total size limit by rebuilding trimmed history keeping newest commits whose cumulative unique...
bool Init(const wxString &aProjectPath)
Initialize the local history repository for the given project path.
void UnregisterSaver(const void *aSaverObject)
Unregister a previously registered saver callback.
void RegisterSaver(const void *aSaverObject, const std::function< void(const wxString &, std::vector< wxString > &)> &aSaver)
Register a saver callback invoked during autosave history commits.
bool OverrideLock(bool aRemoveOnRelease=true)
Force the lock, overwriting the data that existed already.
Definition lockfile.h:174
bool Valid() const
Definition lockfile.h:254
wxString GetUsername()
Definition lockfile.h:236
wxString GetHostname()
Definition lockfile.h:242
bool IsLockedByMe()
Definition lockfile.h:227
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)
Create 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)
Remove status bar from handling.
static REPORTER & GetInstance()
Definition reporter.cpp:97
void SetClosable(bool aYes)
void SetProjectTied(bool aYes)
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition pgm_base.cpp:535
void PreloadDesignBlockLibraries(KIWAY *aKiway)
Starts a background job to preload the global and project design block libraries.
Definition pgm_base.cpp:881
virtual BACKGROUND_JOBS_MONITOR & GetBackgroundJobMonitor() const
Definition pgm_base.h:138
void UnregisterLibraryLoadStatusBar(KISTATUSBAR *aStatusBar)
Unregister a status bar from receiving library load warning messages.
Definition pgm_base.cpp:973
bool m_Quitting
Definition pgm_base.h:395
void RegisterLibraryLoadStatusBar(KISTATUSBAR *aStatusBar)
Register a status bar to receive library load warning messages.
Definition pgm_base.cpp:953
virtual NOTIFICATIONS_MANAGER & GetNotificationsManager() const
Definition pgm_base.h:143
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:132
wxString GetHelpFileName()
Definition pgm_kicad.h:63
SEARCH_STACK & SysSearch()
Definition pgm_kicad.h:61
APP_SETTINGS_BASE * PgmSettings()
Definition pgm_kicad.h:59
The project local settings are things that are attached to a particular project, but also might be pa...
bool SaveToFile(const wxString &aDirectory="", bool aForce=false) override
Calls Store() and then writes the contents of the JSON document to a file.
std::vector< wxString > m_OpenJobSets
PROJECT_TREE_PANE Window to display the tree files.
void SetProjectLock(LOCKFILE *aLockFile)
Definition project.cpp:446
virtual void SetReadOnly(bool aReadOnly=true)
Definition project.h:163
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition project.cpp:162
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:168
void SaveToHistory(const wxString &aProjectPath, std::vector< wxString > &aFiles)
Save project files (.kicad_pro and .kicad_prl) to the .history directory.
Definition project.cpp:452
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition project.h:209
virtual void SetLockOverrideGranted(bool aGranted=true)
Definition project.h:167
Look for files in a number of paths.
static bool ShowNever(const SELECTION &aSelection)
Always returns false.
bool SaveProject(const wxString &aFullPath=wxEmptyString, PROJECT *aProject=nullptr)
Save a loaded project.
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Load a project or sets up a new project with a specified path.
bool IsProjectOpen() const
Helper for checking if we have a project open.
bool UnloadProject(PROJECT *aProject, bool aSave=true)
Save, unload and unregister the given PROJECT.
std::vector< wxString > GetOpenProjects() const
bool TriggerBackupIfNeeded(REPORTER &aReporter) const
Call BackupProject() if a new backup is needed according to the current backup policy.
TOOL_MANAGER * m_toolManager
TOOL_DISPATCHER * m_toolDispatcher
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
ACTIONS * m_actions
virtual void DispatchWxEvent(wxEvent &aEvent)
Process wxEvents (mostly UI events), translate them to TOOL_EVENTs, and make tools handle those.
Master controller class:
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
bool AskOverrideLock(wxWindow *aParent, const wxString &aMessage)
Display a dialog indicating the file is already open, with an option to reset the lock.
Definition confirm.cpp:42
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
This file is part of the common library.
#define KICAD_MESSAGE_DIALOG
Definition confirm.h:52
#define ENABLE(x)
#define _(s)
Base window classes and related definitions.
#define KICAD_DEFAULT_DRAWFRAME_STYLE
#define KICAD_MANAGER_FRAME_NAME
EVT_MENU_RANGE(ID_GERBVIEW_DRILL_FILE1, ID_GERBVIEW_DRILL_FILEMAX, GERBVIEW_FRAME::OnDrlFileHistory) EVT_MENU_RANGE(ID_GERBVIEW_ZIP_FILE1
KiCad executable names.
const wxString GERBVIEW_EXE
@ FRAME_PCB_EDITOR
Definition frame_type.h:42
@ FRAME_SCH
Definition frame_type.h:34
@ 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:61
static const std::string LegacySchematicFileExtension
static const std::string GerberJobFileExtension
static const std::string GerberFileExtension
static const std::string LockFileExtension
static const std::string ProjectFileExtension
static const std::string LegacyPcbFileExtension
static const std::string LegacyProjectFileExtension
static const std::string KiCadSchematicFileExtension
static const std::string LockFilePrefix
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:62
@ ID_LANGUAGE_CHOICE
Definition id.h:66
@ ID_FILEMAX
Definition id.h:60
@ ID_LANGUAGE_CHOICE_END
Definition id.h:110
@ ID_FILE1
Definition id.h:59
PGM_KICAD & PgmTop()
Definition kicad.cpp:87
@ ID_EDIT_ADVANCED_CFG
Definition kicad_id.h:38
@ ID_IMPORT_EAGLE_PROJECT
Definition kicad_id.h:40
@ ID_IMPORT_EASYEDAPRO_PROJECT
Definition kicad_id.h:42
@ ID_IMPORT_CADSTAR_ARCHIVE_PROJECT
Definition kicad_id.h:39
@ ID_EDIT_LOCAL_FILE_IN_TEXT_EDITOR
Definition kicad_id.h:37
@ ID_IMPORT_EASYEDA_PROJECT
Definition kicad_id.h:41
@ ID_IMPORT_ALTIUM_PROJECT
Definition kicad_id.h:43
#define EDITORS_CAPTION
#define ID_INIT_WATCHED_PATHS
#define PROJECT_FILES_CAPTION
File locking utilities.
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
void AddToRecentDocs(const wxString &aPath)
PBOOL GetPolicyBool(const wxString &aKey)
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:717
KICOMMON_API wxFont GetStatusFont(wxWindow *aWindow)
#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.
#define POLICY_KEY_PCM
Definition policy_keys.h:31
#define SEXPR_SCHEMATIC_FILE_VERSION
Schematic file version.
T * GetToolbarSettings(const wxString &aFilename)
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)
unsigned long long limit_total_size
Maximum total size of backups (bytes), 0 for unlimited.
std::shared_ptr< JOBS_OUTPUT_HANDLER > m_outputHandler
Definition jobset.h:136
Implement a participant in the KIWAY alchemy.
Definition kiway.h:155
virtual void PreloadLibraries(KIWAY *aKiway)
Definition kiway.h:258
virtual void CancelPreload(bool aBlock=true)
Definition kiway.h:260
#define ENVVARS_CHANGED
Definition of file extensions used in Kicad.