KiCad PCB EDA Suite
project_template.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) 2012 Brian Sidebotham <brian.sidebotham@gmail.com>
5  * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 
26 #include <wx/bitmap.h>
27 #include <wx/dir.h>
28 #include <wx/txtstrm.h>
29 #include <wx/wfstream.h>
30 #include <wx/log.h>
31 
33 #include "project_template.h"
34 
35 
36 #define SEP wxFileName::GetPathSeparator()
37 
38 
39 PROJECT_TEMPLATE::PROJECT_TEMPLATE( const wxString& aPath )
40 {
41  m_basePath = wxFileName::DirName( aPath );
42  m_metaPath = wxFileName::DirName( aPath + SEP + METADIR );
43  m_metaHtmlFile = wxFileName::FileName( aPath + SEP + METADIR + SEP + METAFILE_INFO_HTML );
44  m_metaIconFile = wxFileName::FileName( aPath + SEP + METADIR + SEP + METAFILE_ICON );
45 
46  m_title = wxEmptyString;
47 
48  // Test the project template requirements to make sure aPath is a valid template structure.
49  if( !wxFileName::DirExists( m_basePath.GetPath() ) )
50  {
51  // Error, the path doesn't exist!
52  m_title = _( "Could open the template path!" ) + wxS( " " ) + aPath;
53  }
54  else if( !wxFileName::DirExists( m_metaPath.GetPath() ) )
55  {
56  // Error, the meta information directory doesn't exist!
57  m_title = _( "Couldn't open the meta information directory for this template!" ) + wxS( " " ) +
58  m_metaPath.GetPath();
59  }
60  else if( !wxFileName::FileExists( m_metaHtmlFile.GetFullPath() ) )
61  {
62  // Error, the meta information directory doesn't contain the informational html file!
63  m_title = _( "Cound't find the meta HTML information file for this template!" );
64  }
65 
66  // Try to load an icon
67  if( !wxFileName::FileExists( m_metaIconFile.GetFullPath() ) )
68  m_metaIcon = &wxNullBitmap;
69  else
70  m_metaIcon = new wxBitmap( m_metaIconFile.GetFullPath(), wxBITMAP_TYPE_PNG );
71 }
72 
73 
74 std::vector<wxFileName> PROJECT_TEMPLATE::GetFileList()
75 {
76  std::vector<wxFileName> files;
77  wxString f = m_basePath.GetPath();
78  wxArrayString allfiles;
79  wxFileName p;
80 
81  wxDir::GetAllFiles( f, &allfiles );
82 
83  // Create the vector and ignore all of the meta data files!
84  for( size_t i=0; i < allfiles.size(); i++ )
85  {
86  p = allfiles[i];
87 
88  // Files that are in the meta directory must not be included
89  if( !p.GetPath().StartsWith( m_metaPath.GetPath() ) )
90  files.emplace_back(allfiles[i] );
91  }
92 
93  return files;
94 }
95 
96 
98 {
99  return m_basePath.GetDirs()[ m_basePath.GetDirCount() - 1 ];
100 }
101 
102 
104 {
105 
106 }
107 
108 
110 {
111  return m_metaHtmlFile;
112 }
113 
114 
116 {
117  return m_metaIcon;
118 }
119 
120 
121 size_t PROJECT_TEMPLATE::GetDestinationFiles( const wxFileName& aNewProjectPath,
122  std::vector< wxFileName >& aDestFiles )
123 {
124  std::vector< wxFileName > srcFiles = GetFileList();
125 
126  // Find the template file name base. this is the name of the .pro template file
127  wxString basename;
128  bool multipleProjectFilesFound = false;
129 
130  for( wxFileName& file : srcFiles )
131  {
132  if( file.GetExt() == ProjectFileExtension || file.GetExt() == LegacyProjectFileExtension )
133  {
134  if( !basename.IsEmpty() && basename != file.GetName() )
135  multipleProjectFilesFound = true;
136 
137  basename = file.GetName();
138  }
139  }
140 
141  if( multipleProjectFilesFound )
142  basename = GetPrjDirName();
143 
144  for( wxFileName& srcFile : srcFiles )
145  {
146  // Replace the template path
147  wxFileName destFile = srcFile;
148 
149  // Replace the template filename with the project filename for the new project creation
150  wxString name = destFile.GetName();
151  name.Replace( basename, aNewProjectPath.GetName() );
152  destFile.SetName( name );
153 
154  // Replace the template path with the project path.
155  wxString path = destFile.GetPathWithSep();
156  path.Replace( m_basePath.GetPathWithSep(), aNewProjectPath.GetPathWithSep() );
157  destFile.SetPath( path );
158 
159  aDestFiles.push_back( destFile );
160  }
161 
162  return aDestFiles.size();
163 }
164 
165 
166 bool PROJECT_TEMPLATE::CreateProject( wxFileName& aNewProjectPath, wxString* aErrorMsg )
167 {
168  // CreateProject copy the files from template to the new project folder and renames files
169  // which have the same name as the template .kicad_pro file
170  bool result = true;
171 
172  std::vector<wxFileName> srcFiles = GetFileList();
173 
174  // Find the template file name base. this is the name of the .kicad_pro (or .pro) template
175  // file
176  wxString basename;
177  bool multipleProjectFilesFound = false;
178 
179  for( wxFileName& file : srcFiles )
180  {
181  if( file.GetExt() == ProjectFileExtension || file.GetExt() == LegacyProjectFileExtension )
182  {
183  if( !basename.IsEmpty() && basename != file.GetName() )
184  multipleProjectFilesFound = true;
185 
186  basename = file.GetName();
187  }
188  }
189 
190  if( multipleProjectFilesFound )
191  basename = GetPrjDirName();
192 
193  for( wxFileName& srcFile : srcFiles )
194  {
195  // Replace the template path
196  wxFileName destFile = srcFile;
197 
198  // Replace the template filename with the project filename for the new project creation
199  wxString currname = destFile.GetName();
200 
201  if( destFile.GetExt() == DrawingSheetFileExtension )
202  {
203  // Skip these; they're often shared
204  }
205  if( destFile.GetName().EndsWith( "-cache" ) || destFile.GetName().EndsWith( "-rescue" ) )
206  {
207  currname.Replace( basename, aNewProjectPath.GetName() );
208  }
209  else if( destFile.GetExt() == "dcm" || destFile.GetExt() == "lib" )
210  {
211  // Don't rename project-specific symbol libraries. This will break the symbol library
212  // table which will cause broken symbol library links in the schematic.
213  }
214  else
215  {
216  currname.Replace( basename, aNewProjectPath.GetName() );
217  }
218 
219  destFile.SetName( currname );
220 
221  // Replace the template path with the project path for the new project creation
222  // but keep the sub directory name, if exists
223  wxString destpath = destFile.GetPathWithSep();
224  destpath.Replace( m_basePath.GetPathWithSep(), aNewProjectPath.GetPathWithSep() );
225 
226  // Check to see if the path already exists, if not attempt to create it here.
227  if( !wxFileName::DirExists( destpath ) )
228  {
229  if( !wxFileName::Mkdir( destpath, 0777, wxPATH_MKDIR_FULL ) )
230  {
231  if( aErrorMsg )
232  {
233  if( !aErrorMsg->empty() )
234  *aErrorMsg += "\n";
235 
236  wxString msg;
237 
238  msg.Printf( _( "Cannot create folder '%s'." ), destpath );
239  *aErrorMsg += msg;
240  }
241 
242  continue;
243  }
244  }
245 
246  destFile.SetPath( destpath );
247 
248  if( !wxCopyFile( srcFile.GetFullPath(), destFile.GetFullPath() ) )
249  {
250  if( aErrorMsg )
251  {
252  if( !aErrorMsg->empty() )
253  *aErrorMsg += "\n";
254 
255  wxString msg;
256 
257  msg.Printf( _( "Cannot copy file '%s'." ), destFile.GetFullPath() );
258  *aErrorMsg += msg;
259  }
260 
261  result = false;
262  }
263  }
264 
265  return result;
266 }
267 
268 
270 {
271  wxFFileInputStream input( GetHtmlFile().GetFullPath() );
272  wxString separator( wxT( "\x9" ) );
273  wxTextInputStream text( input, separator, wxConvUTF8 );
274 
275  /* Open HTML file and get the text between the title tags */
276  if( m_title == wxEmptyString )
277  {
278  int start = 0;
279  int finish = 0;
280  bool done = false;
281 
282  while( input.IsOk() && !input.Eof() && !done )
283  {
284  wxString line = text.ReadLine();
285  wxString upperline = line.Clone().Upper();
286 
287  start = upperline.Find( wxT( "<TITLE>" ) );
288  finish = upperline.Find( wxT( "</TITLE>" ) );
289  int length = finish - start - 7;
290 
291  // find the opening tag
292  if( start != wxNOT_FOUND )
293  {
294  if( finish != wxNOT_FOUND )
295  {
296  m_title = line( start + 7, length );
297  }
298  else
299  {
300  m_title = line.Mid( start + 7 );
301  }
302 
303  done = true;
304  }
305  else
306  {
307  if( finish != wxNOT_FOUND )
308  {
309  m_title += line.SubString( 0, finish );
310  done = true;
311  }
312  }
313 
314  // Remove line endings
315  m_title.Replace( wxT( "\r" ), wxT( " " ) );
316  m_title.Replace( wxT( "\n" ), wxT( " " ) );
317  }
318  }
319 
320  return &m_title;
321 }
wxFileName m_metaIconFile
std::vector< wxFileName > GetFileList()
Get a vector list of filenames for the template.
const std::string ProjectFileExtension
#define METADIR
A directory which contains information about the project template and does not get copied.
wxFileName GetHtmlFile()
Get the full Html filename for the project template.
wxFileName m_metaHtmlFile
#define METAFILE_INFO_HTML
A required html formatted file which contains information about the project template.
#define SEP
PROJECT_TEMPLATE(const wxString &aPath)
Create a new project instance from aPath.
#define METAFILE_ICON
An optional png icon, exactly 64px x 64px which is used in the template selector if present.
Definition of file extensions used in Kicad.
#define _(s)
wxString * GetTitle()
Get the title of the project (extracted from the html title tag)
wxString GetPrjDirName()
Get the dir name of the project template (i.e.
const std::string LegacyProjectFileExtension
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.
const std::string DrawingSheetFileExtension
bool CreateProject(wxFileName &aNewProjectPath, wxString *aErrorMsg=nullptr)
Copies and renames all template files to create a new project.
const char * name
Definition: DXF_plotter.cpp:56
~PROJECT_TEMPLATE()
Non-virtual destructor (so no derived classes)
wxBitmap * GetIcon()
Get the 64px^2 icon for the project template.