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-2023 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>
34#include <tool/selection.h>
35#include <tool/tool_event.h>
39#include <gestfich.h>
40#include <paths.h>
41#include <wx/checkbox.h>
42#include <wx/dir.h>
43#include <wx/filedlg.h>
44#include "dialog_pcm.h"
45#include <macros.h>
46#include <sch_io_mgr.h>
47#include <io_mgr.h>
48#include <import_proj.h>
49
50#if wxCHECK_VERSION( 3, 1, 7 )
52#else
54#endif
55
57 TOOL_INTERACTIVE( "kicad.Control" ),
58 m_frame( nullptr )
59{
60}
61
62
64{
65 m_frame = getEditFrame<KICAD_MANAGER_FRAME>();
66}
67
68
70{
71 wxString default_dir = m_frame->GetMruPath();
72 wxFileDialog dlg( m_frame, _( "Create New Project" ), default_dir, wxEmptyString,
73 ProjectFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
74
75 // Add a "Create a new directory" checkbox
76#if wxCHECK_VERSION( 3, 1, 7 )
77 FILEDLG_NEW_PROJECT newProjectHook;
78 dlg.SetCustomizeHook( newProjectHook );
79#else
80 dlg.SetExtraControlCreator( &LEGACYFILEDLG_NEW_PROJECT::Create );
81#endif
82
83 if( dlg.ShowModal() == wxID_CANCEL )
84 return -1;
85
86 wxFileName pro( dlg.GetPath() );
87
88 // wxFileName automatically extracts an extension. But if it isn't
89 // a .pro extension, we should keep it as part of the filename
90 if( !pro.GetExt().IsEmpty() && pro.GetExt().ToStdString() != ProjectFileExtension )
91 pro.SetName( pro.GetName() + wxT( "." ) + pro.GetExt() );
92
93 pro.SetExt( ProjectFileExtension ); // enforce extension
94
95 if( !pro.IsAbsolute() )
96 pro.MakeAbsolute();
97
98 // Append a new directory with the same name of the project file.
99 bool createNewDir = false;
100
101#if wxCHECK_VERSION( 3, 1, 7 )
102 createNewDir = newProjectHook.GetCreateNewDir();
103#else
104 createNewDir = static_cast<LEGACYFILEDLG_NEW_PROJECT*>( dlg.GetExtraControl() )->CreateNewDir();
105#endif
106
107 if( createNewDir )
108 pro.AppendDir( pro.GetName() );
109
110 // Check if the project directory is empty if it already exists.
111 wxDir directory( pro.GetPath() );
112
113 if( !pro.DirExists() )
114 {
115 if( !pro.Mkdir() )
116 {
117 wxString msg;
118 msg.Printf( _( "Folder '%s' could not be created.\n\n"
119 "Make sure you have write permissions and try again." ),
120 pro.GetPath() );
122 return -1;
123 }
124 }
125 else if( directory.HasFiles() )
126 {
127 wxString msg = _( "The selected folder is not empty. It is recommended that you "
128 "create projects in their own empty folder.\n\n"
129 "Do you want to continue?" );
130
131 if( !IsOK( m_frame, msg ) )
132 return -1;
133 }
134
136 m_frame->LoadProject( pro );
137
138 return 0;
139}
140
141
143{
145
146 wxFileName templatePath;
147
148 // KiCad system template path.
149 ENV_VAR_MAP_CITER it = Pgm().GetLocalEnvVariables().find( "KICAD7_TEMPLATE_DIR" );
150
151 if( it != Pgm().GetLocalEnvVariables().end() && it->second.GetValue() != wxEmptyString )
152 {
153 templatePath.AssignDir( it->second.GetValue() );
154 ps->AddTemplatesPage( _( "System Templates" ), templatePath );
155 }
156
157 // User template path.
158 it = Pgm().GetLocalEnvVariables().find( "KICAD_USER_TEMPLATE_DIR" );
159
160 if( it != Pgm().GetLocalEnvVariables().end() && it->second.GetValue() != wxEmptyString )
161 {
162 templatePath.AssignDir( it->second.GetValue() );
163 ps->AddTemplatesPage( _( "User Templates" ), templatePath );
164 }
165
166 // Show the project template selector dialog
167 if( ps->ShowModal() != wxID_OK )
168 return -1;
169
170 if( !ps->GetSelectedTemplate() )
171 {
172 wxMessageBox( _( "No project template was selected. Cannot generate new project." ),
173 _( "Error" ), wxOK | wxICON_ERROR, m_frame );
174
175 return -1;
176 }
177
178 // Get project destination folder and project file name.
179 wxString default_dir = wxFileName( Prj().GetProjectFullName() ).GetPathWithSep();
180 wxString title = _( "New Project Folder" );
181 wxFileDialog dlg( m_frame, title, default_dir, wxEmptyString, ProjectFileWildcard(),
182 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
183
184 // Add a "Create a new directory" checkbox
185#if wxCHECK_VERSION( 3, 1, 7 )
186 FILEDLG_NEW_PROJECT newProjectHook;
187 dlg.SetCustomizeHook( newProjectHook );
188#else
189 dlg.SetExtraControlCreator( &LEGACYFILEDLG_NEW_PROJECT::Create );
190#endif
191
192
193 if( dlg.ShowModal() == wxID_CANCEL )
194 return -1;
195
196 wxFileName fn( dlg.GetPath() );
197
198 // wxFileName automatically extracts an extension. But if it isn't a .kicad_pro extension,
199 // we should keep it as part of the filename
200 if( !fn.GetExt().IsEmpty() && fn.GetExt().ToStdString() != ProjectFileExtension )
201 fn.SetName( fn.GetName() + wxT( "." ) + fn.GetExt() );
202
203 fn.SetExt( ProjectFileExtension );
204
205 if( !fn.IsAbsolute() )
206 fn.MakeAbsolute();
207
208 bool createNewDir = false;
209#if wxCHECK_VERSION( 3, 1, 7 )
210 createNewDir = newProjectHook.GetCreateNewDir();
211#else
212 createNewDir = static_cast<LEGACYFILEDLG_NEW_PROJECT*>( dlg.GetExtraControl() )->CreateNewDir();
213#endif
214
215 // Append a new directory with the same name of the project file.
216 if( createNewDir )
217 fn.AppendDir( fn.GetName() );
218
219 // Check if the project directory is empty if it already exists.
220
221 if( !fn.DirExists() )
222 {
223 if( !fn.Mkdir() )
224 {
225 wxString msg;
226 msg.Printf( _( "Folder '%s' could not be created.\n\n"
227 "Make sure you have write permissions and try again." ),
228 fn.GetPath() );
230 return -1;
231 }
232 }
233
234 if( !fn.IsDirWritable() )
235 {
236 wxString msg;
237
238 msg.Printf( _( "Insufficient permissions to write to folder '%s'." ), fn.GetPath() );
239 wxMessageDialog msgDlg( m_frame, msg, _( "Error" ), wxICON_ERROR | wxOK | wxCENTER );
240 msgDlg.ShowModal();
241 return -1;
242 }
243
244 // Make sure we are not overwriting anything in the destination folder.
245 std::vector< wxFileName > destFiles;
246
247 if( ps->GetSelectedTemplate()->GetDestinationFiles( fn, destFiles ) )
248 {
249 std::vector<wxFileName> overwrittenFiles;
250
251 for( const wxFileName& file : destFiles )
252 {
253 if( file.FileExists() )
254 overwrittenFiles.push_back( file );
255 }
256
257 if( !overwrittenFiles.empty() )
258 {
259 wxString extendedMsg = _( "Overwriting files:" ) + "\n";
260
261 for( const wxFileName& file : overwrittenFiles )
262 extendedMsg += "\n" + file.GetFullName();
263
264 KIDIALOG msgDlg( m_frame,
265 _( "Similar files already exist in the destination folder." ),
266 _( "Confirmation" ),
267 wxOK | wxCANCEL | wxICON_WARNING );
268 msgDlg.SetExtendedMessage( extendedMsg );
269 msgDlg.SetOKLabel( _( "Overwrite" ) );
270 msgDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
271
272 if( msgDlg.ShowModal() == wxID_CANCEL )
273 return -1;
274 }
275 }
276
277 wxString errorMsg;
278
279 // The selected template widget contains the template we're attempting to use to
280 // create a project
281 if( !ps->GetSelectedTemplate()->CreateProject( fn, &errorMsg ) )
282 {
283 wxMessageDialog createDlg( m_frame,
284 _( "A problem occurred creating new project from template." ),
285 _( "Error" ),
286 wxOK | wxICON_ERROR );
287
288 if( !errorMsg.empty() )
289 createDlg.SetExtendedMessage( errorMsg );
290
291 createDlg.ShowModal();
292 return -1;
293 }
294
295 m_frame->CreateNewProject( fn.GetFullPath() );
296 m_frame->LoadProject( fn );
297 return 0;
298}
299
300
301int KICAD_MANAGER_CONTROL::openProject( const wxString& aDefaultDir )
302{
303 wxString wildcard = AllProjectFilesWildcard()
304 + "|" + ProjectFileWildcard()
306
307 wxFileDialog dlg( m_frame, _( "Open Existing Project" ), aDefaultDir, wxEmptyString, wildcard,
308 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
309
310 if( dlg.ShowModal() == wxID_CANCEL )
311 return -1;
312
313 wxFileName pro( dlg.GetPath() );
314
315 if( !pro.IsAbsolute() )
316 pro.MakeAbsolute();
317
318 if( !pro.FileExists() )
319 return -1;
320
321 m_frame->LoadProject( pro );
322
323 return 0;
324}
325
326
328{
330}
331
332
334{
335 return openProject( m_frame->GetMruPath() );
336}
337
338
340{
341 m_frame->CloseProject( true );
342 return 0;
343}
344
345
347{
348 if( !aEvent.Parameter<wxString*>() )
349 return -1;
350
351 wxFileName droppedFileName( *aEvent.Parameter<wxString*>() );
352
353 wxString schFileExtension, pcbFileExtension;
354 int schFileType, pcbFileType;
355
356 // Define extensions to use according to dropped file.
357 // Eagle project.
358 if( droppedFileName.GetExt() == EagleSchematicFileExtension
359 || droppedFileName.GetExt() == EaglePcbFileExtension )
360 {
361 // Check if droppedFile is an eagle file.
362 // If not, return and do not import files.
363 if( !IsFileFromEDATool( droppedFileName, EDA_TOOLS::EAGLE ) )
364 return -1;
365
366 schFileExtension = EagleSchematicFileExtension;
367 pcbFileExtension = EaglePcbFileExtension;
368 schFileType = SCH_IO_MGR::SCH_EAGLE;
369 pcbFileType = IO_MGR::EAGLE;
370 }
371 // Cadstar project.
372 else if( droppedFileName.GetExt() == CadstarSchematicFileExtension
373 || droppedFileName.GetExt() == CadstarPcbFileExtension )
374 {
375 schFileExtension = CadstarSchematicFileExtension;
376 pcbFileExtension = CadstarPcbFileExtension;
377 schFileType = SCH_IO_MGR::SCH_CADSTAR_ARCHIVE;
378 pcbFileType = IO_MGR::CADSTAR_PCB_ARCHIVE;
379 }
380 else
381 {
382 return -1;
383 }
384
385 IMPORT_PROJ_HELPER importProj( m_frame, droppedFileName.GetFullPath(), schFileExtension,
386 pcbFileExtension );
387
388 // Check if the project directory is empty
389 wxDir directory( importProj.GetProjPath() );
390
391 if( directory.HasFiles() )
392 {
393 // Append a new directory with the same name of the project file
394 // Keep iterating until we find an empty directory
395 importProj.CreateEmptyDirForProject();
396
397 if( !wxMkdir( importProj.GetProjPath() ) )
398 return -1;
399 }
400
401 importProj.SetProjAbsolutePath();
402
403 if( !importProj.CopyImportedFiles( false ) )
404 {
405 wxRmdir( importProj.GetProjPath() ); // Remove the previous created directory, before leaving.
406 return -1;
407 }
408
409 m_frame->CloseProject( true );
410
411 m_frame->CreateNewProject( importProj.GetProjFullPath(), false /* Don't create stub files */ );
412 m_frame->LoadProject( importProj.GetProj() );
413
414 importProj.AssociateFilesWithProj( schFileType, pcbFileType );
416 m_frame->LoadProject( importProj.GetProj() );
417 return 0;
418}
419
421{
422 if( aEvent.Parameter<wxString*>() )
423 m_frame->LoadProject( wxFileName( *aEvent.Parameter<wxString*>() ) );
424 return 0;
425}
426
428{
429 if( aEvent.Parameter<wxString*>() )
430 wxExecute( *aEvent.Parameter<wxString*>(), wxEXEC_ASYNC );
431 return 0;
432}
433
434class SAVE_AS_TRAVERSER : public wxDirTraverser
435{
436public:
438 const wxString& aSrcProjectDirPath,
439 const wxString& aSrcProjectName,
440 const wxString& aNewProjectDirPath,
441 const wxString& aNewProjectName ) :
442 m_frame( aFrame ),
443 m_projectDirPath( aSrcProjectDirPath ),
444 m_projectName( aSrcProjectName ),
445 m_newProjectDirPath( aNewProjectDirPath ),
446 m_newProjectName( aNewProjectName )
447 {
448 }
449
450 virtual wxDirTraverseResult OnFile( const wxString& aSrcFilePath ) override
451 {
452 // Recursion guard for a Save As to a location inside the source project.
453 if( aSrcFilePath.StartsWith( m_newProjectDirPath + wxFileName::GetPathSeparator() ) )
454 return wxDIR_CONTINUE;
455
456 wxFileName destFile( aSrcFilePath );
457 wxString ext = destFile.GetExt();
458 bool atRoot = destFile.GetPath() == m_projectDirPath;
459
461 || ext == ProjectFileExtension
463 {
464 wxString destPath = destFile.GetPath();
465
466 if( destPath.StartsWith( m_projectDirPath ) )
467 {
468 destPath.Replace( m_projectDirPath, m_newProjectDirPath, false );
469 destFile.SetPath( destPath );
470 }
471
472 if( destFile.GetName() == m_projectName )
473 {
474 destFile.SetName( m_newProjectName );
475
476 if( atRoot && ext != ProjectLocalSettingsFileExtension )
477 m_newProjectFile = destFile;
478 }
479
480 if( ext == LegacyProjectFileExtension )
481 {
482 // All paths in the settings file are relative so we can just do a straight copy
483 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), m_errors );
484 }
485 else if( ext == ProjectFileExtension )
486 {
487 PROJECT_FILE projectFile( aSrcFilePath );
488 projectFile.LoadFromFile();
489 projectFile.SaveAs( destFile.GetPath(), destFile.GetName() );
490 }
491 else if( ext == ProjectLocalSettingsFileExtension )
492 {
493 PROJECT_LOCAL_SETTINGS projectLocalSettings( nullptr, aSrcFilePath );
494 projectLocalSettings.LoadFromFile();
495 projectLocalSettings.SaveAs( destFile.GetPath(), destFile.GetName() );
496 }
497 }
498 else if( ext == KiCadSchematicFileExtension
506 || ext == NetlistFileExtension
507 || destFile.GetName() == "sym-lib-table" )
508 {
511 m_newProjectName, aSrcFilePath, m_errors );
512 }
513 else if( ext == KiCadPcbFileExtension
515 || ext == LegacyPcbFileExtension
519 || destFile.GetName() == "fp-lib-table" )
520 {
523 m_newProjectName, aSrcFilePath, m_errors );
524 }
525 else if( ext == DrawingSheetFileExtension )
526 {
529 m_newProjectName, aSrcFilePath, m_errors );
530 }
531 else if( ext == GerberJobFileExtension
532 || ext == DrillFileExtension
533 || IsGerberFileExtension(ext) )
534 {
537 m_newProjectName, aSrcFilePath, m_errors );
538 }
539 else
540 {
541 // Everything we don't recognize just gets a straight copy.
542 wxString destPath = destFile.GetPathWithSep();
543 wxString destName = destFile.GetName();
544 wxUniChar pathSep = wxFileName::GetPathSeparator();
545
546 wxString srcProjectFootprintLib = pathSep + m_projectName + ".pretty" + pathSep;
547 wxString newProjectFootprintLib = pathSep + m_newProjectName + ".pretty" + pathSep;
548
549 if( destPath.StartsWith( m_projectDirPath ) )
550 destPath.Replace( m_projectDirPath, m_newProjectDirPath, false );
551
552 destPath.Replace( srcProjectFootprintLib, newProjectFootprintLib, true );
553
554 if( destName == m_projectName && ext != wxT( "zip" ) /* don't rename archives */ )
555 destFile.SetName( m_newProjectName );
556
557 destFile.SetPath( destPath );
558
559 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), m_errors );
560 }
561
562 return wxDIR_CONTINUE;
563 }
564
565 virtual wxDirTraverseResult OnDir( const wxString& aSrcDirPath ) override
566 {
567 // Recursion guard for a Save As to a location inside the source project.
568 if( aSrcDirPath.StartsWith( m_newProjectDirPath ) )
569 return wxDIR_CONTINUE;
570
571 wxFileName destDir( aSrcDirPath );
572 wxString destDirPath = destDir.GetPathWithSep();
573 wxUniChar pathSep = wxFileName::GetPathSeparator();
574
575 if( destDirPath.StartsWith( m_projectDirPath + pathSep )
576 || destDirPath.StartsWith( m_projectDirPath + PROJECT_BACKUPS_DIR_SUFFIX ) )
577 {
578 destDirPath.Replace( m_projectDirPath, m_newProjectDirPath, false );
579 destDir.SetPath( destDirPath );
580 }
581
582 if( destDir.GetName() == m_projectName )
583 {
584 if( destDir.GetExt() == "pretty" )
585 destDir.SetName( m_newProjectName );
586#if 0
587 // WAYNE STAMBAUGH TODO:
588 // If we end up with a symbol equivalent to ".pretty" we'll want to handle it here....
589 else if( destDir.GetExt() == "sym_lib_dir_extension" )
590 destDir.SetName( m_newProjectName );
591#endif
592 }
593
594 if( !wxMkdir( destDir.GetFullPath() ) )
595 {
596 wxString msg;
597
598 if( !m_errors.empty() )
599 m_errors += "\n";
600
601 msg.Printf( _( "Cannot copy folder '%s'." ), destDir.GetFullPath() );
602 m_errors += msg;
603 }
604
605 return wxDIR_CONTINUE;
606 }
607
608 wxString GetErrors() { return m_errors; }
609
610 wxFileName GetNewProjectFile() { return m_newProjectFile; }
611
612private:
614
619
621 wxString m_errors;
622};
623
624
626{
627 wxString msg;
628
629 wxFileName currentProjectFile( Prj().GetProjectFullName() );
630 wxString currentProjectDirPath = currentProjectFile.GetPath();
631 wxString currentProjectName = Prj().GetProjectName();
632
633 wxString default_dir = m_frame->GetMruPath();
634
635 Prj().GetProjectFile().SaveToFile( currentProjectDirPath );
636 Prj().GetLocalSettings().SaveToFile( currentProjectDirPath );
637
638 if( default_dir == currentProjectDirPath
639 || default_dir == currentProjectDirPath + wxFileName::GetPathSeparator() )
640 {
641 // Don't start within the current project
642 wxFileName default_dir_fn( default_dir );
643 default_dir_fn.RemoveLastDir();
644 default_dir = default_dir_fn.GetPath();
645 }
646
647 wxFileDialog dlg( m_frame, _( "Save Project To" ), default_dir, wxEmptyString, wxEmptyString,
648 wxFD_SAVE );
649
650 if( dlg.ShowModal() == wxID_CANCEL )
651 return -1;
652
653 wxFileName newProjectDir( dlg.GetPath(), wxEmptyString );
654
655 if( !newProjectDir.IsAbsolute() )
656 newProjectDir.MakeAbsolute();
657
658 if( wxDirExists( newProjectDir.GetFullPath() ) )
659 {
660 msg.Printf( _( "'%s' already exists." ), newProjectDir.GetFullPath() );
662 return -1;
663 }
664
665 if( !wxMkdir( newProjectDir.GetFullPath() ) )
666 {
667 msg.Printf( _( "Folder '%s' could not be created.\n\n"
668 "Please make sure you have write permissions and try again." ),
669 newProjectDir.GetPath() );
671 return -1;
672 }
673
674 if( !newProjectDir.IsDirWritable() )
675 {
676 msg.Printf( _( "Insufficient permissions to write to folder '%s'." ),
677 newProjectDir.GetFullPath() );
678 wxMessageDialog msgDlg( m_frame, msg, _( "Error!" ), wxICON_ERROR | wxOK | wxCENTER );
679 msgDlg.ShowModal();
680 return -1;
681 }
682
683 const wxString& newProjectDirPath = newProjectDir.GetFullPath();
684 const wxString& newProjectName = newProjectDir.GetDirs().Last();
685 wxDir currentProjectDir( currentProjectDirPath );
686
687 SAVE_AS_TRAVERSER traverser( m_frame, currentProjectDirPath, currentProjectName,
688 newProjectDirPath, newProjectName );
689
690 currentProjectDir.Traverse( traverser );
691
692 if( !traverser.GetErrors().empty() )
693 DisplayErrorMessage( m_frame, traverser.GetErrors() );
694
695 if( !traverser.GetNewProjectFile().FileExists() )
697
698 m_frame->LoadProject( traverser.GetNewProjectFile() );
699
700 return 0;
701}
702
703
705{
707 return 0;
708}
709
710
712{
713 ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
714 CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
715 SELECTION dummySel;
716
717 if( conditionalMenu )
718 conditionalMenu->Evaluate( dummySel );
719
720 if( actionMenu )
721 actionMenu->UpdateAll();
722
723 return 0;
724}
725
726
728{
729 FRAME_T playerType = aEvent.Parameter<FRAME_T>();
730 KIWAY_PLAYER* player;
731
732 if( playerType == FRAME_SCH && !m_frame->IsProjectActive() )
733 {
734 DisplayInfoMessage( m_frame, _( "Create (or open) a project to edit a schematic." ),
735 wxEmptyString );
736 return -1;
737 }
738 else if( playerType == FRAME_PCB_EDITOR && !m_frame->IsProjectActive() )
739 {
740 DisplayInfoMessage( m_frame, _( "Create (or open) a project to edit a pcb." ),
741 wxEmptyString );
742 return -1;
743 }
744
745 // Prevent multiple KIWAY_PLAYER loading at one time
746 if( !m_loading.try_lock() )
747 return -1;
748
749 const std::lock_guard<std::mutex> lock( m_loading, std::adopt_lock );
750
751 try
752 {
753 player = m_frame->Kiway().Player( playerType, true );
754 }
755 catch( const IO_ERROR& err )
756 {
757 wxMessageBox( _( "Application failed to load:\n" ) + err.What(), _( "KiCad Error" ),
758 wxOK | wxICON_ERROR, m_frame );
759 return -1;
760 }
761
762 if ( !player )
763 {
764 wxMessageBox( _( "Application failed to load." ), _( "KiCad Error" ),
765 wxOK | wxICON_ERROR, m_frame );
766 return -1;
767 }
768
769 if( !player->IsVisible() ) // A hidden frame might not have the document loaded.
770 {
771 wxString filepath;
772
773 if( playerType == FRAME_SCH )
774 {
775 wxFileName kicad_schematic( m_frame->SchFileName() );
776 wxFileName legacy_schematic( m_frame->SchLegacyFileName() );
777
778 if( !legacy_schematic.FileExists() || kicad_schematic.FileExists() )
779 filepath = kicad_schematic.GetFullPath();
780 else
781 filepath = legacy_schematic.GetFullPath();
782 }
783 else if( playerType == FRAME_PCB_EDITOR )
784 {
785 wxFileName kicad_board( m_frame->PcbFileName() );
786 wxFileName legacy_board( m_frame->PcbLegacyFileName() );
787
788 if( !legacy_board.FileExists() || kicad_board.FileExists() )
789 filepath = kicad_board.GetFullPath();
790 else
791 filepath = legacy_board.GetFullPath();
792 }
793
794 if( !filepath.IsEmpty() )
795 {
796 if( !player->OpenProjectFiles( std::vector<wxString>( 1, filepath ) ) )
797 {
798 player->Destroy();
799 return -1;
800 }
801 }
802
803 wxBusyCursor busy;
804 player->Show( true );
805 }
806
807 // Needed on Windows, other platforms do not use it, but it creates no issue
808 if( player->IsIconized() )
809 player->Iconize( false );
810
811 player->Raise();
812
813 // Raising the window does not set the focus on Linux. This should work on
814 // any platform.
815 if( wxWindow::FindFocus() != player )
816 player->SetFocus();
817
818 return 0;
819}
820
821
822class TERMINATE_HANDLER : public wxProcess
823{
824public:
825 TERMINATE_HANDLER( const wxString& appName )
826 { }
827
828 void OnTerminate( int pid, int status ) override
829 {
830 delete this;
831 }
832};
833
834
836{
837 wxString execFile;
838 wxString param;
839
841 execFile = GERBVIEW_EXE;
843 execFile = BITMAPCONVERTER_EXE;
845 execFile = PCB_CALCULATOR_EXE;
847 execFile = PL_EDITOR_EXE;
849 execFile = Pgm().GetTextEditor();
851 execFile = EESCHEMA_EXE;
853 execFile = PCBNEW_EXE;
854 else
855 wxFAIL_MSG( "Execute(): unexpected request" );
856
857 if( execFile.IsEmpty() )
858 return 0;
859
860 if( aEvent.Parameter<wxString*>() )
861 param = *aEvent.Parameter<wxString*>();
863 param = m_frame->Prj().GetProjectPath();
864
865 TERMINATE_HANDLER* callback = new TERMINATE_HANDLER( execFile );
866
867 long pid = ExecuteFile( execFile, param, callback );
868
869 if( pid > 0 )
870 {
871#ifdef __WXMAC__
872 // This non-parameterized use of wxExecute is fine because execFile is not derived
873 // from user input.
874 wxExecute( "osascript -e 'activate application \"" + execFile + "\"'" );
875#endif
876 }
877 else
878 {
879 delete callback;
880 }
881
882 return 0;
883}
884
885
887{
890 {
891 // policy disables the plugin manager
892 return 0;
893 }
894
895 // For some reason, after a click or a double click the bitmap button calling
896 // PCM keeps the focus althougt the focus was not set to this button.
897 // This hack force removing the focus from this button
898 m_frame->SetFocus();
899 wxSafeYield();
900
901 DIALOG_PCM pcm( m_frame, m_frame->GetPcm() );
902 pcm.ShowModal();
903
904 const std::unordered_set<PCM_PACKAGE_TYPE>& changed = pcm.GetChangedPackageTypes();
905
906 if( changed.count( PCM_PACKAGE_TYPE::PT_PLUGIN ) )
907 {
908 std::string payload = "";
910 }
911
912 KICAD_SETTINGS* settings = Pgm().GetSettingsManager().GetAppSettings<KICAD_SETTINGS>();
913
914 if( changed.count( PCM_PACKAGE_TYPE::PT_LIBRARY )
915 && ( settings->m_PcmLibAutoAdd || settings->m_PcmLibAutoRemove ) )
916 {
917 // Reset project tables
919 Prj().SetElem( PROJECT::ELEM_FPTBL, nullptr );
920
921 KIWAY& kiway = m_frame->Kiway();
922
923 // Reset state containing global lib tables
924 KIFACE* kiface;
925
926 if( ( kiface = kiway.KiFACE( KIWAY::FACE_SCH, false ) ) )
927 kiface->Reset();
928
929 if( ( kiface = kiway.KiFACE( KIWAY::FACE_PCB, false ) ) )
930 kiface->Reset();
931
932 // Reload lib tables
933 std::string payload = "";
934
937 kiway.ExpressMail( FRAME_CVPCB, MAIL_RELOAD_LIB, payload );
940 }
941
942 if( changed.count( PCM_PACKAGE_TYPE::PT_COLORTHEME ) )
943 Pgm().GetSettingsManager().ReloadColorSettings();
944
945 return 0;
946}
947
948
950{
960
963
973
976
978}
static TOOL_ACTION zoomRedraw
Definition: actions.h:93
static TOOL_ACTION saveAs
Definition: actions.h:52
static TOOL_ACTION updateMenu
Definition: actions.h:172
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
const std::unordered_set< PCM_PACKAGE_TYPE > & GetChangedPackageTypes() const
Definition: dialog_pcm.h:77
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:76
int ShowModal() override
Definition: confirm.cpp:120
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
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:279
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:286
@ FACE_PL_EDITOR
Definition: kiway.h:290
@ FACE_PCB
pcbnew DSO
Definition: kiway.h:287
@ FACE_GERBVIEW
Definition: kiway.h:289
virtual void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string &aPayload, wxWindow *aSource=nullptr)
Send aPayload to aDestination from aSource.
Definition: kiway.cpp:491
‍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:155
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:149
virtual void SetElem(ELEM_T aIndex, _ELEM *aElem)
Definition: project.cpp:294
@ ELEM_SYMBOL_LIB_TABLE
Definition: project.h:211
@ ELEM_FPTBL
Definition: project.h:206
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:81
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:380
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:352
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:325
This file is part of the common library.
return & kiface
Definition: cvpcb.cpp:112
#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_SYMBOL_EDITOR
Definition: frame_type.h:35
@ FRAME_FOOTPRINT_VIEWER
Definition: frame_type.h:42
@ FRAME_SCH_VIEWER
Definition: frame_type.h:36
@ FRAME_SCH
Definition: frame_type.h:34
@ FRAME_FOOTPRINT_EDITOR
Definition: frame_type.h:41
@ FRAME_CVPCB
Definition: frame_type.h:48
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:573
This file contains miscellaneous commonly used macros and functions.
@ MAIL_RELOAD_PLUGINS
Definition: mail_type.h:56
@ MAIL_RELOAD_LIB
Definition: mail_type.h:55
STATE GetPolicyState(const wxString &aKey)
Definition: gtk/policy.cpp:25
@ PT_COLORTHEME
Definition: pcm_data.h:45
@ PT_PLUGIN
Definition: pcm_data.h:43
@ PT_LIBRARY
Definition: pcm_data.h:44
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:216
Definition of file extensions used in Kicad.