KiCad PCB EDA Suite
kicad_manager_control.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) 2019 CERN
5  * Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software: you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation, either version 3 of the License, or (at your
10  * option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
22 #include <executable_names.h>
23 #include <pgm_base.h>
24 #include <kiway.h>
25 #include <kicad_manager_frame.h>
26 #include <confirm.h>
27 #include <project/project_file.h>
30 #include <tool/selection.h>
31 #include <tool/tool_event.h>
35 #include <gestfich.h>
36 #include <paths.h>
37 #include <wx/checkbox.h>
38 #include <wx/dir.h>
39 #include <wx/filedlg.h>
40 
41 #ifdef PCM
42 #include "dialog_pcm.h"
43 #endif
44 
45 
47 class DIR_CHECKBOX : public wxPanel
48 {
49 public:
50  DIR_CHECKBOX( wxWindow* aParent )
51  : wxPanel( aParent )
52  {
53  m_cbCreateDir = new wxCheckBox( this, wxID_ANY,
54  _( "Create a new folder for the project" ) );
55  m_cbCreateDir->SetValue( true );
56 
57  wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
58  sizer->Add( m_cbCreateDir, 0, wxALL, 8 );
59 
60  SetSizerAndFit( sizer );
61  }
62 
63  bool CreateNewDir() const
64  {
65  return m_cbCreateDir->GetValue();
66  }
67 
68  static wxWindow* Create( wxWindow* aParent )
69  {
70  return new DIR_CHECKBOX( aParent );
71  }
72 
73 protected:
74  wxCheckBox* m_cbCreateDir;
75 };
76 
77 
79  TOOL_INTERACTIVE( "kicad.Control" ),
80  m_frame( nullptr )
81 {
82 }
83 
84 
86 {
87  m_frame = getEditFrame<KICAD_MANAGER_FRAME>();
88 }
89 
90 
92 {
93  wxString default_dir = m_frame->GetMruPath();
94  wxFileDialog dlg( m_frame, _( "Create New Project" ), default_dir, wxEmptyString,
95  ProjectFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
96 
97  // Add a "Create a new directory" checkbox
98  dlg.SetExtraControlCreator( &DIR_CHECKBOX::Create );
99 
100  if( dlg.ShowModal() == wxID_CANCEL )
101  return -1;
102 
103  wxFileName pro( dlg.GetPath() );
104 
105  // wxFileName automatically extracts an extension. But if it isn't
106  // a .pro extension, we should keep it as part of the filename
107  if( !pro.GetExt().IsEmpty() && pro.GetExt().ToStdString() != ProjectFileExtension )
108  pro.SetName( pro.GetName() + wxT( "." ) + pro.GetExt() );
109 
110  pro.SetExt( ProjectFileExtension ); // enforce extension
111 
112  if( !pro.IsAbsolute() )
113  pro.MakeAbsolute();
114 
115  // Append a new directory with the same name of the project file.
116  if( static_cast<DIR_CHECKBOX*>( dlg.GetExtraControl() )->CreateNewDir() )
117  pro.AppendDir( pro.GetName() );
118 
119  // Check if the project directory is empty if it already exists.
120  wxDir directory( pro.GetPath() );
121 
122  if( !pro.DirExists() )
123  {
124  if( !pro.Mkdir() )
125  {
126  wxString msg;
127  msg.Printf( _( "Folder '%s' could not be created.\n\n"
128  "Make sure you have write permissions and try again." ),
129  pro.GetPath() );
131  return -1;
132  }
133  }
134  else if( directory.HasFiles() )
135  {
136  wxString msg = _( "The selected folder is not empty. It is recommended that you "
137  "create projects in their own empty folder.\n\n"
138  "Do you want to continue?" );
139 
140  if( !IsOK( m_frame, msg ) )
141  return -1;
142  }
143 
144  m_frame->CreateNewProject( pro );
145  m_frame->LoadProject( pro );
146 
147  return 0;
148 }
149 
150 
152 {
154 
155  wxFileName templatePath;
156  wxString envStr;
157 
158  // KiCad system template path.
159  ENV_VAR_MAP_CITER it = Pgm().GetLocalEnvVariables().find( "KICAD6_TEMPLATE_DIR" );
160 
161  if( it != Pgm().GetLocalEnvVariables().end() && it->second.GetValue() != wxEmptyString )
162  {
163  templatePath.AssignDir( it->second.GetValue() );
164  ps->AddTemplatesPage( _( "System Templates" ), templatePath );
165  }
166 
167  // User template path.
168  it = Pgm().GetLocalEnvVariables().find( "KICAD_USER_TEMPLATE_DIR" );
169 
170  if( it != Pgm().GetLocalEnvVariables().end() && it->second.GetValue() != wxEmptyString )
171  {
172  templatePath.AssignDir( it->second.GetValue() );
173  ps->AddTemplatesPage( _( "User Templates" ), templatePath );
174  }
175 
176  // Show the project template selector dialog
177  if( ps->ShowModal() != wxID_OK )
178  return -1;
179 
180  if( !ps->GetSelectedTemplate() )
181  {
182  wxMessageBox( _( "No project template was selected. Cannot generate new project." ),
183  _( "Error" ), wxOK | wxICON_ERROR, m_frame );
184 
185  return -1;
186  }
187 
188  // Get project destination folder and project file name.
189  wxString default_dir = wxFileName( Prj().GetProjectFullName() ).GetPathWithSep();
190  wxString title = _( "New Project Folder" );
191  wxFileDialog dlg( m_frame, title, default_dir, wxEmptyString, ProjectFileWildcard(),
192  wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
193 
194  // Add a "Create a new directory" checkbox
195  dlg.SetExtraControlCreator( &DIR_CHECKBOX::Create );
196 
197  if( dlg.ShowModal() == wxID_CANCEL )
198  return -1;
199 
200  wxFileName fn( dlg.GetPath() );
201 
202  // wxFileName automatically extracts an extension. But if it isn't a .kicad_pro extension,
203  // we should keep it as part of the filename
204  if( !fn.GetExt().IsEmpty() && fn.GetExt().ToStdString() != ProjectFileExtension )
205  fn.SetName( fn.GetName() + wxT( "." ) + fn.GetExt() );
206 
207  fn.SetExt( ProjectFileExtension );
208 
209  if( !fn.IsAbsolute() )
210  fn.MakeAbsolute();
211 
212  // Append a new directory with the same name of the project file.
213  if( static_cast<DIR_CHECKBOX*>( dlg.GetExtraControl() )->CreateNewDir() )
214  fn.AppendDir( fn.GetName() );
215 
216  // Check if the project directory is empty if it already exists.
217  wxDir directory( fn.GetPath() );
218 
219  if( !fn.DirExists() )
220  {
221  if( !fn.Mkdir() )
222  {
223  wxString msg;
224  msg.Printf( _( "Folder '%s' could not be created.\n\n"
225  "Make sure you have write permissions and try again." ),
226  fn.GetPath() );
228  return -1;
229  }
230  }
231 
232  if( !fn.IsDirWritable() )
233  {
234  wxString msg;
235 
236  msg.Printf( _( "Insufficient permissions to write to folder '%s'." ), fn.GetPath() );
237  wxMessageDialog msgDlg( m_frame, msg, _( "Error" ), wxICON_ERROR | wxOK | wxCENTER );
238  msgDlg.ShowModal();
239  return -1;
240  }
241 
242  // Make sure we are not overwriting anything in the destination folder.
243  std::vector< wxFileName > destFiles;
244 
245  if( ps->GetSelectedTemplate()->GetDestinationFiles( fn, destFiles ) )
246  {
247  std::vector< wxFileName > overwrittenFiles;
248 
249  for( const auto& file : destFiles )
250  {
251  if( file.FileExists() )
252  overwrittenFiles.push_back( file );
253  }
254 
255  if( !overwrittenFiles.empty() )
256  {
257  wxString extendedMsg = _( "Overwriting files:" ) + "\n";
258 
259  for( const auto& file : overwrittenFiles )
260  extendedMsg += "\n" + file.GetFullName();
261 
262  KIDIALOG msgDlg( m_frame, _( "Similar files already exist in the destination folder." ),
263  _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
264  msgDlg.SetExtendedMessage( extendedMsg );
265  msgDlg.SetOKLabel( _( "Overwrite" ) );
266  msgDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
267 
268  if( msgDlg.ShowModal() == wxID_CANCEL )
269  return -1;
270  }
271  }
272 
273  wxString errorMsg;
274 
275  // The selected template widget contains the template we're attempting to use to
276  // create a project
277  if( !ps->GetSelectedTemplate()->CreateProject( fn, &errorMsg ) )
278  {
279  wxMessageDialog createDlg( m_frame,
280  _( "A problem occurred creating new project from template." ),
281  _( "Error" ),
282  wxOK | wxICON_ERROR );
283 
284  if( !errorMsg.empty() )
285  createDlg.SetExtendedMessage( errorMsg );
286 
287  createDlg.ShowModal();
288  return -1;
289  }
290 
291  m_frame->CreateNewProject( fn.GetFullPath() );
292  m_frame->LoadProject( fn );
293  return 0;
294 }
295 
296 
297 int KICAD_MANAGER_CONTROL::openProject( const wxString& aDefaultDir )
298 {
299  wxString wildcard = AllProjectFilesWildcard()
300  + "|" + ProjectFileWildcard()
301  + "|" + LegacyProjectFileWildcard();
302 
303  wxFileDialog dlg( m_frame, _( "Open Existing Project" ), aDefaultDir, wxEmptyString, wildcard,
304  wxFD_OPEN | wxFD_FILE_MUST_EXIST );
305 
306  if( dlg.ShowModal() == wxID_CANCEL )
307  return -1;
308 
309  wxFileName pro( dlg.GetPath() );
310 
311  if( !pro.IsAbsolute() )
312  pro.MakeAbsolute();
313 
314  if( !pro.FileExists() )
315  return -1;
316 
317  m_frame->LoadProject( pro );
318 
319  return 0;
320 }
321 
322 
324 {
326 }
327 
328 
330 {
331  return openProject( m_frame->GetMruPath() );
332 }
333 
334 
336 {
337  m_frame->CloseProject( true );
338  return 0;
339 }
340 
341 
342 class SAVE_AS_TRAVERSER : public wxDirTraverser
343 {
344 public:
346  const wxString& aSrcProjectDirPath,
347  const wxString& aSrcProjectName,
348  const wxString& aNewProjectDirPath,
349  const wxString& aNewProjectName ) :
350  m_frame( aFrame ),
351  m_projectDirPath( aSrcProjectDirPath ),
352  m_projectName( aSrcProjectName ),
353  m_newProjectDirPath( aNewProjectDirPath ),
354  m_newProjectName( aNewProjectName )
355  {
356  }
357 
358  virtual wxDirTraverseResult OnFile( const wxString& aSrcFilePath ) override
359  {
360  // Recursion guard for a Save As to a location inside the source project.
361  if( aSrcFilePath.StartsWith( m_newProjectDirPath + wxFileName::GetPathSeparator() ) )
362  return wxDIR_CONTINUE;
363 
364  wxFileName destFile( aSrcFilePath );
365  wxString ext = destFile.GetExt();
366  bool atRoot = destFile.GetPath() == m_projectDirPath;
367 
368  if( ext == LegacyProjectFileExtension
369  || ext == ProjectFileExtension
371  {
372  wxString destPath = destFile.GetPath();
373 
374  if( destPath.StartsWith( m_projectDirPath ) )
375  {
376  destPath.Replace( m_projectDirPath, m_newProjectDirPath, false );
377  destFile.SetPath( destPath );
378  }
379 
380  if( destFile.GetName() == m_projectName )
381  {
382  destFile.SetName( m_newProjectName );
383 
384  if( atRoot && ext != ProjectLocalSettingsFileExtension )
385  m_newProjectFile = destFile;
386  }
387 
388  if( ext == LegacyProjectFileExtension )
389  {
390  // All paths in the settings file are relative so we can just do a straight copy
391  KiCopyFile( aSrcFilePath, destFile.GetFullPath(), m_errors );
392  }
393  else if( ext == ProjectFileExtension )
394  {
395  PROJECT_FILE projectFile( aSrcFilePath );
396  projectFile.LoadFromFile();
397  projectFile.SaveAs( destFile.GetPath(), destFile.GetName() );
398  }
399  else if( ext == ProjectLocalSettingsFileExtension )
400  {
401  PROJECT_LOCAL_SETTINGS projectLocalSettings( nullptr, aSrcFilePath );
402  projectLocalSettings.LoadFromFile();
403  projectLocalSettings.SaveAs( destFile.GetPath(), destFile.GetName() );
404  }
405  }
406  else if( ext == KiCadSchematicFileExtension
414  || ext == NetlistFileExtension
415  || destFile.GetName() == "sym-lib-table" )
416  {
419  m_newProjectName, aSrcFilePath, m_errors );
420  }
421  else if( ext == KiCadPcbFileExtension
423  || ext == LegacyPcbFileExtension
427  || destFile.GetName() == "fp-lib-table" )
428  {
431  m_newProjectName, aSrcFilePath, m_errors );
432  }
433  else if( ext == DrawingSheetFileExtension )
434  {
435  KIFACE* pleditor = m_frame->Kiway().KiFACE( KIWAY::FACE_PL_EDITOR );
437  m_newProjectName, aSrcFilePath, m_errors );
438  }
439  else if( ext == GerberFileExtension
440  || ext == GerberJobFileExtension
441  || ext == DrillFileExtension
442  || IsProtelExtension( ext ) )
443  {
444  KIFACE* gerbview = m_frame->Kiway().KiFACE( KIWAY::FACE_GERBVIEW );
446  m_newProjectName, aSrcFilePath, m_errors );
447  }
448  else
449  {
450  // Everything we don't recognize just gets a straight copy.
451  wxString destPath = destFile.GetPathWithSep();
452  wxString destName = destFile.GetName();
453  wxUniChar pathSep = wxFileName::GetPathSeparator();
454 
455  wxString srcProjectFootprintLib = pathSep + m_projectName + ".pretty" + pathSep;
456  wxString newProjectFootprintLib = pathSep + m_newProjectName + ".pretty" + pathSep;
457 
458  if( destPath.StartsWith( m_projectDirPath ) )
459  {
460  destPath.Replace( m_projectDirPath, m_newProjectDirPath, false );
461  destFile.SetPath( destPath );
462  }
463 
464  if( destName == m_projectName )
465  destFile.SetName( m_newProjectName );
466 
467  destPath.Replace( srcProjectFootprintLib, newProjectFootprintLib, true );
468  destFile.SetPath( destPath );
469 
470  KiCopyFile( aSrcFilePath, destFile.GetFullPath(), m_errors );
471  }
472 
473  return wxDIR_CONTINUE;
474  }
475 
476  virtual wxDirTraverseResult OnDir( const wxString& aSrcDirPath ) override
477  {
478  // Recursion guard for a Save As to a location inside the source project.
479  if( aSrcDirPath.StartsWith( m_newProjectDirPath ) )
480  return wxDIR_CONTINUE;
481 
482  wxFileName destDir( aSrcDirPath );
483  wxString destDirPath = destDir.GetPathWithSep();
484  wxUniChar pathSep = wxFileName::GetPathSeparator();
485 
486  if( destDirPath.StartsWith( m_projectDirPath + pathSep )
487  || destDirPath.StartsWith( m_projectDirPath + PROJECT_BACKUPS_DIR_SUFFIX ) )
488  {
489  destDirPath.Replace( m_projectDirPath, m_newProjectDirPath, false );
490  destDir.SetPath( destDirPath );
491  }
492 
493  if( destDir.GetName() == m_projectName )
494  {
495  if( destDir.GetExt() == "pretty" )
496  destDir.SetName( m_newProjectName );
497 #if 0
498  // WAYNE STAMBAUGH TODO:
499  // If we end up with a symbol equivalent to ".pretty" we'll want to handle it here....
500  else if( destDir.GetExt() == "sym_lib_dir_extension" )
501  destDir.SetName( m_newProjectName );
502 #endif
503  }
504 
505  if( !wxMkdir( destDir.GetFullPath() ) )
506  {
507  wxString msg;
508 
509  if( !m_errors.empty() )
510  m_errors += "\n";
511 
512  msg.Printf( _( "Cannot copy folder '%s'." ), destDir.GetFullPath() );
513  m_errors += msg;
514  }
515 
516  return wxDIR_CONTINUE;
517  }
518 
519  wxString GetErrors() { return m_errors; }
520 
521  wxFileName GetNewProjectFile() { return m_newProjectFile; }
522 
523 private:
525 
527  wxString m_projectName;
530 
531  wxFileName m_newProjectFile;
532  wxString m_errors;
533 };
534 
535 
537 {
538  wxString msg;
539 
540  wxFileName currentProjectFile( Prj().GetProjectFullName() );
541  wxString currentProjectDirPath = currentProjectFile.GetPath();
542  wxString currentProjectName = Prj().GetProjectName();
543 
544  wxString default_dir = m_frame->GetMruPath();
545 
546  Prj().GetProjectFile().SaveToFile( currentProjectDirPath );
547  Prj().GetLocalSettings().SaveToFile( currentProjectDirPath );
548 
549  if( default_dir == currentProjectDirPath
550  || default_dir == currentProjectDirPath + wxFileName::GetPathSeparator() )
551  {
552  // Don't start within the current project
553  wxFileName default_dir_fn( default_dir );
554  default_dir_fn.RemoveLastDir();
555  default_dir = default_dir_fn.GetPath();
556  }
557 
558  wxFileDialog dlg( m_frame, _( "Save Project To" ), default_dir, wxEmptyString, wxEmptyString,
559  wxFD_SAVE );
560 
561  if( dlg.ShowModal() == wxID_CANCEL )
562  return -1;
563 
564  wxFileName newProjectDir( dlg.GetPath(), wxEmptyString );
565 
566  if( !newProjectDir.IsAbsolute() )
567  newProjectDir.MakeAbsolute();
568 
569  if( wxDirExists( newProjectDir.GetFullPath() ) )
570  {
571  msg.Printf( _( "'%s' already exists." ), newProjectDir.GetFullPath() );
573  return -1;
574  }
575 
576  if( !wxMkdir( newProjectDir.GetFullPath() ) )
577  {
578  msg.Printf( _( "Folder '%s' could not be created.\n\n"
579  "Please make sure you have write permissions and try again." ),
580  newProjectDir.GetPath() );
582  return -1;
583  }
584 
585  if( !newProjectDir.IsDirWritable() )
586  {
587  msg.Printf( _( "Insufficient permissions to write to folder '%s'." ),
588  newProjectDir.GetFullPath() );
589  wxMessageDialog msgDlg( m_frame, msg, _( "Error!" ), wxICON_ERROR | wxOK | wxCENTER );
590  msgDlg.ShowModal();
591  return -1;
592  }
593 
594  const wxString& newProjectDirPath = newProjectDir.GetFullPath();
595  const wxString& newProjectName = newProjectDir.GetDirs().Last();
596  wxDir currentProjectDir( currentProjectDirPath );
597 
598  SAVE_AS_TRAVERSER traverser( m_frame, currentProjectDirPath, currentProjectName,
599  newProjectDirPath, newProjectName );
600 
601  currentProjectDir.Traverse( traverser );
602 
603  if( !traverser.GetErrors().empty() )
604  DisplayErrorMessage( m_frame, traverser.GetErrors() );
605 
606  if( traverser.GetNewProjectFile().FileExists() )
607  {
609  m_frame->LoadProject( traverser.GetNewProjectFile() );
610  }
611 
612  return 0;
613 }
614 
615 
617 {
619  return 0;
620 }
621 
622 
624 {
625  ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
626  CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
627  SELECTION dummySel;
628 
629  if( conditionalMenu )
630  conditionalMenu->Evaluate( dummySel );
631 
632  if( actionMenu )
633  actionMenu->UpdateAll();
634 
635  return 0;
636 }
637 
638 
640 {
641  FRAME_T playerType = aEvent.Parameter<FRAME_T>();
642  KIWAY_PLAYER* player;
643 
644  if( playerType == FRAME_SCH && !m_frame->IsProjectActive() )
645  {
646  DisplayInfoMessage( m_frame, _( "Create (or open) a project to edit a schematic." ),
647  wxEmptyString );
648  return -1;
649  }
650  else if( playerType == FRAME_PCB_EDITOR && !m_frame->IsProjectActive() )
651  {
652  DisplayInfoMessage( m_frame, _( "Create (or open) a project to edit a pcb." ),
653  wxEmptyString );
654  return -1;
655  }
656 
657  // Prevent multiple KIWAY_PLAYER loading at one time
658  if( !m_loading.try_lock() )
659  return -1;
660 
661  wxBusyCursor dummy;
662 
663  const std::lock_guard<std::mutex> lock( m_loading, std::adopt_lock );
664 
665  try
666  {
667  player = m_frame->Kiway().Player( playerType, true );
668  }
669  catch( const IO_ERROR& err )
670  {
671  wxMessageBox( _( "Application failed to load:\n" ) + err.What(), _( "KiCad Error" ),
672  wxOK | wxICON_ERROR, m_frame );
673  return -1;
674  }
675 
676  if ( !player )
677  {
678  wxMessageBox( _( "Application failed to load." ), _( "KiCad Error" ),
679  wxOK | wxICON_ERROR, m_frame );
680  return -1;
681  }
682 
683  if( !player->IsVisible() ) // A hidden frame might not have the document loaded.
684  {
685  wxString filepath;
686 
687  if( playerType == FRAME_SCH )
688  {
689  wxFileName kicad_schematic( m_frame->SchFileName() );
690  wxFileName legacy_schematic( m_frame->SchLegacyFileName() );
691 
692  if( !legacy_schematic.FileExists() || kicad_schematic.FileExists() )
693  filepath = kicad_schematic.GetFullPath();
694  else
695  filepath = legacy_schematic.GetFullPath();
696  }
697  else if( playerType == FRAME_PCB_EDITOR )
698  {
699  wxFileName kicad_board( m_frame->PcbFileName() );
700  wxFileName legacy_board( m_frame->PcbLegacyFileName() );
701 
702  if( !legacy_board.FileExists() || kicad_board.FileExists() )
703  filepath = kicad_board.GetFullPath();
704  else
705  filepath = legacy_board.GetFullPath();
706  }
707 
708  if( !filepath.IsEmpty() )
709  {
710  if( !player->OpenProjectFiles( std::vector<wxString>( 1, filepath ) ) )
711  {
712  player->Destroy();
713  return -1;
714  }
715  }
716 
717  player->Show( true );
718  }
719 
720  // Needed on Windows, other platforms do not use it, but it creates no issue
721  if( player->IsIconized() )
722  player->Iconize( false );
723 
724  player->Raise();
725 
726  // Raising the window does not set the focus on Linux. This should work on
727  // any platform.
728  if( wxWindow::FindFocus() != player )
729  player->SetFocus();
730 
731  return 0;
732 }
733 
734 
735 class TERMINATE_HANDLER : public wxProcess
736 {
737 public:
738  TERMINATE_HANDLER( const wxString& appName ) :
739  m_appName( appName )
740  { }
741 
742  void OnTerminate( int pid, int status ) override
743  {
744  wxString msg = wxString::Format( _( "%s closed [pid=%d]\n" ), m_appName, pid );
745 
746  wxWindow* window = wxWindow::FindWindowByName( KICAD_MANAGER_FRAME_NAME );
747 
748  if( window ) // Should always happen.
749  {
750  // Be sure the kicad frame manager is found
751  // This dynamic cast is not really mandatory, but ...
752  KICAD_MANAGER_FRAME* frame = dynamic_cast<KICAD_MANAGER_FRAME*>( window );
753 
754  if( frame )
755  frame->PrintMsg( msg );
756  }
757 
758  delete this;
759  }
760 
761 private:
762  wxString m_appName;
763 };
764 
765 
767 {
768  wxString execFile;
769  wxString param;
770 
772  execFile = GERBVIEW_EXE;
773  else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::convertImage ) )
774  execFile = BITMAPCONVERTER_EXE;
775  else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::showCalculator ) )
776  execFile = PCB_CALCULATOR_EXE;
778  execFile = PL_EDITOR_EXE;
779  else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::openTextEditor ) )
780  execFile = Pgm().GetTextEditor();
781  else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::editOtherSch ) )
782  execFile = EESCHEMA_EXE;
783  else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::editOtherPCB ) )
784  execFile = PCBNEW_EXE;
785  else
786  wxFAIL_MSG( "Execute(): unexpected request" );
787 
788  if( execFile.IsEmpty() )
789  return 0;
790 
791  if( aEvent.Parameter<wxString*>() )
792  param = *aEvent.Parameter<wxString*>();
794  param = m_frame->Prj().GetProjectPath();
795 
796  TERMINATE_HANDLER* callback = new TERMINATE_HANDLER( execFile );
797 
798  long pid = ExecuteFile( execFile, param, callback );
799 
800  if( pid > 0 )
801  {
802  wxString msg = wxString::Format( _( "%s %s opened [pid=%ld]\n" ), execFile, param, pid );
803  m_frame->PrintMsg( msg );
804 
805 #ifdef __WXMAC__
806  // This non-parameterized use of wxExecute is fine because execFile is not derived
807  // from user input.
808  wxExecute( "osascript -e 'activate application \"" + execFile + "\"'" );
809 #endif
810  }
811  else
812  {
813  delete callback;
814  }
815 
816  return 0;
817 }
818 
819 
821 {
822 #ifdef PCM
823  DIALOG_PCM pcm( m_frame );
824  pcm.ShowModal();
825 
826  // For some reason, after a double click the bitmap button calling
827  // PCM keeps the focus althougt the focus was not set to this button.
828  // This hack force removing the focus from this button
829  m_frame->SetFocus();
830 #endif
831 
832  return 0;
833 }
834 
835 
837 {
844 
847 
857 
860 
861 #ifdef PCM
862  Go( &KICAD_MANAGER_CONTROL::ShowPluginManager, KICAD_MANAGER_ACTIONS::showPluginManager.MakeEvent() );
863 #endif
864 }
const std::string NetlistFileExtension
wxString AllProjectFilesWildcard()
static TOOL_ACTION newProject
void PrintMsg(const wxString &text)
int ShowPluginManager(const TOOL_EVENT &aEvent)
Set up handlers for various events.
KiCad executable names.
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Definition: kiway_player.h:64
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
Definition: confirm.cpp:55
int ShowPlayer(const TOOL_EVENT &aEvent)
const std::string LegacyFootprintLibPathExtension
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:53
const wxString PL_EDITOR_EXE
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:292
wxString LegacyProjectFileWildcard()
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: confirm.h:45
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:48
This file is part of the common library.
Helper widget to select whether a new directory should be created for a project.
const std::string KiCadFootprintFileExtension
const wxString PCBNEW_EXE
const std::string ProjectFileExtension
PROJECT_TEMPLATE * GetSelectedTemplate()
const std::string LegacyPcbFileExtension
const std::string LegacySymbolLibFileExtension
FRAME_T
The set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
Definition: frame_type.h:32
PROJECT & Prj()
Definition: kicad.cpp:403
const std::string BackupFileSuffix
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:145
static TOOL_ACTION showCalculator
static TOOL_ACTION openDemoProject
bool SaveToFile(const wxString &aDirectory="", bool aForce=false) override
virtual bool LoadFromFile(const wxString &aDirectory="")
Loads the backing file from disk and then calls Load()
The project local settings are things that are attached to a particular project, but also might be pa...
const wxString SchLegacyFileName()
bool SaveToFile(const wxString &aDirectory="", bool aForce=false) override
static TOOL_ACTION viewGerbers
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Definition: gestfich.cpp:214
int OpenDemoProject(const TOOL_EVENT &aEvent)
static TOOL_ACTION newFromTemplate
const std::string SchematicSymbolFileExtension
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:383
void UpdateAll()
Run update handlers for the menu and its submenus.
void OnTerminate(int pid, int status) override
const std::string GerberFileExtension
const std::string KiCadPcbFileExtension
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
int ExecuteFile(const wxString &aEditorName, const wxString &aFileName, wxProcess *aCallback)
Call the executable file aEditorName with the parameter aFileName.
Definition: gestfich.cpp:115
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:122
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:64
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
bool IsProtelExtension(const wxString &ext)
const wxString GERBVIEW_EXE
static TOOL_ACTION convertImage
virtual wxDirTraverseResult OnDir(const wxString &aSrcDirPath) override
static TOOL_ACTION closeProject
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition: project.h:151
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
Definition: tool_event.cpp:88
int Refresh(const TOOL_EVENT &aEvent)
const std::string ProjectLocalSettingsFileExtension
static TOOL_ACTION editOtherPCB
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:72
SAVE_AS_TRAVERSER(KICAD_MANAGER_FRAME *aFrame, const wxString &aSrcProjectDirPath, const wxString &aSrcProjectName, const wxString &aNewProjectDirPath, const wxString &aNewProjectName)
wxString GetMruPath() const
const std::string FootprintAssignmentFileExtension
const wxString SchFileName()
const wxString EESCHEMA_EXE
static TOOL_ACTION editSchematic
int OpenProject(const TOOL_EVENT &aEvent)
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
TERMINATE_HANDLER(const wxString &appName)
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
Implementing pcm main dialog.
Definition: dialog_pcm.h:35
KICAD_MANAGER_FRAME * m_frame
< Pointer to the currently used edit/draw frame.
T Parameter() const
Return a non-standard parameter assigned to the event.
Definition: tool_event.h:432
const std::string LegacySymbolDocumentFileExtension
Generic, UI-independent tool event.
Definition: tool_event.h:152
DIR_CHECKBOX(wxWindow *aParent)
const std::string GerberJobFileExtension
Definition of file extensions used in Kicad.
const wxString PCB_CALCULATOR_EXE
static TOOL_ACTION editFootprints
#define _(s)
pcbnew DSO
Definition: kiway.h:269
static TOOL_ACTION updateMenu
Definition: actions.h:167
virtual KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
Definition: kiway.cpp:196
const std::string LegacyProjectFileExtension
int NewProject(const TOOL_EVENT &aEvent)
int SaveProjectAs(const TOOL_EVENT &aEvent)
const std::string LegacySchematicFileExtension
virtual void SaveFileAs(const wxString &srcProjectBasePath, const wxString &srcProjectName, const wxString &newProjectBasePath, const wxString &newProjectName, const wxString &srcFilePath, wxString &aErrors)
Saving a file under a different name is delegated to the various KIFACEs because the project doesn't ...
Definition: kiway.h:208
int CloseProject(const TOOL_EVENT &aEvent)
wxCheckBox * m_cbCreateDir
void CreateNewProject(const wxFileName &aProjectFileName, bool aCreateStubFiles=true)
Creates a new project by setting up and initial project, schematic, and board files.
wxString ProjectFileWildcard()
eeschema DSO
Definition: kiway.h:268
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
bool CloseProject(bool aSave)
Closes the project, and saves it if aSave is true;.
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
static TOOL_ACTION editOtherSch
KICAD_MANAGER_FRAME * m_frame
size_t GetDestinationFiles(const wxFileName &aNewProjectPath, std::vector< wxFileName > &aDestFiles)
Fetch the list of destination files to be copied when the new project is created.
static TOOL_ACTION editPCB
int UpdateMenu(const TOOL_EVENT &aEvent)
const std::string DrawingSheetFileExtension
see class PGM_BASE
bool CreateProject(wxFileName &aNewProjectPath, wxString *aErrorMsg=nullptr)
Copies and renames all template files to create a new project.
const wxString PcbLegacyFileName()
static TOOL_ACTION openProject
static TOOL_ACTION saveAs
Definition: actions.h:52
#define KICAD_MANAGER_FRAME_NAME
static TOOL_ACTION zoomRedraw
Definition: actions.h:90
bool SaveAs(const wxString &aDirectory, const wxString &aFile)
static wxString GetStockDemosPath()
Gets the stock (install) demos path.
Definition: paths.cpp:282
#define PROJECT_BACKUPS_DIR_SUFFIX
Project settings path will be <projectname> + this.
static wxWindow * Create(wxWindow *aParent)
const wxString PcbFileName()
Implement a participant in the KIWAY alchemy.
Definition: kiway.h:148
int NewFromTemplate(const TOOL_EVENT &aEvent)
const std::string KiCadSchematicFileExtension
void AddTemplatesPage(const wxString &aTitle, wxFileName &aPath)
Add a new page with aTitle, populated with templates from aPath.
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:77
int ShowModal() override
Definition: confirm.cpp:99
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition: project.cpp:128
bool SaveAs(const wxString &aDirectory, const wxString &aFile)
int openProject(const wxString &aDefaultDir)
void LoadProject(const wxFileName &aProjectFileName)
const wxString BITMAPCONVERTER_EXE
std::map< wxString, ENV_VAR_ITEM >::const_iterator ENV_VAR_MAP_CITER
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:307
static TOOL_ACTION editSymbols
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:75
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:323
The main KiCad project manager frame.
int Execute(const TOOL_EVENT &aEvent)
static TOOL_ACTION openTextEditor
static TOOL_ACTION editDrawingSheet
const std::string DrillFileExtension
bool CreateNewDir() const
const std::string KiCadSymbolLibFileExtension
virtual wxDirTraverseResult OnFile(const wxString &aSrcFilePath) override