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-2022 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( wxT( "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( wxT( "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 += wxT( "\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  + wxT( "|" ) + ProjectFileWildcard()
301  + wxT( "|" ) + 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() == wxT( "sym-lib-table" ) )
416  {
419  m_newProjectName, aSrcFilePath, m_errors );
420  }
421  else if( ext == KiCadPcbFileExtension
423  || ext == LegacyPcbFileExtension
427  || destFile.GetName() == wxT( "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 + wxT( ".pretty" ) + pathSep;
456  wxString newProjectFootprintLib = pathSep + m_newProjectName + wxT( ".pretty" ) + pathSep;
457 
458  if( destPath.StartsWith( m_projectDirPath ) )
459  destPath.Replace( m_projectDirPath, m_newProjectDirPath, false );
460 
461  destPath.Replace( srcProjectFootprintLib, newProjectFootprintLib, true );
462 
463  if( destName == m_projectName && ext != wxT( "zip" ) /* don't rename archives */ )
464  destFile.SetName( m_newProjectName );
465 
466  destFile.SetPath( destPath );
467 
468  KiCopyFile( aSrcFilePath, destFile.GetFullPath(), m_errors );
469  }
470 
471  return wxDIR_CONTINUE;
472  }
473 
474  virtual wxDirTraverseResult OnDir( const wxString& aSrcDirPath ) override
475  {
476  // Recursion guard for a Save As to a location inside the source project.
477  if( aSrcDirPath.StartsWith( m_newProjectDirPath ) )
478  return wxDIR_CONTINUE;
479 
480  wxFileName destDir( aSrcDirPath );
481  wxString destDirPath = destDir.GetPathWithSep();
482  wxUniChar pathSep = wxFileName::GetPathSeparator();
483 
484  if( destDirPath.StartsWith( m_projectDirPath + pathSep )
485  || destDirPath.StartsWith( m_projectDirPath + PROJECT_BACKUPS_DIR_SUFFIX ) )
486  {
487  destDirPath.Replace( m_projectDirPath, m_newProjectDirPath, false );
488  destDir.SetPath( destDirPath );
489  }
490 
491  if( destDir.GetName() == m_projectName )
492  {
493  if( destDir.GetExt() == wxT( "pretty" ) )
494  destDir.SetName( m_newProjectName );
495 #if 0
496  // WAYNE STAMBAUGH TODO:
497  // If we end up with a symbol equivalent to ".pretty" we'll want to handle it here....
498  else if( destDir.GetExt() == wxT( "sym_lib_dir_extension" ) )
499  destDir.SetName( m_newProjectName );
500 #endif
501  }
502 
503  if( !wxMkdir( destDir.GetFullPath() ) )
504  {
505  wxString msg;
506 
507  if( !m_errors.empty() )
508  m_errors += wxT( "\n" );
509 
510  msg.Printf( _( "Cannot copy folder '%s'." ), destDir.GetFullPath() );
511  m_errors += msg;
512  }
513 
514  return wxDIR_CONTINUE;
515  }
516 
517  wxString GetErrors() { return m_errors; }
518 
519  wxFileName GetNewProjectFile() { return m_newProjectFile; }
520 
521 private:
523 
525  wxString m_projectName;
528 
529  wxFileName m_newProjectFile;
530  wxString m_errors;
531 };
532 
533 
535 {
536  wxString msg;
537 
538  wxFileName currentProjectFile( Prj().GetProjectFullName() );
539  wxString currentProjectDirPath = currentProjectFile.GetPath();
540  wxString currentProjectName = Prj().GetProjectName();
541 
542  wxString default_dir = m_frame->GetMruPath();
543 
544  Prj().GetProjectFile().SaveToFile( currentProjectDirPath );
545  Prj().GetLocalSettings().SaveToFile( currentProjectDirPath );
546 
547  if( default_dir == currentProjectDirPath
548  || default_dir == currentProjectDirPath + wxFileName::GetPathSeparator() )
549  {
550  // Don't start within the current project
551  wxFileName default_dir_fn( default_dir );
552  default_dir_fn.RemoveLastDir();
553  default_dir = default_dir_fn.GetPath();
554  }
555 
556  wxFileDialog dlg( m_frame, _( "Save Project To" ), default_dir, wxEmptyString, wxEmptyString,
557  wxFD_SAVE );
558 
559  if( dlg.ShowModal() == wxID_CANCEL )
560  return -1;
561 
562  wxFileName newProjectDir( dlg.GetPath(), wxEmptyString );
563 
564  if( !newProjectDir.IsAbsolute() )
565  newProjectDir.MakeAbsolute();
566 
567  if( wxDirExists( newProjectDir.GetFullPath() ) )
568  {
569  msg.Printf( _( "'%s' already exists." ), newProjectDir.GetFullPath() );
571  return -1;
572  }
573 
574  if( !wxMkdir( newProjectDir.GetFullPath() ) )
575  {
576  msg.Printf( _( "Folder '%s' could not be created.\n\n"
577  "Please make sure you have write permissions and try again." ),
578  newProjectDir.GetPath() );
580  return -1;
581  }
582 
583  if( !newProjectDir.IsDirWritable() )
584  {
585  msg.Printf( _( "Insufficient permissions to write to folder '%s'." ),
586  newProjectDir.GetFullPath() );
587  wxMessageDialog msgDlg( m_frame, msg, _( "Error!" ), wxICON_ERROR | wxOK | wxCENTER );
588  msgDlg.ShowModal();
589  return -1;
590  }
591 
592  const wxString& newProjectDirPath = newProjectDir.GetFullPath();
593  const wxString& newProjectName = newProjectDir.GetDirs().Last();
594  wxDir currentProjectDir( currentProjectDirPath );
595 
596  SAVE_AS_TRAVERSER traverser( m_frame, currentProjectDirPath, currentProjectName,
597  newProjectDirPath, newProjectName );
598 
599  currentProjectDir.Traverse( traverser );
600 
601  if( !traverser.GetErrors().empty() )
602  DisplayErrorMessage( m_frame, traverser.GetErrors() );
603 
604  if( !traverser.GetNewProjectFile().FileExists() )
606 
607  m_frame->LoadProject( traverser.GetNewProjectFile() );
608 
609  return 0;
610 }
611 
612 
614 {
616  return 0;
617 }
618 
619 
621 {
622  ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
623  CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
624  SELECTION dummySel;
625 
626  if( conditionalMenu )
627  conditionalMenu->Evaluate( dummySel );
628 
629  if( actionMenu )
630  actionMenu->UpdateAll();
631 
632  return 0;
633 }
634 
635 
637 {
638  FRAME_T playerType = aEvent.Parameter<FRAME_T>();
639  KIWAY_PLAYER* player;
640 
641  if( playerType == FRAME_SCH && !m_frame->IsProjectActive() )
642  {
643  DisplayInfoMessage( m_frame, _( "Create (or open) a project to edit a schematic." ),
644  wxEmptyString );
645  return -1;
646  }
647  else if( playerType == FRAME_PCB_EDITOR && !m_frame->IsProjectActive() )
648  {
649  DisplayInfoMessage( m_frame, _( "Create (or open) a project to edit a pcb." ),
650  wxEmptyString );
651  return -1;
652  }
653 
654  // Prevent multiple KIWAY_PLAYER loading at one time
655  if( !m_loading.try_lock() )
656  return -1;
657 
658  wxBusyCursor dummy;
659 
660  const std::lock_guard<std::mutex> lock( m_loading, std::adopt_lock );
661 
662  try
663  {
664  player = m_frame->Kiway().Player( playerType, true );
665  }
666  catch( const IO_ERROR& err )
667  {
668  wxMessageBox( _( "Application failed to load:\n" ) + err.What(), _( "KiCad Error" ),
669  wxOK | wxICON_ERROR, m_frame );
670  return -1;
671  }
672 
673  if ( !player )
674  {
675  wxMessageBox( _( "Application failed to load." ), _( "KiCad Error" ),
676  wxOK | wxICON_ERROR, m_frame );
677  return -1;
678  }
679 
680  if( !player->IsVisible() ) // A hidden frame might not have the document loaded.
681  {
682  wxString filepath;
683 
684  if( playerType == FRAME_SCH )
685  {
686  wxFileName kicad_schematic( m_frame->SchFileName() );
687  wxFileName legacy_schematic( m_frame->SchLegacyFileName() );
688 
689  if( !legacy_schematic.FileExists() || kicad_schematic.FileExists() )
690  filepath = kicad_schematic.GetFullPath();
691  else
692  filepath = legacy_schematic.GetFullPath();
693  }
694  else if( playerType == FRAME_PCB_EDITOR )
695  {
696  wxFileName kicad_board( m_frame->PcbFileName() );
697  wxFileName legacy_board( m_frame->PcbLegacyFileName() );
698 
699  if( !legacy_board.FileExists() || kicad_board.FileExists() )
700  filepath = kicad_board.GetFullPath();
701  else
702  filepath = legacy_board.GetFullPath();
703  }
704 
705  if( !filepath.IsEmpty() )
706  {
707  if( !player->OpenProjectFiles( std::vector<wxString>( 1, filepath ) ) )
708  {
709  player->Destroy();
710  return -1;
711  }
712  }
713 
714  player->Show( true );
715  }
716 
717  // Needed on Windows, other platforms do not use it, but it creates no issue
718  if( player->IsIconized() )
719  player->Iconize( false );
720 
721  player->Raise();
722 
723  // Raising the window does not set the focus on Linux. This should work on
724  // any platform.
725  if( wxWindow::FindFocus() != player )
726  player->SetFocus();
727 
728  return 0;
729 }
730 
731 
732 class TERMINATE_HANDLER : public wxProcess
733 {
734 public:
735  TERMINATE_HANDLER( const wxString& appName ) :
736  m_appName( appName )
737  { }
738 
739  void OnTerminate( int pid, int status ) override
740  {
741  wxString msg = wxString::Format( _( "%s closed [pid=%d]\n" ), m_appName, pid );
742 
743  wxWindow* window = wxWindow::FindWindowByName( KICAD_MANAGER_FRAME_NAME );
744 
745  if( window ) // Should always happen.
746  {
747  // Be sure the kicad frame manager is found
748  // This dynamic cast is not really mandatory, but ...
749  KICAD_MANAGER_FRAME* frame = dynamic_cast<KICAD_MANAGER_FRAME*>( window );
750 
751  if( frame )
752  frame->PrintMsg( msg );
753  }
754 
755  delete this;
756  }
757 
758 private:
759  wxString m_appName;
760 };
761 
762 
764 {
765  wxString execFile;
766  wxString param;
767 
769  execFile = GERBVIEW_EXE;
770  else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::convertImage ) )
771  execFile = BITMAPCONVERTER_EXE;
772  else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::showCalculator ) )
773  execFile = PCB_CALCULATOR_EXE;
775  execFile = PL_EDITOR_EXE;
776  else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::openTextEditor ) )
777  execFile = Pgm().GetTextEditor();
778  else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::editOtherSch ) )
779  execFile = EESCHEMA_EXE;
780  else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::editOtherPCB ) )
781  execFile = PCBNEW_EXE;
782  else
783  wxFAIL_MSG( wxT( "Execute(): unexpected request" ) );
784 
785  if( execFile.IsEmpty() )
786  return 0;
787 
788  if( aEvent.Parameter<wxString*>() )
789  param = *aEvent.Parameter<wxString*>();
791  param = m_frame->Prj().GetProjectPath();
792 
793  TERMINATE_HANDLER* callback = new TERMINATE_HANDLER( execFile );
794 
795  long pid = ExecuteFile( execFile, param, callback );
796 
797  if( pid > 0 )
798  {
799  wxString msg = wxString::Format( _( "%s %s opened [pid=%ld]\n" ), execFile, param, pid );
800  m_frame->PrintMsg( msg );
801 
802 #ifdef __WXMAC__
803  // This non-parameterized use of wxExecute is fine because execFile is not derived
804  // from user input.
805  wxExecute( "osascript -e 'activate application \"" + execFile + "\"'" );
806 #endif
807  }
808  else
809  {
810  delete callback;
811  }
812 
813  return 0;
814 }
815 
816 
818 {
819 #ifdef PCM
820  DIALOG_PCM pcm( m_frame );
821  pcm.ShowModal();
822 
823  // For some reason, after a double click the bitmap button calling
824  // PCM keeps the focus althougt the focus was not set to this button.
825  // This hack force removing the focus from this button
826  m_frame->SetFocus();
827 #endif
828 
829  return 0;
830 }
831 
832 
834 {
841 
844 
854 
857 
858 #ifdef PCM
859  Go( &KICAD_MANAGER_CONTROL::ShowPluginManager, KICAD_MANAGER_ACTIONS::showPluginManager.MakeEvent() );
860 #endif
861 }
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:393
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:197
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:302
#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