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-2020 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! " ) + 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! " ) +
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  int projectCount = 0;
129 
130  for( wxFileName& file : srcFiles )
131  {
132  if( file.GetExt() == ProjectFileExtension || file.GetExt() == LegacyProjectFileExtension )
133  {
134  basename = file.GetName();
135  projectCount++;
136  }
137  }
138 
139  if( projectCount != 1 )
140  basename = GetPrjDirName();
141 
142  for( wxFileName& srcFile : srcFiles )
143  {
144  // Replace the template path
145  wxFileName destFile = srcFile;
146 
147  // Replace the template filename with the project filename for the new project creation
148  wxString name = destFile.GetName();
149  name.Replace( basename, aNewProjectPath.GetName() );
150  destFile.SetName( name );
151 
152  // Replace the template path with the project path.
153  wxString path = destFile.GetPathWithSep();
154  path.Replace( m_basePath.GetPathWithSep(), aNewProjectPath.GetPathWithSep() );
155  destFile.SetPath( path );
156 
157  aDestFiles.push_back( destFile );
158  }
159 
160  return aDestFiles.size();
161 }
162 
163 
164 bool PROJECT_TEMPLATE::CreateProject( wxFileName& aNewProjectPath, wxString* aErrorMsg )
165 {
166  // CreateProject copy the files from template to the new project folder
167  // and rename files which have the same name as the template .pro file
168  bool result = true;
169 
170  std::vector<wxFileName> srcFiles = GetFileList();
171 
172  // Find the template file name base. this is the name of the .pro template file
173  wxString basename;
174  int projectCount = 0;
175 
176  for( wxFileName& file : srcFiles )
177  {
178  if( file.GetExt() == ProjectFileExtension || file.GetExt() == LegacyProjectFileExtension )
179  {
180  basename = file.GetName();
181  projectCount++;
182  }
183  }
184 
185  if( projectCount != 1 )
186  basename = GetPrjDirName();
187 
188  for( wxFileName& srcFile : srcFiles )
189  {
190  // Replace the template path
191  wxFileName destFile = srcFile;
192 
193  // Replace the template filename with the project filename for the new project creation
194  wxString currname = destFile.GetName();
195 
196  // Do not rename project specific symbol libraries. This will break the symbol library
197  // table which will cause broken symbol library links in the schematic.
198  if( !( destFile.GetExt() == "dcm"
199  || ( destFile.GetExt() == "lib" && !destFile.GetName().EndsWith( "-cache" ) ) ) )
200  {
201  currname.Replace( basename, aNewProjectPath.GetName() );
202  }
203 
204  destFile.SetName( currname );
205 
206  // Replace the template path with the project path for the new project creation
207  // but keep the sub directory name, if exists
208  wxString destpath = destFile.GetPathWithSep();
209  destpath.Replace( m_basePath.GetPathWithSep(), aNewProjectPath.GetPathWithSep() );
210 
211  // Check to see if the path already exists, if not attempt to create it here. Don't worry
212  // about error checking, if the path isn't created the file copy will fail anyway
213  if( !wxFileName::DirExists( destpath ) )
214  {
215  if( !wxFileName::Mkdir( destpath, 0777, wxPATH_MKDIR_FULL ) )
216  {
217  if( aErrorMsg )
218  {
219  if( !aErrorMsg->empty() )
220  *aErrorMsg += "\n";
221 
222  wxString msg;
223 
224  msg.Printf( _( "Cannot create folder \"%s\"." ), destpath );
225  *aErrorMsg += msg;
226  }
227 
228  continue;
229  }
230  }
231 
232  destFile.SetPath( destpath );
233 
234  if( !wxCopyFile( srcFile.GetFullPath(), destFile.GetFullPath() ) )
235  {
236  if( aErrorMsg )
237  {
238  if( !aErrorMsg->empty() )
239  *aErrorMsg += "\n";
240 
241  wxString msg;
242 
243  msg.Printf( _( "Cannot copy file \"%s\"." ), destFile.GetFullPath() );
244  *aErrorMsg += msg;
245  }
246 
247  result = false;
248  }
249  }
250 
251  return result;
252 }
253 
254 
256 {
257  wxFileInputStream input( GetHtmlFile().GetFullPath() );
258  wxString separator( wxT( "\x9" ) );
259  wxTextInputStream text( input, separator, wxConvUTF8 );
260 
261  /* Open HTML file and get the text between the title tags */
262  if( m_title == wxEmptyString )
263  {
264  int start = 0;
265  int finish = 0;
266  bool done = false;
267 
268  while( input.IsOk() && !input.Eof() && !done )
269  {
270  wxString line = text.ReadLine();
271  wxString upperline = line.Clone().Upper();
272 
273  start = upperline.Find( wxT( "<TITLE>" ) );
274  finish = upperline.Find( wxT( "</TITLE>" ) );
275  int length = finish - start - 7;
276 
277  // find the opening tag
278  if( start != wxNOT_FOUND )
279  {
280  if( finish != wxNOT_FOUND )
281  {
282  m_title = line( start + 7, length );
283  }
284  else
285  {
286  m_title = line.Mid( start + 7 );
287  }
288 
289  done = true;
290  }
291  else
292  {
293  if( finish != wxNOT_FOUND )
294  {
295  m_title += line.SubString( 0, finish );
296  done = true;
297  }
298  }
299 
300  // Remove line endings
301  m_title.Replace( wxT( "\r" ), wxT( " " ) );
302  m_title.Replace( wxT( "\n" ), wxT( " " ) );
303  }
304  }
305 
306  return &m_title;
307 }
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.
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.
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:60
#define _(s)
Definition: 3d_actions.cpp:33
~PROJECT_TEMPLATE()
Non-virtual destructor (so no derived classes)
wxBitmap * GetIcon()
Get the 64px^2 icon for the project template.