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