KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 The 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 <env_vars.h>
23#include <executable_names.h>
24#include <pgm_base.h>
25#include <pgm_kicad.h>
26#include <policy_keys.h>
27#include <kiway.h>
28#include <kicad_manager_frame.h>
29#include <kiplatform/policy.h>
30#include <kiplatform/secrets.h>
31#include <confirm.h>
32#include <kidialog.h>
37#include <tool/selection.h>
38#include <tool/tool_event.h>
39#include <tool/tool_manager.h>
40#include <tool/common_control.h>
47#include <gestfich.h>
48#include <paths.h>
49#include <wx/dir.h>
50#include <wx/filedlg.h>
52#include "dialog_pcm.h"
54#include <project_tree_pane.h>
55#include <project_tree.h>
56#include <launch_ext.h>
57
59
61 TOOL_INTERACTIVE( "kicad.Control" ),
62 m_frame( nullptr ),
63 m_inShowPlayer( false )
64{
65}
66
67
69{
70 m_frame = getEditFrame<KICAD_MANAGER_FRAME>();
71}
72
73
74wxFileName KICAD_MANAGER_CONTROL::newProjectDirectory( wxString* aFileName, bool isRepo )
75{
76 wxString default_filename = aFileName ? *aFileName : wxString();
77
78 wxString default_dir = m_frame->GetMruPath();
79 wxFileDialog dlg( m_frame, _( "Create New Project" ), default_dir, default_filename,
80 ( isRepo ? wxString( "" ) : FILEEXT::ProjectFileWildcard() ),
81 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
82
83 dlg.AddShortcut( PATHS::GetDefaultUserProjectsPath() );
84
85 // Add a "Create a new directory" checkbox
86 FILEDLG_NEW_PROJECT newProjectHook;
87 dlg.SetCustomizeHook( newProjectHook );
88
89 if( dlg.ShowModal() == wxID_CANCEL )
90 return wxFileName();
91
92 wxFileName pro( dlg.GetPath() );
93
94 // wxFileName automatically extracts an extension. But if it isn't
95 // a .pro extension, we should keep it as part of the filename
96 if( !pro.GetExt().IsEmpty() && pro.GetExt().ToStdString() != FILEEXT::ProjectFileExtension )
97 pro.SetName( pro.GetName() + wxT( "." ) + pro.GetExt() );
98
99 pro.SetExt( FILEEXT::ProjectFileExtension ); // enforce extension
100
101 if( !pro.IsAbsolute() )
102 pro.MakeAbsolute();
103
104 // Append a new directory with the same name of the project file.
105 bool createNewDir = false;
106
107 createNewDir = newProjectHook.GetCreateNewDir();
108
109 if( createNewDir )
110 pro.AppendDir( pro.GetName() );
111
112 // Check if the project directory is empty if it already exists.
113 wxDir directory( pro.GetPath() );
114
115 if( !pro.DirExists() )
116 {
117 if( !pro.Mkdir() )
118 {
119 wxString msg;
120 msg.Printf( _( "Folder '%s' could not be created.\n\n"
121 "Make sure you have write permissions and try again." ),
122 pro.GetPath() );
124 return wxFileName();
125 }
126 }
127 else if( directory.HasFiles() )
128 {
129 wxString msg = _( "The selected folder is not empty. It is recommended that you "
130 "create projects in their own empty folder.\n\n"
131 "Do you want to continue?" );
132
133 if( !IsOK( m_frame, msg ) )
134 return wxFileName();
135 }
136
137 return pro;
138}
139
140
142{
143 wxFileName pro = newProjectDirectory();
144
145 if( !pro.IsOk() )
146 return -1;
147
149 m_frame->LoadProject( pro );
150
151 return 0;
152}
153
154
156{
157 DIALOG_GIT_REPOSITORY dlg( m_frame, nullptr );
158
159 dlg.SetTitle( _( "Clone Project from Git Repository" ) );
160
161 int ret = dlg.ShowModal();
162
163 if( ret != wxID_OK )
164 return -1;
165
166 wxString project_name = dlg.GetRepoName();
167 wxFileName pro = newProjectDirectory( &project_name, true );
168
169 if( !pro.IsOk() )
170 return -1;
171
172 PROJECT_TREE_PANE *pane = static_cast<PROJECT_TREE_PANE*>( m_frame->GetToolCanvas() );
173
174
175 GIT_CLONE_HANDLER cloneHandler( pane->m_TreeProject->GitCommon() );
176
177 cloneHandler.SetRemote( dlg.GetFullURL() );
178 cloneHandler.SetClonePath( pro.GetPath() );
179 cloneHandler.SetUsername( dlg.GetUsername() );
180 cloneHandler.SetPassword( dlg.GetPassword() );
181 cloneHandler.SetSSHKey( dlg.GetRepoSSHPath() );
182
183 cloneHandler.SetProgressReporter( std::make_unique<WX_PROGRESS_REPORTER>( m_frame, _( "Clone Repository" ), 1,
184 PR_NO_ABORT ) );
185
186 if( !cloneHandler.PerformClone() )
187 {
188 DisplayErrorMessage( m_frame, cloneHandler.GetErrorString() );
189 return -1;
190 }
191
192 std::vector<wxString> projects = cloneHandler.GetProjectDirs();
193
194 if( projects.empty() )
195 {
196 DisplayErrorMessage( m_frame, _( "No project files were found in the repository." ) );
197 return -1;
198 }
199
200 // Currently, we pick the first project file we find in the repository.
201 // TODO: Look into spare checkout to allow the user to pick a partial repository
202 wxString dest = pro.GetPath() + wxFileName::GetPathSeparator() + projects.front();
203 m_frame->LoadProject( dest );
204
208
212 Prj().GetLocalSettings().m_GitRepoType = "https";
213 else
214 Prj().GetLocalSettings().m_GitRepoType = "local";
215
216 return 0;
217}
218
219
221{
222 wxString default_dir = wxFileName( Prj().GetProjectFullName() ).GetPathWithSep();
223 wxFileDialog dlg( m_frame, _( "Create New Jobset" ), default_dir, wxEmptyString, FILEEXT::JobsetFileWildcard(),
224 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
225
226 if( dlg.ShowModal() == wxID_CANCEL )
227 return -1;
228
229 wxFileName jobsetFn( dlg.GetPath() );
230
231 m_frame->OpenJobsFile( jobsetFn.GetFullPath(), true );
232
233 return 0;
234}
235
236
238{
239 KICAD_SETTINGS* settings = GetAppSettings<KICAD_SETTINGS>( "kicad" );
240 std::map<wxString, wxFileName> titleDirMap;
241 wxFileName templatePath;
242
243 // KiCad system template path.
244 std::optional<wxString> v = ENV_VAR::GetVersionedEnvVarValue( Pgm().GetLocalEnvVariables(),
245 wxT( "TEMPLATE_DIR" ) );
246
247 if( v && !v->IsEmpty() )
248 {
249 templatePath.AssignDir( *v );
250 titleDirMap.emplace( _( "System Templates" ), templatePath );
251 }
252
253 // User template path.
254 ENV_VAR_MAP_CITER it = Pgm().GetLocalEnvVariables().find( "KICAD_USER_TEMPLATE_DIR" );
255
256 if( it != Pgm().GetLocalEnvVariables().end() && it->second.GetValue() != wxEmptyString )
257 {
258 templatePath.AssignDir( it->second.GetValue() );
259 titleDirMap.emplace( _( "User Templates" ), templatePath );
260 }
261
263 titleDirMap );
264
265 // Show the project template selector dialog
266 int result = ps.ShowModal();
267
268 settings->m_TemplateWindowPos = ps.GetPosition();
269 settings->m_TemplateWindowSize = ps.GetSize();
270
271 if( result != wxID_OK )
272 return -1;
273
274 if( !ps.GetSelectedTemplate() )
275 {
276 wxMessageBox( _( "No project template was selected. Cannot generate new project." ), _( "Error" ),
277 wxOK | wxICON_ERROR, m_frame );
278
279 return -1;
280 }
281
282 // Get project destination folder and project file name.
283 wxString default_dir = wxFileName( Prj().GetProjectFullName() ).GetPathWithSep();
284 wxString title = _( "New Project Folder" );
285 wxFileDialog dlg( m_frame, title, default_dir, wxEmptyString, FILEEXT::ProjectFileWildcard(),
286 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
287
288 dlg.AddShortcut( PATHS::GetDefaultUserProjectsPath() );
289
290 // Add a "Create a new directory" checkbox
291 FILEDLG_NEW_PROJECT newProjectHook;
292 dlg.SetCustomizeHook( newProjectHook );
293
294 if( dlg.ShowModal() == wxID_CANCEL )
295 return -1;
296
297 wxFileName fn( dlg.GetPath() );
298
299 // wxFileName automatically extracts an extension. But if it isn't a .kicad_pro extension,
300 // we should keep it as part of the filename
301 if( !fn.GetExt().IsEmpty() && fn.GetExt().ToStdString() != FILEEXT::ProjectFileExtension )
302 fn.SetName( fn.GetName() + wxT( "." ) + fn.GetExt() );
303
305
306 if( !fn.IsAbsolute() )
307 fn.MakeAbsolute();
308
309 bool createNewDir = false;
310 createNewDir = newProjectHook.GetCreateNewDir();
311
312 // Append a new directory with the same name of the project file.
313 if( createNewDir )
314 fn.AppendDir( fn.GetName() );
315
316 // Check if the project directory is empty if it already exists.
317 if( !fn.DirExists() && !fn.Mkdir() )
318 {
319 DisplayErrorMessage( m_frame, wxString::Format( _( "Folder '%s' could not be created.\n\n"
320 "Make sure you have write permissions and try again." ),
321 fn.GetPath() ) );
322 return -1;
323 }
324
325 if( !fn.IsDirWritable() )
326 {
327 DisplayErrorMessage( m_frame, wxString::Format( _( "Insufficient permissions to write to folder '%s'." ),
328 fn.GetPath() ) );
329 return -1;
330 }
331
332 // Make sure we are not overwriting anything in the destination folder.
333 std::vector< wxFileName > destFiles;
334
335 if( ps.GetSelectedTemplate()->GetDestinationFiles( fn, destFiles ) )
336 {
337 std::vector<wxFileName> overwrittenFiles;
338
339 for( const wxFileName& file : destFiles )
340 {
341 if( file.FileExists() )
342 overwrittenFiles.push_back( file );
343 }
344
345 if( !overwrittenFiles.empty() )
346 {
347 wxString extendedMsg = _( "Overwriting files:" ) + "\n";
348
349 for( const wxFileName& file : overwrittenFiles )
350 extendedMsg += "\n" + file.GetFullName();
351
352 KIDIALOG msgDlg( m_frame, _( "Similar files already exist in the destination folder." ),
353 _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
354 msgDlg.SetExtendedMessage( extendedMsg );
355 msgDlg.SetOKLabel( _( "Overwrite" ) );
356 msgDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
357
358 if( msgDlg.ShowModal() == wxID_CANCEL )
359 return -1;
360 }
361 }
362
363 wxString errorMsg;
364
365 // The selected template widget contains the template we're attempting to use to
366 // create a project
367 if( !ps.GetSelectedTemplate()->CreateProject( fn, &errorMsg ) )
368 {
369 DisplayErrorMessage( m_frame, _( "A problem occurred creating new project from template." ), errorMsg );
370 return -1;
371 }
372
373 m_frame->CreateNewProject( fn.GetFullPath() );
374 m_frame->LoadProject( fn );
375 return 0;
376}
377
378
379int KICAD_MANAGER_CONTROL::openProject( const wxString& aDefaultDir )
380{
381 wxString wildcard = FILEEXT::AllProjectFilesWildcard()
384
385 wxFileDialog dlg( m_frame, _( "Open Existing Project" ), aDefaultDir, wxEmptyString, wildcard,
386 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
387
388 dlg.AddShortcut( PATHS::GetDefaultUserProjectsPath() );
389
390 if( dlg.ShowModal() == wxID_CANCEL )
391 return -1;
392
393 wxFileName pro( dlg.GetPath() );
394
395 if( !pro.IsAbsolute() )
396 pro.MakeAbsolute();
397
398 // You'd think wxFD_FILE_MUST_EXIST and the wild-cards would enforce these. Sentry
399 // indicates otherwise (at least on MSW).
400 if( !pro.Exists() || ( pro.GetExt() != FILEEXT::ProjectFileExtension
401 && pro.GetExt() != FILEEXT::LegacyProjectFileExtension ) )
402 {
403 return -1;
404 }
405
406 m_frame->LoadProject( pro );
407
408 return 0;
409}
410
411
413{
415}
416
417
419{
420 return openProject( m_frame->GetMruPath() );
421}
422
423
425{
426 wxString default_dir = wxFileName( Prj().GetProjectFullName() ).GetPathWithSep();
427 wxFileDialog dlg( m_frame, _( "Open Jobset" ), default_dir, wxEmptyString, FILEEXT::JobsetFileWildcard(),
428 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
429
430 if( dlg.ShowModal() == wxID_CANCEL )
431 return -1;
432
433 wxFileName jobsetFn( dlg.GetPath() );
434
435 m_frame->OpenJobsFile( jobsetFn.GetFullPath(), true );
436
437 return 0;
438}
439
440
442{
443 m_frame->CloseProject( true );
444 return 0;
445}
446
447
449{
450 if( aEvent.Parameter<wxString*>() )
451 m_frame->LoadProject( wxFileName( *aEvent.Parameter<wxString*>() ) );
452 return 0;
453}
454
455
457{
458 wxFileName fileName = m_frame->GetProjectFileName();
459
460 fileName.SetExt( FILEEXT::ArchiveFileExtension );
461
462 wxFileDialog dlg( m_frame, _( "Archive Project Files" ), fileName.GetPath(), fileName.GetFullName(),
463 FILEEXT::ZipFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
464
465 if( dlg.ShowModal() == wxID_CANCEL )
466 return 0;
467
468 wxFileName zipFile = dlg.GetPath();
469
470 wxString currdirname = fileName.GetPathWithSep();
471 wxDir dir( currdirname );
472
473 if( !dir.IsOpened() ) // wxWidgets display a error message on issue.
474 return 0;
475
476 STATUSBAR_REPORTER reporter( m_frame->GetStatusBar(), 1 );
477 PROJECT_ARCHIVER archiver;
478
479 archiver.Archive( currdirname, zipFile.GetFullPath(), reporter, true, true );
480 return 0;
481}
482
483
485{
487 return 0;
488}
489
490
492{
493 // Open project directory in host OS's file explorer
494 LaunchExternal( Prj().GetProjectPath() );
495 return 0;
496}
497
498
500{
501 if( aEvent.Parameter<wxString*>() )
502 wxExecute( *aEvent.Parameter<wxString*>(), wxEXEC_ASYNC );
503 return 0;
504}
505
506class SAVE_AS_TRAVERSER : public wxDirTraverser
507{
508public:
510 const wxString& aSrcProjectDirPath,
511 const wxString& aSrcProjectName,
512 const wxString& aNewProjectDirPath,
513 const wxString& aNewProjectName ) :
514 m_frame( aFrame ),
515 m_projectDirPath( aSrcProjectDirPath ),
516 m_projectName( aSrcProjectName ),
517 m_newProjectDirPath( aNewProjectDirPath ),
518 m_newProjectName( aNewProjectName )
519 {
520 }
521
522 virtual wxDirTraverseResult OnFile( const wxString& aSrcFilePath ) override
523 {
524 // Recursion guard for a Save As to a location inside the source project.
525 if( aSrcFilePath.StartsWith( m_newProjectDirPath + wxFileName::GetPathSeparator() ) )
526 return wxDIR_CONTINUE;
527
528 wxFileName destFile( aSrcFilePath );
529 wxString ext = destFile.GetExt();
530 bool atRoot = destFile.GetPath() == m_projectDirPath;
531
535 {
536 wxString destPath = destFile.GetPath();
537
538 if( destPath.StartsWith( m_projectDirPath ) )
539 {
540 destPath.Replace( m_projectDirPath, m_newProjectDirPath, false );
541 destFile.SetPath( destPath );
542 }
543
544 if( destFile.GetName() == m_projectName )
545 {
546 destFile.SetName( m_newProjectName );
547
548 if( atRoot && ext != FILEEXT::ProjectLocalSettingsFileExtension )
549 m_newProjectFile = destFile;
550 }
551
553 {
554 // All paths in the settings file are relative so we can just do a straight copy
555 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), m_errors );
556 }
557 else if( ext == FILEEXT::ProjectFileExtension )
558 {
559 PROJECT_FILE projectFile( aSrcFilePath );
560 projectFile.LoadFromFile();
561 projectFile.SaveAs( destFile.GetPath(), destFile.GetName() );
562 }
564 {
565 PROJECT_LOCAL_SETTINGS projectLocalSettings( nullptr, aSrcFilePath );
566 projectLocalSettings.LoadFromFile();
567 projectLocalSettings.SaveAs( destFile.GetPath(), destFile.GetName() );
568 }
569 }
579 || destFile.GetName() == FILEEXT::SymbolLibraryTableFileName )
580 {
583 m_newProjectName, aSrcFilePath, m_errors );
584 }
585 else if( ext == FILEEXT::KiCadPcbFileExtension
591 || destFile.GetName() == FILEEXT::FootprintLibraryTableFileName )
592 {
595 m_newProjectName, aSrcFilePath, m_errors );
596 }
597 else if( ext == FILEEXT::DrawingSheetFileExtension )
598 {
601 m_newProjectName, aSrcFilePath, m_errors );
602 }
603 else if( ext == FILEEXT::GerberJobFileExtension
606 {
609 m_newProjectName, aSrcFilePath, m_errors );
610 }
611 else if( destFile.GetName().StartsWith( FILEEXT::LockFilePrefix )
613 {
614 // Ignore lock files
615 }
616 else
617 {
618 // Everything we don't recognize just gets a straight copy.
619 wxString destPath = destFile.GetPathWithSep();
620 wxString destName = destFile.GetName();
621 wxUniChar pathSep = wxFileName::GetPathSeparator();
622
623 wxString srcProjectFootprintLib = pathSep + m_projectName + ".pretty" + pathSep;
624 wxString newProjectFootprintLib = pathSep + m_newProjectName + ".pretty" + pathSep;
625
626 if( destPath.StartsWith( m_projectDirPath ) )
627 destPath.Replace( m_projectDirPath, m_newProjectDirPath, false );
628
629 destPath.Replace( srcProjectFootprintLib, newProjectFootprintLib, true );
630
631 if( destName == m_projectName && ext != wxT( "zip" ) /* don't rename archives */ )
632 destFile.SetName( m_newProjectName );
633
634 destFile.SetPath( destPath );
635
636 KiCopyFile( aSrcFilePath, destFile.GetFullPath(), m_errors );
637 }
638
639 return wxDIR_CONTINUE;
640 }
641
642 virtual wxDirTraverseResult OnDir( const wxString& aSrcDirPath ) override
643 {
644 // Recursion guard for a Save As to a location inside the source project.
645 if( aSrcDirPath.StartsWith( m_newProjectDirPath ) )
646 return wxDIR_CONTINUE;
647
648 wxFileName destDir( aSrcDirPath );
649 wxString destDirPath = destDir.GetPathWithSep();
650 wxUniChar pathSep = wxFileName::GetPathSeparator();
651
652 if( destDirPath.StartsWith( m_projectDirPath + pathSep )
653 || destDirPath.StartsWith( m_projectDirPath + PROJECT_BACKUPS_DIR_SUFFIX ) )
654 {
655 destDirPath.Replace( m_projectDirPath, m_newProjectDirPath, false );
656 destDir.SetPath( destDirPath );
657 }
658
659 if( destDir.GetName() == m_projectName )
660 {
661 if( destDir.GetExt() == "pretty" )
662 destDir.SetName( m_newProjectName );
663#if 0
664 // WAYNE STAMBAUGH TODO:
665 // If we end up with a symbol equivalent to ".pretty" we'll want to handle it here....
666 else if( destDir.GetExt() == "sym_lib_dir_extension" )
667 destDir.SetName( m_newProjectName );
668#endif
669 }
670
671 if( !wxMkdir( destDir.GetFullPath() ) )
672 {
673 wxString msg;
674
675 if( !m_errors.empty() )
676 m_errors += "\n";
677
678 msg.Printf( _( "Cannot copy folder '%s'." ), destDir.GetFullPath() );
679 m_errors += msg;
680 }
681
682 return wxDIR_CONTINUE;
683 }
684
685 wxString GetErrors() { return m_errors; }
686
687 wxFileName GetNewProjectFile() { return m_newProjectFile; }
688
689private:
691
696
698 wxString m_errors;
699};
700
701
703{
704 wxString msg;
705
706 wxFileName currentProjectFile( Prj().GetProjectFullName() );
707 wxString currentProjectDirPath = currentProjectFile.GetPath();
708 wxString currentProjectName = Prj().GetProjectName();
709
710 wxString default_dir = m_frame->GetMruPath();
711
712 Prj().GetProjectFile().SaveToFile( currentProjectDirPath );
713 Prj().GetLocalSettings().SaveToFile( currentProjectDirPath );
714
715 if( default_dir == currentProjectDirPath
716 || default_dir == currentProjectDirPath + wxFileName::GetPathSeparator() )
717 {
718 // Don't start within the current project
719 wxFileName default_dir_fn( default_dir );
720 default_dir_fn.RemoveLastDir();
721 default_dir = default_dir_fn.GetPath();
722 }
723
724 wxFileDialog dlg( m_frame, _( "Save Project To" ), default_dir, wxEmptyString, wxEmptyString, wxFD_SAVE );
725
726 dlg.AddShortcut( PATHS::GetDefaultUserProjectsPath() );
727
728 if( dlg.ShowModal() == wxID_CANCEL )
729 return -1;
730
731 wxFileName newProjectDir( dlg.GetPath(), wxEmptyString );
732
733 if( !newProjectDir.IsAbsolute() )
734 newProjectDir.MakeAbsolute();
735
736 if( wxDirExists( newProjectDir.GetFullPath() ) )
737 {
738 msg.Printf( _( "'%s' already exists." ), newProjectDir.GetFullPath() );
740 return -1;
741 }
742
743 if( !wxMkdir( newProjectDir.GetFullPath() ) )
744 {
745 DisplayErrorMessage( m_frame, wxString::Format( _( "Folder '%s' could not be created.\n\n"
746 "Please make sure you have sufficient permissions." ),
747 newProjectDir.GetPath() ) );
748 return -1;
749 }
750
751 if( !newProjectDir.IsDirWritable() )
752 {
753 DisplayErrorMessage( m_frame, wxString::Format( _( "Insufficient permissions to write to folder '%s'." ),
754 newProjectDir.GetFullPath() ) );
755 return -1;
756 }
757
758 const wxString& newProjectDirPath = newProjectDir.GetFullPath();
759 const wxString& newProjectName = newProjectDir.GetDirs().Last();
760 wxDir currentProjectDir( currentProjectDirPath );
761
762 SAVE_AS_TRAVERSER traverser( m_frame, currentProjectDirPath, currentProjectName, newProjectDirPath,
763 newProjectName );
764
765 currentProjectDir.Traverse( traverser );
766
767 if( !traverser.GetErrors().empty() )
768 DisplayErrorMessage( m_frame, traverser.GetErrors() );
769
770 if( !traverser.GetNewProjectFile().FileExists() )
772
773 m_frame->LoadProject( traverser.GetNewProjectFile() );
774
775 return 0;
776}
777
778
780{
782 return 0;
783}
784
785
787{
788 ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
789 CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
790 SELECTION dummySel;
791
792 if( conditionalMenu )
793 conditionalMenu->Evaluate( dummySel );
794
795 if( actionMenu )
796 actionMenu->UpdateAll();
797
798 return 0;
799}
800
801
803{
804 FRAME_T playerType = aEvent.Parameter<FRAME_T>();
805 KIWAY_PLAYER* player;
806
807 if( playerType == FRAME_SCH && !m_frame->IsProjectActive() )
808 {
809 DisplayInfoMessage( m_frame, _( "Create (or open) a project to edit a schematic." ), wxEmptyString );
810 return -1;
811 }
812 else if( playerType == FRAME_PCB_EDITOR && !m_frame->IsProjectActive() )
813 {
814 DisplayInfoMessage( m_frame, _( "Create (or open) a project to edit a pcb." ), wxEmptyString );
815 return -1;
816 }
817
818 if( m_inShowPlayer )
819 return -1;
820
822
823 try
824 {
825 player = m_frame->Kiway().Player( playerType, true );
826 }
827 catch( const IO_ERROR& err )
828 {
829 wxLogError( _( "Application failed to load:\n" ) + err.What() );
830 return -1;
831 }
832
833 if ( !player )
834 {
835 wxLogError( _( "Application cannot start." ) );
836 return -1;
837 }
838
839 if( !player->IsVisible() ) // A hidden frame might not have the document loaded.
840 {
841 wxString filepath;
842
843 if( playerType == FRAME_SCH )
844 {
845 wxFileName kicad_schematic( m_frame->SchFileName() );
846 wxFileName legacy_schematic( m_frame->SchLegacyFileName() );
847
848 if( !legacy_schematic.FileExists() || kicad_schematic.FileExists() )
849 filepath = kicad_schematic.GetFullPath();
850 else
851 filepath = legacy_schematic.GetFullPath();
852 }
853 else if( playerType == FRAME_PCB_EDITOR )
854 {
855 wxFileName kicad_board( m_frame->PcbFileName() );
856 wxFileName legacy_board( m_frame->PcbLegacyFileName() );
857
858 if( !legacy_board.FileExists() || kicad_board.FileExists() )
859 filepath = kicad_board.GetFullPath();
860 else
861 filepath = legacy_board.GetFullPath();
862 }
863
864 if( !filepath.IsEmpty() )
865 {
866 std::vector<wxString> file_list{ filepath };
867
868 if( !player->OpenProjectFiles( file_list ) )
869 {
870 player->Destroy();
871 return -1;
872 }
873 }
874
875 wxBusyCursor busy;
876 player->Show( true );
877 }
878
879 // Needed on Windows, other platforms do not use it, but it creates no issue
880 if( player->IsIconized() )
881 player->Iconize( false );
882
883 player->Raise();
884
885 // Raising the window does not set the focus on Linux. This should work on
886 // any platform.
887 if( wxWindow::FindFocus() != player )
888 player->SetFocus();
889
890 // Save window state to disk now. Don't wait around for a crash.
891 if( Pgm().GetCommonSettings()->m_Session.remember_open_files
892 && !player->GetCurrentFileName().IsEmpty()
893 && Prj().GetLocalSettings().ShouldAutoSave() )
894 {
895 wxFileName rfn( player->GetCurrentFileName() );
896 rfn.MakeRelativeTo( Prj().GetProjectPath() );
897
898 WINDOW_SETTINGS windowSettings;
899 player->SaveWindowSettings( &windowSettings );
900
901 Prj().GetLocalSettings().SaveFileState( rfn.GetFullPath(), &windowSettings, true );
902 Prj().GetLocalSettings().SaveToFile( Prj().GetProjectPath() );
903 }
904
905 return 0;
906}
907
908
910{
911 wxString execFile;
912 wxString param;
913
915 execFile = GERBVIEW_EXE;
917 execFile = BITMAPCONVERTER_EXE;
919 execFile = PCB_CALCULATOR_EXE;
921 execFile = PL_EDITOR_EXE;
923 execFile = Pgm().GetTextEditor();
925 execFile = EESCHEMA_EXE;
927 execFile = PCBNEW_EXE;
928 else
929 wxFAIL_MSG( "Execute(): unexpected request" );
930
931 if( execFile.IsEmpty() )
932 return 0;
933
934 if( aEvent.Parameter<wxString*>() )
935 param = *aEvent.Parameter<wxString*>();
937 param = m_frame->Prj().GetProjectPath();
938
939 COMMON_CONTROL* commonControl = m_toolMgr->GetTool<COMMON_CONTROL>();
940 return commonControl->Execute( execFile, param );
941}
942
943
945{
947 {
948 // policy disables the plugin manager
949 return 0;
950 }
951
952 // For some reason, after a click or a double click the bitmap button calling
953 // PCM keeps the focus althougt the focus was not set to this button.
954 // This hack force removing the focus from this button
955 m_frame->SetFocus();
956 wxSafeYield();
957
958 if( !m_frame->GetPcm() )
960
961 DIALOG_PCM pcm( m_frame, m_frame->GetPcm() );
962 pcm.ShowModal();
963
964 const std::unordered_set<PCM_PACKAGE_TYPE>& changed = pcm.GetChangedPackageTypes();
965
966 if( changed.count( PCM_PACKAGE_TYPE::PT_PLUGIN ) || changed.count( PCM_PACKAGE_TYPE::PT_FAB ) )
967 {
968 std::string payload = "";
970 }
971
972 KICAD_SETTINGS* settings = GetAppSettings<KICAD_SETTINGS>( "kicad" );
973
974 if( changed.count( PCM_PACKAGE_TYPE::PT_LIBRARY )
975 && ( settings->m_PcmLibAutoAdd || settings->m_PcmLibAutoRemove ) )
976 {
977 // Reset project tables
979 Prj().SetElem( PROJECT::ELEM::FPTBL, nullptr );
981
982 KIWAY& kiway = m_frame->Kiway();
983
984 // Reset state containing global lib tables
985 if( KIFACE* kiface = kiway.KiFACE( KIWAY::FACE_SCH, false ) )
986 kiface->Reset();
987
988 if( KIFACE* kiface = kiway.KiFACE( KIWAY::FACE_PCB, false ) )
989 kiface->Reset();
990
991 // Reload lib tables
992 std::string payload = "";
993
996 kiway.ExpressMail( FRAME_CVPCB, MAIL_RELOAD_LIB, payload );
999 }
1000
1001 if( changed.count( PCM_PACKAGE_TYPE::PT_COLORTHEME ) )
1003
1004 return 0;
1005}
1006
1007
1009{
1021
1025
1028
1038
1041
1043}
static TOOL_ACTION zoomRedraw
Definition: actions.h:131
static TOOL_ACTION saveAs
Definition: actions.h:59
static TOOL_ACTION updateMenu
Definition: actions.h:267
Define the structure of a menu based on ACTIONs.
Definition: action_menu.h:49
void UpdateAll()
Run update handlers for the menu and its submenus.
Handle actions that are shared between different applications.
int Execute(const TOOL_EVENT &aEvent)
const wxString & GetFullURL() const
KIGIT_COMMON::GIT_CONN_TYPE GetRepoType() const
wxString GetRepoSSHPath() const
wxString GetUsername() const
wxString GetRepoName() const
wxString GetPassword() const
Implementing pcm main dialog.
Definition: dialog_pcm.h:38
const std::unordered_set< PCM_PACKAGE_TYPE > & GetChangedPackageTypes() const
Definition: dialog_pcm.h:81
int ShowModal() override
PROJECT_TEMPLATE * GetSelectedTemplate()
wxString GetMruPath() const
bool GetCreateNewDir() const
void SetRemote(const wxString &aRemote)
void SetClonePath(const wxString &aPath)
void SetProgressReporter(std::unique_ptr< WX_PROGRESS_REPORTER > aProgressReporter)
Definition: git_progress.h:40
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
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 unarchiveProject
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 archiveProject
static TOOL_ACTION openProject
static TOOL_ACTION closeProject
static TOOL_ACTION convertImage
static TOOL_ACTION editDrawingSheet
static TOOL_ACTION openProjectDirectory
static TOOL_ACTION openJobsetFile
static TOOL_ACTION newJobsetFile
static TOOL_ACTION editFootprints
static TOOL_ACTION showPluginManager
static TOOL_ACTION showCalculator
static TOOL_ACTION viewGerbers
static TOOL_ACTION newFromRepository
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)
int NewJobsetFile(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 ArchiveProject(const TOOL_EVENT &aEvent)
bool m_inShowPlayer
Re-entrancy guard.
int SaveProjectAs(const TOOL_EVENT &aEvent)
int NewProject(const TOOL_EVENT &aEvent)
int UnarchiveProject(const TOOL_EVENT &aEvent)
int ViewDroppedViewers(const TOOL_EVENT &aEvent)
Imports a non kicad project from a sch/pcb dropped file.
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 OpenJobsetFile(const TOOL_EVENT &aEvent)
wxFileName newProjectDirectory(wxString *aFileName=nullptr, bool isRepo=false)
int NewFromRepository(const TOOL_EVENT &aEvent)
int LoadProject(const TOOL_EVENT &aEvent)
KICAD_MANAGER_FRAME * m_frame
Pointer to the currently used edit/draw frame.
int ExploreProject(const TOOL_EVENT &aEvent)
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()
wxWindow * GetToolCanvas() const override
Canvas access.
const wxString GetProjectFileName() const
const wxString SchFileName()
void OpenJobsFile(const wxFileName &aFileName, bool aCreate=false, bool aResaveProjectPreferences=true)
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()
wxSize m_TemplateWindowSize
wxPoint m_TemplateWindowPos
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: kidialog.h:50
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
Definition: kidialog.cpp:51
int ShowModal() override
Definition: kidialog.cpp:95
virtual void Reset() override
Reloads global state.
Definition: kiface_base.h:55
wxString GetErrorString()
void SetPassword(const wxString &aPassword)
Set the password.
std::vector< wxString > GetProjectDirs()
Get a list of project directories.
void SetUsername(const wxString &aUsername)
Set the username.
void SetSSHKey(const wxString &aSSHKey)
Set the SSH key.
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:55
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Definition: kiway_player.h:65
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:286
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:395
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:293
@ FACE_PL_EDITOR
Definition: kiway.h:297
@ FACE_PCB
pcbnew DSO
Definition: kiway.h:294
@ FACE_GERBVIEW
Definition: kiway.h:296
virtual void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string &aPayload, wxWindow *aSource=nullptr)
Send aPayload to aDestination from aSource.
Definition: kiway.cpp:499
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
Definition: paths.cpp:136
static wxString GetStockDemosPath()
Gets the stock (install) demos path.
Definition: paths.cpp:408
virtual ENV_VAR_MAP & GetLocalEnvVariables() const
Definition: pgm_base.cpp:811
virtual const wxString & GetTextEditor(bool aCanShowFileChooser=true)
Return the path to the preferred text editor application.
Definition: pgm_base.cpp:197
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:125
static bool Archive(const wxString &aSrcDir, const wxString &aDestFile, REPORTER &aReporter, bool aVerbose=true, bool aIncludeExtraFiles=false)
Create an archive of the project.
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:68
bool SaveAs(const wxString &aDirectory, const wxString &aFile)
bool SaveToFile(const wxString &aDirectory="", bool aForce=false) override
Calls Store() and then writes the contents of the JSON document to a file.
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
Calls Store() and then writes the contents of the JSON document to a file.
void SaveFileState(const wxString &aFileName, const WINDOW_SETTINGS *aWindowCfg, bool aOpen)
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.
PROJECT_TREE_PANE Window to display the tree files.
PROJECT_TREE * m_TreeProject
KIGIT_COMMON * GitCommon() const
Definition: project_tree.h:65
virtual void SetElem(PROJECT::ELEM aIndex, _ELEM *aElem)
Definition: project.cpp:362
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:149
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition: project.cpp:161
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition: project.h:210
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:204
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 ReloadColorSettings()
Re-scan the color themes directory, reloading any changes it finds.
A wrapper for reporting to a specific text location in a statusbar.
Definition: reporter.h:295
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:220
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
Generic, UI-independent tool event.
Definition: tool_event.h:168
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:82
T Parameter() const
Return a parameter assigned to the event.
Definition: tool_event.h:465
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:251
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:222
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:194
This file is part of the common library.
#define _(s)
Functions related to environment variables, including help functions.
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:42
@ FRAME_SCH_SYMBOL_EDITOR
Definition: frame_type.h:35
@ FRAME_FOOTPRINT_VIEWER
Definition: frame_type.h:45
@ FRAME_SCH_VIEWER
Definition: frame_type.h:36
@ FRAME_SCH
Definition: frame_type.h:34
@ FRAME_FOOTPRINT_EDITOR
Definition: frame_type.h:43
@ FRAME_CVPCB
Definition: frame_type.h:52
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Definition: gestfich.cpp:290
static const std::string LegacySchematicFileExtension
static const std::string NetlistFileExtension
static const std::string SymbolLibraryTableFileName
static const std::string GerberJobFileExtension
static const std::string LockFileExtension
static const std::string ProjectFileExtension
static const std::string LegacyPcbFileExtension
static const std::string SchematicSymbolFileExtension
static const std::string LegacyProjectFileExtension
static const std::string ProjectLocalSettingsFileExtension
static const std::string KiCadSchematicFileExtension
static const std::string LegacySymbolLibFileExtension
static const std::string LockFilePrefix
static const std::string KiCadSymbolLibFileExtension
static const std::string FootprintLibraryTableFileName
static const std::string DrawingSheetFileExtension
static const std::string BackupFileSuffix
static const std::string LegacyFootprintLibPathExtension
static const std::string LegacySymbolDocumentFileExtension
static const std::string FootprintAssignmentFileExtension
static const std::string DrillFileExtension
static const std::string KiCadFootprintFileExtension
static const std::string ArchiveFileExtension
static const std::string KiCadPcbFileExtension
static wxString ProjectFileWildcard()
static bool IsGerberFileExtension(const wxString &ext)
static wxString JobsetFileWildcard()
static wxString LegacyProjectFileWildcard()
static wxString AllProjectFilesWildcard()
static wxString ZipFileWildcard()
std::map< wxString, ENV_VAR_ITEM >::const_iterator ENV_VAR_MAP_CITER
PROJECT & Prj()
Definition: kicad.cpp:608
This file is part of the common library.
bool LaunchExternal(const wxString &aPath)
Launches the given file or folder in the host OS.
Definition: launch_ext.cpp:25
@ MAIL_RELOAD_PLUGINS
Definition: mail_type.h:58
@ MAIL_RELOAD_LIB
Definition: mail_type.h:57
KICOMMON_API std::optional< wxString > GetVersionedEnvVarValue(const std::map< wxString, ENV_VAR_ITEM > &aMap, const wxString &aBaseName)
Attempt to retrieve the value of a versioned environment variable, such as KICAD8_TEMPLATE_DIR.
Definition: env_vars.cpp:86
PBOOL GetPolicyBool(const wxString &aKey)
Definition: unix/policy.cpp:26
bool StoreSecret(const wxString &aService, const wxString &aKey, const wxString &aSecret)
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:902
see class PGM_BASE
#define POLICY_KEY_PCM
Definition: policy_keys.h:31
#define PROJECT_BACKUPS_DIR_SUFFIX
Project settings path will be <projectname> + this.
Implement a participant in the KIWAY alchemy.
Definition: kiway.h:153
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:218
Store the common settings that are saved and loaded for each window / frame.
Definition: app_settings.h:90
IFACE KIFACE_BASE kiface("pcb_test_frame", KIWAY::FACE_PCB)
VECTOR2I end
Definition of file extensions used in Kicad.
#define PR_NO_ABORT