KiCad PCB EDA Suite
import_project.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) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * @author Russell Oliver <roliver8143@gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
32 #include <wx/filefn.h>
33 #include <wx/filename.h>
34 #include <wx/dir.h>
35 #include <wx/filedlg.h>
36 #include <wx/dirdlg.h>
37 
38 #include <common.h>
39 #include <confirm.h>
40 #include <kiway.h>
41 #include <macros.h>
42 #include <richio.h>
44 #include <kiway_player.h>
45 #include <stdexcept>
46 #include "pgm_kicad.h"
47 
48 #include <io_mgr.h>
49 #include <sch_io_mgr.h>
50 
51 #include "kicad_manager_frame.h"
52 
53 
54 void KICAD_MANAGER_FRAME::ImportNonKiCadProject( const wxString& aWindowTitle,
55  const wxString& aFilesWildcard,
56  const wxString& aSchFileExtension,
57  const wxString& aPcbFileExtension,
58  int aSchFileType, int aPcbFileType )
59 {
60  wxString msg;
61  wxString default_dir = GetMruPath();
62  int style = wxFD_OPEN | wxFD_FILE_MUST_EXIST;
63 
64  wxFileDialog schdlg( this, aWindowTitle, default_dir, wxEmptyString, aFilesWildcard, style );
65 
66  if( schdlg.ShowModal() == wxID_CANCEL )
67  return;
68 
69  // OK, we got a new project to open. Time to close any existing project before we go on
70  // to collect info about where to put the new one, etc. Otherwise the workflow is kind of
71  // disjoint.
72  CloseProject( true );
73 
74  wxFileName sch( schdlg.GetPath() );
75  sch.SetExt( aSchFileExtension );
76 
77  wxFileName pcb( sch );
78  pcb.SetExt( aPcbFileExtension );
79 
80  wxFileName pro( sch );
81  pro.SetExt( ProjectFileExtension );
82 
83  wxString protitle = _( "KiCad Project Destination" );
84 
85  // Don't use wxFileDialog here. On GTK builds, the default path is returned unless a
86  // file is actually selected.
87  wxDirDialog prodlg( this, protitle, pro.GetPath(), wxDD_DEFAULT_STYLE );
88 
89  if( prodlg.ShowModal() == wxID_CANCEL )
90  return;
91 
92  pro.SetPath( prodlg.GetPath() );
93 
94  // Check if the project directory is empty
95  wxDir directory( pro.GetPath() );
96 
97  if( directory.HasFiles() )
98  {
99  msg = _( "The selected directory is not empty. We recommend you "
100  "create projects in their own clean directory.\n\nDo you "
101  "want to create a new empty directory for the project?" );
102 
103  KIDIALOG dlg( this, msg, _( "Confirmation" ), wxYES_NO | wxICON_WARNING );
104  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
105 
106  if( dlg.ShowModal() == wxID_YES )
107  {
108  // Append a new directory with the same name of the project file
109  // Keep iterating until we find an empty directory
110  wxString newDir = pro.GetName();
111  int attempt = 0;
112 
113  pro.AppendDir( newDir );
114 
115  while( pro.DirExists() )
116  {
117  pro.RemoveLastDir();
118  wxString suffix = wxString::Format( "_%d", ++attempt );
119  pro.AppendDir( newDir + suffix );
120  }
121 
122  if( !wxMkdir( pro.GetPath() ) )
123  {
124  msg = _( "Error creating new directory. Please try a different path. The "
125  "project cannot be imported." );
126 
127  wxMessageDialog dirErrorDlg( this, msg, _( "Error" ), wxOK_DEFAULT | wxICON_ERROR );
128  dirErrorDlg.ShowModal();
129  return;
130  }
131  }
132  }
133 
134  std::string packet;
135 
136  pro.SetExt( ProjectFileExtension );
137 
138  if( !pro.IsAbsolute() )
139  pro.MakeAbsolute();
140 
141  wxFileName schCopy( pro );
142  schCopy.SetExt( aSchFileExtension );
143 
144  if( sch.Exists() && !schCopy.SameAs( sch ) )
145  {
146  if( !wxCopyFile( sch.GetFullPath(), schCopy.GetFullPath(), true ) )
147  {
149  msg.Printf( _( "Cannot copy file '%s'\n"
150  "to '%s'\n"
151  "The project cannot be imported." ),
152  sch.GetFullPath(), schCopy.GetFullPath() );
153 
154  wxMessageDialog schCopyErrorDlg( this, msg, _( "Error" ), wxOK_DEFAULT | wxICON_ERROR );
155  schCopyErrorDlg.ShowModal();
156  return;
157  }
158  }
159 
160  wxFileName pcbCopy( pro );
161  pcbCopy.SetExt( aPcbFileExtension );
162 
163  if( pcb.Exists() && !pcbCopy.SameAs( pcb ) )
164  {
165  if( !wxCopyFile( pcb.GetFullPath(), pcbCopy.GetFullPath(), true ) )
166  {
168  msg.Printf( _( "Cannot copy file '%s'\n"
169  "to '%s'\n"
170  "The project cannot be imported." ),
171  pcb.GetFullPath(), pcbCopy.GetFullPath() );
172 
173  wxMessageDialog brdCopyErrorDlg( this, msg, _( "Error" ), wxOK_DEFAULT | wxICON_ERROR );
174  brdCopyErrorDlg.ShowModal();
175  return;
176  }
177  }
178 
179  CreateNewProject( pro.GetFullPath(), false /* Don't create stub files */ );
180  LoadProject( pro );
181 
182  if( schCopy.FileExists() )
183  {
184  KIWAY_PLAYER* schframe = Kiway().Player( FRAME_SCH, true );
185 
186  packet = StrPrintf( "%d\n%s", aSchFileType, TO_UTF8( schCopy.GetFullPath() ) );
187  schframe->Kiway().ExpressMail( FRAME_SCH, MAIL_IMPORT_FILE, packet, this );
188 
189  if( !schframe->IsShown() )
190  schframe->Show( true );
191 
192  // On Windows, Raise() does not bring the window on screen, when iconized
193  if( schframe->IsIconized() )
194  schframe->Iconize( false );
195 
196  schframe->Raise();
197 
198  if( !schCopy.SameAs( sch ) ) // Do not delete the original file!
199  wxRemoveFile( schCopy.GetFullPath() );
200  }
201 
202  if( pcbCopy.FileExists() )
203  {
204  KIWAY_PLAYER* pcbframe = Kiway().Player( FRAME_PCB_EDITOR, true );
205 
206  if( !pcbframe->IsVisible() )
207  pcbframe->Show( true );
208 
209  packet = StrPrintf( "%d\n%s", aPcbFileType, TO_UTF8( pcbCopy.GetFullPath() ) );
210  pcbframe->Kiway().ExpressMail( FRAME_PCB_EDITOR, MAIL_IMPORT_FILE, packet, this );
211 
212  // On Windows, Raise() does not bring the window on screen, when iconized
213  if( pcbframe->IsIconized() )
214  pcbframe->Iconize( false );
215 
216  pcbframe->Raise();
217 
218  if( !pcbCopy.SameAs( pcb ) ) // Do not delete the original file!
219  wxRemoveFile( pcbCopy.GetFullPath() );
220  }
221 
222  ReCreateTreePrj();
223  m_active_project = true;
224 }
225 
226 
228 {
229  ImportNonKiCadProject( _( "Import CADSTAR Archive Project Files" ),
230  CadstarArchiveFilesWildcard(), "csa", "cpa", SCH_IO_MGR::SCH_CADSTAR_ARCHIVE,
232 }
233 
234 
235 void KICAD_MANAGER_FRAME::OnImportEagleFiles( wxCommandEvent& event )
236 {
237  ImportNonKiCadProject( _( "Import Eagle Project Files" ), EagleFilesWildcard(),
239  SCH_IO_MGR::SCH_EAGLE, IO_MGR::EAGLE );
240 }
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Definition: kiway_player.h:64
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
Definition: confirm.cpp:55
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:53
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: confirm.h:45
This file is part of the common library.
const std::string ProjectFileExtension
const std::string LegacyPcbFileExtension
void OnImportEagleFiles(wxCommandEvent &event)
Open dialog to import Eagle schematic and board files.
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:383
virtual void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string &aPayload, wxWindow *aSource=nullptr)
Send aPayload to aDestination from aSource.
Definition: kiway.cpp:477
void ImportNonKiCadProject(const wxString &aWindowTitle, const wxString &aFilesWildcard, const wxString &aSchFileExtension, const wxString &aPcbFileExtension, int aSchFileType, int aPcbFileType)
Creates a project and imports a non-KiCad Schematic and PCB.
This file contains miscellaneous commonly used macros and functions.
int StrPrintf(std::string *result, const char *format,...)
This is like sprintf() but the output is appended to a std::string instead of to a character array.
Definition: richio.cpp:79
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
void OnImportCadstarArchiveFiles(wxCommandEvent &event)
Open dialog to import CADSTAR Schematic and PCB Archive files.
wxString GetMruPath() const
Definition of file extensions used in Kicad.
#define _(s)
const std::string LegacySchematicFileExtension
void CreateNewProject(const wxFileName &aProjectFileName, bool aCreateStubFiles=true)
Creates a new project by setting up and initial project, schematic, and board files.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
bool CloseProject(bool aSave)
Closes the project, and saves it if aSave is true;.
The common library.
int ShowModal() override
Definition: confirm.cpp:99
wxString EagleFilesWildcard()
void LoadProject(const wxFileName &aProjectFileName)
wxString CadstarArchiveFilesWildcard()