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-2017 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 
32 #include "project_template.h"
33 
34 
35 #define SEP() wxFileName::GetPathSeparator()
36 
37 
38 PROJECT_TEMPLATE::PROJECT_TEMPLATE( const wxString& aPath )
39 {
40  templateBasePath = wxFileName::DirName( aPath );
41  templateMetaPath = wxFileName::DirName( aPath + SEP() + METADIR );
42  templateMetaHtmlFile = wxFileName::FileName( aPath + SEP() + METADIR + SEP() +
44  templateMetaIconFile = wxFileName::FileName( aPath + SEP() + METADIR + SEP() + METAFILE_ICON );
45 
46  title = wxEmptyString;
47 
48  // Test the project template requirements to make sure aPath is a valid template structure.
49  if( !wxFileName::DirExists( templateBasePath.GetPath() ) )
50  {
51  // Error, the path doesn't exist!
52  title = _( "Could open the template path! " ) + aPath;
53  }
54  else if( !wxFileName::DirExists( templateMetaPath.GetPath() ) )
55  {
56  // Error, the meta information directory doesn't exist!
57  title = _( "Couldn't open the meta information directory for this template! " ) +
58  templateMetaPath.GetPath();
59  }
60  else if( !wxFileName::FileExists( templateMetaHtmlFile.GetFullPath() ) )
61  {
62  // Error, the meta information directory doesn't contain the informational html file!
63  title = _( "Cound't find the meta HTML information file for this template!" );
64  }
65 
66  // Try to load an icon
67  metaIcon = new wxBitmap( templateMetaIconFile.GetFullPath(), wxBITMAP_TYPE_PNG );
68 }
69 
70 
71 std::vector<wxFileName> PROJECT_TEMPLATE::GetFileList()
72 {
73  std::vector<wxFileName> files;
74  wxString f = templateBasePath.GetPath();
75  wxArrayString allfiles;
76  wxFileName p;
77 
78  wxDir::GetAllFiles( f, &allfiles );
79 
80  // Create the vector and ignore all of the meta data files!
81  for( size_t i=0; i < allfiles.size(); i++ )
82  {
83  p = allfiles[i];
84 
85  // Files that are in the meta directory must not be included
86  if( !p.GetPath().StartsWith( templateMetaPath.GetPath() ) )
87  files.push_back( allfiles[i] );
88  }
89 
90  return files;
91 }
92 
93 
95 {
96  return templateBasePath.GetDirs()[ templateBasePath.GetDirCount()-1 ];
97 }
98 
99 
101 {
102 
103 }
104 
105 
107 {
108  return templateMetaHtmlFile;
109 }
110 
111 
113 {
114  return metaIcon;
115 }
116 
117 
118 size_t PROJECT_TEMPLATE::GetDestinationFiles( const wxFileName& aNewProjectPath,
119  std::vector< wxFileName >& aDestFiles )
120 {
121  std::vector< wxFileName > srcFiles = GetFileList();
122 
123  // Find the template file name base. this is the name of the .pro template file
124  wxString basename;
125 
126  for( auto file : srcFiles )
127  {
128  if( file.GetExt() == wxT( "pro" ) )
129  {
130  basename = file.GetName();
131  break;
132  }
133  }
134 
135  for( auto file : srcFiles )
136  {
137  wxFileName destFile = file;
138 
139  // Replace the template filename with the project filename for the new project creation
140  wxString name = destFile.GetName();
141  name.Replace( basename, aNewProjectPath.GetName() );
142  destFile.SetName( name );
143 
144  // Replace the template path with the project path.
145  wxString path = destFile.GetPathWithSep();
146  path.Replace( templateBasePath.GetPathWithSep(), aNewProjectPath.GetPathWithSep() );
147  destFile.SetPath( path );
148 
149  aDestFiles.push_back( destFile );
150  }
151 
152  return aDestFiles.size();
153 }
154 
155 
156 bool PROJECT_TEMPLATE::CreateProject( wxFileName& aNewProjectPath, wxString* aErrorMsg )
157 {
158  // CreateProject copy the files from template to the new project folder
159  // and rename files which have the same name as the template .pro file
160  bool result = true;
161 
162  std::vector<wxFileName> srcFiles = GetFileList();
163 
164  // Find the template file name base. this is the name of the .pro template file
165  wxString basename;
166 
167  for( size_t i=0; i < srcFiles.size(); i++ )
168  {
169  if( srcFiles[i].GetExt() == wxT( "pro" ) )
170  {
171  basename = srcFiles[i].GetName();
172  break;
173  }
174  }
175 
176  for( size_t i=0; i < srcFiles.size(); i++ )
177  {
178  // Replace the template path
179  wxFileName destination = srcFiles[i];
180 
181  // Replace the template filename with the project filename for the new project creation
182  wxString currname = destination.GetName();
183  currname.Replace( basename, aNewProjectPath.GetName() );
184  destination.SetName( currname );
185 
186  // Replace the template path with the project path for the new project creation
187  // but keep the sub directory name, if exists
188  wxString destpath = destination.GetPathWithSep();
189  destpath.Replace( templateBasePath.GetPathWithSep(), aNewProjectPath.GetPathWithSep() );
190 
191  // Check to see if the path already exists, if not attempt to create it here. Don't worry
192  // about error checking, if the path isn't created the file copy will fail anyway
193 
194  if( !wxFileName::DirExists( destpath ) )
195  {
196  if( !wxFileName::Mkdir( destpath, 0777, wxPATH_MKDIR_FULL ) )
197  {
198  if( aErrorMsg )
199  {
200  if( !aErrorMsg->empty() )
201  *aErrorMsg += "\n";
202 
203  wxString msg;
204 
205  msg.Printf( _( "Cannot create folder '%s'." ), destpath );
206  *aErrorMsg += msg;
207  }
208 
209  continue;
210  }
211  }
212 
213  destination.SetPath( destpath );
214 
215  wxString srcFile = srcFiles[i].GetFullPath();
216  wxString dstFile = destination.GetFullPath();
217 
218  if( !wxCopyFile( srcFile, dstFile ) )
219  {
220  if( aErrorMsg )
221  {
222  if( !aErrorMsg->empty() )
223  *aErrorMsg += "\n";
224 
225  wxString msg;
226 
227  msg.Printf( _( "Cannot copy file '%s'." ), dstFile );
228  *aErrorMsg += msg;
229  }
230 
231 
232  result = false;
233  }
234  }
235 
236  return result;
237 }
238 
239 
241 {
242  wxFileInputStream input( GetHtmlFile().GetFullPath() );
243  wxString separator( wxT( "\x9" ) );
244  wxTextInputStream text( input, separator, wxConvUTF8 );
245 
246  /* Open HTML file and get the text between the title tags */
247  if( title == wxEmptyString )
248  {
249  int start = 0;
250  int finish = 0;
251  bool done = false;
252 
253  while( input.IsOk() && !input.Eof() && !done )
254  {
255  wxString line = text.ReadLine();
256 
257  start = line.Find( wxT( "<title>" ) );
258  if( start == wxNOT_FOUND )
259  start = line.Find( wxT( "<TITLE>" ) );
260 
261  finish = line.Find( wxT( "</title>" ) );
262  if( finish == wxNOT_FOUND )
263  finish = line.Find( wxT( "</TITLE>" ) );
264 
265  // find the opening tag
266  if( start != wxNOT_FOUND )
267  {
268  if( finish != wxNOT_FOUND )
269  {
270  title = line.SubString( start + 7, finish );
271  }
272  else
273  {
274  title = line.SubString( start + 7, line.Len() - 1 );
275  done = true;
276  }
277  }
278  else
279  {
280  if( finish != wxNOT_FOUND )
281  {
282  title += line.SubString( 0, finish );
283  done = true;
284  }
285  else
286  {
287  title += line;
288  }
289  }
290 
291  // Remove line endings
292  title.Replace( wxT( "\r" ), wxT( "" ) );
293  title.Replace( wxT( "\n" ), wxT( "" ) );
294  }
295  }
296 
297  return &title;
298 }
std::vector< wxFileName > GetFileList()
Get a vector list of filenames for the template.
wxFileName templateMetaHtmlFile
#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 templateBasePath
#define METAFILE_INFO_HTML
A required html formatted file which contains information about the project template.
#define SEP()
wxFileName templateMetaIconFile
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...
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.
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
wxFileName templateMetaPath
~PROJECT_TEMPLATE()
Non-virtual destructor (so no derived classes)
wxBitmap * GetIcon()
Get the 64px^2 icon for the project template.