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 )
125
126 // Range menu events
129
130 // Special functions
132
133 // Drop files event
134 EVT_DROP_FILES( KICAD_MANAGER_FRAME::OnDropFiles )
135
136END_EVENT_TABLE()
137
138// See below the purpose of this include
139#include <wx/xml/xml.h>
140
141KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent, const wxString& title,
142 const wxPoint& pos, const wxSize& size ) :
145 m_openSavedWindows( false ),
146 m_restoredFromHistory( false ),
147 m_active_project( false ),
148 m_showHistoryPanel( false ),
149 m_projectTreePane( nullptr ),
150 m_historyPane( nullptr ),
151 m_launcher( nullptr ),
153 m_pcmButton( nullptr ),
155{
156 const int defaultLeftWinWidth = FromDIP( 250 );
157
158 m_leftWinWidth = defaultLeftWinWidth; // Default value
159 m_aboutTitle = "KiCad";
160
161 // JPC: A very ugly hack to fix an issue on Linux: if the wxbase315u_xml_gcc_custom.so is
162 // used **only** in PCM, it is not found in some cases at run time.
163 // So just use it in the main module to avoid a not found issue
164 // wxbase315u_xml_gcc_custom shared object when launching Kicad
165 wxXmlDocument dummy;
166
167 // Create the status line (bottom of the frame). Left half is for project name; right half
168 // is for Reporter (currently used by archiver/unarchiver and PCM).
169 // Note: this is a KISTATUSBAR status bar. Therefore the specified number of fields
170 // is the extra number of fields, not the full field count.
171 // We need here 2 fields: the extra fiels to display the project name, and another field
172 // to display a info (specific to Windows) using the FIELD_OFFSET_BGJOB_TEXT id offset (=1)
173 // So the extra field count is 1
174 CreateStatusBar( 2 );
177 Pgm().RegisterLibraryLoadStatusBar( (KISTATUSBAR*) GetStatusBar() );
178 GetStatusBar()->SetFont( KIUI::GetStatusFont( this ) );
179
180 // Give an icon
181 wxIcon icon;
182 wxIconBundle icon_bundle;
183
184 if( IsNightlyVersion())
185 {
186 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly, 48 ) );
187 icon_bundle.AddIcon( icon );
188 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly, 128 ) );
189 icon_bundle.AddIcon( icon );
190 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly, 256 ) );
191 icon_bundle.AddIcon( icon );
192 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly_32 ) );
193 icon_bundle.AddIcon( icon );
194 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_nightly_16 ) );
195 icon_bundle.AddIcon( icon );
196 }
197 else
198 {
199 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad, 48 ) );
200 icon_bundle.AddIcon( icon );
201 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad, 128 ) );
202 icon_bundle.AddIcon( icon );
203 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad, 256 ) );
204 icon_bundle.AddIcon( icon );
205 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_32 ) );
206 icon_bundle.AddIcon( icon );
207 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_kicad_16 ) );
208 icon_bundle.AddIcon( icon );
209 }
210
211 SetIcons( icon_bundle );
212
213 // Load the settings
214 LoadSettings( config() );
215
216 // Left window: is the box which display tree project
218
219 setupTools();
221
226
227 m_auimgr.SetManagedWindow( this );
228 m_auimgr.SetFlags( wxAUI_MGR_LIVE_RESIZE );
229
230 m_auimgr.AddPane( m_tbLeft, EDA_PANE().VToolbar().Name( "TopMainToolbar" ).Left().Layer( 2 ) );
231
232 // There is no wxAUIPaneInfo::SetSize(), but a trick is to use MinSize() to set the required pane width,
233 // and after give a reasonable MinSize value.
235 EDA_PANE().Palette().Name( "ProjectTree" ).Left().Layer( 1 )
236 .Caption( PROJECT_FILES_CAPTION ).PaneBorder( false )
237 .MinSize( m_leftWinWidth, -1 ).Floatable( false ).Movable( false ) );
238
239 m_historyPane = new LOCAL_HISTORY_PANE( this );
240 m_auimgr.AddPane( m_historyPane,
241 EDA_PANE().Palette().Name( "LocalHistory" ).Left().Layer( 1 ).Position( 1 )
242 .Caption( _( "Local History" ) ).PaneBorder( false )
243 .Floatable( false ).Movable( false ).CloseButton( true ).Hide() );
244
246 m_auimgr.GetPane( m_historyPane ).Show();
247
248 wxSize client_size = GetClientSize();
249 m_notebook = new wxAuiNotebook( this, wxID_ANY, wxPoint( client_size.x, client_size.y ),
250 FromDIP( wxSize( 700, 590 ) ),
251 wxAUI_NB_TOP | wxAUI_NB_CLOSE_ON_ALL_TABS | wxAUI_NB_TAB_MOVE
252 | wxAUI_NB_SCROLL_BUTTONS | wxNO_BORDER );
253
254 m_notebook->SetArtProvider( new WX_AUI_TAB_ART() );
255
256 m_notebook->Bind( wxEVT_AUINOTEBOOK_PAGE_CLOSE, &KICAD_MANAGER_FRAME::onNotebookPageCloseRequest, this );
257 m_notebook->Bind( wxEVT_AUINOTEBOOK_PAGE_CLOSED, &KICAD_MANAGER_FRAME::onNotebookPageCountChanged, this );
259
260 m_notebook->Freeze();
261 m_launcher->SetClosable( false );
262 m_notebook->AddPage( m_launcher, EDITORS_CAPTION, false );
263 m_notebook->SetTabCtrlHeight( 0 );
264 m_notebook->Thaw();
265
266 m_auimgr.AddPane( m_notebook, EDA_PANE().Canvas().Name( "Editors" ).Center().Caption( EDITORS_CAPTION )
267 .PaneBorder( false ).MinSize( m_notebook->GetBestSize() ) );
268
269 m_auimgr.Update();
270
271 // Now the actual m_projectTreePane size is set, give it a reasonable min width
272 m_auimgr.GetPane( m_projectTreePane ).MinSize( defaultLeftWinWidth, FromDIP( 80 ) );
273
274
275 wxSizer* mainSizer = GetSizer();
276
277 // Only fit the initial window size the first time KiCad is run.
278 if( mainSizer && config()->m_Window.state.size_x == 0 && config()->m_Window.state.size_y == 0 )
279 {
280 Layout();
281 mainSizer->Fit( this );
282 Center();
283 }
284
285 if( ADVANCED_CFG::GetCfg().m_HideVersionFromTitle )
286 SetTitle( wxT( "KiCad" ) );
287 else
288 SetTitle( wxString( "KiCad " ) + GetMajorMinorVersion() );
289
290 // Do not let the messages window have initial focus
291 m_projectTreePane->SetFocus();
292
293 // Init for dropping files
296
297 // Gerber files
298 // Note that all gerber files are aliased as GerberFileExtension
302
303 DragAcceptFiles( true );
304}
305
306
308{
310 Unbind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
311
312 m_notebook->Unbind( wxEVT_AUINOTEBOOK_PAGE_CLOSE, &KICAD_MANAGER_FRAME::onNotebookPageCloseRequest, this );
313 m_notebook->Unbind( wxEVT_AUINOTEBOOK_PAGE_CLOSED, &KICAD_MANAGER_FRAME::onNotebookPageCountChanged, this );
314
317 Pgm().UnregisterLibraryLoadStatusBar( (KISTATUSBAR*) GetStatusBar() );
318
319 // Shutdown all running tools
320 if( m_toolManager )
321 m_toolManager->ShutdownAllTools();
322
323 if( m_pcm )
324 m_pcm->StopBackgroundUpdate();
325
326 // Stop update manager before tearing down the AUI framework. The update
327 // task runs on the thread pool and may call CallAfter on this frame, so it
328 // must complete before we uninitialize AUI or destroy child windows.
329 m_updateManager.reset();
330
331 delete m_actions;
332 delete m_toolManager;
333 delete m_toolDispatcher;
334
335 m_auimgr.UnInit();
336}
337
339{
340 if( m_notebook->GetPageCount() == 1 )
341 m_notebook->SetTabCtrlHeight( 0 );
342 else
343 m_notebook->SetTabCtrlHeight( -1 );
344}
345
346
348{
350}
351
352
354{
355 wxAuiNotebook* notebook = (wxAuiNotebook*) evt.GetEventObject();
356 wxWindow* page = notebook->GetPage( evt.GetSelection() );
357
358 if( PANEL_NOTEBOOK_BASE* panel = dynamic_cast<PANEL_NOTEBOOK_BASE*>( page ) )
359 {
360 if( panel->GetClosable() )
361 {
362 if( !panel->GetCanClose() )
363 evt.Veto();
364
365 CallAfter(
366 [this]()
367 {
369 } );
370 }
371 else
372 {
373 evt.Veto();
374 }
375 }
376}
377
378
379wxStatusBar* KICAD_MANAGER_FRAME::OnCreateStatusBar( int number, long style, wxWindowID id,
380 const wxString& name )
381{
382 return new KISTATUSBAR( number, this, id,
386}
387
388
390{
391 // creates the PLUGIN_CONTENT_MANAGER, if not exists
392 if( m_pcm )
393 return;
394
395 m_pcm = std::make_shared<PLUGIN_CONTENT_MANAGER>(
396 [this]( int aUpdateCount )
397 {
398 if( Pgm().m_Quitting )
399 return;
400
401 m_pcmUpdateCount = aUpdateCount;
402
403 if( aUpdateCount > 0 )
404 {
406 wxS( "pcm" ),
407 _( "PCM Updates Available" ),
408 wxString::Format( _( "%d package update(s) available" ), aUpdateCount ),
409 wxT( "" ) );
410 }
411 else
412 {
413 Pgm().GetNotificationsManager().Remove( wxS( "pcm" ) );
414 }
415
416 CallAfter(
417 [this]()
418 {
420 } );
421 });
422
423 m_pcm->SetRepositoryList( kicadSettings()->m_PcmRepositories );
424}
425
426
428{
429 // Create the manager
431 m_toolManager->SetEnvironment( nullptr, nullptr, nullptr, config(), this );
433
435
436 // Attach the events to the tool dispatcher
438 Bind( wxEVT_CHAR_HOOK, &TOOL_DISPATCHER::DispatchWxEvent, m_toolDispatcher );
439
440 // Register tools
441 m_toolManager->RegisterTool( new COMMON_CONTROL );
442 m_toolManager->RegisterTool( new KICAD_MANAGER_CONTROL );
443 m_toolManager->InitTools();
444}
445
446
448{
450
451 ACTION_MANAGER* manager = m_toolManager->GetActionManager();
452
453 wxASSERT( manager );
454
455 auto activeProject =
456 [this] ( const SELECTION& )
457 {
458 return m_active_project;
459 };
460
461#define ENABLE( x ) ACTION_CONDITIONS().Enable( x )
462
463 ACTION_CONDITIONS activeProjectCond;
464 activeProjectCond.Enable( activeProject );
465
466 manager->SetConditions( ACTIONS::saveAs, activeProjectCond );
467 manager->SetConditions( KICAD_MANAGER_ACTIONS::closeProject, activeProjectCond );
468 manager->SetConditions( KICAD_MANAGER_ACTIONS::archiveProject, activeProjectCond );
469 manager->SetConditions( KICAD_MANAGER_ACTIONS::newJobsetFile, activeProjectCond );
470 manager->SetConditions( KICAD_MANAGER_ACTIONS::openJobsetFile, activeProjectCond );
471
472 auto historyCond =
473 [this]( const SELECTION& )
474 {
475 return HistoryPanelShown();
476 };
477
479
480 // These are just here for text boxes, search boxes, etc. in places such as the standard
481 // file dialogs.
485
486#undef ENABLE
487}
488
489
491{
492 return m_projectTreePane;
493}
494
495
497{
499 wxASSERT( ret );
500 return ret;
501}
502
503
505{
506 KICAD_SETTINGS* ret = dynamic_cast<KICAD_SETTINGS*>( config() );
507 wxASSERT( ret );
508 return ret;
509}
510
511
513{
514 CallAfter(
515 [&]()
516 {
517 KIFACE *schface = Kiway().KiFACE( KIWAY::FACE_SCH );
518 schface->PreloadLibraries( &Kiway() );
519
520 KIFACE *pcbface = Kiway().KiFACE( KIWAY::FACE_PCB );
521 pcbface->PreloadLibraries( &Kiway() );
522
524 } );
525}
526
527
529{
530 return GetProjectFileName();
531}
532
533
535{
537 : wxString( wxEmptyString );
538}
539
540
542{
543 wxFileName fn( GetProjectFileName() );
544
546 return fn.GetFullPath();
547}
548
549
551{
552 wxFileName fn( GetProjectFileName() );
553
555 return fn.GetFullPath();
556}
557
558
560{
561 wxFileName fn( GetProjectFileName() );
562
563 fn.SetExt( FILEEXT::PcbFileExtension );
564 return fn.GetFullPath();
565}
566
567
569{
570 wxFileName fn( GetProjectFileName() );
571
573 return fn.GetFullPath();
574}
575
576
578{
579 m_projectTreePane->ReCreateTreePrj();
580}
581
582
587
588
590{
591 return PgmTop().GetHelpFileName();
592}
593
594
595void KICAD_MANAGER_FRAME::OnSize( wxSizeEvent& event )
596{
597 if( m_auimgr.GetManagedWindow() )
598 m_auimgr.Update();
599
600 PrintPrjInfo();
601
602#if defined( _WIN32 )
603 KISTATUSBAR* statusBar = static_cast<KISTATUSBAR*>( GetStatusBar() );
605#endif
606
607 event.Skip();
608}
609
610
612{
613 // All fileNames are now in m_AcceptedFiles vector.
614 // Check if contains a project file name and load project.
615 // If not, open files in dedicated app.
616 for( const wxFileName& fileName : m_AcceptedFiles )
617 {
618 wxString ext = fileName.GetExt();
619
621 {
622 wxString fn = fileName.GetFullPath();
623 m_toolManager->RunAction<wxString*>( *m_acceptedExts.at( fileName.GetExt() ), &fn );
624
625 return;
626 }
627 }
628
629 // Then stock gerber files in gerberFiles and run action for other files.
630 wxString gerberFiles;
631
632 // Gerbview editor should be able to open Gerber and drill files
633 for( const wxFileName& fileName : m_AcceptedFiles )
634 {
635 wxString ext = fileName.GetExt();
636
640 {
641 gerberFiles += wxT( '\"' );
642 gerberFiles += fileName.GetFullPath() + wxT( '\"' );
643 gerberFiles = gerberFiles.Pad( 1 );
644 }
645 else
646 {
647 wxString fn = fileName.GetFullPath();
648 m_toolManager->RunAction<wxString*>( *m_acceptedExts.at( fileName.GetExt() ), &fn );
649 }
650 }
651
652 // Execute Gerbviewer
653 if( !gerberFiles.IsEmpty() )
654 {
655 wxString fullEditorName = FindKicadFile( GERBVIEW_EXE );
656
657 if( wxFileExists( fullEditorName ) )
658 {
659 wxString command = fullEditorName + " " + gerberFiles;
660 m_toolManager->RunAction<wxString*>( *m_acceptedExts.at( FILEEXT::GerberFileExtension ), &command );
661 }
662 }
663}
664
665
666bool KICAD_MANAGER_FRAME::canCloseWindow( wxCloseEvent& aEvent )
667{
668 KICAD_SETTINGS* settings = kicadSettings();
670
671 for( size_t i = 0; i < m_notebook->GetPageCount(); i++ )
672 {
673 wxWindow* page = m_notebook->GetPage( i );
674
675 if( PANEL_NOTEBOOK_BASE* panel = dynamic_cast<PANEL_NOTEBOOK_BASE*>( page ) )
676 {
677 if( !panel->GetCanClose() )
678 return false;
679 }
680 }
681
682 // CloseProject will recursively ask all the open editors if they need to save changes.
683 // If any of them cancel then we need to cancel closing the KICAD_MANAGER_FRAME.
684 if( CloseProject( true ) )
685 {
686 // Don't propagate event to frames which have already been closed
687 aEvent.StopPropagation();
688
689 return true;
690 }
691 else
692 {
693 if( aEvent.CanVeto() )
694 aEvent.Veto();
695
696 return false;
697 }
698}
699
700
702{
703#ifdef _WINDOWS_
704 // For some obscure reason, on Windows, when killing Kicad from the Windows task manager
705 // if a editor frame (schematic, library, board editor or fp editor) is open and has
706 // some edition to save, OnCloseWindow is run twice *at the same time*, creating race
707 // conditions between OnCloseWindow() code.
708 // Therefore I added (JPC) a ugly hack to discard the second call (unwanted) during
709 // execution of the first call (only one call is right).
710 // Note also if there is no change made in editors, this behavior does not happen.
711 static std::atomic<unsigned int> lock_close_event( 0 );
712
713 if( ++lock_close_event > 1 ) // Skip extra calls
714 {
715 return;
716 }
717#endif
718
719 m_projectTreePane->Show( false );
720 Pgm().m_Quitting = true;
721
722 Destroy();
723
724#ifdef _WINDOWS_
725 lock_close_event = 0; // Reenable event management
726#endif
727}
728
729
731{
733
734 if( !aIsExplicitUserSave && !cfg.ShouldAutoSave() )
735 return;
736
737 cfg.m_OpenJobSets.clear();
738
739 for( size_t i = 0; i < m_notebook->GetPageCount(); i++ )
740 {
741 if( PANEL_JOBSET* jobset = dynamic_cast<PANEL_JOBSET*>( m_notebook->GetPage( i ) ) )
742 {
743 wxFileName jobsetFn( jobset->GetFilePath() );
744 jobsetFn.MakeRelativeTo( Prj().GetProjectPath() );
745 cfg.m_OpenJobSets.emplace_back( jobsetFn.GetFullPath() );
746 }
747 }
748
749 cfg.SaveToFile( Prj().GetProjectPath() );
750}
751
752
753void KICAD_MANAGER_FRAME::OnExit( wxCommandEvent& event )
754{
755 Close( true );
756}
757
758
760{
761 if( !Kiway().PlayersClose( false ) )
762 return false;
763
764 // Abort any in-progress background load, since the threads depend on the project not changing
765 KIFACE *schface = Kiway().KiFACE( KIWAY::FACE_SCH );
766 schface->CancelPreload();
767
768 KIFACE *pcbface = Kiway().KiFACE( KIWAY::FACE_PCB );
769 pcbface->CancelPreload();
770
771 // Save the project file for the currently loaded project.
772 if( m_active_project )
773 {
775
776 if( Prj().GetLocalSettings().ShouldAutoSave() && Prj().GetProjectFile().ShouldAutoSave() )
777 {
779
780 if( aSave )
781 mgr.SaveProject();
782 }
783
784 // Ensure the Last_Save tag is at HEAD before closing. This handles the case where
785 // autosave commits were made after the last explicit save - without this, the next
786 // project load would offer to restore the autosave state, which is incorrect after
787 // a clean close.
788 wxString projPath = Prj().GetProjectPath();
789
790 // Wait for any in-flight autosave so the HEAD check below isn't racing it.
792
793 if( !projPath.IsEmpty() && Kiway().LocalHistory().HistoryExists( projPath ) )
794 {
795 if( Kiway().LocalHistory().HeadNewerThanLastSave( projPath ) )
796 {
797 // Tag unconditionally: even on no-op snapshots Last_Save must anchor at HEAD.
798 Kiway().LocalHistory().CommitFullProjectSnapshot( projPath, wxS( "Close" ) );
799 Kiway().LocalHistory().TagSave( projPath, wxS( "project" ) );
800 }
801 }
802
803 // The editors clean up autosaves for sheets actually dirtied in their session.
804 // Anything still on disk here was deferred by the user in the recovery dialog
805 // and must survive so the dialog can offer it again on the next open.
806
807 m_active_project = false;
808 // Enforce local history size limit (if enabled) once all pending saves/backups are done.
809 if( Pgm().GetCommonSettings() && Pgm().GetCommonSettings()->m_Backup.enabled )
810 {
811 unsigned long long int limit = Pgm().GetCommonSettings()->m_Backup.limit_total_size;
812
813 if( limit > 0 )
814 {
815 WX_PROGRESS_REPORTER reporter( this, _( "Local History" ), 3, PR_NO_ABORT );
816 Kiway().LocalHistory().EnforceSizeLimit( Prj().GetProjectPath(), (size_t) limit, &reporter );
817 }
818 }
819
820 // Unregister the project saver before unloading the project to prevent
821 // dangling references
823
824 mgr.UnloadProject( &Prj() );
825 }
826
827 SetStatusText( "" );
828
829 // Traverse pages in reverse order so deleting them doesn't mess up our iterator.
830 for( int i = (int) m_notebook->GetPageCount() - 1; i >= 0; i-- )
831 {
832 wxWindow* page = m_notebook->GetPage( i );
833
834 if( PANEL_NOTEBOOK_BASE* panel = dynamic_cast<PANEL_NOTEBOOK_BASE*>( page ) )
835 {
836 if( panel->GetProjectTied() )
837 m_notebook->DeletePage( i );
838 }
839 }
840
841 m_projectTreePane->EmptyTreePrj();
843
844 return true;
845}
846
847
848void KICAD_MANAGER_FRAME::OpenJobsFile( const wxFileName& aFileName, bool aCreate, bool aResaveProjectPreferences )
849{
850 for( size_t i = 0; i < m_notebook->GetPageCount(); i++ )
851 {
852 if( PANEL_JOBSET* panel = dynamic_cast<PANEL_JOBSET*>( m_notebook->GetPage( i ) ) )
853 {
854 if( aFileName.GetFullPath() == panel->GetFilePath() )
855 {
856 m_notebook->SetSelection( i );
857 return;
858 }
859 }
860 }
861
862 try
863 {
864 std::unique_ptr<JOBSET> jobsFile = std::make_unique<JOBSET>( aFileName.GetFullPath().ToStdString() );
865
866 jobsFile->LoadFromFile();
867
868 if( aCreate && !aFileName.FileExists() )
869 {
870 JOBSET_DESTINATION* dest = jobsFile->AddNewDestination( JOBSET_DESTINATION_T::FOLDER );
871 dest->m_outputHandler->SetOutputPath( aFileName.GetName() );
872 jobsFile->SaveToFile( wxEmptyString, true );
873 }
874
875 PANEL_JOBSET* jobPanel = new PANEL_JOBSET( m_notebook, this, std::move( jobsFile ) );
876 jobPanel->SetProjectTied( true );
877 jobPanel->SetClosable( true );
878 m_notebook->AddPage( jobPanel, aFileName.GetFullName(), true );
880
881 if( aResaveProjectPreferences )
883 }
884 catch( ... )
885 {
886 DisplayErrorMessage( this, _( "Error opening jobs file" ) );
887 }
888}
889
890
891bool KICAD_MANAGER_FRAME::LoadProject( const wxFileName& aProjectFileName )
892{
893 // The project file should be valid by the time we get here or something has gone wrong.
894 if( !aProjectFileName.Exists() )
895 return false;
896
897 wxString fullPath = aProjectFileName.GetFullPath();
898
899 // Check if a lock file already exists BEFORE we try to acquire it. We only want to warn
900 // the user if the lock file pre-existed, not if we're about to create it ourselves.
901 // The actual lock acquisition happens in SETTINGS_MANAGER::LoadProject().
902 wxFileName lockFn( fullPath );
903 lockFn.SetName( FILEEXT::LockFilePrefix + lockFn.GetName() );
904 lockFn.SetExt( lockFn.GetExt() + wxS( "." ) + FILEEXT::LockFileExtension );
905 bool lockFilePreExisted = lockFn.FileExists();
906
907 bool lockOverrideGranted = false;
908
909 if( lockFilePreExisted )
910 {
911 // A lock file exists. Create a LOCKFILE to read who owns it and decide what to do.
912 LOCKFILE lockFile( fullPath );
913
914 if( !lockFile.Valid() && lockFile.IsLockedByMe() )
915 {
916 // If we cannot acquire the lock but we appear to be the one who locked it, check to
917 // see if there is another KiCad instance running. If not, then we can override the
918 // lock. This could happen if KiCad crashed or was interrupted.
919 if( !Pgm().SingleInstance()->IsAnotherRunning() )
920 lockFile.OverrideLock();
921 }
922
923 if( !lockFile.Valid() )
924 {
925 wxString msg;
926 msg.Printf( _( "Project '%s' is already open by '%s' at '%s'." ),
927 fullPath,
928 lockFile.GetUsername(),
929 lockFile.GetHostname() );
930
931 if( !AskOverrideLock( this, msg ) )
932 return false; // User clicked Cancel - abort project loading entirely
933
934 lockFile.OverrideLock();
935 lockOverrideGranted = true;
936 }
937
938 // The LOCKFILE goes out of scope here and releases/removes the lock file.
939 // SETTINGS_MANAGER::LoadProject() will create the actual persistent lock.
940 }
941
942 // Any open KIFACE's must be closed if they are not part of the new project.
943 // (We never want a KIWAY_PLAYER open on a KIWAY that isn't in the same project.)
944 // User is prompted here to close those KIWAY_PLAYERs:
945 if( !CloseProject( true ) )
946 return false;
947
948 m_active_project = true;
949
950 // NB: when loading a legacy project SETTINGS_MANAGER::LoadProject() will convert it to
951 // current extension. Be very careful with aProjectFileName vs. Prj().GetProjectPath()
952 // from here on out.
953
954 Pgm().GetSettingsManager().LoadProject( fullPath );
955
956 // Propagate lock override decision to the loaded project
957 if( lockOverrideGranted )
958 Prj().SetLockOverrideGranted( true );
959
960 LoadWindowState( aProjectFileName.GetFullName() );
961
962 if( aProjectFileName.IsDirWritable() )
963 SetMruPath( Prj().GetProjectPath() );
964
965 if( Kiway().LocalHistory().HeadNewerThanLastSave( Prj().GetProjectPath() ) )
966 {
967 wxString head = Kiway().LocalHistory().GetHeadHash( Prj().GetProjectPath() );
968
969 KICAD_MESSAGE_DIALOG dlg( this, _( "KiCad found unsaved changes from your last session that are newer than "
970 "the saved project files." ),
971 _( "Recover Unsaved Changes" ), wxYES_NO | wxICON_QUESTION );
972
973 dlg.SetExtendedMessage( _( "This can happen if your previous session ended unexpectedly.\n\n"
974 "Choose 'Restore' to recover those changes, or 'Discard' to keep the "
975 "currently saved files." ) );
976
977 dlg.SetYesNoLabels( _( "Restore" ), _( "Discard" ) );
978
979 if( dlg.ShowModal() == wxID_YES )
980 {
981 Kiway().LocalHistory().RestoreCommit( Prj().GetProjectPath(), head, this );
982 }
983 else
984 {
985 // User declined; commit on-disk state and tag unconditionally so Last_Save anchors
986 // at HEAD even if no new commit was needed.
987 Kiway().LocalHistory().CommitFullProjectSnapshot( Prj().GetProjectPath(), wxS( "Declined restore" ) );
988 Kiway().LocalHistory().TagSave( Prj().GetProjectPath(), wxS( "project" ) );
989 }
990 }
991
992 // Save history & window state to disk now. Don't wait around for a crash.
993 KICAD_SETTINGS* settings = kicadSettings();
994 SaveSettings( settings );
995 settings->SaveToFile( Pgm().GetSettingsManager().GetPathForSettingsFile( settings ) );
996
997 m_projectTreePane->ReCreateTreePrj();
998 m_historyPane->RefreshHistory( Prj().GetProjectPath() );
999
1000 for( const wxString& jobset : Prj().GetLocalSettings().m_OpenJobSets )
1001 {
1002 wxFileName jobsetFn( jobset );
1003 jobsetFn.MakeAbsolute( Prj().GetProjectPath() );
1004
1005 if( jobsetFn.Exists() )
1006 OpenJobsFile( jobsetFn.GetFullPath(), false, false );
1007 }
1008
1009 // Always start with the apps page
1010 m_notebook->SetSelection( 0 );
1011
1012 // Rebuild the list of watched paths.
1013 // however this is possible only when the main loop event handler is running,
1014 // so we use it to run the rebuild function.
1015 wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED, ID_INIT_WATCHED_PATHS );
1016
1017 wxPostEvent( this, cmd );
1018
1019 PrintPrjInfo();
1020
1021 KIPLATFORM::APP::RegisterApplicationRestart( aProjectFileName.GetFullPath() );
1022 m_openSavedWindows = true;
1023
1024 KIPLATFORM::ENV::AddToRecentDocs( aProjectFileName.GetFullPath() );
1025
1026 // Now that we have a new project, trigger a library preload, which will load in any
1027 // project-specific symbol and footprint libraries into the manager
1029 return true;
1030}
1031
1032
1033void KICAD_MANAGER_FRAME::CreateNewProject( const wxFileName& aProjectFileName, bool aCreateStubFiles )
1034{
1035 wxCHECK_RET( aProjectFileName.DirExists() && aProjectFileName.IsDirWritable(),
1036 "Project folder must exist and be writable to create a new project." );
1037
1038 // If the project is legacy, convert it
1039 if( !aProjectFileName.FileExists() )
1040 {
1041 wxFileName legacyPro( aProjectFileName );
1042 legacyPro.SetExt( FILEEXT::LegacyProjectFileExtension );
1043
1044 if( legacyPro.FileExists() )
1045 {
1046 GetSettingsManager()->LoadProject( legacyPro.GetFullPath() );
1048
1049 wxRemoveFile( legacyPro.GetFullPath() );
1050 }
1051 else
1052 {
1053 // Copy template project file from template folder.
1054 wxString srcFileName = sys_search().FindValidPath( "kicad.kicad_pro" );
1055
1056 wxFileName destFileName( aProjectFileName );
1057 destFileName.SetExt( FILEEXT::ProjectFileExtension );
1058
1059 // Create a minimal project file if the template project file could not be copied
1060 if( !wxFileName::FileExists( srcFileName )
1061 || !wxCopyFile( srcFileName, destFileName.GetFullPath() ) )
1062 {
1063 wxFFile file( destFileName.GetFullPath(), "wb" );
1064
1065 if( file.IsOpened() )
1066 file.Write( wxT( "{\n}\n") );
1067
1068 // wxFFile dtor will close the file
1069 }
1070 }
1071 }
1072
1073 // Create a "stub" for a schematic root sheet and a board if requested.
1074 // It will avoid messages from the schematic editor or the board editor to create a new file
1075 // And forces the user to create main files under the right name for the project manager
1076 if( aCreateStubFiles )
1077 {
1078 wxFileName fn( aProjectFileName.GetFullPath() );
1080
1081 // If a <project>.kicad_sch file does not exist, create a "stub" file ( minimal schematic
1082 // file ).
1083 if( !fn.FileExists() )
1084 {
1085 wxFFile file( fn.GetFullPath(), "wb" );
1086
1087 if( file.IsOpened() )
1088 {
1089 file.Write( wxString::Format( "(kicad_sch\n"
1090 "\t(version %d)\n"
1091 "\t(generator \"eeschema\")\n"
1092 "\t(generator_version \"%s\")\n"
1093 "\t(uuid %s)\n"
1094 "\t(paper \"A4\")\n"
1095 "\t(lib_symbols)\n"
1096 "\t(sheet_instances\n"
1097 "\t\t(path \"/\"\n"
1098 "\t\t\t(page \"1\")\n"
1099 "\t\t)\n"
1100 "\t)\n"
1101 "\t(embedded_fonts no)\n"
1102 ")",
1105 KIID().AsString() ) );
1106 }
1107
1108 // wxFFile dtor will close the file
1109 }
1110
1111 // If a <project>.kicad_pcb or <project>.brd file does not exist,
1112 // create a .kicad_pcb "stub" file
1113 fn.SetExt( FILEEXT::KiCadPcbFileExtension );
1114 wxFileName leg_fn( fn );
1115 leg_fn.SetExt( FILEEXT::LegacyPcbFileExtension );
1116
1117 if( !fn.FileExists() && !leg_fn.FileExists() )
1118 {
1119 wxFFile file( fn.GetFullPath(), "wb" );
1120
1121 if( file.IsOpened() )
1122 {
1123 // Create a small dummy file as a stub for pcbnew:
1124 file.Write( wxString::Format( "(kicad_pcb (version %d) (generator \"pcbnew\") (generator_version \"%s\")\n)",
1126 }
1127
1128 // wxFFile dtor will close the file
1129 }
1130 }
1131
1132 // Save history & window state to disk now. Don't wait around for a crash.
1133 KICAD_SETTINGS* settings = kicadSettings();
1134 SaveSettings( settings );
1135 settings->SaveToFile( Pgm().GetSettingsManager().GetPathForSettingsFile( settings ) );
1136
1137 m_openSavedWindows = true;
1138}
1139
1140
1142{
1143 // show all files in file dialog (in Kicad all files are editable texts):
1144 wxString wildcard = FILEEXT::AllFilesWildcard();
1145
1146 wxString default_dir = Prj().GetProjectPath();
1147
1148 wxFileDialog dlg( this, _( "Edit File in Text Editor" ), default_dir, wxEmptyString, wildcard,
1149 wxFD_OPEN );
1150
1152
1153 if( dlg.ShowModal() == wxID_CANCEL )
1154 return;
1155
1156 wxString filename = dlg.GetPath();
1157
1158 if( !dlg.GetPath().IsEmpty() && !Pgm().GetTextEditor().IsEmpty() )
1159 m_toolManager->RunAction<wxString*>( KICAD_MANAGER_ACTIONS::openTextEditor, &filename );
1160}
1161
1162
1163void KICAD_MANAGER_FRAME::OnEditAdvancedCfg( wxCommandEvent& WXUNUSED( event ) )
1164{
1165 DIALOG_EDIT_CFG dlg( this );
1166 dlg.ShowModal();
1167}
1168
1169
1171{
1172 m_projectTreePane->ReCreateTreePrj();
1173}
1174
1175
1177{
1178 // call my base class
1180
1181 // tooltips in toolbars
1183 m_launcher->CreateLaunchers();
1184
1185 // update captions
1186 int pageId = m_notebook->FindPage( m_launcher );
1187
1188 if( pageId != wxNOT_FOUND )
1189 m_notebook->SetPageText( pageId, EDITORS_CAPTION );
1190
1191 m_auimgr.GetPane( m_projectTreePane ).Caption( PROJECT_FILES_CAPTION );
1192 m_auimgr.Update();
1193
1194 m_projectTreePane->FileWatcherReset();
1195
1196 PrintPrjInfo();
1197}
1198
1199
1201{
1203
1204 if( m_pcm && ( aFlags & ENVVARS_CHANGED ) )
1205 m_pcm->ReadEnvVar();
1206
1207 COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
1208
1209 if( m_lastToolbarIconSize == 0
1211 {
1214 }
1215
1216 m_projectTreePane->ReCreateTreePrj();
1217}
1218
1219
1221{
1222 wxString file = GetProjectFileName();
1223
1224 // empty file string means no project loaded
1225 if( !Prj().IsNullProject() &&
1226 Prj().GetProjectLock() == nullptr )
1227 {
1228 LOCKFILE lockFile( file );
1229
1230 if( !lockFile.Valid() && lockFile.IsLockedByMe() )
1231 {
1232 // If we cannot acquire the lock but we appear to be the one who
1233 // locked it, check to see if there is another KiCad instance running.
1234 // If there is not, then we can override the lock. This could happen if
1235 // KiCad crashed or was interrupted
1236 if( !Pgm().SingleInstance()->IsAnotherRunning() )
1237 {
1238 lockFile.OverrideLock();
1239 }
1240 }
1241
1242 if( !lockFile.Valid() )
1243 {
1244 wxString msg;
1245 msg.Printf( _( "Project '%s' is already open by '%s' at '%s'." ),
1246 file,
1247 lockFile.GetUsername(),
1248 lockFile.GetHostname() );
1249
1250 if( AskOverrideLock( this, msg ) )
1251 {
1252 lockFile.OverrideLock();
1253 }
1254 }
1255
1256 Prj().SetReadOnly( !lockFile.Valid() || Prj().GetProjectFile().IsReadOnly() );
1257 Prj().SetProjectLock( new LOCKFILE( std::move( lockFile ) ) );
1258 }
1259
1260 wxString title;
1261
1262 if( !file.IsEmpty() )
1263 {
1264 wxFileName fn( file );
1265
1266 title = fn.GetName();
1267
1268 if( Prj().IsReadOnly() )
1269 title += wxS( " " ) + _( "[Read Only]" );
1270 }
1271 else
1272 {
1273 title = _( "[no project loaded]" );
1274 }
1275
1276 if( ADVANCED_CFG::GetCfg().m_HideVersionFromTitle )
1277 title += wxT( " \u2014 " ) + wxString( wxS( "KiCad" ) );
1278 else
1279 title += wxT( " \u2014 " ) + wxString( wxS( "KiCad " ) ) + GetMajorMinorVersion();
1280
1281 SetTitle( title );
1282
1283 // Register project file saver. Ensures project file participates in
1284 // autosave history commits without affecting dirty state.
1286 [this]( const wxString& aProjectPath, std::vector<HISTORY_FILE_DATA>& aFileData )
1287 {
1288 Prj().SaveToHistory( aProjectPath, aFileData );
1289 } );
1290}
1291
1292
1294{
1296
1297 auto settings = dynamic_cast<KICAD_SETTINGS*>( aCfg );
1298
1299 wxCHECK( settings, /*void*/ );
1300
1301 m_leftWinWidth = settings->m_LeftWinWidth;
1302 m_showHistoryPanel = settings->m_ShowHistoryPanel;
1303}
1304
1305
1307{
1309
1310 KICAD_SETTINGS* settings = dynamic_cast<KICAD_SETTINGS*>( aCfg );
1311
1312 wxCHECK( settings, /*void*/ );
1313
1314 settings->m_LeftWinWidth = m_projectTreePane->GetSize().x;
1315 settings->m_ShowHistoryPanel = m_historyPane && m_auimgr.GetPane( m_historyPane ).IsShown();
1316
1317 if( !m_isClosing )
1319}
1320
1321
1323{
1324 // wxStatusBar's wxELLIPSIZE_MIDDLE flag doesn't work (at least on Mac).
1325
1326 wxString status = wxString::Format( _( "Project: %s" ), Prj().GetProjectFullName() );
1327 KISTATUSBAR* statusBar = static_cast<KISTATUSBAR*>( GetStatusBar() );
1328 statusBar->SetEllipsedTextField( status, 0 );
1329}
1330
1331
1336
1337
1338void KICAD_MANAGER_FRAME::OnIdle( wxIdleEvent& aEvent )
1339{
1345 if( !m_openSavedWindows )
1346 return;
1347
1348 m_openSavedWindows = false;
1349
1350 if( Pgm().GetCommonSettings()->m_Session.remember_open_files )
1351 {
1352 int previousOpenCount = std::count_if( Prj().GetLocalSettings().m_files.begin(),
1353 Prj().GetLocalSettings().m_files.end(),
1354 [&]( const PROJECT_FILE_STATE& f )
1355 {
1356 return !f.fileName.EndsWith( FILEEXT::ProjectFileExtension ) && f.open;
1357 } );
1358
1359 if( previousOpenCount > 0 )
1360 {
1361 APP_PROGRESS_DIALOG progressReporter( _( "Restoring session" ), wxEmptyString, previousOpenCount, this );
1362
1363 // We don't currently support opening more than one view per file
1364 std::set<wxString> openedFiles;
1365
1366 int i = 0;
1367
1368 for( const PROJECT_FILE_STATE& file : Prj().GetLocalSettings().m_files )
1369 {
1370 if( file.open && !openedFiles.count( file.fileName ) )
1371 {
1372 progressReporter.Update( i++, wxString::Format( _( "Restoring '%s'" ), file.fileName ) );
1373
1374 openedFiles.insert( file.fileName );
1375 wxFileName fn( file.fileName );
1376
1377 if( fn.GetExt() == FILEEXT::LegacySchematicFileExtension
1378 || fn.GetExt() == FILEEXT::KiCadSchematicFileExtension )
1379 {
1381 }
1382 else if( fn.GetExt() == FILEEXT::LegacyPcbFileExtension
1383 || fn.GetExt() == FILEEXT::KiCadPcbFileExtension )
1384 {
1386 }
1387 }
1388
1389 wxYield();
1390 }
1391 }
1392 }
1393
1394 // clear file states regardless if we opened windows or not due to setting
1396
1397 // After restore from history, mark open editors as dirty so user is prompted to save
1399 {
1400 m_restoredFromHistory = false;
1401
1402 // Mark schematic editor as dirty if open
1403 if( KIWAY_PLAYER* schFrame = Kiway().Player( FRAME_SCH, false ) )
1404 schFrame->OnModify();
1405
1406 // Mark PCB editor as dirty if open
1407 if( KIWAY_PLAYER* pcbFrame = Kiway().Player( FRAME_PCB_EDITOR, false ) )
1408 pcbFrame->OnModify();
1409 }
1410
1411 KICAD_SETTINGS* settings = kicadSettings();
1412
1414 && settings->m_PcmUpdateCheck )
1415 {
1416 if( !m_pcm )
1417 CreatePCM();
1418
1419 m_pcm->RunBackgroundUpdate();
1420 }
1421
1422#ifdef KICAD_UPDATE_CHECK
1423 if( !m_updateManager && settings->m_KiCadUpdateCheck )
1424 {
1425 m_updateManager = std::make_unique<UPDATE_MANAGER>();
1426 m_updateManager->CheckForUpdate( this );
1427 }
1428#endif
1429
1430 // This little diddy is needed to get the window put into the Mac dock icon's context menu.
1431 Raise();
1432}
1433
1434
1436{
1437 m_pcmButton = aButton;
1438
1440}
1441
1442
1444{
1445 if( m_pcmButton )
1446 {
1447 if( m_pcmUpdateCount > 0 )
1448 {
1449 m_pcmButton->SetShowBadge( true );
1450 m_pcmButton->SetBadgeText( wxString::Format( "%d", m_pcmUpdateCount ) );
1451 }
1452 else
1453 {
1454 m_pcmButton->SetShowBadge( false );
1455 }
1456
1457 m_pcmButton->Refresh();
1458 }
1459}
1460
1461
1463{
1464 // No idea why, but the same mechanism used in EDA_DRAW_FRAME doesn't work here
1465 // the only thing that seems to work is to blow it all up and start from scratch.
1466 m_auimgr.DetachPane( m_tbLeft );
1467 delete m_tbLeft;
1468 m_tbLeft = nullptr;
1470 m_auimgr.AddPane( m_tbLeft, EDA_PANE().HToolbar().Name( "TopMainToolbar" ).Left().Layer( 2 ) );
1471
1472 m_auimgr.Update();
1473}
1474
1475
1477{
1478 wxAuiPaneInfo& pane = m_auimgr.GetPane( m_historyPane );
1479 bool show = !pane.IsShown();
1480 pane.Show( show );
1481
1482 if( show )
1483 m_historyPane->RefreshHistory( Prj().GetProjectPath() );
1484
1485 m_auimgr.Update();
1486}
1487
1488
1490{
1491 if( !Kiway().PlayersClose( true ) )
1492 return;
1493
1494 if( Kiway().LocalHistory().RestoreCommit( Prj().GetProjectPath(), aHash, this ) )
1495 {
1496 m_restoredFromHistory = true; // Mark editors dirty when they reopen
1497 }
1498
1499 m_projectTreePane->ReCreateTreePrj();
1500 m_openSavedWindows = true;
1501 m_historyPane->RefreshHistory( Prj().GetProjectPath() );
1502}
1503
1504
1506{
1507 return m_historyPane && m_auimgr.GetPane( m_historyPane ).IsShown();
1508}
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 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.
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: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: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:62
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:88
@ 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_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:435
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
#define ENVVARS_CHANGED
Definition of file extensions used in Kicad.
#define PR_NO_ABORT