2019-06-09 14:12:44 +01:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
2019-08-14 09:28:07 +01:00
|
|
|
* Copyright (C) 2019 CERN
|
2023-02-17 15:29:45 -05:00
|
|
|
* Copyright (C) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
2019-06-09 14:12:44 +01:00
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License as published by the
|
|
|
|
* Free Software Foundation, either version 3 of the License, or (at your
|
|
|
|
* option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2019-06-10 15:23:37 +01:00
|
|
|
#include <wildcards_and_files_ext.h>
|
|
|
|
#include <executable_names.h>
|
|
|
|
#include <pgm_base.h>
|
2022-04-12 00:11:16 -04:00
|
|
|
#include <policy_keys.h>
|
2019-06-10 15:23:37 +01:00
|
|
|
#include <kiway.h>
|
2019-06-09 14:12:44 +01:00
|
|
|
#include <kicad_manager_frame.h>
|
2022-04-12 00:11:16 -04:00
|
|
|
#include <kiplatform/policy.h>
|
2019-06-10 15:23:37 +01:00
|
|
|
#include <confirm.h>
|
2022-09-14 22:28:09 +00:00
|
|
|
#include <eda_tools.h>
|
2021-10-30 23:01:19 +01:00
|
|
|
#include <project/project_file.h>
|
2021-11-09 17:24:53 +00:00
|
|
|
#include <project/project_local_settings.h>
|
2021-09-27 13:24:11 +01:00
|
|
|
#include <settings/settings_manager.h>
|
2023-01-18 16:14:31 -08:00
|
|
|
#include <settings/kicad_settings.h>
|
2019-06-09 14:12:44 +01:00
|
|
|
#include <tool/selection.h>
|
|
|
|
#include <tool/tool_event.h>
|
|
|
|
#include <tools/kicad_manager_actions.h>
|
|
|
|
#include <tools/kicad_manager_control.h>
|
|
|
|
#include <dialogs/dialog_template_selector.h>
|
2023-09-14 14:39:42 -07:00
|
|
|
#include <dialogs/git/dialog_git_repository.h>
|
|
|
|
#include <git/git_clone_handler.h>
|
2019-11-10 09:37:39 +01:00
|
|
|
#include <gestfich.h>
|
2021-07-25 21:58:44 -04:00
|
|
|
#include <paths.h>
|
2021-06-03 07:49:49 -04:00
|
|
|
#include <wx/checkbox.h>
|
2020-10-24 10:45:37 -04:00
|
|
|
#include <wx/dir.h>
|
2021-05-01 09:50:29 +02:00
|
|
|
#include <wx/filedlg.h>
|
2020-10-26 03:54:36 -07:00
|
|
|
#include "dialog_pcm.h"
|
2022-09-14 22:28:09 +00:00
|
|
|
#include <macros.h>
|
2023-12-19 17:39:26 +00:00
|
|
|
#include <sch_io/sch_io_mgr.h>
|
|
|
|
#include <pcb_io/pcb_io_mgr.h>
|
2022-09-14 22:28:09 +00:00
|
|
|
#include <import_proj.h>
|
2020-10-26 03:54:36 -07:00
|
|
|
|
2022-06-11 23:03:29 -04:00
|
|
|
#include "widgets/filedlg_new_project.h"
|
2019-06-09 14:12:44 +01:00
|
|
|
|
|
|
|
KICAD_MANAGER_CONTROL::KICAD_MANAGER_CONTROL() :
|
|
|
|
TOOL_INTERACTIVE( "kicad.Control" ),
|
|
|
|
m_frame( nullptr )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KICAD_MANAGER_CONTROL::Reset( RESET_REASON aReason )
|
|
|
|
{
|
|
|
|
m_frame = getEditFrame<KICAD_MANAGER_FRAME>();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-01-19 23:52:37 +00:00
|
|
|
wxFileName KICAD_MANAGER_CONTROL::newProjectDirectory( wxString* aFileName, bool isRepo )
|
2019-06-09 14:12:44 +01:00
|
|
|
{
|
2023-09-14 14:39:42 -07:00
|
|
|
wxString default_filename = aFileName ? *aFileName : wxString();
|
|
|
|
|
2019-06-09 14:12:44 +01:00
|
|
|
wxString default_dir = m_frame->GetMruPath();
|
2023-09-14 14:39:42 -07:00
|
|
|
wxFileDialog dlg( m_frame, _( "Create New Project" ), default_dir, default_filename,
|
2024-01-19 23:52:37 +00:00
|
|
|
( isRepo ? wxString( "" ) : FILEEXT::ProjectFileWildcard() ),
|
|
|
|
wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
|
2019-06-09 14:12:44 +01:00
|
|
|
|
|
|
|
// Add a "Create a new directory" checkbox
|
2022-06-11 23:03:29 -04:00
|
|
|
FILEDLG_NEW_PROJECT newProjectHook;
|
2022-06-11 21:44:46 -04:00
|
|
|
dlg.SetCustomizeHook( newProjectHook );
|
2019-06-09 14:12:44 +01:00
|
|
|
|
|
|
|
if( dlg.ShowModal() == wxID_CANCEL )
|
2023-09-14 14:39:42 -07:00
|
|
|
return wxFileName();
|
2019-06-09 14:12:44 +01:00
|
|
|
|
|
|
|
wxFileName pro( dlg.GetPath() );
|
|
|
|
|
|
|
|
// wxFileName automatically extracts an extension. But if it isn't
|
|
|
|
// a .pro extension, we should keep it as part of the filename
|
2023-12-27 21:10:01 -05:00
|
|
|
if( !pro.GetExt().IsEmpty() && pro.GetExt().ToStdString() != FILEEXT::ProjectFileExtension )
|
2019-06-09 14:12:44 +01:00
|
|
|
pro.SetName( pro.GetName() + wxT( "." ) + pro.GetExt() );
|
|
|
|
|
2023-12-27 21:10:01 -05:00
|
|
|
pro.SetExt( FILEEXT::ProjectFileExtension ); // enforce extension
|
2019-06-09 14:12:44 +01:00
|
|
|
|
|
|
|
if( !pro.IsAbsolute() )
|
|
|
|
pro.MakeAbsolute();
|
|
|
|
|
|
|
|
// Append a new directory with the same name of the project file.
|
2022-06-11 21:44:46 -04:00
|
|
|
bool createNewDir = false;
|
|
|
|
|
|
|
|
createNewDir = newProjectHook.GetCreateNewDir();
|
|
|
|
|
|
|
|
if( createNewDir )
|
2019-06-09 14:12:44 +01:00
|
|
|
pro.AppendDir( pro.GetName() );
|
|
|
|
|
|
|
|
// Check if the project directory is empty if it already exists.
|
|
|
|
wxDir directory( pro.GetPath() );
|
|
|
|
|
|
|
|
if( !pro.DirExists() )
|
|
|
|
{
|
|
|
|
if( !pro.Mkdir() )
|
|
|
|
{
|
|
|
|
wxString msg;
|
2021-06-08 14:40:27 +01:00
|
|
|
msg.Printf( _( "Folder '%s' could not be created.\n\n"
|
|
|
|
"Make sure you have write permissions and try again." ),
|
2019-06-09 14:12:44 +01:00
|
|
|
pro.GetPath() );
|
|
|
|
DisplayErrorMessage( m_frame, msg );
|
2023-09-14 14:39:42 -07:00
|
|
|
return wxFileName();
|
2019-06-09 14:12:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( directory.HasFiles() )
|
|
|
|
{
|
2021-06-08 14:40:27 +01:00
|
|
|
wxString msg = _( "The selected folder is not empty. It is recommended that you "
|
|
|
|
"create projects in their own empty folder.\n\n"
|
|
|
|
"Do you want to continue?" );
|
2019-06-09 14:12:44 +01:00
|
|
|
|
|
|
|
if( !IsOK( m_frame, msg ) )
|
2023-09-14 14:39:42 -07:00
|
|
|
return wxFileName();
|
2019-06-09 14:12:44 +01:00
|
|
|
}
|
|
|
|
|
2023-09-14 14:39:42 -07:00
|
|
|
return pro;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int KICAD_MANAGER_CONTROL::NewProject( const TOOL_EVENT& aEvent )
|
|
|
|
{
|
|
|
|
|
|
|
|
wxFileName pro = newProjectDirectory();
|
|
|
|
|
|
|
|
if( !pro.IsOk() )
|
|
|
|
return -1;
|
|
|
|
|
2019-06-09 14:12:44 +01:00
|
|
|
m_frame->CreateNewProject( pro );
|
|
|
|
m_frame->LoadProject( pro );
|
2019-11-10 09:37:39 +01:00
|
|
|
|
2019-06-09 14:12:44 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-09-14 14:39:42 -07:00
|
|
|
int KICAD_MANAGER_CONTROL::NewFromRepository( const TOOL_EVENT& aEvent )
|
|
|
|
{
|
|
|
|
DIALOG_GIT_REPOSITORY dlg( m_frame, nullptr );
|
|
|
|
|
|
|
|
dlg.SetTitle( _( "Clone Project from Git Repository" ) );
|
|
|
|
|
|
|
|
int ret = dlg.ShowModal();
|
|
|
|
|
|
|
|
if( ret != wxID_OK )
|
|
|
|
return -1;
|
|
|
|
|
2024-01-19 23:52:37 +00:00
|
|
|
wxString project_name = dlg.GetRepoName();
|
|
|
|
wxFileName pro = newProjectDirectory( &project_name, true );
|
2023-09-14 14:39:42 -07:00
|
|
|
|
|
|
|
if( !pro.IsOk() )
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
GIT_CLONE_HANDLER cloneHandler;
|
|
|
|
|
|
|
|
cloneHandler.SetURL( dlg.GetRepoURL() );
|
|
|
|
cloneHandler.SetClonePath( pro.GetPath() );
|
|
|
|
cloneHandler.SetConnType( dlg.GetRepoType() );
|
|
|
|
cloneHandler.SetUsername( dlg.GetUsername() );
|
|
|
|
cloneHandler.SetPassword( dlg.GetPassword() );
|
|
|
|
cloneHandler.SetSSHKey( dlg.GetRepoSSHPath() );
|
|
|
|
|
|
|
|
cloneHandler.SetProgressReporter( std::make_unique<WX_PROGRESS_REPORTER>( m_frame, _( "Cloning Repository" ), 1 ) );
|
|
|
|
|
|
|
|
if( !cloneHandler.PerformClone() )
|
|
|
|
{
|
|
|
|
DisplayErrorMessage( m_frame, cloneHandler.GetErrorString() );
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<wxString> projects = cloneHandler.GetProjectDirs();
|
|
|
|
|
|
|
|
if( projects.empty() )
|
|
|
|
{
|
|
|
|
DisplayErrorMessage( m_frame, _( "No project files were found in the repository." ) );
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Currently, we pick the first project file we find in the repository.
|
|
|
|
// TODO: Look into spare checkout to allow the user to pick a partial repository
|
|
|
|
wxString dest = pro.GetPath() + wxFileName::GetPathSeparator() + projects.front();
|
|
|
|
m_frame->LoadProject( dest );
|
|
|
|
|
|
|
|
Prj().GetLocalSettings().m_GitRepoPassword = dlg.GetPassword();
|
|
|
|
Prj().GetLocalSettings().m_GitRepoUsername = dlg.GetUsername();
|
|
|
|
Prj().GetLocalSettings().m_GitSSHKey = dlg.GetRepoSSHPath();
|
|
|
|
|
|
|
|
if( dlg.GetRepoType() == KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_SSH )
|
|
|
|
Prj().GetLocalSettings().m_GitRepoType = "ssh";
|
|
|
|
else if( dlg.GetRepoType() == KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_HTTPS )
|
|
|
|
Prj().GetLocalSettings().m_GitRepoType = "https";
|
|
|
|
else
|
|
|
|
Prj().GetLocalSettings().m_GitRepoType = "local";
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-06-09 14:12:44 +01:00
|
|
|
int KICAD_MANAGER_CONTROL::NewFromTemplate( const TOOL_EVENT& aEvent )
|
|
|
|
{
|
|
|
|
DIALOG_TEMPLATE_SELECTOR* ps = new DIALOG_TEMPLATE_SELECTOR( m_frame );
|
|
|
|
|
|
|
|
wxFileName templatePath;
|
|
|
|
|
|
|
|
// KiCad system template path.
|
2023-01-22 10:38:02 -08:00
|
|
|
ENV_VAR_MAP_CITER it = Pgm().GetLocalEnvVariables().find( "KICAD7_TEMPLATE_DIR" );
|
2019-06-09 14:12:44 +01:00
|
|
|
|
|
|
|
if( it != Pgm().GetLocalEnvVariables().end() && it->second.GetValue() != wxEmptyString )
|
|
|
|
{
|
|
|
|
templatePath.AssignDir( it->second.GetValue() );
|
|
|
|
ps->AddTemplatesPage( _( "System Templates" ), templatePath );
|
|
|
|
}
|
|
|
|
|
|
|
|
// User template path.
|
|
|
|
it = Pgm().GetLocalEnvVariables().find( "KICAD_USER_TEMPLATE_DIR" );
|
|
|
|
|
|
|
|
if( it != Pgm().GetLocalEnvVariables().end() && it->second.GetValue() != wxEmptyString )
|
|
|
|
{
|
|
|
|
templatePath.AssignDir( it->second.GetValue() );
|
|
|
|
ps->AddTemplatesPage( _( "User Templates" ), templatePath );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the project template selector dialog
|
|
|
|
if( ps->ShowModal() != wxID_OK )
|
|
|
|
return -1;
|
|
|
|
|
2019-06-10 15:23:37 +01:00
|
|
|
if( !ps->GetSelectedTemplate() )
|
2019-06-09 14:12:44 +01:00
|
|
|
{
|
|
|
|
wxMessageBox( _( "No project template was selected. Cannot generate new project." ),
|
2019-06-10 15:23:37 +01:00
|
|
|
_( "Error" ), wxOK | wxICON_ERROR, m_frame );
|
2019-06-09 14:12:44 +01:00
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get project destination folder and project file name.
|
|
|
|
wxString default_dir = wxFileName( Prj().GetProjectFullName() ).GetPathWithSep();
|
|
|
|
wxString title = _( "New Project Folder" );
|
2023-12-27 21:10:01 -05:00
|
|
|
wxFileDialog dlg( m_frame, title, default_dir, wxEmptyString, FILEEXT::ProjectFileWildcard(),
|
2019-06-09 22:57:23 +01:00
|
|
|
wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
|
2019-06-09 14:12:44 +01:00
|
|
|
|
|
|
|
// Add a "Create a new directory" checkbox
|
2022-06-11 23:03:29 -04:00
|
|
|
FILEDLG_NEW_PROJECT newProjectHook;
|
2022-06-11 21:44:46 -04:00
|
|
|
dlg.SetCustomizeHook( newProjectHook );
|
2019-06-09 14:12:44 +01:00
|
|
|
|
|
|
|
if( dlg.ShowModal() == wxID_CANCEL )
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
wxFileName fn( dlg.GetPath() );
|
|
|
|
|
2021-06-08 14:40:27 +01:00
|
|
|
// wxFileName automatically extracts an extension. But if it isn't a .kicad_pro extension,
|
|
|
|
// we should keep it as part of the filename
|
2023-12-27 21:10:01 -05:00
|
|
|
if( !fn.GetExt().IsEmpty() && fn.GetExt().ToStdString() != FILEEXT::ProjectFileExtension )
|
2019-06-09 14:12:44 +01:00
|
|
|
fn.SetName( fn.GetName() + wxT( "." ) + fn.GetExt() );
|
|
|
|
|
2023-12-27 21:10:01 -05:00
|
|
|
fn.SetExt( FILEEXT::ProjectFileExtension );
|
2019-06-09 14:12:44 +01:00
|
|
|
|
|
|
|
if( !fn.IsAbsolute() )
|
|
|
|
fn.MakeAbsolute();
|
|
|
|
|
2022-06-11 21:44:46 -04:00
|
|
|
bool createNewDir = false;
|
|
|
|
createNewDir = newProjectHook.GetCreateNewDir();
|
|
|
|
|
2019-06-09 14:12:44 +01:00
|
|
|
// Append a new directory with the same name of the project file.
|
2022-06-11 21:44:46 -04:00
|
|
|
if( createNewDir )
|
2019-06-09 14:12:44 +01:00
|
|
|
fn.AppendDir( fn.GetName() );
|
|
|
|
|
|
|
|
// Check if the project directory is empty if it already exists.
|
|
|
|
|
|
|
|
if( !fn.DirExists() )
|
|
|
|
{
|
|
|
|
if( !fn.Mkdir() )
|
|
|
|
{
|
|
|
|
wxString msg;
|
2021-06-08 14:40:27 +01:00
|
|
|
msg.Printf( _( "Folder '%s' could not be created.\n\n"
|
|
|
|
"Make sure you have write permissions and try again." ),
|
2019-06-09 14:12:44 +01:00
|
|
|
fn.GetPath() );
|
|
|
|
DisplayErrorMessage( m_frame, msg );
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !fn.IsDirWritable() )
|
|
|
|
{
|
|
|
|
wxString msg;
|
|
|
|
|
2021-06-27 14:24:02 +01:00
|
|
|
msg.Printf( _( "Insufficient permissions to write to folder '%s'." ), fn.GetPath() );
|
2021-06-08 14:40:27 +01:00
|
|
|
wxMessageDialog msgDlg( m_frame, msg, _( "Error" ), wxICON_ERROR | wxOK | wxCENTER );
|
2019-06-09 14:12:44 +01:00
|
|
|
msgDlg.ShowModal();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure we are not overwriting anything in the destination folder.
|
|
|
|
std::vector< wxFileName > destFiles;
|
|
|
|
|
|
|
|
if( ps->GetSelectedTemplate()->GetDestinationFiles( fn, destFiles ) )
|
|
|
|
{
|
2022-05-31 15:12:11 +01:00
|
|
|
std::vector<wxFileName> overwrittenFiles;
|
2019-06-09 14:12:44 +01:00
|
|
|
|
2022-05-31 15:12:11 +01:00
|
|
|
for( const wxFileName& file : destFiles )
|
2019-06-09 14:12:44 +01:00
|
|
|
{
|
|
|
|
if( file.FileExists() )
|
|
|
|
overwrittenFiles.push_back( file );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !overwrittenFiles.empty() )
|
|
|
|
{
|
|
|
|
wxString extendedMsg = _( "Overwriting files:" ) + "\n";
|
|
|
|
|
2022-05-31 15:12:11 +01:00
|
|
|
for( const wxFileName& file : overwrittenFiles )
|
2019-06-09 14:12:44 +01:00
|
|
|
extendedMsg += "\n" + file.GetFullName();
|
|
|
|
|
2022-05-31 15:12:11 +01:00
|
|
|
KIDIALOG msgDlg( m_frame,
|
|
|
|
_( "Similar files already exist in the destination folder." ),
|
|
|
|
_( "Confirmation" ),
|
|
|
|
wxOK | wxCANCEL | wxICON_WARNING );
|
2019-06-09 14:12:44 +01:00
|
|
|
msgDlg.SetExtendedMessage( extendedMsg );
|
|
|
|
msgDlg.SetOKLabel( _( "Overwrite" ) );
|
|
|
|
msgDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
|
|
|
|
|
|
|
|
if( msgDlg.ShowModal() == wxID_CANCEL )
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
wxString errorMsg;
|
|
|
|
|
|
|
|
// The selected template widget contains the template we're attempting to use to
|
|
|
|
// create a project
|
|
|
|
if( !ps->GetSelectedTemplate()->CreateProject( fn, &errorMsg ) )
|
|
|
|
{
|
|
|
|
wxMessageDialog createDlg( m_frame,
|
2021-06-08 14:40:27 +01:00
|
|
|
_( "A problem occurred creating new project from template." ),
|
|
|
|
_( "Error" ),
|
2019-06-09 14:12:44 +01:00
|
|
|
wxOK | wxICON_ERROR );
|
|
|
|
|
|
|
|
if( !errorMsg.empty() )
|
|
|
|
createDlg.SetExtendedMessage( errorMsg );
|
|
|
|
|
|
|
|
createDlg.ShowModal();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_frame->CreateNewProject( fn.GetFullPath() );
|
|
|
|
m_frame->LoadProject( fn );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-25 21:58:44 -04:00
|
|
|
int KICAD_MANAGER_CONTROL::openProject( const wxString& aDefaultDir )
|
2019-06-09 14:12:44 +01:00
|
|
|
{
|
2023-12-27 21:10:01 -05:00
|
|
|
wxString wildcard = FILEEXT::AllProjectFilesWildcard()
|
|
|
|
+ "|" + FILEEXT::ProjectFileWildcard()
|
|
|
|
+ "|" + FILEEXT::LegacyProjectFileWildcard();
|
2020-05-25 16:41:24 -04:00
|
|
|
|
2021-07-25 21:58:44 -04:00
|
|
|
wxFileDialog dlg( m_frame, _( "Open Existing Project" ), aDefaultDir, wxEmptyString, wildcard,
|
|
|
|
wxFD_OPEN | wxFD_FILE_MUST_EXIST );
|
2019-06-09 14:12:44 +01:00
|
|
|
|
|
|
|
if( dlg.ShowModal() == wxID_CANCEL )
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
wxFileName pro( dlg.GetPath() );
|
|
|
|
|
|
|
|
if( !pro.IsAbsolute() )
|
|
|
|
pro.MakeAbsolute();
|
|
|
|
|
|
|
|
if( !pro.FileExists() )
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
m_frame->LoadProject( pro );
|
2021-07-25 21:58:44 -04:00
|
|
|
|
2019-06-09 14:12:44 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-06-14 14:00:08 -04:00
|
|
|
|
2021-07-25 21:58:44 -04:00
|
|
|
int KICAD_MANAGER_CONTROL::OpenDemoProject( const TOOL_EVENT& aEvent )
|
|
|
|
{
|
|
|
|
return openProject( PATHS::GetStockDemosPath() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int KICAD_MANAGER_CONTROL::OpenProject( const TOOL_EVENT& aEvent )
|
|
|
|
{
|
|
|
|
return openProject( m_frame->GetMruPath() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-08 18:52:14 +00:00
|
|
|
int KICAD_MANAGER_CONTROL::CloseProject( const TOOL_EVENT& aEvent )
|
|
|
|
{
|
|
|
|
m_frame->CloseProject( true );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-06-09 14:12:44 +01:00
|
|
|
|
2022-09-14 22:28:09 +00:00
|
|
|
int KICAD_MANAGER_CONTROL::LoadProject( const TOOL_EVENT& aEvent )
|
|
|
|
{
|
|
|
|
if( aEvent.Parameter<wxString*>() )
|
|
|
|
m_frame->LoadProject( wxFileName( *aEvent.Parameter<wxString*>() ) );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KICAD_MANAGER_CONTROL::ViewDroppedViewers( const TOOL_EVENT& aEvent )
|
|
|
|
{
|
|
|
|
if( aEvent.Parameter<wxString*>() )
|
|
|
|
wxExecute( *aEvent.Parameter<wxString*>(), wxEXEC_ASYNC );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-11-09 19:39:08 +00:00
|
|
|
class SAVE_AS_TRAVERSER : public wxDirTraverser
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SAVE_AS_TRAVERSER( KICAD_MANAGER_FRAME* aFrame,
|
2019-11-10 09:37:39 +01:00
|
|
|
const wxString& aSrcProjectDirPath,
|
|
|
|
const wxString& aSrcProjectName,
|
|
|
|
const wxString& aNewProjectDirPath,
|
|
|
|
const wxString& aNewProjectName ) :
|
2019-11-09 19:39:08 +00:00
|
|
|
m_frame( aFrame ),
|
|
|
|
m_projectDirPath( aSrcProjectDirPath ),
|
|
|
|
m_projectName( aSrcProjectName ),
|
|
|
|
m_newProjectDirPath( aNewProjectDirPath ),
|
|
|
|
m_newProjectName( aNewProjectName )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-11-10 09:37:39 +01:00
|
|
|
virtual wxDirTraverseResult OnFile( const wxString& aSrcFilePath ) override
|
2019-11-09 19:39:08 +00:00
|
|
|
{
|
2020-11-22 11:46:52 +00:00
|
|
|
// Recursion guard for a Save As to a location inside the source project.
|
2021-12-09 16:49:57 +00:00
|
|
|
if( aSrcFilePath.StartsWith( m_newProjectDirPath + wxFileName::GetPathSeparator() ) )
|
2020-11-22 11:46:52 +00:00
|
|
|
return wxDIR_CONTINUE;
|
|
|
|
|
2019-11-09 19:39:08 +00:00
|
|
|
wxFileName destFile( aSrcFilePath );
|
|
|
|
wxString ext = destFile.GetExt();
|
|
|
|
bool atRoot = destFile.GetPath() == m_projectDirPath;
|
|
|
|
|
2023-12-27 21:10:01 -05:00
|
|
|
if( ext == FILEEXT::LegacyProjectFileExtension
|
|
|
|
|| ext == FILEEXT::ProjectFileExtension
|
|
|
|
|| ext == FILEEXT::ProjectLocalSettingsFileExtension )
|
2019-11-09 19:39:08 +00:00
|
|
|
{
|
|
|
|
wxString destPath = destFile.GetPath();
|
|
|
|
|
|
|
|
if( destPath.StartsWith( m_projectDirPath ) )
|
|
|
|
{
|
|
|
|
destPath.Replace( m_projectDirPath, m_newProjectDirPath, false );
|
|
|
|
destFile.SetPath( destPath );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( destFile.GetName() == m_projectName )
|
|
|
|
{
|
|
|
|
destFile.SetName( m_newProjectName );
|
|
|
|
|
2023-12-27 21:10:01 -05:00
|
|
|
if( atRoot && ext != FILEEXT::ProjectLocalSettingsFileExtension )
|
2019-11-09 19:39:08 +00:00
|
|
|
m_newProjectFile = destFile;
|
|
|
|
}
|
|
|
|
|
2023-12-27 21:10:01 -05:00
|
|
|
if( ext == FILEEXT::LegacyProjectFileExtension )
|
2021-10-30 23:01:19 +01:00
|
|
|
{
|
|
|
|
// All paths in the settings file are relative so we can just do a straight copy
|
|
|
|
KiCopyFile( aSrcFilePath, destFile.GetFullPath(), m_errors );
|
|
|
|
}
|
2023-12-27 21:10:01 -05:00
|
|
|
else if( ext == FILEEXT::ProjectFileExtension )
|
2021-10-30 23:01:19 +01:00
|
|
|
{
|
|
|
|
PROJECT_FILE projectFile( aSrcFilePath );
|
2021-11-09 20:17:23 +00:00
|
|
|
projectFile.LoadFromFile();
|
2021-10-30 23:01:19 +01:00
|
|
|
projectFile.SaveAs( destFile.GetPath(), destFile.GetName() );
|
|
|
|
}
|
2023-12-27 21:10:01 -05:00
|
|
|
else if( ext == FILEEXT::ProjectLocalSettingsFileExtension )
|
2021-11-09 17:24:53 +00:00
|
|
|
{
|
|
|
|
PROJECT_LOCAL_SETTINGS projectLocalSettings( nullptr, aSrcFilePath );
|
2021-11-09 20:17:23 +00:00
|
|
|
projectLocalSettings.LoadFromFile();
|
2021-11-09 17:24:53 +00:00
|
|
|
projectLocalSettings.SaveAs( destFile.GetPath(), destFile.GetName() );
|
|
|
|
}
|
2019-11-09 19:39:08 +00:00
|
|
|
}
|
2023-12-27 21:10:01 -05:00
|
|
|
else if( ext == FILEEXT::KiCadSchematicFileExtension
|
|
|
|
|| ext == FILEEXT::KiCadSchematicFileExtension + FILEEXT::BackupFileSuffix
|
|
|
|
|| ext == FILEEXT::LegacySchematicFileExtension
|
|
|
|
|| ext == FILEEXT::LegacySchematicFileExtension + FILEEXT::BackupFileSuffix
|
|
|
|
|| ext == FILEEXT::SchematicSymbolFileExtension
|
|
|
|
|| ext == FILEEXT::LegacySymbolLibFileExtension
|
|
|
|
|| ext == FILEEXT::LegacySymbolDocumentFileExtension
|
|
|
|
|| ext == FILEEXT::KiCadSymbolLibFileExtension
|
|
|
|
|| ext == FILEEXT::NetlistFileExtension
|
2021-01-27 17:15:38 -05:00
|
|
|
|| destFile.GetName() == "sym-lib-table" )
|
2019-11-09 19:39:08 +00:00
|
|
|
{
|
|
|
|
KIFACE* eeschema = m_frame->Kiway().KiFACE( KIWAY::FACE_SCH );
|
|
|
|
eeschema->SaveFileAs( m_projectDirPath, m_projectName, m_newProjectDirPath,
|
|
|
|
m_newProjectName, aSrcFilePath, m_errors );
|
|
|
|
}
|
2023-12-27 21:10:01 -05:00
|
|
|
else if( ext == FILEEXT::KiCadPcbFileExtension
|
|
|
|
|| ext == FILEEXT::KiCadPcbFileExtension + FILEEXT::BackupFileSuffix
|
|
|
|
|| ext == FILEEXT::LegacyPcbFileExtension
|
|
|
|
|| ext == FILEEXT::KiCadFootprintFileExtension
|
|
|
|
|| ext == FILEEXT::LegacyFootprintLibPathExtension
|
|
|
|
|| ext == FILEEXT::FootprintAssignmentFileExtension
|
2021-01-27 17:15:38 -05:00
|
|
|
|| destFile.GetName() == "fp-lib-table" )
|
2019-11-09 19:39:08 +00:00
|
|
|
{
|
|
|
|
KIFACE* pcbnew = m_frame->Kiway().KiFACE( KIWAY::FACE_PCB );
|
|
|
|
pcbnew->SaveFileAs( m_projectDirPath, m_projectName, m_newProjectDirPath,
|
|
|
|
m_newProjectName, aSrcFilePath, m_errors );
|
|
|
|
}
|
2023-12-27 21:10:01 -05:00
|
|
|
else if( ext == FILEEXT::DrawingSheetFileExtension )
|
2019-11-09 19:39:08 +00:00
|
|
|
{
|
|
|
|
KIFACE* pleditor = m_frame->Kiway().KiFACE( KIWAY::FACE_PL_EDITOR );
|
|
|
|
pleditor->SaveFileAs( m_projectDirPath, m_projectName, m_newProjectDirPath,
|
|
|
|
m_newProjectName, aSrcFilePath, m_errors );
|
|
|
|
}
|
2023-12-27 21:10:01 -05:00
|
|
|
else if( ext == FILEEXT::GerberJobFileExtension
|
|
|
|
|| ext == FILEEXT::DrillFileExtension
|
|
|
|
|| FILEEXT::IsGerberFileExtension( ext ) )
|
2019-11-09 19:39:08 +00:00
|
|
|
{
|
|
|
|
KIFACE* gerbview = m_frame->Kiway().KiFACE( KIWAY::FACE_GERBVIEW );
|
|
|
|
gerbview->SaveFileAs( m_projectDirPath, m_projectName, m_newProjectDirPath,
|
|
|
|
m_newProjectName, aSrcFilePath, m_errors );
|
|
|
|
}
|
2023-12-27 21:10:01 -05:00
|
|
|
else if( destFile.GetName().StartsWith( FILEEXT::LockFilePrefix )
|
|
|
|
&& ext == FILEEXT::LockFileExtension )
|
2023-07-16 15:02:12 +01:00
|
|
|
{
|
|
|
|
// Ignore lock files
|
|
|
|
}
|
2019-11-09 19:39:08 +00:00
|
|
|
else
|
|
|
|
{
|
2020-06-03 16:13:01 -04:00
|
|
|
// Everything we don't recognize just gets a straight copy.
|
2021-10-30 23:01:19 +01:00
|
|
|
wxString destPath = destFile.GetPathWithSep();
|
|
|
|
wxString destName = destFile.GetName();
|
|
|
|
wxUniChar pathSep = wxFileName::GetPathSeparator();
|
2021-05-28 16:19:20 -07:00
|
|
|
|
|
|
|
wxString srcProjectFootprintLib = pathSep + m_projectName + ".pretty" + pathSep;
|
|
|
|
wxString newProjectFootprintLib = pathSep + m_newProjectName + ".pretty" + pathSep;
|
2019-11-09 19:39:08 +00:00
|
|
|
|
|
|
|
if( destPath.StartsWith( m_projectDirPath ) )
|
|
|
|
destPath.Replace( m_projectDirPath, m_newProjectDirPath, false );
|
|
|
|
|
2022-02-27 20:15:03 +00:00
|
|
|
destPath.Replace( srcProjectFootprintLib, newProjectFootprintLib, true );
|
|
|
|
|
|
|
|
if( destName == m_projectName && ext != wxT( "zip" ) /* don't rename archives */ )
|
2019-11-09 19:39:08 +00:00
|
|
|
destFile.SetName( m_newProjectName );
|
|
|
|
|
2021-05-28 16:19:20 -07:00
|
|
|
destFile.SetPath( destPath );
|
|
|
|
|
2020-10-02 20:36:06 +02:00
|
|
|
KiCopyFile( aSrcFilePath, destFile.GetFullPath(), m_errors );
|
2019-11-09 19:39:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return wxDIR_CONTINUE;
|
|
|
|
}
|
|
|
|
|
2020-11-22 11:46:52 +00:00
|
|
|
virtual wxDirTraverseResult OnDir( const wxString& aSrcDirPath ) override
|
2019-11-09 19:39:08 +00:00
|
|
|
{
|
2020-11-22 11:46:52 +00:00
|
|
|
// Recursion guard for a Save As to a location inside the source project.
|
|
|
|
if( aSrcDirPath.StartsWith( m_newProjectDirPath ) )
|
|
|
|
return wxDIR_CONTINUE;
|
|
|
|
|
|
|
|
wxFileName destDir( aSrcDirPath );
|
2020-02-02 23:00:54 +00:00
|
|
|
wxString destDirPath = destDir.GetPathWithSep();
|
|
|
|
wxUniChar pathSep = wxFileName::GetPathSeparator();
|
2019-11-09 19:39:08 +00:00
|
|
|
|
2021-09-27 13:24:11 +01:00
|
|
|
if( destDirPath.StartsWith( m_projectDirPath + pathSep )
|
2022-02-05 11:30:21 -05:00
|
|
|
|| destDirPath.StartsWith( m_projectDirPath + PROJECT_BACKUPS_DIR_SUFFIX ) )
|
2019-11-09 19:39:08 +00:00
|
|
|
{
|
|
|
|
destDirPath.Replace( m_projectDirPath, m_newProjectDirPath, false );
|
|
|
|
destDir.SetPath( destDirPath );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( destDir.GetName() == m_projectName )
|
2020-02-02 23:00:54 +00:00
|
|
|
{
|
|
|
|
if( destDir.GetExt() == "pretty" )
|
|
|
|
destDir.SetName( m_newProjectName );
|
|
|
|
#if 0
|
|
|
|
// WAYNE STAMBAUGH TODO:
|
|
|
|
// If we end up with a symbol equivalent to ".pretty" we'll want to handle it here....
|
|
|
|
else if( destDir.GetExt() == "sym_lib_dir_extension" )
|
|
|
|
destDir.SetName( m_newProjectName );
|
|
|
|
#endif
|
|
|
|
}
|
2019-11-09 19:39:08 +00:00
|
|
|
|
|
|
|
if( !wxMkdir( destDir.GetFullPath() ) )
|
|
|
|
{
|
|
|
|
wxString msg;
|
|
|
|
|
|
|
|
if( !m_errors.empty() )
|
|
|
|
m_errors += "\n";
|
|
|
|
|
2021-06-16 23:35:00 +01:00
|
|
|
msg.Printf( _( "Cannot copy folder '%s'." ), destDir.GetFullPath() );
|
2019-11-09 19:39:08 +00:00
|
|
|
m_errors += msg;
|
|
|
|
}
|
|
|
|
|
|
|
|
return wxDIR_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
wxString GetErrors() { return m_errors; }
|
|
|
|
|
|
|
|
wxFileName GetNewProjectFile() { return m_newProjectFile; }
|
2021-01-27 17:15:38 -05:00
|
|
|
|
|
|
|
private:
|
|
|
|
KICAD_MANAGER_FRAME* m_frame;
|
|
|
|
|
|
|
|
wxString m_projectDirPath;
|
|
|
|
wxString m_projectName;
|
|
|
|
wxString m_newProjectDirPath;
|
|
|
|
wxString m_newProjectName;
|
|
|
|
|
|
|
|
wxFileName m_newProjectFile;
|
|
|
|
wxString m_errors;
|
2019-11-09 19:39:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int KICAD_MANAGER_CONTROL::SaveProjectAs( const TOOL_EVENT& aEvent )
|
|
|
|
{
|
|
|
|
wxString msg;
|
|
|
|
|
|
|
|
wxFileName currentProjectFile( Prj().GetProjectFullName() );
|
|
|
|
wxString currentProjectDirPath = currentProjectFile.GetPath();
|
|
|
|
wxString currentProjectName = Prj().GetProjectName();
|
|
|
|
|
|
|
|
wxString default_dir = m_frame->GetMruPath();
|
|
|
|
|
2021-11-09 20:57:58 +00:00
|
|
|
Prj().GetProjectFile().SaveToFile( currentProjectDirPath );
|
|
|
|
Prj().GetLocalSettings().SaveToFile( currentProjectDirPath );
|
2021-11-09 20:17:23 +00:00
|
|
|
|
2019-11-09 19:39:08 +00:00
|
|
|
if( default_dir == currentProjectDirPath
|
|
|
|
|| default_dir == currentProjectDirPath + wxFileName::GetPathSeparator() )
|
|
|
|
{
|
|
|
|
// Don't start within the current project
|
|
|
|
wxFileName default_dir_fn( default_dir );
|
|
|
|
default_dir_fn.RemoveLastDir();
|
|
|
|
default_dir = default_dir_fn.GetPath();
|
|
|
|
}
|
|
|
|
|
|
|
|
wxFileDialog dlg( m_frame, _( "Save Project To" ), default_dir, wxEmptyString, wxEmptyString,
|
|
|
|
wxFD_SAVE );
|
|
|
|
|
|
|
|
if( dlg.ShowModal() == wxID_CANCEL )
|
|
|
|
return -1;
|
|
|
|
|
2021-12-26 17:02:54 -05:00
|
|
|
wxFileName newProjectDir( dlg.GetPath(), wxEmptyString );
|
2019-11-09 19:39:08 +00:00
|
|
|
|
|
|
|
if( !newProjectDir.IsAbsolute() )
|
|
|
|
newProjectDir.MakeAbsolute();
|
|
|
|
|
|
|
|
if( wxDirExists( newProjectDir.GetFullPath() ) )
|
|
|
|
{
|
2021-06-16 23:35:00 +01:00
|
|
|
msg.Printf( _( "'%s' already exists." ), newProjectDir.GetFullPath() );
|
2019-11-09 19:39:08 +00:00
|
|
|
DisplayErrorMessage( m_frame, msg );
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !wxMkdir( newProjectDir.GetFullPath() ) )
|
|
|
|
{
|
2021-06-27 14:24:02 +01:00
|
|
|
msg.Printf( _( "Folder '%s' could not be created.\n\n"
|
2019-11-09 19:39:08 +00:00
|
|
|
"Please make sure you have write permissions and try again." ),
|
|
|
|
newProjectDir.GetPath() );
|
|
|
|
DisplayErrorMessage( m_frame, msg );
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !newProjectDir.IsDirWritable() )
|
|
|
|
{
|
2021-06-27 14:24:02 +01:00
|
|
|
msg.Printf( _( "Insufficient permissions to write to folder '%s'." ),
|
|
|
|
newProjectDir.GetFullPath() );
|
2019-11-09 19:39:08 +00:00
|
|
|
wxMessageDialog msgDlg( m_frame, msg, _( "Error!" ), wxICON_ERROR | wxOK | wxCENTER );
|
|
|
|
msgDlg.ShowModal();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
const wxString& newProjectDirPath = newProjectDir.GetFullPath();
|
2021-12-26 17:02:54 -05:00
|
|
|
const wxString& newProjectName = newProjectDir.GetDirs().Last();
|
2019-11-09 19:39:08 +00:00
|
|
|
wxDir currentProjectDir( currentProjectDirPath );
|
|
|
|
|
2020-11-22 11:46:52 +00:00
|
|
|
SAVE_AS_TRAVERSER traverser( m_frame, currentProjectDirPath, currentProjectName,
|
2019-11-09 19:39:08 +00:00
|
|
|
newProjectDirPath, newProjectName );
|
|
|
|
|
|
|
|
currentProjectDir.Traverse( traverser );
|
|
|
|
|
|
|
|
if( !traverser.GetErrors().empty() )
|
|
|
|
DisplayErrorMessage( m_frame, traverser.GetErrors() );
|
|
|
|
|
2022-02-05 11:30:21 -05:00
|
|
|
if( !traverser.GetNewProjectFile().FileExists() )
|
2019-11-09 19:39:08 +00:00
|
|
|
m_frame->CreateNewProject( traverser.GetNewProjectFile() );
|
2022-02-05 11:30:21 -05:00
|
|
|
|
|
|
|
m_frame->LoadProject( traverser.GetNewProjectFile() );
|
2019-11-09 19:39:08 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-06-09 14:12:44 +01:00
|
|
|
int KICAD_MANAGER_CONTROL::Refresh( const TOOL_EVENT& aEvent )
|
|
|
|
{
|
|
|
|
m_frame->RefreshProjectTree();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-06-16 20:11:08 +01:00
|
|
|
int KICAD_MANAGER_CONTROL::UpdateMenu( const TOOL_EVENT& aEvent )
|
|
|
|
{
|
|
|
|
ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
|
|
|
|
CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
|
|
|
|
SELECTION dummySel;
|
|
|
|
|
|
|
|
if( conditionalMenu )
|
|
|
|
conditionalMenu->Evaluate( dummySel );
|
|
|
|
|
|
|
|
if( actionMenu )
|
|
|
|
actionMenu->UpdateAll();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-06-10 15:23:37 +01:00
|
|
|
int KICAD_MANAGER_CONTROL::ShowPlayer( const TOOL_EVENT& aEvent )
|
|
|
|
{
|
2019-06-17 23:02:30 +01:00
|
|
|
FRAME_T playerType = aEvent.Parameter<FRAME_T>();
|
2019-06-10 15:23:37 +01:00
|
|
|
KIWAY_PLAYER* player;
|
|
|
|
|
2021-02-01 18:00:11 +00:00
|
|
|
if( playerType == FRAME_SCH && !m_frame->IsProjectActive() )
|
|
|
|
{
|
|
|
|
DisplayInfoMessage( m_frame, _( "Create (or open) a project to edit a schematic." ),
|
|
|
|
wxEmptyString );
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else if( playerType == FRAME_PCB_EDITOR && !m_frame->IsProjectActive() )
|
|
|
|
{
|
|
|
|
DisplayInfoMessage( m_frame, _( "Create (or open) a project to edit a pcb." ),
|
|
|
|
wxEmptyString );
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-06-04 16:47:49 -07:00
|
|
|
// Prevent multiple KIWAY_PLAYER loading at one time
|
2020-12-03 14:36:57 -08:00
|
|
|
if( !m_loading.try_lock() )
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
const std::lock_guard<std::mutex> lock( m_loading, std::adopt_lock );
|
2020-06-04 16:47:49 -07:00
|
|
|
|
2019-06-10 15:23:37 +01:00
|
|
|
try
|
|
|
|
{
|
|
|
|
player = m_frame->Kiway().Player( playerType, true );
|
|
|
|
}
|
|
|
|
catch( const IO_ERROR& err )
|
|
|
|
{
|
2023-03-19 13:01:54 +03:00
|
|
|
wxLogError( _( "Application failed to load:\n" ) + err.What() );
|
2020-09-06 23:18:37 -07:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !player )
|
|
|
|
{
|
2023-03-19 14:30:53 +03:00
|
|
|
wxLogError( _( "Application cannot start." ) );
|
2019-06-10 15:23:37 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !player->IsVisible() ) // A hidden frame might not have the document loaded.
|
|
|
|
{
|
|
|
|
wxString filepath;
|
2019-11-10 09:37:39 +01:00
|
|
|
|
2019-06-10 15:23:37 +01:00
|
|
|
if( playerType == FRAME_SCH )
|
|
|
|
{
|
2020-04-16 12:43:50 -04:00
|
|
|
wxFileName kicad_schematic( m_frame->SchFileName() );
|
|
|
|
wxFileName legacy_schematic( m_frame->SchLegacyFileName() );
|
|
|
|
|
|
|
|
if( !legacy_schematic.FileExists() || kicad_schematic.FileExists() )
|
|
|
|
filepath = kicad_schematic.GetFullPath();
|
|
|
|
else
|
|
|
|
filepath = legacy_schematic.GetFullPath();
|
2019-06-10 15:23:37 +01:00
|
|
|
}
|
2019-09-05 23:00:47 +01:00
|
|
|
else if( playerType == FRAME_PCB_EDITOR )
|
2019-06-10 15:23:37 +01:00
|
|
|
{
|
|
|
|
wxFileName kicad_board( m_frame->PcbFileName() );
|
|
|
|
wxFileName legacy_board( m_frame->PcbLegacyFileName() );
|
2019-11-10 09:37:39 +01:00
|
|
|
|
2019-06-10 15:23:37 +01:00
|
|
|
if( !legacy_board.FileExists() || kicad_board.FileExists() )
|
|
|
|
filepath = kicad_board.GetFullPath();
|
|
|
|
else
|
|
|
|
filepath = legacy_board.GetFullPath();
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !filepath.IsEmpty() )
|
|
|
|
{
|
2023-09-01 20:20:25 +02:00
|
|
|
std::vector<wxString> file_list{ filepath };
|
|
|
|
|
|
|
|
if( !player->OpenProjectFiles( file_list ) )
|
2021-06-30 16:06:07 +01:00
|
|
|
{
|
|
|
|
player->Destroy();
|
2019-06-10 15:23:37 +01:00
|
|
|
return -1;
|
2021-06-30 16:06:07 +01:00
|
|
|
}
|
2019-06-10 15:23:37 +01:00
|
|
|
}
|
2021-06-23 23:53:08 +01:00
|
|
|
|
2022-10-11 12:36:15 +01:00
|
|
|
wxBusyCursor busy;
|
2021-06-23 23:53:08 +01:00
|
|
|
player->Show( true );
|
2019-06-10 15:23:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Needed on Windows, other platforms do not use it, but it creates no issue
|
|
|
|
if( player->IsIconized() )
|
|
|
|
player->Iconize( false );
|
|
|
|
|
|
|
|
player->Raise();
|
|
|
|
|
|
|
|
// Raising the window does not set the focus on Linux. This should work on
|
|
|
|
// any platform.
|
|
|
|
if( wxWindow::FindFocus() != player )
|
|
|
|
player->SetFocus();
|
|
|
|
|
2023-08-14 22:43:17 +01:00
|
|
|
// Save window state to disk now. Don't wait around for a crash.
|
|
|
|
if( Pgm().GetCommonSettings()->m_Session.remember_open_files
|
|
|
|
&& !player->GetCurrentFileName().IsEmpty() )
|
|
|
|
{
|
|
|
|
wxFileName rfn( player->GetCurrentFileName() );
|
|
|
|
rfn.MakeRelativeTo( Prj().GetProjectPath() );
|
|
|
|
|
|
|
|
WINDOW_SETTINGS windowSettings;
|
|
|
|
player->SaveWindowSettings( &windowSettings );
|
|
|
|
|
|
|
|
Prj().GetLocalSettings().SaveFileState( rfn.GetFullPath(), &windowSettings, true );
|
|
|
|
Prj().GetLocalSettings().SaveToFile( Prj().GetProjectPath() );
|
|
|
|
}
|
|
|
|
|
2019-06-10 15:23:37 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class TERMINATE_HANDLER : public wxProcess
|
|
|
|
{
|
|
|
|
public:
|
2022-05-21 22:55:49 +01:00
|
|
|
TERMINATE_HANDLER( const wxString& appName )
|
2019-06-10 15:30:42 +01:00
|
|
|
{ }
|
2019-06-10 15:23:37 +01:00
|
|
|
|
|
|
|
void OnTerminate( int pid, int status ) override
|
|
|
|
{
|
|
|
|
delete this;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int KICAD_MANAGER_CONTROL::Execute( const TOOL_EVENT& aEvent )
|
|
|
|
{
|
|
|
|
wxString execFile;
|
2021-09-26 15:02:14 +01:00
|
|
|
wxString param;
|
2019-06-10 15:23:37 +01:00
|
|
|
|
|
|
|
if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::viewGerbers ) )
|
|
|
|
execFile = GERBVIEW_EXE;
|
|
|
|
else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::convertImage ) )
|
|
|
|
execFile = BITMAPCONVERTER_EXE;
|
|
|
|
else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::showCalculator ) )
|
|
|
|
execFile = PCB_CALCULATOR_EXE;
|
2021-02-22 16:37:43 +00:00
|
|
|
else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::editDrawingSheet ) )
|
2019-06-10 15:23:37 +01:00
|
|
|
execFile = PL_EDITOR_EXE;
|
|
|
|
else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::openTextEditor ) )
|
2021-09-19 14:45:27 +01:00
|
|
|
execFile = Pgm().GetTextEditor();
|
2019-06-10 15:23:37 +01:00
|
|
|
else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::editOtherSch ) )
|
|
|
|
execFile = EESCHEMA_EXE;
|
|
|
|
else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::editOtherPCB ) )
|
|
|
|
execFile = PCBNEW_EXE;
|
|
|
|
else
|
|
|
|
wxFAIL_MSG( "Execute(): unexpected request" );
|
|
|
|
|
|
|
|
if( execFile.IsEmpty() )
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if( aEvent.Parameter<wxString*>() )
|
2021-09-26 15:02:14 +01:00
|
|
|
param = *aEvent.Parameter<wxString*>();
|
|
|
|
else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::viewGerbers ) && m_frame->IsProjectActive() )
|
|
|
|
param = m_frame->Prj().GetProjectPath();
|
2019-06-10 15:23:37 +01:00
|
|
|
|
|
|
|
TERMINATE_HANDLER* callback = new TERMINATE_HANDLER( execFile );
|
|
|
|
|
2021-09-26 15:02:14 +01:00
|
|
|
long pid = ExecuteFile( execFile, param, callback );
|
2019-06-10 15:23:37 +01:00
|
|
|
|
|
|
|
if( pid > 0 )
|
|
|
|
{
|
2022-01-31 15:57:56 -08:00
|
|
|
#ifdef __WXMAC__
|
2023-10-24 17:27:20 -04:00
|
|
|
wxString script = wxString::Format( wxS( "tell application \"System Events\"\n"
|
|
|
|
" set frontmost of the first process whose unix id is %l to true\n"
|
|
|
|
"end tell" ), pid );
|
|
|
|
|
2023-10-28 15:37:19 -04:00
|
|
|
// This non-parameterized use of wxExecute is fine because script is not derived
|
2021-10-15 10:38:41 +01:00
|
|
|
// from user input.
|
2023-10-24 17:27:20 -04:00
|
|
|
wxExecute( wxString::Format( "osascript -e '%s'", script ) );
|
2019-06-10 15:23:37 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
delete callback;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-26 10:52:38 +01:00
|
|
|
int KICAD_MANAGER_CONTROL::ShowPluginManager( const TOOL_EVENT& aEvent )
|
|
|
|
{
|
2023-07-13 18:58:36 -04:00
|
|
|
if( KIPLATFORM::POLICY::GetPolicyBool( POLICY_KEY_PCM )
|
|
|
|
== KIPLATFORM::POLICY::PBOOL::DISABLED )
|
2022-04-12 00:11:16 -04:00
|
|
|
{
|
|
|
|
// policy disables the plugin manager
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-02-01 18:05:42 +01:00
|
|
|
// For some reason, after a click or a double click the bitmap button calling
|
2021-11-26 10:52:38 +01:00
|
|
|
// PCM keeps the focus althougt the focus was not set to this button.
|
|
|
|
// This hack force removing the focus from this button
|
|
|
|
m_frame->SetFocus();
|
2022-02-01 18:05:42 +01:00
|
|
|
wxSafeYield();
|
|
|
|
|
2023-07-18 11:19:52 +02:00
|
|
|
if( !m_frame->GetPcm() )
|
|
|
|
m_frame->CreatePCM();
|
|
|
|
|
2022-08-18 20:41:43 +00:00
|
|
|
DIALOG_PCM pcm( m_frame, m_frame->GetPcm() );
|
2022-02-01 18:05:42 +01:00
|
|
|
pcm.ShowModal();
|
2021-11-26 10:52:38 +01:00
|
|
|
|
2023-01-18 16:14:31 -08:00
|
|
|
const std::unordered_set<PCM_PACKAGE_TYPE>& changed = pcm.GetChangedPackageTypes();
|
|
|
|
|
|
|
|
if( changed.count( PCM_PACKAGE_TYPE::PT_PLUGIN ) )
|
|
|
|
{
|
|
|
|
std::string payload = "";
|
|
|
|
m_frame->Kiway().ExpressMail( FRAME_PCB_EDITOR, MAIL_RELOAD_PLUGINS, payload );
|
|
|
|
}
|
|
|
|
|
|
|
|
KICAD_SETTINGS* settings = Pgm().GetSettingsManager().GetAppSettings<KICAD_SETTINGS>();
|
|
|
|
|
|
|
|
if( changed.count( PCM_PACKAGE_TYPE::PT_LIBRARY )
|
|
|
|
&& ( settings->m_PcmLibAutoAdd || settings->m_PcmLibAutoRemove ) )
|
|
|
|
{
|
|
|
|
// Reset project tables
|
|
|
|
Prj().SetElem( PROJECT::ELEM_SYMBOL_LIB_TABLE, nullptr );
|
|
|
|
Prj().SetElem( PROJECT::ELEM_FPTBL, nullptr );
|
|
|
|
|
|
|
|
KIWAY& kiway = m_frame->Kiway();
|
|
|
|
|
|
|
|
// Reset state containing global lib tables
|
2023-03-10 23:07:38 +01:00
|
|
|
if( KIFACE* kiface = kiway.KiFACE( KIWAY::FACE_SCH, false ) )
|
2023-01-18 16:14:31 -08:00
|
|
|
kiface->Reset();
|
|
|
|
|
2023-03-10 23:07:38 +01:00
|
|
|
if( KIFACE* kiface = kiway.KiFACE( KIWAY::FACE_PCB, false ) )
|
2023-01-18 16:14:31 -08:00
|
|
|
kiface->Reset();
|
|
|
|
|
|
|
|
// Reload lib tables
|
|
|
|
std::string payload = "";
|
|
|
|
|
|
|
|
kiway.ExpressMail( FRAME_FOOTPRINT_EDITOR, MAIL_RELOAD_LIB, payload );
|
|
|
|
kiway.ExpressMail( FRAME_FOOTPRINT_VIEWER, MAIL_RELOAD_LIB, payload );
|
|
|
|
kiway.ExpressMail( FRAME_CVPCB, MAIL_RELOAD_LIB, payload );
|
|
|
|
kiway.ExpressMail( FRAME_SCH_SYMBOL_EDITOR, MAIL_RELOAD_LIB, payload );
|
|
|
|
kiway.ExpressMail( FRAME_SCH_VIEWER, MAIL_RELOAD_LIB, payload );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( changed.count( PCM_PACKAGE_TYPE::PT_COLORTHEME ) )
|
|
|
|
Pgm().GetSettingsManager().ReloadColorSettings();
|
|
|
|
|
2021-11-26 10:52:38 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-06-09 14:12:44 +01:00
|
|
|
void KICAD_MANAGER_CONTROL::setTransitions()
|
|
|
|
{
|
2022-09-14 22:28:09 +00:00
|
|
|
Go( &KICAD_MANAGER_CONTROL::NewProject, KICAD_MANAGER_ACTIONS::newProject.MakeEvent() );
|
|
|
|
Go( &KICAD_MANAGER_CONTROL::NewFromTemplate, KICAD_MANAGER_ACTIONS::newFromTemplate.MakeEvent() );
|
2023-09-14 14:39:42 -07:00
|
|
|
Go( &KICAD_MANAGER_CONTROL::NewFromRepository, KICAD_MANAGER_ACTIONS::newFromRepository.MakeEvent() );
|
2022-09-14 22:28:09 +00:00
|
|
|
Go( &KICAD_MANAGER_CONTROL::OpenDemoProject, KICAD_MANAGER_ACTIONS::openDemoProject.MakeEvent() );
|
|
|
|
Go( &KICAD_MANAGER_CONTROL::OpenProject, KICAD_MANAGER_ACTIONS::openProject.MakeEvent() );
|
|
|
|
Go( &KICAD_MANAGER_CONTROL::CloseProject, KICAD_MANAGER_ACTIONS::closeProject.MakeEvent() );
|
|
|
|
Go( &KICAD_MANAGER_CONTROL::SaveProjectAs, ACTIONS::saveAs.MakeEvent() );
|
|
|
|
Go( &KICAD_MANAGER_CONTROL::LoadProject, KICAD_MANAGER_ACTIONS::loadProject.MakeEvent() );
|
|
|
|
Go( &KICAD_MANAGER_CONTROL::ViewDroppedViewers, KICAD_MANAGER_ACTIONS::viewDroppedGerbers.MakeEvent() );
|
2020-12-18 15:06:59 +00:00
|
|
|
|
|
|
|
Go( &KICAD_MANAGER_CONTROL::Refresh, ACTIONS::zoomRedraw.MakeEvent() );
|
|
|
|
Go( &KICAD_MANAGER_CONTROL::UpdateMenu, ACTIONS::updateMenu.MakeEvent() );
|
|
|
|
|
|
|
|
Go( &KICAD_MANAGER_CONTROL::ShowPlayer, KICAD_MANAGER_ACTIONS::editSchematic.MakeEvent() );
|
|
|
|
Go( &KICAD_MANAGER_CONTROL::ShowPlayer, KICAD_MANAGER_ACTIONS::editSymbols.MakeEvent() );
|
|
|
|
Go( &KICAD_MANAGER_CONTROL::ShowPlayer, KICAD_MANAGER_ACTIONS::editPCB.MakeEvent() );
|
2021-02-22 16:37:43 +00:00
|
|
|
Go( &KICAD_MANAGER_CONTROL::ShowPlayer, KICAD_MANAGER_ACTIONS::editFootprints.MakeEvent() );
|
2020-12-18 15:06:59 +00:00
|
|
|
Go( &KICAD_MANAGER_CONTROL::Execute, KICAD_MANAGER_ACTIONS::viewGerbers.MakeEvent() );
|
|
|
|
Go( &KICAD_MANAGER_CONTROL::Execute, KICAD_MANAGER_ACTIONS::convertImage.MakeEvent() );
|
2021-02-22 16:37:43 +00:00
|
|
|
Go( &KICAD_MANAGER_CONTROL::Execute, KICAD_MANAGER_ACTIONS::showCalculator.MakeEvent() );
|
|
|
|
Go( &KICAD_MANAGER_CONTROL::Execute, KICAD_MANAGER_ACTIONS::editDrawingSheet.MakeEvent() );
|
|
|
|
Go( &KICAD_MANAGER_CONTROL::Execute, KICAD_MANAGER_ACTIONS::openTextEditor.MakeEvent() );
|
2020-12-18 15:06:59 +00:00
|
|
|
|
|
|
|
Go( &KICAD_MANAGER_CONTROL::Execute, KICAD_MANAGER_ACTIONS::editOtherSch.MakeEvent() );
|
|
|
|
Go( &KICAD_MANAGER_CONTROL::Execute, KICAD_MANAGER_ACTIONS::editOtherPCB.MakeEvent() );
|
2020-10-26 03:54:36 -07:00
|
|
|
|
2021-11-26 10:52:38 +01:00
|
|
|
Go( &KICAD_MANAGER_CONTROL::ShowPluginManager, KICAD_MANAGER_ACTIONS::showPluginManager.MakeEvent() );
|
2019-06-09 14:12:44 +01:00
|
|
|
}
|