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>
43#include <wx/msgdlg.h>
44#include <eda_base_frame.h>
45#include <executable_names.h>
46#include <file_history.h>
47#include <local_history.h>
48#include <policy_keys.h>
49#include <gestfich.h>
50#include <kiplatform/app.h>
52#include <kiplatform/ui.h>
53#include <kiplatform/policy.h>
54#include <build_version.h>
55#include <kiway.h>
56#include <kiway_mail.h>
57#include <launch_ext.h>
58#include <lockfile.h>
60#include <reporter.h>
62#include <sch_file_versions.h>
65#include <tool/action_manager.h>
66#include <tool/action_toolbar.h>
67#include <tool/common_control.h>
69#include <tool/tool_manager.h>
75#include <widgets/kistatusbar.h>
76#include <wx/ffile.h>
77#include <wx/filedlg.h>
78#include <wx/dnd.h>
79#include <wx/process.h>
80#include <wx/snglinst.h>
81#include <atomic>
82#include <update_manager.h>
83#include <jobs/jobset.h>
85
86#include <../pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h> // for SEXPR_BOARD_FILE_VERSION def
87
88
89#ifdef __WXMAC__
90#include <MacTypes.h>
91#include <ApplicationServices/ApplicationServices.h>
92#endif
93
94#include "kicad_manager_frame.h"
96
98
99
100#define EDITORS_CAPTION _( "Editors" )
101#define PROJECT_FILES_CAPTION _( "Project Files" )
102
103#define ID_INIT_WATCHED_PATHS 52913
104
105#define SEP() wxFileName::GetPathSeparator()
106
107
108// Menubar and toolbar event table
109BEGIN_EVENT_TABLE( KICAD_MANAGER_FRAME, EDA_BASE_FRAME )
110 // Window events
113
114 // Menu events
115 EVT_MENU( wxID_EXIT, KICAD_MANAGER_FRAME::OnExit )
126
127 // Range menu events
130
131 // Special functions
133
134 // Drop files event
135 EVT_DROP_FILES( KICAD_MANAGER_FRAME::OnDropFiles )
136
137END_EVENT_TABLE()
138
139// See below the purpose of this include
140#include <wx/xml/xml.h>
141
142KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent, const wxString& title,
143 const wxPoint& pos, const wxSize& size ) :
146 m_openSavedWindows( false ),
147 m_restoredFromHistory( false ),
148 m_active_project( false ),
149 m_showHistoryPanel( false ),
150 m_projectTreePane( nullptr ),
151 m_historyPane( nullptr ),
152 m_launcher( nullptr ),
154 m_pcmButton( nullptr ),
156{
157 const int defaultLeftWinWidth = FromDIP( 250 );
158
159 m_leftWinWidth = defaultLeftWinWidth; // Default value
160 m_aboutTitle = "KiCad";
161
162 // JPC: A very ugly hack to fix an issue on Linux: if the wxbase315u_xml_gcc_custom.so is
163 // used **only** in PCM, it is not found in some cases at run time.
164 // So just use it in the main module to avoid a not found issue
165 // wxbase315u_xml_gcc_custom shared object when launching Kicad
166 wxXmlDocument dummy;
167
168 // Create the status line (bottom of the frame). Left half is for project name; right half
169 // is for Reporter (currently used by archiver/unarchiver and PCM).
170 // Note: this is a KISTATUSBAR status bar. Therefore the specified number of fields
171 // is the extra number of fields, not the full field count.
172 // We need here 2 fields: the extra fiels to display the project name, and another field
173 // to display a info (specific to Windows) using the FIELD_OFFSET_BGJOB_TEXT id offset (=1)
174 // So the extra field count is 1
175 CreateStatusBar( 2 );
178 Pgm().RegisterLibraryLoadStatusBar( (KISTATUSBAR*) GetStatusBar() );
179 GetStatusBar()->SetFont( KIUI::GetStatusFont( this ) );
180
181 // Give an icon
182 wxIcon icon;
183 wxIconBundle icon_bundle;
184
185 if( IsNightlyVersion())
186 {
187 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly, 48 ) );
188 icon_bundle.AddIcon( icon );
189 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly, 128 ) );
190 icon_bundle.AddIcon( icon );
191 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly, 256 ) );
192 icon_bundle.AddIcon( icon );
193 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly_32 ) );
194 icon_bundle.AddIcon( icon );
195 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly_16 ) );
196 icon_bundle.AddIcon( icon );
197 }
198 else
199 {
200 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad, 48 ) );
201 icon_bundle.AddIcon( icon );
202 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad, 128 ) );
203 icon_bundle.AddIcon( icon );
204 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad, 256 ) );
205 icon_bundle.AddIcon( icon );
206 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_32 ) );
207 icon_bundle.AddIcon( icon );
208 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_16 ) );
209 icon_bundle.AddIcon( icon );
210 }
211
212 SetIcons( icon_bundle );
213
214 // Load the settings
215 LoadSettings( config() );
216
217 // Left window: is the box which display tree project
219
220 setupTools();
222
227
228 m_auimgr.SetManagedWindow( this );
229 m_auimgr.SetFlags( wxAUI_MGR_LIVE_RESIZE );
230
231 m_auimgr.AddPane( m_tbLeft, EDA_PANE().VToolbar().Name( "TopMainToolbar" ).Left().Layer( 2 ) );
232
233 // There is no wxAUIPaneInfo::SetSize(), but a trick is to use MinSize() to set the required pane width,
234 // and after give a reasonable MinSize value.
236 EDA_PANE().Palette().Name( "ProjectTree" ).Left().Layer( 1 )
237 .Caption( PROJECT_FILES_CAPTION ).PaneBorder( false )
238 .MinSize( m_leftWinWidth, -1 ).Floatable( false ).Movable( false ) );
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
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 );
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_projectTreePane size is set, give it a reasonable min width
273 m_auimgr.GetPane( m_projectTreePane ).MinSize( defaultLeftWinWidth, FromDIP( 80 ) );
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_projectTreePane->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
307
309{
311 Unbind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
312
313 m_notebook->Unbind( wxEVT_AUINOTEBOOK_PAGE_CLOSE, &KICAD_MANAGER_FRAME::onNotebookPageCloseRequest, this );
314 m_notebook->Unbind( wxEVT_AUINOTEBOOK_PAGE_CLOSED, &KICAD_MANAGER_FRAME::onNotebookPageCountChanged, this );
315
318 Pgm().UnregisterLibraryLoadStatusBar( (KISTATUSBAR*) GetStatusBar() );
319
320 // Shutdown all running tools
321 if( m_toolManager )
322 m_toolManager->ShutdownAllTools();
323
324 if( m_pcm )
325 m_pcm->StopBackgroundUpdate();
326
327 // Stop update manager before tearing down the AUI framework. The update
328 // task runs on the thread pool and may call CallAfter on this frame, so it
329 // must complete before we uninitialize AUI or destroy child windows.
330 m_updateManager.reset();
331
332 delete m_actions;
333 delete m_toolManager;
334 delete m_toolDispatcher;
335
336 m_auimgr.UnInit();
337}
338
340{
341 if( m_notebook->GetPageCount() == 1 )
342 m_notebook->SetTabCtrlHeight( 0 );
343 else
344 m_notebook->SetTabCtrlHeight( -1 );
345}
346
347
349{
351}
352
353
355{
356 wxAuiNotebook* notebook = (wxAuiNotebook*) evt.GetEventObject();
357 wxWindow* page = notebook->GetPage( evt.GetSelection() );
358
359 if( PANEL_NOTEBOOK_BASE* panel = dynamic_cast<PANEL_NOTEBOOK_BASE*>( page ) )
360 {
361 if( panel->GetClosable() )
362 {
363 if( !panel->GetCanClose() )
364 evt.Veto();
365
366 CallAfter(
367 [this]()
368 {
370 } );
371 }
372 else
373 {
374 evt.Veto();
375 }
376 }
377}
378
379
380wxStatusBar* KICAD_MANAGER_FRAME::OnCreateStatusBar( int number, long style, wxWindowID id,
381 const wxString& name )
382{
383 KISTATUSBAR* sb = new KISTATUSBAR( number, this, id,
387
388 size_t sbFieldCnt = static_cast<size_t>( sb->GetFieldsCount() );
389 std::vector<int> sbFieldSizes( sbFieldCnt );
390
391 for( size_t i = 0; i < sbFieldCnt; i++ )
392 sbFieldSizes[i] = sb->GetStatusWidth( static_cast<int>( i ) );
393
394 if( sbFieldCnt )
395 sbFieldSizes[0] = -3;
396
397 sb->SetStatusWidths( sbFieldCnt, sbFieldSizes.data() );
398
399 return sb;
400}
401
402
404{
405 // creates the PLUGIN_CONTENT_MANAGER, if not exists
406 if( m_pcm )
407 return;
408
409 m_pcm = std::make_shared<PLUGIN_CONTENT_MANAGER>(
410 [this]( int aUpdateCount )
411 {
412 if( Pgm().m_Quitting )
413 return;
414
415 m_pcmUpdateCount = aUpdateCount;
416
417 if( aUpdateCount > 0 )
418 {
420 wxS( "pcm" ),
421 _( "PCM Updates Available" ),
422 wxString::Format( _( "%d package update(s) available" ), aUpdateCount ),
423 wxT( "" ) );
424 }
425 else
426 {
427 Pgm().GetNotificationsManager().Remove( wxS( "pcm" ) );
428 }
429
430 CallAfter(
431 [this]()
432 {
434 } );
435 });
436
437 m_pcm->SetRepositoryList( kicadSettings()->m_PcmRepositories );
438}
439
440
442{
443 // Create the manager
445 m_toolManager->SetEnvironment( nullptr, nullptr, nullptr, config(), this );
447
449
450 // Attach the events to the tool dispatcher
452 Bind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
453
454 // Register tools
455 m_toolManager->RegisterTool( new COMMON_CONTROL );
456 m_toolManager->RegisterTool( new KICAD_MANAGER_CONTROL );
457 m_toolManager->InitTools();
458}
459
460
462{
464
465 ACTION_MANAGER* manager = m_toolManager->GetActionManager();
466
467 wxASSERT( manager );
468
469 auto activeProject =
470 [this] ( const SELECTION& )
471 {
472 return m_active_project;
473 };
474
475#define ENABLE( x ) ACTION_CONDITIONS().Enable( x )
476
477 ACTION_CONDITIONS activeProjectCond;
478 activeProjectCond.Enable( activeProject );
479
480 manager->SetConditions( ACTIONS::saveAs, activeProjectCond );
481 manager->SetConditions( KICAD_MANAGER_ACTIONS::closeProject, activeProjectCond );
482 manager->SetConditions( KICAD_MANAGER_ACTIONS::archiveProject, activeProjectCond );
483 manager->SetConditions( KICAD_MANAGER_ACTIONS::newJobsetFile, activeProjectCond );
484 manager->SetConditions( KICAD_MANAGER_ACTIONS::openJobsetFile, activeProjectCond );
485
486 auto historyCond =
487 [this]( const SELECTION& )
488 {
489 return HistoryPanelShown();
490 };
491
493
494 // These are just here for text boxes, search boxes, etc. in places such as the standard
495 // file dialogs.
499
500#undef ENABLE
501}
502
503
505{
506 return m_projectTreePane;
507}
508
509
511{
513 wxASSERT( ret );
514 return ret;
515}
516
517
519{
520 KICAD_SETTINGS* ret = dynamic_cast<KICAD_SETTINGS*>( config() );
521 wxASSERT( ret );
522 return ret;
523}
524
525
527{
528 CallAfter(
529 [&]()
530 {
531 KIFACE *schface = Kiway().KiFACE( KIWAY::FACE_SCH );
532 schface->PreloadLibraries( &Kiway() );
533
534 KIFACE *pcbface = Kiway().KiFACE( KIWAY::FACE_PCB );
535 pcbface->PreloadLibraries( &Kiway() );
536
538 } );
539}
540
541
543{
544 return GetProjectFileName();
545}
546
547
549{
551 : wxString( wxEmptyString );
552}
553
554
556{
557 wxFileName fn( GetProjectFileName() );
558
560 return fn.GetFullPath();
561}
562
563
565{
566 wxFileName fn( GetProjectFileName() );
567
569 return fn.GetFullPath();
570}
571
572
574{
575 wxFileName fn( GetProjectFileName() );
576
577 fn.SetExt( FILEEXT::PcbFileExtension );
578 return fn.GetFullPath();
579}
580
581
583{
584 wxFileName fn( GetProjectFileName() );
585
587 return fn.GetFullPath();
588}
589
590
592{
593 m_projectTreePane->ReCreateTreePrj();
594}
595
596
601
602
604{
605 return PgmTop().GetHelpFileName();
606}
607
608
609void KICAD_MANAGER_FRAME::OnSize( wxSizeEvent& event )
610{
611 if( m_auimgr.GetManagedWindow() )
612 m_auimgr.Update();
613
614 PrintPrjInfo();
615
616#if defined( _WIN32 )
617 KISTATUSBAR* statusBar = static_cast<KISTATUSBAR*>( GetStatusBar() );
619#endif
620
621 event.Skip();
622}
623
624
626{
627 // All fileNames are now in m_AcceptedFiles vector.
628 // Check if contains a project file name and load project.
629 // If not, open files in dedicated app.
630 for( const wxFileName& fileName : m_AcceptedFiles )
631 {
632 wxString ext = fileName.GetExt();
633
635 {
636 wxString fn = fileName.GetFullPath();
637 m_toolManager->RunAction<wxString*>( *m_acceptedExts.at( fileName.GetExt() ), &fn );
638
639 return;
640 }
641 }
642
643 // Then stock gerber files in gerberFiles and run action for other files.
644 wxString gerberFiles;
645
646 // Gerbview editor should be able to open Gerber and drill files
647 for( const wxFileName& fileName : m_AcceptedFiles )
648 {
649 wxString ext = fileName.GetExt();
650
654 {
655 gerberFiles += wxT( '\"' );
656 gerberFiles += fileName.GetFullPath() + wxT( '\"' );
657 gerberFiles = gerberFiles.Pad( 1 );
658 }
659 else
660 {
661 wxString fn = fileName.GetFullPath();
662 m_toolManager->RunAction<wxString*>( *m_acceptedExts.at( fileName.GetExt() ), &fn );
663 }
664 }
665
666 // Execute Gerbviewer
667 if( !gerberFiles.IsEmpty() )
668 {
669 wxString fullEditorName = FindKicadFile( GERBVIEW_EXE );
670
671 if( wxFileExists( fullEditorName ) )
672 {
673 wxString command = fullEditorName + " " + gerberFiles;
674 m_toolManager->RunAction<wxString*>( *m_acceptedExts.at( FILEEXT::GerberFileExtension ), &command );
675 }
676 }
677}
678
679
680bool KICAD_MANAGER_FRAME::canCloseWindow( wxCloseEvent& aEvent )
681{
682 KICAD_SETTINGS* settings = kicadSettings();
684
685 for( size_t i = 0; i < m_notebook->GetPageCount(); i++ )
686 {
687 wxWindow* page = m_notebook->GetPage( i );
688
689 if( PANEL_NOTEBOOK_BASE* panel = dynamic_cast<PANEL_NOTEBOOK_BASE*>( page ) )
690 {
691 if( !panel->GetCanClose() )
692 return false;
693 }
694 }
695
696 // CloseProject will recursively ask all the open editors if they need to save changes.
697 // If any of them cancel then we need to cancel closing the KICAD_MANAGER_FRAME.
698 if( CloseProject( true ) )
699 {
700 // Don't propagate event to frames which have already been closed
701 aEvent.StopPropagation();
702
703 return true;
704 }
705 else
706 {
707 if( aEvent.CanVeto() )
708 aEvent.Veto();
709
710 return false;
711 }
712}
713
714
716{
717#ifdef _WINDOWS_
718 // For some obscure reason, on Windows, when killing Kicad from the Windows task manager
719 // if a editor frame (schematic, library, board editor or fp editor) is open and has
720 // some edition to save, OnCloseWindow is run twice *at the same time*, creating race
721 // conditions between OnCloseWindow() code.
722 // Therefore I added (JPC) a ugly hack to discard the second call (unwanted) during
723 // execution of the first call (only one call is right).
724 // Note also if there is no change made in editors, this behavior does not happen.
725 static std::atomic<unsigned int> lock_close_event( 0 );
726
727 if( ++lock_close_event > 1 ) // Skip extra calls
728 {
729 return;
730 }
731#endif
732
733 m_projectTreePane->Show( false );
734 Pgm().m_Quitting = true;
735
736 Destroy();
737
738#ifdef _WINDOWS_
739 lock_close_event = 0; // Reenable event management
740#endif
741}
742
743
745{
747
748 if( !aIsExplicitUserSave && !cfg.ShouldAutoSave() )
749 return;
750
751 cfg.m_OpenJobSets.clear();
752
753 for( size_t i = 0; i < m_notebook->GetPageCount(); i++ )
754 {
755 if( PANEL_JOBSET* jobset = dynamic_cast<PANEL_JOBSET*>( m_notebook->GetPage( i ) ) )
756 {
757 wxFileName jobsetFn( jobset->GetFilePath() );
758 jobsetFn.MakeRelativeTo( Prj().GetProjectPath() );
759 cfg.m_OpenJobSets.emplace_back( jobsetFn.GetFullPath() );
760 }
761 }
762
763 cfg.SaveToFile( Prj().GetProjectPath() );
764}
765
766
767void KICAD_MANAGER_FRAME::OnExit( wxCommandEvent& event )
768{
769 Close( true );
770}
771
772
774{
775 if( !Kiway().PlayersClose( false ) )
776 return false;
777
778 // Abort any in-progress background load, since the threads depend on the project not changing
779 KIFACE *schface = Kiway().KiFACE( KIWAY::FACE_SCH );
780 schface->CancelPreload();
781
782 KIFACE *pcbface = Kiway().KiFACE( KIWAY::FACE_PCB );
783 pcbface->CancelPreload();
784
785 // Save the project file for the currently loaded project.
786 if( m_active_project )
787 {
789
790 if( Prj().GetLocalSettings().ShouldAutoSave() && Prj().GetProjectFile().ShouldAutoSave() )
791 {
793
794 if( aSave )
795 mgr.SaveProject();
796 }
797
798 // Ensure the Last_Save tag is at HEAD before closing. This handles the case where
799 // autosave commits were made after the last explicit save - without this, the next
800 // project load would offer to restore the autosave state, which is incorrect after
801 // a clean close.
802 wxString projPath = Prj().GetProjectPath();
803
804 // Wait for any in-flight autosave so the HEAD check below isn't racing it.
806
807 if( !projPath.IsEmpty() && Kiway().LocalHistory().HistoryExists( projPath ) )
808 {
809 if( Kiway().LocalHistory().HeadNewerThanLastSave( projPath ) )
810 {
811 // Tag unconditionally: even on no-op snapshots Last_Save must anchor at HEAD.
812 Kiway().LocalHistory().CommitFullProjectSnapshot( projPath, wxS( "Close" ) );
813 Kiway().LocalHistory().TagSave( projPath, wxS( "project" ) );
814 }
815 }
816
817 // The editors clean up autosaves for sheets actually dirtied in their session.
818 // Anything still on disk here was deferred by the user in the recovery dialog
819 // and must survive so the dialog can offer it again on the next open.
820
821 m_active_project = false;
822 // Enforce local history size limit (if enabled) once all pending saves/backups are done.
823 if( Pgm().GetCommonSettings() && Pgm().GetCommonSettings()->m_Backup.enabled )
824 {
825 unsigned long long int limit = Pgm().GetCommonSettings()->m_Backup.limit_total_size;
826
827 if( limit > 0 )
828 {
829 WX_PROGRESS_REPORTER reporter( this, _( "Local History" ), 3, PR_NO_ABORT );
830 Kiway().LocalHistory().EnforceSizeLimit( Prj().GetProjectPath(), (size_t) limit, &reporter );
831 }
832 }
833
834 // Unregister the project saver before unloading the project to prevent
835 // dangling references
837
838 mgr.UnloadProject( &Prj() );
839 }
840
841 SetStatusText( "" );
842
843 // Traverse pages in reverse order so deleting them doesn't mess up our iterator.
844 for( int i = (int) m_notebook->GetPageCount() - 1; i >= 0; i-- )
845 {
846 wxWindow* page = m_notebook->GetPage( i );
847
848 if( PANEL_NOTEBOOK_BASE* panel = dynamic_cast<PANEL_NOTEBOOK_BASE*>( page ) )
849 {
850 if( panel->GetProjectTied() )
851 m_notebook->DeletePage( i );
852 }
853 }
854
855 m_projectTreePane->EmptyTreePrj();
857
858 return true;
859}
860
861
862void KICAD_MANAGER_FRAME::OpenJobsFile( const wxFileName& aFileName, bool aCreate, bool aResaveProjectPreferences )
863{
864 for( size_t i = 0; i < m_notebook->GetPageCount(); i++ )
865 {
866 if( PANEL_JOBSET* panel = dynamic_cast<PANEL_JOBSET*>( m_notebook->GetPage( i ) ) )
867 {
868 if( aFileName.GetFullPath() == panel->GetFilePath() )
869 {
870 m_notebook->SetSelection( i );
871 return;
872 }
873 }
874 }
875
876 try
877 {
878 std::unique_ptr<JOBSET> jobsFile = std::make_unique<JOBSET>( aFileName.GetFullPath().ToStdString() );
879
880 jobsFile->LoadFromFile();
881
882 if( aCreate && !aFileName.FileExists() )
883 {
884 JOBSET_DESTINATION* dest = jobsFile->AddNewDestination( JOBSET_DESTINATION_T::FOLDER );
885 dest->m_outputHandler->SetOutputPath( aFileName.GetName() );
886 jobsFile->SaveToFile( wxEmptyString, true );
887 }
888
889 PANEL_JOBSET* jobPanel = new PANEL_JOBSET( m_notebook, this, std::move( jobsFile ) );
890 jobPanel->SetProjectTied( true );
891 jobPanel->SetClosable( true );
892 m_notebook->AddPage( jobPanel, aFileName.GetFullName(), true );
894
895 if( aResaveProjectPreferences )
897 }
898 catch( ... )
899 {
900 DisplayErrorMessage( this, _( "Error opening jobs file" ) );
901 }
902}
903
904
905bool KICAD_MANAGER_FRAME::LoadProject( const wxFileName& aProjectFileName )
906{
907 // The project file should be valid by the time we get here or something has gone wrong.
908 if( !aProjectFileName.Exists() )
909 return false;
910
911 wxString fullPath = aProjectFileName.GetFullPath();
912
913 // Check if a lock file already exists BEFORE we try to acquire it. We only want to warn
914 // the user if the lock file pre-existed, not if we're about to create it ourselves.
915 // The actual lock acquisition happens in SETTINGS_MANAGER::LoadProject().
916 wxFileName lockFn( fullPath );
917 lockFn.SetName( FILEEXT::LockFilePrefix + lockFn.GetName() );
918 lockFn.SetExt( lockFn.GetExt() + wxS( "." ) + FILEEXT::LockFileExtension );
919 bool lockFilePreExisted = lockFn.FileExists();
920
921 bool lockOverrideGranted = false;
922
923 if( lockFilePreExisted )
924 {
925 // A lock file exists. Create a LOCKFILE to read who owns it and decide what to do.
926 LOCKFILE lockFile( fullPath );
927
928 if( !lockFile.Valid() && lockFile.IsLockedByMe() )
929 {
930 // If we cannot acquire the lock but we appear to be the one who locked it, check to
931 // see if there is another KiCad instance running. If not, then we can override the
932 // lock. This could happen if KiCad crashed or was interrupted.
933 if( !Pgm().SingleInstance()->IsAnotherRunning() )
934 lockFile.OverrideLock();
935 }
936
937 if( !lockFile.Valid() )
938 {
939 wxString msg;
940 msg.Printf( _( "Project '%s' is already open by '%s' at '%s'." ),
941 fullPath,
942 lockFile.GetUsername(),
943 lockFile.GetHostname() );
944
945 if( !AskOverrideLock( this, msg ) )
946 return false; // User clicked Cancel - abort project loading entirely
947
948 lockFile.OverrideLock();
949 lockOverrideGranted = true;
950 }
951
952 // The LOCKFILE goes out of scope here and releases/removes the lock file.
953 // SETTINGS_MANAGER::LoadProject() will create the actual persistent lock.
954 }
955
956 // Any open KIFACE's must be closed if they are not part of the new project.
957 // (We never want a KIWAY_PLAYER open on a KIWAY that isn't in the same project.)
958 // User is prompted here to close those KIWAY_PLAYERs:
959 if( !CloseProject( true ) )
960 return false;
961
962 m_active_project = true;
963
964 // NB: when loading a legacy project SETTINGS_MANAGER::LoadProject() will convert it to
965 // current extension. Be very careful with aProjectFileName vs. Prj().GetProjectPath()
966 // from here on out.
967
968 Pgm().GetSettingsManager().LoadProject( fullPath );
969
970 // Propagate lock override decision to the loaded project
971 if( lockOverrideGranted )
972 Prj().SetLockOverrideGranted( true );
973
974 LoadWindowState( aProjectFileName.GetFullName() );
975
976 if( aProjectFileName.IsDirWritable() )
977 SetMruPath( Prj().GetProjectPath() );
978
979 if( Kiway().LocalHistory().HeadNewerThanLastSave( Prj().GetProjectPath() ) )
980 {
981 wxString head = Kiway().LocalHistory().GetHeadHash( Prj().GetProjectPath() );
982
983 KICAD_MESSAGE_DIALOG dlg( this, _( "KiCad found unsaved changes from your last session that are newer than "
984 "the saved project files." ),
985 _( "Recover Unsaved Changes" ), wxYES_NO | wxICON_QUESTION );
986
987 dlg.SetExtendedMessage( _( "This can happen if your previous session ended unexpectedly.\n\n"
988 "Choose 'Restore' to recover those changes, or 'Discard' to keep the "
989 "currently saved files." ) );
990
991 dlg.SetYesNoLabels( _( "Restore" ), _( "Discard" ) );
992
993 if( dlg.ShowModal() == wxID_YES )
994 {
995 Kiway().LocalHistory().RestoreCommit( Prj().GetProjectPath(), head, this );
996 }
997 else
998 {
999 // User declined; commit on-disk state and tag unconditionally so Last_Save anchors
1000 // at HEAD even if no new commit was needed.
1001 Kiway().LocalHistory().CommitFullProjectSnapshot( Prj().GetProjectPath(), wxS( "Declined restore" ) );
1002 Kiway().LocalHistory().TagSave( Prj().GetProjectPath(), wxS( "project" ) );
1003 }
1004 }
1005
1006 // Save history & window state to disk now. Don't wait around for a crash.
1007 KICAD_SETTINGS* settings = kicadSettings();
1008 SaveSettings( settings );
1009 settings->SaveToFile( Pgm().GetSettingsManager().GetPathForSettingsFile( settings ) );
1010
1011 m_projectTreePane->ReCreateTreePrj();
1012 m_historyPane->RefreshHistory( Prj().GetProjectPath() );
1013
1014 for( const wxString& jobset : Prj().GetLocalSettings().m_OpenJobSets )
1015 {
1016 wxFileName jobsetFn( jobset );
1017 jobsetFn.MakeAbsolute( Prj().GetProjectPath() );
1018
1019 if( jobsetFn.Exists() )
1020 OpenJobsFile( jobsetFn.GetFullPath(), false, false );
1021 }
1022
1023 // Always start with the apps page
1024 m_notebook->SetSelection( 0 );
1025
1026 // Rebuild the list of watched paths.
1027 // however this is possible only when the main loop event handler is running,
1028 // so we use it to run the rebuild function.
1029 wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED, ID_INIT_WATCHED_PATHS );
1030
1031 wxPostEvent( this, cmd );
1032
1033 PrintPrjInfo();
1034
1035 KIPLATFORM::APP::RegisterApplicationRestart( aProjectFileName.GetFullPath() );
1036 m_openSavedWindows = true;
1037
1038 KIPLATFORM::ENV::AddToRecentDocs( aProjectFileName.GetFullPath() );
1039
1040 // Now that we have a new project, trigger a library preload, which will load in any
1041 // project-specific symbol and footprint libraries into the manager
1043 return true;
1044}
1045
1046
1047void KICAD_MANAGER_FRAME::CreateNewProject( const wxFileName& aProjectFileName, bool aCreateStubFiles )
1048{
1049 wxCHECK_RET( aProjectFileName.DirExists() && aProjectFileName.IsDirWritable(),
1050 "Project folder must exist and be writable to create a new project." );
1051
1052 // If the project is legacy, convert it
1053 if( !aProjectFileName.FileExists() )
1054 {
1055 wxFileName legacyPro( aProjectFileName );
1056 legacyPro.SetExt( FILEEXT::LegacyProjectFileExtension );
1057
1058 if( legacyPro.FileExists() )
1059 {
1060 GetSettingsManager()->LoadProject( legacyPro.GetFullPath() );
1062
1063 wxRemoveFile( legacyPro.GetFullPath() );
1064 }
1065 else
1066 {
1067 // Copy template project file from template folder.
1068 wxString srcFileName = sys_search().FindValidPath( "kicad.kicad_pro" );
1069
1070 wxFileName destFileName( aProjectFileName );
1071 destFileName.SetExt( FILEEXT::ProjectFileExtension );
1072
1073 // Create a minimal project file if the template project file could not be copied
1074 if( !wxFileName::FileExists( srcFileName )
1075 || !wxCopyFile( srcFileName, destFileName.GetFullPath() ) )
1076 {
1077 wxFFile file( destFileName.GetFullPath(), "wb" );
1078
1079 if( file.IsOpened() )
1080 file.Write( wxT( "{\n}\n") );
1081
1082 // wxFFile dtor will close the file
1083 }
1084 }
1085 }
1086
1087 // Create a "stub" for a schematic root sheet and a board if requested.
1088 // It will avoid messages from the schematic editor or the board editor to create a new file
1089 // And forces the user to create main files under the right name for the project manager
1090 if( aCreateStubFiles )
1091 {
1092 wxFileName fn( aProjectFileName.GetFullPath() );
1094
1095 // If a <project>.kicad_sch file does not exist, create a "stub" file ( minimal schematic
1096 // file ).
1097 if( !fn.FileExists() )
1098 {
1099 wxFFile file( fn.GetFullPath(), "wb" );
1100
1101 if( file.IsOpened() )
1102 {
1103 file.Write( wxString::Format( "(kicad_sch\n"
1104 "\t(version %d)\n"
1105 "\t(generator \"eeschema\")\n"
1106 "\t(generator_version \"%s\")\n"
1107 "\t(uuid %s)\n"
1108 "\t(paper \"A4\")\n"
1109 "\t(lib_symbols)\n"
1110 "\t(sheet_instances\n"
1111 "\t\t(path \"/\"\n"
1112 "\t\t\t(page \"1\")\n"
1113 "\t\t)\n"
1114 "\t)\n"
1115 "\t(embedded_fonts no)\n"
1116 ")",
1119 KIID().AsString() ) );
1120 }
1121
1122 // wxFFile dtor will close the file
1123 }
1124
1125 // If a <project>.kicad_pcb or <project>.brd file does not exist,
1126 // create a .kicad_pcb "stub" file
1127 fn.SetExt( FILEEXT::KiCadPcbFileExtension );
1128 wxFileName leg_fn( fn );
1129 leg_fn.SetExt( FILEEXT::LegacyPcbFileExtension );
1130
1131 if( !fn.FileExists() && !leg_fn.FileExists() )
1132 {
1133 wxFFile file( fn.GetFullPath(), "wb" );
1134
1135 if( file.IsOpened() )
1136 {
1137 // Create a small dummy file as a stub for pcbnew:
1138 file.Write( wxString::Format( "(kicad_pcb (version %d) (generator \"pcbnew\") (generator_version \"%s\")\n)",
1140 }
1141
1142 // wxFFile dtor will close the file
1143 }
1144 }
1145
1146 // Save history & window state to disk now. Don't wait around for a crash.
1147 KICAD_SETTINGS* settings = kicadSettings();
1148 SaveSettings( settings );
1149 settings->SaveToFile( Pgm().GetSettingsManager().GetPathForSettingsFile( settings ) );
1150
1151 m_openSavedWindows = true;
1152}
1153
1154
1156{
1157 // show all files in file dialog (in Kicad all files are editable texts):
1158 wxString wildcard = FILEEXT::AllFilesWildcard();
1159
1160 wxString default_dir = Prj().GetProjectPath();
1161
1162 wxFileDialog dlg( this, _( "Edit File in Text Editor" ), default_dir, wxEmptyString, wildcard,
1163 wxFD_OPEN );
1164
1166
1167 if( dlg.ShowModal() == wxID_CANCEL )
1168 return;
1169
1170 wxString filename = dlg.GetPath();
1171
1172 if( !dlg.GetPath().IsEmpty() && !Pgm().GetTextEditor().IsEmpty() )
1173 m_toolManager->RunAction<wxString*>( KICAD_MANAGER_ACTIONS::openTextEditor, &filename );
1174}
1175
1176
1177void KICAD_MANAGER_FRAME::OnEditAdvancedCfg( wxCommandEvent& WXUNUSED( event ) )
1178{
1179 DIALOG_EDIT_CFG dlg( this );
1180 dlg.ShowModal();
1181}
1182
1183
1185{
1186 m_projectTreePane->ReCreateTreePrj();
1187}
1188
1189
1191{
1192 // call my base class
1194
1195 // tooltips in toolbars
1197 m_launcher->CreateLaunchers();
1198
1199 // update captions
1200 int pageId = m_notebook->FindPage( m_launcher );
1201
1202 if( pageId != wxNOT_FOUND )
1203 m_notebook->SetPageText( pageId, EDITORS_CAPTION );
1204
1205 m_auimgr.GetPane( m_projectTreePane ).Caption( PROJECT_FILES_CAPTION );
1206 m_auimgr.Update();
1207
1208 m_projectTreePane->FileWatcherReset();
1209
1210 PrintPrjInfo();
1211}
1212
1213
1215{
1217
1218 if( m_pcm && ( aFlags & ENVVARS_CHANGED ) )
1219 m_pcm->ReadEnvVar();
1220
1221 COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
1222
1223 if( m_lastToolbarIconSize == 0
1225 {
1228 }
1229
1230 m_projectTreePane->ReCreateTreePrj();
1231}
1232
1233
1235{
1236 wxString file = GetProjectFileName();
1237
1238 // empty file string means no project loaded
1239 if( !Prj().IsNullProject() &&
1240 Prj().GetProjectLock() == nullptr )
1241 {
1242 LOCKFILE lockFile( file );
1243
1244 if( !lockFile.Valid() && lockFile.IsLockedByMe() )
1245 {
1246 // If we cannot acquire the lock but we appear to be the one who
1247 // locked it, check to see if there is another KiCad instance running.
1248 // If there is not, then we can override the lock. This could happen if
1249 // KiCad crashed or was interrupted
1250 if( !Pgm().SingleInstance()->IsAnotherRunning() )
1251 {
1252 lockFile.OverrideLock();
1253 }
1254 }
1255
1256 if( !lockFile.Valid() )
1257 {
1258 wxString msg;
1259 msg.Printf( _( "Project '%s' is already open by '%s' at '%s'." ),
1260 file,
1261 lockFile.GetUsername(),
1262 lockFile.GetHostname() );
1263
1264 if( AskOverrideLock( this, msg ) )
1265 {
1266 lockFile.OverrideLock();
1267 }
1268 }
1269
1270 Prj().SetReadOnly( !lockFile.Valid() || Prj().GetProjectFile().IsReadOnly() );
1271 Prj().SetProjectLock( new LOCKFILE( std::move( lockFile ) ) );
1272 }
1273
1274 wxString title;
1275
1276 if( !file.IsEmpty() )
1277 {
1278 wxFileName fn( file );
1279
1280 title = fn.GetName();
1281
1282 if( Prj().IsReadOnly() )
1283 title += wxS( " " ) + _( "[Read Only]" );
1284 }
1285 else
1286 {
1287 title = _( "[no project loaded]" );
1288 }
1289
1290 if( ADVANCED_CFG::GetCfg().m_HideVersionFromTitle )
1291 title += wxT( " \u2014 " ) + wxString( wxS( "KiCad" ) );
1292 else
1293 title += wxT( " \u2014 " ) + wxString( wxS( "KiCad " ) ) + GetMajorMinorVersion();
1294
1295 SetTitle( title );
1296
1297 // Register project file saver. Ensures project file participates in
1298 // autosave history commits without affecting dirty state.
1300 [this]( const wxString& aProjectPath, std::vector<HISTORY_FILE_DATA>& aFileData )
1301 {
1302 Prj().SaveToHistory( aProjectPath, aFileData );
1303 } );
1304}
1305
1306
1308{
1310
1311 auto settings = dynamic_cast<KICAD_SETTINGS*>( aCfg );
1312
1313 wxCHECK( settings, /*void*/ );
1314
1315 m_leftWinWidth = settings->m_LeftWinWidth;
1316 m_showHistoryPanel = settings->m_ShowHistoryPanel;
1317}
1318
1319
1321{
1323
1324 KICAD_SETTINGS* settings = dynamic_cast<KICAD_SETTINGS*>( aCfg );
1325
1326 wxCHECK( settings, /*void*/ );
1327
1328 settings->m_LeftWinWidth = m_projectTreePane->GetSize().x;
1329 settings->m_ShowHistoryPanel = m_historyPane && m_auimgr.GetPane( m_historyPane ).IsShown();
1330
1331 if( !m_isClosing )
1333}
1334
1335
1337{
1338 // wxStatusBar's wxELLIPSIZE_MIDDLE flag doesn't work (at least on Mac).
1339
1340 wxString status = wxString::Format( _( "Project: %s" ), Prj().GetProjectFullName() );
1341 KISTATUSBAR* statusBar = static_cast<KISTATUSBAR*>( GetStatusBar() );
1342 statusBar->SetEllipsedTextField( status, 0 );
1343}
1344
1345
1350
1351
1352void KICAD_MANAGER_FRAME::OnIdle( wxIdleEvent& aEvent )
1353{
1359 if( !m_openSavedWindows )
1360 return;
1361
1362 m_openSavedWindows = false;
1363
1364 if( Pgm().GetCommonSettings()->m_Session.remember_open_files )
1365 {
1366 int previousOpenCount = std::count_if( Prj().GetLocalSettings().m_files.begin(),
1367 Prj().GetLocalSettings().m_files.end(),
1368 [&]( const PROJECT_FILE_STATE& f )
1369 {
1370 return !f.fileName.EndsWith( FILEEXT::ProjectFileExtension ) && f.open;
1371 } );
1372
1373 if( previousOpenCount > 0 )
1374 {
1375 APP_PROGRESS_DIALOG progressReporter( _( "Restoring session" ), wxEmptyString, previousOpenCount, this );
1376
1377 // We don't currently support opening more than one view per file
1378 std::set<wxString> openedFiles;
1379
1380 int i = 0;
1381
1382 for( const PROJECT_FILE_STATE& file : Prj().GetLocalSettings().m_files )
1383 {
1384 if( file.open && !openedFiles.count( file.fileName ) )
1385 {
1386 progressReporter.Update( i++, wxString::Format( _( "Restoring '%s'" ), file.fileName ) );
1387
1388 openedFiles.insert( file.fileName );
1389 wxFileName fn( file.fileName );
1390
1391 if( fn.GetExt() == FILEEXT::LegacySchematicFileExtension
1392 || fn.GetExt() == FILEEXT::KiCadSchematicFileExtension )
1393 {
1395 }
1396 else if( fn.GetExt() == FILEEXT::LegacyPcbFileExtension
1397 || fn.GetExt() == FILEEXT::KiCadPcbFileExtension )
1398 {
1400 }
1401 }
1402
1403 wxYield();
1404 }
1405 }
1406 }
1407
1408 // clear file states regardless if we opened windows or not due to setting
1410
1411 // After restore from history, mark open editors as dirty so user is prompted to save
1413 {
1414 m_restoredFromHistory = false;
1415
1416 // Mark schematic editor as dirty if open
1417 if( KIWAY_PLAYER* schFrame = Kiway().Player( FRAME_SCH, false ) )
1418 schFrame->OnModify();
1419
1420 // Mark PCB editor as dirty if open
1421 if( KIWAY_PLAYER* pcbFrame = Kiway().Player( FRAME_PCB_EDITOR, false ) )
1422 pcbFrame->OnModify();
1423 }
1424
1425 KICAD_SETTINGS* settings = kicadSettings();
1426
1428 && settings->m_PcmUpdateCheck )
1429 {
1430 if( !m_pcm )
1431 CreatePCM();
1432
1433 m_pcm->RunBackgroundUpdate();
1434 }
1435
1436#ifdef KICAD_UPDATE_CHECK
1437 if( !m_updateManager && settings->m_KiCadUpdateCheck )
1438 {
1439 m_updateManager = std::make_unique<UPDATE_MANAGER>();
1440 m_updateManager->CheckForUpdate( this );
1441 }
1442#endif
1443
1444 // This little diddy is needed to get the window put into the Mac dock icon's context menu.
1445 Raise();
1446}
1447
1448
1450{
1451 m_pcmButton = aButton;
1452
1454}
1455
1456
1458{
1459 if( m_pcmButton )
1460 {
1461 if( m_pcmUpdateCount > 0 )
1462 {
1463 m_pcmButton->SetShowBadge( true );
1464 m_pcmButton->SetBadgeText( wxString::Format( "%d", m_pcmUpdateCount ) );
1465 }
1466 else
1467 {
1468 m_pcmButton->SetShowBadge( false );
1469 }
1470
1471 m_pcmButton->Refresh();
1472 }
1473}
1474
1475
1477{
1478 // No idea why, but the same mechanism used in EDA_DRAW_FRAME doesn't work here
1479 // the only thing that seems to work is to blow it all up and start from scratch.
1480 m_auimgr.DetachPane( m_tbLeft );
1481 delete m_tbLeft;
1482 m_tbLeft = nullptr;
1484 m_auimgr.AddPane( m_tbLeft, EDA_PANE().HToolbar().Name( "TopMainToolbar" ).Left().Layer( 2 ) );
1485
1486 m_auimgr.Update();
1487}
1488
1489
1491{
1492 wxAuiPaneInfo& pane = m_auimgr.GetPane( m_historyPane );
1493 bool show = !pane.IsShown();
1494 pane.Show( show );
1495
1496 if( show )
1497 m_historyPane->RefreshHistory( Prj().GetProjectPath() );
1498
1499 m_auimgr.Update();
1500}
1501
1502
1504{
1505 if( !Kiway().PlayersClose( true ) )
1506 return;
1507
1508 if( Kiway().LocalHistory().RestoreCommit( Prj().GetProjectPath(), aHash, this ) )
1509 {
1510 m_restoredFromHistory = true; // Mark editors dirty when they reopen
1511 }
1512
1513 m_projectTreePane->ReCreateTreePrj();
1514 m_openSavedWindows = true;
1515 m_historyPane->RefreshHistory( Prj().GetProjectPath() );
1516}
1517
1518
1520{
1521 return m_historyPane && m_auimgr.GetPane( m_historyPane ).IsShown();
1522}
const char * name
constexpr EDA_IU_SCALE unityScale
Definition base_units.h:128
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
EDA_BASE_FRAME(wxWindow *aParent, FRAME_T aFrameType, const wxString &aTitle, const wxPoint &aPos, const wxSize &aSize, long aStyle, const wxString &aFrameName, KIWAY *aKiway, const EDA_IU_SCALE &aIuScale)
TOOLBAR_SETTINGS * m_toolbarSettings
virtual void configureToolbars()
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
virtual void OnDropFiles(wxDropFilesEvent &aEvent)
Handle event fired when a file is dropped to the window.
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)
wxString m_aboutTitle
bool m_isClosing
Set by the close window event handler after frames are asked if they can close.
void ReCreateMenuBar()
Recreate the menu bar.
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 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.
void OnImportPadsProjectFiles(wxCommandEvent &event)
Open dialog to import PADS Logic schematic and PCB files.
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 OnChangeWatchedPaths(wxCommandEvent &aEvent)
Called by sending a event with id = ID_INIT_WATCHED_PATHS rebuild the list of watched paths.
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 OnFileHistory(wxCommandEvent &event)
PROJECT_TREE_PANE * m_projectTreePane
void OnImportGedaFiles(wxCommandEvent &event)
Open dialog to import gEDA/gaf schematic and PCB files.
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;.
wxString GetCurrentFileName() const override
Get the full filename + path of the currently opened file in the frame.
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 OnImportDipTraceFiles(wxCommandEvent &event)
Open dialog to import DipTrace schematic and board files.
void SaveOpenJobSetsToLocalSettings(bool aIsExplicitUserSave=false)
bool LoadProject(const wxFileName &aProjectFileName)
Loads a new project.
bool m_restoredFromHistory
Set after restore to mark editors dirty.
void onNotebookPageCountChanged(wxAuiNotebookEvent &evt)
LOCAL_HISTORY_PANE * m_historyPane
void OnClearFileHistory(wxCommandEvent &aEvent)
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:48
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.
virtual void SetStatusWidths(int aSize, const int *aWidths) override
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 KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
Definition kiway.cpp:211
@ FACE_SCH
eeschema DSO
Definition kiway.h:322
@ FACE_PCB
pcbnew DSO
Definition kiway.h:323
LOCAL_HISTORY & LocalHistory()
Return the LOCAL_HISTORY associated with this KIWAY.
Definition kiway.h:426
bool EnforceSizeLimit(const wxString &aProjectPath, size_t aMaxBytes, PROGRESS_REPORTER *aReporter=nullptr)
Enforce total size limit by rebuilding trimmed history keeping newest commits whose cumulative unique...
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.
void WaitForPendingSave()
Block until any pending background save completes.
void RegisterSaver(const void *aSaverObject, const std::function< void(const wxString &, std::vector< HISTORY_FILE_DATA > &)> &aSaver)
Register a saver callback invoked during autosave history commits.
bool CommitFullProjectSnapshot(const wxString &aProjectPath, const wxString &aTitle)
Commit a snapshot of the entire project directory (excluding the .history directory and ignored trans...
void UnregisterSaver(const void *aSaverObject)
Unregister a previously registered saver callback.
bool OverrideLock(bool aRemoveOnRelease=true)
Force the lock, overwriting the data that existed already.
Definition lockfile.h:183
bool Valid() const
Definition lockfile.h:268
wxString GetUsername()
Definition lockfile.h:250
wxString GetHostname()
Definition lockfile.h:256
bool IsLockedByMe()
Definition lockfile.h:236
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:124
void SetClosable(bool aYes)
void SetProjectTied(bool aYes)
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition pgm_base.cpp:541
void PreloadDesignBlockLibraries(KIWAY *aKiway)
Starts a background job to preload the global and project design block libraries.
Definition pgm_base.cpp:887
virtual BACKGROUND_JOBS_MONITOR & GetBackgroundJobMonitor() const
Definition pgm_base.h:136
void UnregisterLibraryLoadStatusBar(KISTATUSBAR *aStatusBar)
Unregister a status bar from receiving library load warning messages.
Definition pgm_base.cpp:989
bool m_Quitting
Definition pgm_base.h:394
void RegisterLibraryLoadStatusBar(KISTATUSBAR *aStatusBar)
Register a status bar to receive library load warning messages.
Definition pgm_base.cpp:969
virtual NOTIFICATIONS_MANAGER & GetNotificationsManager() const
Definition pgm_base.h:141
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:130
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:465
virtual void SetReadOnly(bool aReadOnly=true)
Definition project.h:164
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition project.cpp:181
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:187
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition project.h:210
virtual void SetLockOverrideGranted(bool aGranted=true)
Definition project.h:168
void SaveToHistory(const wxString &aProjectPath, std::vector< HISTORY_FILE_DATA > &aFileData)
Produce HISTORY_FILE_DATA entries for project files (.kicad_pro and .kicad_prl).
Definition project.cpp:471
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.
Multi-thread safe progress reporter dialog, intended for use of tasks that parallel reporting back of...
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:221
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:65
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_FILEMAX
Definition id.h:60
@ ID_FILE1
Definition id.h:59
PGM_KICAD & PgmTop()
Definition kicad.cpp:89
@ ID_EDIT_ADVANCED_CFG
Definition kicad_id.h:38
@ ID_IMPORT_DIPTRACE_PROJECT
Definition kicad_id.h:46
@ ID_IMPORT_EAGLE_PROJECT
Definition kicad_id.h:40
@ ID_IMPORT_EASYEDAPRO_PROJECT
Definition kicad_id.h:42
@ ID_IMPORT_PADS_PROJECT
Definition kicad_id.h:44
@ ID_IMPORT_GEDA_PROJECT
Definition kicad_id.h:45
@ 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:77
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:448
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)
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:156
virtual void PreloadLibraries(KIWAY *aKiway)
Definition kiway.h:279
virtual void CancelPreload(bool aBlock=true)
Definition kiway.h:281
IbisParser parser & reporter
#define ENVVARS_CHANGED
Definition of file extensions used in Kicad.
#define PR_NO_ABORT