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 <policy_keys.h>
25#include <kiway.h>
26#include <kicad_manager_frame.h>
27#include <kiplatform/policy.h>
28#include <confirm.h>
29#include <eda_tools.h>
33#include <tool/selection.h>
34#include <tool/tool_event.h>
38#include <gestfich.h>
39#include <paths.h>
40#include <wx/checkbox.h>
41#include <wx/dir.h>
42#include <wx/filedlg.h>
43#include "dialog_pcm.h"
44#include <macros.h>
45#include <sch_io_mgr.h>
46#include <io_mgr.h>
47#include <import_proj.h>
48
49#if wxCHECK_VERSION( 3, 1, 7 )
51#else
53#endif
54
56 TOOL_INTERACTIVE( "kicad.Control" ),
57 m_frame( nullptr )
58{
59}
60
61
63{
64 m_frame = getEditFrame<KICAD_MANAGER_FRAME>();
65}
66
67
69{
70 wxString default_dir = m_frame->GetMruPath();
71 wxFileDialog dlg( m_frame, _( "Create New Project" ), default_dir, wxEmptyString,
72 ProjectFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
73
74 // Add a "Create a new directory" checkbox
75#if wxCHECK_VERSION( 3, 1, 7 )
76 FILEDLG_NEW_PROJECT newProjectHook;
77 dlg.SetCustomizeHook( newProjectHook );
78#else
79 dlg.SetExtraControlCreator( &LEGACYFILEDLG_NEW_PROJECT::Create );
80#endif
81
82 if( dlg.ShowModal() == wxID_CANCEL )
83 return -1;
84
85 wxFileName pro( dlg.GetPath() );
86
87 // wxFileName automatically extracts an extension. But if it isn't
88 // a .pro extension, we should keep it as part of the filename
89 if( !pro.GetExt().IsEmpty() && pro.GetExt().ToStdString() != ProjectFileExtension )
90 pro.SetName( pro.GetName() + wxT( "." ) + pro.GetExt() );
91
92 pro.SetExt( ProjectFileExtension ); // enforce extension
93
94 if( !pro.IsAbsolute() )
95 pro.MakeAbsolute();
96
97 // Append a new directory with the same name of the project file.
98 bool createNewDir = false;
99
100#if wxCHECK_VERSION( 3, 1, 7 )
101 createNewDir = newProjectHook.GetCreateNewDir();
102#else
103 createNewDir = static_cast<LEGACYFILEDLG_NEW_PROJECT*>( dlg.GetExtraControl() )->CreateNewDir();
104#endif
105
106 if( createNewDir )
107 pro.AppendDir( pro.GetName() );
108
109 // Check if the project directory is empty if it already exists.
110 wxDir directory( pro.GetPath() );
111
112 if( !pro.DirExists() )
113 {
114 if( !pro.Mkdir() )
115 {
116 wxString msg;
117 msg.Printf( _( "Folder '%s' could not be created.\n\n"
118 "Make sure you have write permissions and try again." ),
119 pro.GetPath() );
121 return -1;
122 }
123 }
124 else if( directory.HasFiles() )
125 {
126 wxString msg = _( "The selected folder is not empty. It is recommended that you "
127 "create projects in their own empty folder.\n\n"
128 "Do you want to continue?" );
129
130 if( !IsOK( m_frame, msg ) )
131 return -1;
132 }
133
135 m_frame->LoadProject( pro );
136
137 return 0;
138}
139
140
142{
144
145 wxFileName templatePath;
146
147 // KiCad system template path.
148 ENV_VAR_MAP_CITER it = Pgm().GetLocalEnvVariables().find( "KICAD6_TEMPLATE_DIR" );
149
150 if( it != Pgm().GetLocalEnvVariables().end() && it->second.GetValue() != wxEmptyString )
151 {
152 templatePath.AssignDir( it->second.GetValue() );
153 ps->AddTemplatesPage( _( "System Templates" ), templatePath );
154 }
155
156 // User template path.
157 it = Pgm().GetLocalEnvVariables().find( "KICAD_USER_TEMPLATE_DIR" );
158
159 if( it != Pgm().GetLocalEnvVariables().end() && it->second.GetValue() != wxEmptyString )
160 {
161 templatePath.AssignDir( it->second.GetValue() );
162 ps->AddTemplatesPage( _( "User Templates" ), templatePath );
163 }
164
165 // Show the project template selector dialog
166 if( ps->ShowModal() != wxID_OK )
167 return -1;
168
169 if( !ps->GetSelectedTemplate() )
170 {
171 wxMessageBox( _( "No project template was selected. Cannot generate new project." ),
172 _( "Error" ), wxOK | wxICON_ERROR, m_frame );
173
174 return -1;
175 }
176
177 // Get project destination folder and project file name.
178 wxString default_dir = wxFileName( Prj().GetProjectFullName() ).GetPathWithSep();
179 wxString title = _( "New Project Folder" );
180 wxFileDialog dlg( m_frame, title, default_dir, wxEmptyString, ProjectFileWildcard(),
181 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
182
183 // Add a "Create a new directory" checkbox
184#if wxCHECK_VERSION( 3, 1, 7 )
185 FILEDLG_NEW_PROJECT newProjectHook;
186 dlg.SetCustomizeHook( newProjectHook );
187#else
188 dlg.SetExtraControlCreator( &LEGACYFILEDLG_NEW_PROJECT::Create );
189#endif
190
191
192 if( dlg.ShowModal() == wxID_CANCEL )
193 return -1;
194
195 wxFileName fn( dlg.GetPath() );
196
197 // wxFileName automatically extracts an extension. But if it isn't a .kicad_pro extension,
198 // we should keep it as part of the filename
199 if( !fn.GetExt().IsEmpty() && fn.GetExt().ToStdString() != ProjectFileExtension )
200 fn.SetName( fn.GetName() + wxT( "." ) + fn.GetExt() );
201
202 fn.SetExt( ProjectFileExtension );
203
204 if( !fn.IsAbsolute() )
205 fn.MakeAbsolute();
206
207 bool createNewDir = false;
208#if wxCHECK_VERSION( 3, 1, 7 )
209 createNewDir = newProjectHook.GetCreateNewDir();
210#else
211 createNewDir = static_cast<LEGACYFILEDLG_NEW_PROJECT*>( dlg.GetExtraControl() )->CreateNewDir();
212#endif
213
214 // Append a new directory with the same name of the project file.
215 if( createNewDir )
216 fn.AppendDir( fn.GetName() );
217
218 // Check if the project directory is empty if it already exists.
219
220 if( !fn.DirExists() )
221 {
222 if( !fn.Mkdir() )
223 {
224 wxString msg;
225 msg.Printf( _( "Folder '%s' could not be created.\n\n"
226 "Make sure you have write permissions and try again." ),
227 fn.GetPath() );
229 return -1;
230 }
231 }
232
233 if( !fn.IsDirWritable() )
234 {
235 wxString msg;
236
237 msg.Printf( _( "Insufficient permissions to write to folder '%s'." ), fn.GetPath() );
238 wxMessageDialog msgDlg( m_frame, msg, _( "Error" ), wxICON_ERROR | wxOK | wxCENTER );
239 msgDlg.ShowModal();
240 return -1;
241 }
242
243 // Make sure we are not overwriting anything in the destination folder.
244 std::vector< wxFileName > destFiles;
245
246 if( ps->GetSelectedTemplate()->GetDestinationFiles( fn, destFiles ) )
247 {
248 std::vector<wxFileName> overwrittenFiles;
249
250 for( const wxFileName& file : destFiles )
251 {
252 if( file.FileExists() )
253 overwrittenFiles.push_back( file );
254 }
255
256 if( !overwrittenFiles.empty() )
257 {
258 wxString extendedMsg = _( "Overwriting files:" ) + "\n";
259
260 for( const wxFileName& file : overwrittenFiles )
261 extendedMsg += "\n" + file.GetFullName();
262
263 KIDIALOG msgDlg( m_frame,
264 _( "Similar files already exist in the destination folder." ),
265 _( "Confirmation" ),
266 wxOK | wxCANCEL | wxICON_WARNING );
267 msgDlg.SetExtendedMessage( extendedMsg );
268 msgDlg.SetOKLabel( _( "Overwrite" ) );
269 msgDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
270
271 if( msgDlg.ShowModal() == wxID_CANCEL )
272 return -1;
273 }
274 }
275
276 wxString errorMsg;
277
278 // The selected template widget contains the template we're attempting to use to
279 // create a project
280 if( !ps->GetSelectedTemplate()->CreateProject( fn, &errorMsg ) )
281 {
282 wxMessageDialog createDlg( m_frame,
283 _( "A problem occurred creating new project from template." ),
284 _( "Error" ),
285 wxOK | wxICON_ERROR );
286
287 if( !errorMsg.empty() )
288 createDlg.SetExtendedMessage( errorMsg );
289
290 createDlg.ShowModal();
291 return -1;
292 }
293
294 m_frame->CreateNewProject( fn.GetFullPath() );
295 m_frame->LoadProject( fn );
296 return 0;
297}
298
299
300int KICAD_MANAGER_CONTROL::openProject( const wxString& aDefaultDir )
301{
302 wxString wildcard = AllProjectFilesWildcard()
303 + "|" + ProjectFileWildcard()
305
306 wxFileDialog dlg( m_frame, _( "Open Existing Project" ), aDefaultDir, wxEmptyString, wildcard,
307 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
308
309 if( dlg.ShowModal() == wxID_CANCEL )
310 return -1;
311
312 wxFileName pro( dlg.GetPath() );
313
314 if( !pro.IsAbsolute() )
315 pro.MakeAbsolute();
316
317 if( !pro.FileExists() )
318 return -1;
319
320 m_frame->LoadProject( pro );
321
322 return 0;
323}
324
325
327{
329}
330
331
333{
334 return openProject( m_frame->GetMruPath() );
335}
336
337
339{
340 m_frame->CloseProject( true );
341 return 0;
342}
343
344
346{
347 if( !aEvent.Parameter<wxString*>() )
348 return -1;
349
350 wxFileName droppedFileName( *aEvent.Parameter<wxString*>() );
351
352 wxString schFileExtension, pcbFileExtension;
353 int schFileType, pcbFileType;
354
355 // Define extensions to use according to dropped file.
356 // Eagle project.
357 if( droppedFileName.GetExt() == EagleSchematicFileExtension
358 || droppedFileName.GetExt() == EaglePcbFileExtension )
359 {
360 // Check if droppedFile is an eagle file.
361 // If not, return and do not import files.
362 if( !IsFileFromEDATool( droppedFileName, EDA_TOOLS::EAGLE ) )
363 return -1;
364
365 schFileExtension = EagleSchematicFileExtension;
366 pcbFileExtension = EaglePcbFileExtension;
367 schFileType = SCH_IO_MGR::SCH_EAGLE;
368 pcbFileType = IO_MGR::EAGLE;
369 }
370 // Cadstar project.
371 else if( droppedFileName.GetExt() == CadstarSchematicFileExtension
372 || droppedFileName.GetExt() == CadstarPcbFileExtension )
373 {
374 schFileExtension = CadstarSchematicFileExtension;
375 pcbFileExtension = CadstarPcbFileExtension;
376 schFileType = SCH_IO_MGR::SCH_CADSTAR_ARCHIVE;
377 pcbFileType = IO_MGR::CADSTAR_PCB_ARCHIVE;
378 }
379 else
380 {
381 return -1;
382 }
383
384 IMPORT_PROJ_HELPER importProj( m_frame, droppedFileName.GetFullPath(), schFileExtension,
385 pcbFileExtension );
386
387 // Check if the project directory is empty
388 wxDir directory( importProj.GetProjPath() );
389
390 if( directory.HasFiles() )
391 {
392 // Append a new directory with the same name of the project file
393 // Keep iterating until we find an empty directory
394 importProj.CreateEmptyDirForProject();
395
396 if( !wxMkdir( importProj.GetProjPath() ) )
397 return -1;
398 }
399
400 importProj.SetProjAbsolutePath();
401
402 if( !importProj.CopyImportedFiles( false ) )
403 {
404 wxRmdir( importProj.GetProjPath() ); // Remove the previous created directory, before leaving.
405 return -1;
406 }
407
408 m_frame->CloseProject( true );
409
410 m_frame->CreateNewProject( importProj.GetProjFullPath(), false /* Don't create stub files */ );
411 m_frame->LoadProject( importProj.GetProj() );
412
413 importProj.AssociateFilesWithProj( schFileType, pcbFileType );
415 m_frame->LoadProject( importProj.GetProj() );
416 return 0;
417}
418
420{
421 if( aEvent.Parameter<wxString*>() )
422 m_frame->LoadProject( wxFileName( *aEvent.Parameter<wxString*>() ) );
423 return 0;
424}
425
427{
428 if( aEvent.Parameter<wxString*>() )
429 wxExecute( *aEvent.Parameter<wxString*>(), wxEXEC_ASYNC );
430 return 0;
431}
432
433class SAVE_AS_TRAVERSER : public wxDirTraverser
434{
435public:
437 const wxString& aSrcProjectDirPath,
438 const wxString& aSrcProjectName,
439 const wxString& aNewProjectDirPath,
440 const wxString& aNewProjectName ) :
441 m_frame( aFrame ),
442 m_projectDirPath( aSrcProjectDirPath ),
443 m_projectName( aSrcProjectName ),
444 m_newProjectDirPath( aNewProjectDirPath ),
445 m_newProjectName( aNewProjectName )
446 {
447 }
448
449 virtual wxDirTraverseResult OnFile( const wxString& aSrcFilePath ) override
450 {
451 // Recursion guard for a Save As to a location inside the source project.
452 if( aSrcFilePath.StartsWith( m_newProjectDirPath + wxFileName::GetPathSeparator() ) )
453 return wxDIR_CONTINUE;
454
455 wxFileName destFile( aSrcFilePath );
456 wxString ext = destFile.GetExt();
457 bool atRoot = destFile.GetPath() == m_projectDirPath;
458
460 || ext == ProjectFileExtension
462 {
463 wxString destPath = destFile.GetPath();
464
465 if( destPath.StartsWith( m_projectDirPath ) )
466 {
467 destPath.Replace( m_projectDirPath, m_newProjectDirPath, false );
468 destFile.SetPath( destPath );
469 }
470
471 if( destFile.GetName() == m_projectName )
472 {
473 destFile.SetName( m_newProjectName );
474
475 if( atRoot && ext != ProjectLocalSettingsFileExtension )
476 m_newProjectFile = destFile;
477 }
478
479 if( ext == LegacyProjectFileExtension )
480 {
481 // All paths in the settings file are relative so we can just do a straight copy
482 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), m_errors );
483 }
484 else if( ext == ProjectFileExtension )
485 {
486 PROJECT_FILE projectFile( aSrcFilePath );
487 projectFile.LoadFromFile();
488 projectFile.SaveAs( destFile.GetPath(), destFile.GetName() );
489 }
490 else if( ext == ProjectLocalSettingsFileExtension )
491 {
492 PROJECT_LOCAL_SETTINGS projectLocalSettings( nullptr, aSrcFilePath );
493 projectLocalSettings.LoadFromFile();
494 projectLocalSettings.SaveAs( destFile.GetPath(), destFile.GetName() );
495 }
496 }
497 else if( ext == KiCadSchematicFileExtension
505 || ext == NetlistFileExtension
506 || destFile.GetName() == "sym-lib-table" )
507 {
510 m_newProjectName, aSrcFilePath, m_errors );
511 }
512 else if( ext == KiCadPcbFileExtension
514 || ext == LegacyPcbFileExtension
518 || destFile.GetName() == "fp-lib-table" )
519 {
522 m_newProjectName, aSrcFilePath, m_errors );
523 }
524 else if( ext == DrawingSheetFileExtension )
525 {
528 m_newProjectName, aSrcFilePath, m_errors );
529 }
530 else if( ext == GerberJobFileExtension
531 || ext == DrillFileExtension
532 || IsGerberFileExtension(ext) )
533 {
536 m_newProjectName, aSrcFilePath, m_errors );
537 }
538 else
539 {
540 // Everything we don't recognize just gets a straight copy.
541 wxString destPath = destFile.GetPathWithSep();
542 wxString destName = destFile.GetName();
543 wxUniChar pathSep = wxFileName::GetPathSeparator();
544
545 wxString srcProjectFootprintLib = pathSep + m_projectName + ".pretty" + pathSep;
546 wxString newProjectFootprintLib = pathSep + m_newProjectName + ".pretty" + pathSep;
547
548 if( destPath.StartsWith( m_projectDirPath ) )
549 destPath.Replace( m_projectDirPath, m_newProjectDirPath, false );
550
551 destPath.Replace( srcProjectFootprintLib, newProjectFootprintLib, true );
552
553 if( destName == m_projectName && ext != wxT( "zip" ) /* don't rename archives */ )
554 destFile.SetName( m_newProjectName );
555
556 destFile.SetPath( destPath );
557
558 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), m_errors );
559 }
560
561 return wxDIR_CONTINUE;
562 }
563
564 virtual wxDirTraverseResult OnDir( const wxString& aSrcDirPath ) override
565 {
566 // Recursion guard for a Save As to a location inside the source project.
567 if( aSrcDirPath.StartsWith( m_newProjectDirPath ) )
568 return wxDIR_CONTINUE;
569
570 wxFileName destDir( aSrcDirPath );
571 wxString destDirPath = destDir.GetPathWithSep();
572 wxUniChar pathSep = wxFileName::GetPathSeparator();
573
574 if( destDirPath.StartsWith( m_projectDirPath + pathSep )
575 || destDirPath.StartsWith( m_projectDirPath + PROJECT_BACKUPS_DIR_SUFFIX ) )
576 {
577 destDirPath.Replace( m_projectDirPath, m_newProjectDirPath, false );
578 destDir.SetPath( destDirPath );
579 }
580
581 if( destDir.GetName() == m_projectName )
582 {
583 if( destDir.GetExt() == "pretty" )
584 destDir.SetName( m_newProjectName );
585#if 0
586 // WAYNE STAMBAUGH TODO:
587 // If we end up with a symbol equivalent to ".pretty" we'll want to handle it here....
588 else if( destDir.GetExt() == "sym_lib_dir_extension" )
589 destDir.SetName( m_newProjectName );
590#endif
591 }
592
593 if( !wxMkdir( destDir.GetFullPath() ) )
594 {
595 wxString msg;
596
597 if( !m_errors.empty() )
598 m_errors += "\n";
599
600 msg.Printf( _( "Cannot copy folder '%s'." ), destDir.GetFullPath() );
601 m_errors += msg;
602 }
603
604 return wxDIR_CONTINUE;
605 }
606
607 wxString GetErrors() { return m_errors; }
608
609 wxFileName GetNewProjectFile() { return m_newProjectFile; }
610
611private:
613
618
620 wxString m_errors;
621};
622
623
625{
626 wxString msg;
627
628 wxFileName currentProjectFile( Prj().GetProjectFullName() );
629 wxString currentProjectDirPath = currentProjectFile.GetPath();
630 wxString currentProjectName = Prj().GetProjectName();
631
632 wxString default_dir = m_frame->GetMruPath();
633
634 Prj().GetProjectFile().SaveToFile( currentProjectDirPath );
635 Prj().GetLocalSettings().SaveToFile( currentProjectDirPath );
636
637 if( default_dir == currentProjectDirPath
638 || default_dir == currentProjectDirPath + wxFileName::GetPathSeparator() )
639 {
640 // Don't start within the current project
641 wxFileName default_dir_fn( default_dir );
642 default_dir_fn.RemoveLastDir();
643 default_dir = default_dir_fn.GetPath();
644 }
645
646 wxFileDialog dlg( m_frame, _( "Save Project To" ), default_dir, wxEmptyString, wxEmptyString,
647 wxFD_SAVE );
648
649 if( dlg.ShowModal() == wxID_CANCEL )
650 return -1;
651
652 wxFileName newProjectDir( dlg.GetPath(), wxEmptyString );
653
654 if( !newProjectDir.IsAbsolute() )
655 newProjectDir.MakeAbsolute();
656
657 if( wxDirExists( newProjectDir.GetFullPath() ) )
658 {
659 msg.Printf( _( "'%s' already exists." ), newProjectDir.GetFullPath() );
661 return -1;
662 }
663
664 if( !wxMkdir( newProjectDir.GetFullPath() ) )
665 {
666 msg.Printf( _( "Folder '%s' could not be created.\n\n"
667 "Please make sure you have write permissions and try again." ),
668 newProjectDir.GetPath() );
670 return -1;
671 }
672
673 if( !newProjectDir.IsDirWritable() )
674 {
675 msg.Printf( _( "Insufficient permissions to write to folder '%s'." ),
676 newProjectDir.GetFullPath() );
677 wxMessageDialog msgDlg( m_frame, msg, _( "Error!" ), wxICON_ERROR | wxOK | wxCENTER );
678 msgDlg.ShowModal();
679 return -1;
680 }
681
682 const wxString& newProjectDirPath = newProjectDir.GetFullPath();
683 const wxString& newProjectName = newProjectDir.GetDirs().Last();
684 wxDir currentProjectDir( currentProjectDirPath );
685
686 SAVE_AS_TRAVERSER traverser( m_frame, currentProjectDirPath, currentProjectName,
687 newProjectDirPath, newProjectName );
688
689 currentProjectDir.Traverse( traverser );
690
691 if( !traverser.GetErrors().empty() )
692 DisplayErrorMessage( m_frame, traverser.GetErrors() );
693
694 if( !traverser.GetNewProjectFile().FileExists() )
696
697 m_frame->LoadProject( traverser.GetNewProjectFile() );
698
699 return 0;
700}
701
702
704{
706 return 0;
707}
708
709
711{
712 ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
713 CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
714 SELECTION dummySel;
715
716 if( conditionalMenu )
717 conditionalMenu->Evaluate( dummySel );
718
719 if( actionMenu )
720 actionMenu->UpdateAll();
721
722 return 0;
723}
724
725
727{
728 FRAME_T playerType = aEvent.Parameter<FRAME_T>();
729 KIWAY_PLAYER* player;
730
731 if( playerType == FRAME_SCH && !m_frame->IsProjectActive() )
732 {
733 DisplayInfoMessage( m_frame, _( "Create (or open) a project to edit a schematic." ),
734 wxEmptyString );
735 return -1;
736 }
737 else if( playerType == FRAME_PCB_EDITOR && !m_frame->IsProjectActive() )
738 {
739 DisplayInfoMessage( m_frame, _( "Create (or open) a project to edit a pcb." ),
740 wxEmptyString );
741 return -1;
742 }
743
744 // Prevent multiple KIWAY_PLAYER loading at one time
745 if( !m_loading.try_lock() )
746 return -1;
747
748 const std::lock_guard<std::mutex> lock( m_loading, std::adopt_lock );
749
750 try
751 {
752 player = m_frame->Kiway().Player( playerType, true );
753 }
754 catch( const IO_ERROR& err )
755 {
756 wxMessageBox( _( "Application failed to load:\n" ) + err.What(), _( "KiCad Error" ),
757 wxOK | wxICON_ERROR, m_frame );
758 return -1;
759 }
760
761 if ( !player )
762 {
763 wxMessageBox( _( "Application failed to load." ), _( "KiCad Error" ),
764 wxOK | wxICON_ERROR, m_frame );
765 return -1;
766 }
767
768 if( !player->IsVisible() ) // A hidden frame might not have the document loaded.
769 {
770 wxString filepath;
771
772 if( playerType == FRAME_SCH )
773 {
774 wxFileName kicad_schematic( m_frame->SchFileName() );
775 wxFileName legacy_schematic( m_frame->SchLegacyFileName() );
776
777 if( !legacy_schematic.FileExists() || kicad_schematic.FileExists() )
778 filepath = kicad_schematic.GetFullPath();
779 else
780 filepath = legacy_schematic.GetFullPath();
781 }
782 else if( playerType == FRAME_PCB_EDITOR )
783 {
784 wxFileName kicad_board( m_frame->PcbFileName() );
785 wxFileName legacy_board( m_frame->PcbLegacyFileName() );
786
787 if( !legacy_board.FileExists() || kicad_board.FileExists() )
788 filepath = kicad_board.GetFullPath();
789 else
790 filepath = legacy_board.GetFullPath();
791 }
792
793 if( !filepath.IsEmpty() )
794 {
795 if( !player->OpenProjectFiles( std::vector<wxString>( 1, filepath ) ) )
796 {
797 player->Destroy();
798 return -1;
799 }
800 }
801
802 wxBusyCursor busy;
803 player->Show( true );
804 }
805
806 // Needed on Windows, other platforms do not use it, but it creates no issue
807 if( player->IsIconized() )
808 player->Iconize( false );
809
810 player->Raise();
811
812 // Raising the window does not set the focus on Linux. This should work on
813 // any platform.
814 if( wxWindow::FindFocus() != player )
815 player->SetFocus();
816
817 return 0;
818}
819
820
821class TERMINATE_HANDLER : public wxProcess
822{
823public:
824 TERMINATE_HANDLER( const wxString& appName )
825 { }
826
827 void OnTerminate( int pid, int status ) override
828 {
829 delete this;
830 }
831};
832
833
835{
836 wxString execFile;
837 wxString param;
838
840 execFile = GERBVIEW_EXE;
842 execFile = BITMAPCONVERTER_EXE;
844 execFile = PCB_CALCULATOR_EXE;
846 execFile = PL_EDITOR_EXE;
848 execFile = Pgm().GetTextEditor();
850 execFile = EESCHEMA_EXE;
852 execFile = PCBNEW_EXE;
853 else
854 wxFAIL_MSG( "Execute(): unexpected request" );
855
856 if( execFile.IsEmpty() )
857 return 0;
858
859 if( aEvent.Parameter<wxString*>() )
860 param = *aEvent.Parameter<wxString*>();
862 param = m_frame->Prj().GetProjectPath();
863
864 TERMINATE_HANDLER* callback = new TERMINATE_HANDLER( execFile );
865
866 long pid = ExecuteFile( execFile, param, callback );
867
868 if( pid > 0 )
869 {
870#ifdef __WXMAC__
871 // This non-parameterized use of wxExecute is fine because execFile is not derived
872 // from user input.
873 wxExecute( "osascript -e 'activate application \"" + execFile + "\"'" );
874#endif
875 }
876 else
877 {
878 delete callback;
879 }
880
881 return 0;
882}
883
884
886{
889 {
890 // policy disables the plugin manager
891 return 0;
892 }
893
894 // For some reason, after a click or a double click the bitmap button calling
895 // PCM keeps the focus althougt the focus was not set to this button.
896 // This hack force removing the focus from this button
897 m_frame->SetFocus();
898 wxSafeYield();
899
900 DIALOG_PCM pcm( m_frame, m_frame->GetPcm() );
901 pcm.ShowModal();
902
903 return 0;
904}
905
906
908{
918
921
931
934
936}
static TOOL_ACTION zoomRedraw
Definition: actions.h:92
static TOOL_ACTION saveAs
Definition: actions.h:52
static TOOL_ACTION updateMenu
Definition: actions.h:171
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:49
void UpdateAll()
Run update handlers for the menu and its submenus.
Implementing pcm main dialog.
Definition: dialog_pcm.h:36
void AddTemplatesPage(const wxString &aTitle, wxFileName &aPath)
Add a new page with aTitle, populated with templates from aPath.
PROJECT_TEMPLATE * GetSelectedTemplate()
wxString GetMruPath() const
bool GetCreateNewDir() const
A helper class to import non Kicad project.
Definition: import_proj.h:12
void AssociateFilesWithProj(int aImportedSchFileType, int aImportedPcbFileType)
Converts imported files to kicad type files.
wxString GetProjFullPath()
Definition: import_proj.cpp:62
wxString GetProjPath()
Definition: import_proj.cpp:50
const wxFileName & GetProj()
Definition: import_proj.cpp:44
void CreateEmptyDirForProject()
Appends a new directory with the name of the project file Keep iterating until an empty directory is ...
Definition: import_proj.cpp:74
void SetProjAbsolutePath()
Definition: import_proj.cpp:92
bool CopyImportedFiles(bool displayError=true)
Copies project files to the destination directory.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:76
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
@ EAGLE
Definition: io_mgr.h:57
@ CADSTAR_PCB_ARCHIVE
Definition: io_mgr.h:63
virtual bool LoadFromFile(const wxString &aDirectory="")
Loads the backing file from disk and then calls Load()
static TOOL_ACTION viewDroppedGerbers
static TOOL_ACTION openDemoProject
static TOOL_ACTION editPCB
static TOOL_ACTION loadProject
static TOOL_ACTION editOtherPCB
static TOOL_ACTION newProject
static TOOL_ACTION editOtherSch
static TOOL_ACTION editSchematic
static TOOL_ACTION openTextEditor
static TOOL_ACTION openProject
static TOOL_ACTION closeProject
static TOOL_ACTION convertImage
static TOOL_ACTION editDrawingSheet
static TOOL_ACTION editFootprints
static TOOL_ACTION showPluginManager
static TOOL_ACTION showCalculator
static TOOL_ACTION importNonKicadProj
static TOOL_ACTION viewGerbers
static TOOL_ACTION newFromTemplate
static TOOL_ACTION editSymbols
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
int OpenProject(const TOOL_EVENT &aEvent)
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
int OpenDemoProject(const TOOL_EVENT &aEvent)
int CloseProject(const TOOL_EVENT &aEvent)
int SaveProjectAs(const TOOL_EVENT &aEvent)
int NewProject(const TOOL_EVENT &aEvent)
int ViewDroppedViewers(const TOOL_EVENT &aEvent)
int NewFromTemplate(const TOOL_EVENT &aEvent)
int ShowPluginManager(const TOOL_EVENT &aEvent)
Set up handlers for various events.
int UpdateMenu(const TOOL_EVENT &aEvent)
int ImportNonKicadProj(const TOOL_EVENT &aEvent)
Imports a non kicad project from a sch/pcb dropped file.
int LoadProject(const TOOL_EVENT &aEvent)
KICAD_MANAGER_FRAME * m_frame
< Pointer to the currently used edit/draw frame.
int ShowPlayer(const TOOL_EVENT &aEvent)
int Refresh(const TOOL_EVENT &aEvent)
int openProject(const wxString &aDefaultDir)
int Execute(const TOOL_EVENT &aEvent)
The main KiCad project manager frame.
void CreateNewProject(const wxFileName &aProjectFileName, bool aCreateStubFiles=true)
Creates a new project by setting up and initial project, schematic, and board files.
const wxString SchLegacyFileName()
const wxString SchFileName()
void LoadProject(const wxFileName &aProjectFileName)
std::shared_ptr< PLUGIN_CONTENT_MANAGER > GetPcm()
const wxString PcbLegacyFileName()
bool CloseProject(bool aSave)
Closes the project, and saves it if aSave is true;.
const wxString PcbFileName()
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: confirm.h:46
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
Definition: confirm.cpp:56
int ShowModal() override
Definition: confirm.cpp:100
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:53
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Definition: kiway_player.h:66
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:394
virtual KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
Definition: kiway.cpp:198
@ FACE_SCH
eeschema DSO
Definition: kiway.h:280
@ FACE_PL_EDITOR
Definition: kiway.h:284
@ FACE_PCB
pcbnew DSO
Definition: kiway.h:281
@ FACE_GERBVIEW
Definition: kiway.h:283
ā€¨Helper widget to select whether a new directory should be created for a project.
static wxWindow * Create(wxWindow *aParent)
static wxString GetStockDemosPath()
Gets the stock (install) demos path.
Definition: paths.cpp:310
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:65
bool SaveAs(const wxString &aDirectory, const wxString &aFile)
bool SaveToFile(const wxString &aDirectory="", bool aForce=false) override
The project local settings are things that are attached to a particular project, but also might be pa...
bool SaveAs(const wxString &aDirectory, const wxString &aFile)
bool SaveToFile(const wxString &aDirectory="", bool aForce=false) override
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.
bool CreateProject(wxFileName &aNewProjectPath, wxString *aErrorMsg=nullptr)
Copies and renames all template files to create a new project.
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:126
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition: project.cpp:132
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition: project.h:154
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:148
KICAD_MANAGER_FRAME * m_frame
virtual wxDirTraverseResult OnFile(const wxString &aSrcFilePath) override
SAVE_AS_TRAVERSER(KICAD_MANAGER_FRAME *aFrame, const wxString &aSrcProjectDirPath, const wxString &aSrcProjectName, const wxString &aNewProjectDirPath, const wxString &aNewProjectName)
virtual wxDirTraverseResult OnDir(const wxString &aSrcDirPath) override
void OnTerminate(int pid, int status) override
TERMINATE_HANDLER(const wxString &appName)
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
Generic, UI-independent tool event.
Definition: tool_event.h:156
T Parameter() const
Return a non-standard parameter assigned to the event.
Definition: tool_event.h:442
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
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).
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:342
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:320
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:299
This file is part of the common library.
#define _(s)
bool IsFileFromEDATool(const wxFileName &aFileName, const EDA_TOOLS aTool)
Check if aFileName is a aTool file As an example, can be used to check if a .sch file is an EAGLE fil...
Definition: eda_tools.cpp:29
Enums and utilities for different EDA tools.
KiCad executable names.
const wxString EESCHEMA_EXE
const wxString GERBVIEW_EXE
const wxString PL_EDITOR_EXE
const wxString BITMAPCONVERTER_EXE
const wxString PCBNEW_EXE
const wxString PCB_CALCULATOR_EXE
FRAME_T
The set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
Definition: frame_type.h:33
@ FRAME_PCB_EDITOR
Definition: frame_type.h:40
@ FRAME_SCH
Definition: frame_type.h:34
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Definition: gestfich.cpp:214
int ExecuteFile(const wxString &aEditorName, const wxString &aFileName, wxProcess *aCallback)
Call the executable file aEditorName with the parameter aFileName.
Definition: gestfich.cpp:115
const std::string LegacyPcbFileExtension
const std::string CadstarPcbFileExtension
const std::string BackupFileSuffix
const std::string KiCadSymbolLibFileExtension
const std::string LegacySchematicFileExtension
const std::string FootprintAssignmentFileExtension
const std::string GerberJobFileExtension
const std::string LegacySymbolDocumentFileExtension
const std::string DrillFileExtension
const std::string EagleSchematicFileExtension
const std::string KiCadFootprintFileExtension
const std::string LegacyProjectFileExtension
const std::string KiCadPcbFileExtension
bool IsGerberFileExtension(const wxString &ext)
const std::string LegacyFootprintLibPathExtension
const std::string ProjectLocalSettingsFileExtension
const std::string ProjectFileExtension
const std::string NetlistFileExtension
const std::string EaglePcbFileExtension
const std::string CadstarSchematicFileExtension
const std::string KiCadSchematicFileExtension
const std::string DrawingSheetFileExtension
const std::string SchematicSymbolFileExtension
const std::string LegacySymbolLibFileExtension
wxString AllProjectFilesWildcard()
wxString LegacyProjectFileWildcard()
wxString ProjectFileWildcard()
std::map< wxString, ENV_VAR_ITEM >::const_iterator ENV_VAR_MAP_CITER
PROJECT & Prj()
Definition: kicad.cpp:556
This file contains miscellaneous commonly used macros and functions.
STATE GetPolicyState(const wxString &aKey)
Definition: gtk/policy.cpp:25
see class PGM_BASE
#define POLICY_KEY_PCM
Definition: policy_keys.h:29
#define PROJECT_BACKUPS_DIR_SUFFIX
Project settings path will be <projectname> + this.
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111
Implement a participant in the KIWAY alchemy.
Definition: kiway.h:151
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:210
Definition of file extensions used in Kicad.