25#include <wx/txtstrm.h>
26#include <wx/wfstream.h>
28#include <wx/textfile.h>
29#include <unordered_map>
37#define SEP wxFileName::GetPathSeparator()
50 if( !wxFileName::DirExists(
m_basePath.GetPath() ) )
53 m_error.Printf(
_(
"Could not open the template path '%s'" ), aPath );
55 else if( !wxFileName::DirExists(
m_metaPath.GetPath() ) )
58 m_error.Printf(
_(
"Could not find the expected 'meta' directory at '%s'" ),
m_metaPath.GetPath() );
86 virtual wxDirTraverseResult
OnFile(
const wxString& filename )
override
88 wxFileName fn( filename );
89 wxString
path( fn.GetPathWithSep() );
94 return wxDIR_CONTINUE;
96 bool exclude = fn.GetName().Contains(
"fp-info-cache" )
100 m_files.emplace_back( wxFileName( filename ) );
102 return wxDIR_CONTINUE;
105 virtual wxDirTraverseResult
OnDir(
const wxString& dirname )
override
107 wxFileName dir( dirname );
108 wxString parent = dir.GetPathWithSep();
112 if( dir.GetFullName() == wxT(
".git" ) ||
IsIgnored( parent, dir.GetFullName(),
true )
113 || dirname.StartsWith(
m_exclude ) || dirname.EndsWith(
"-backups" ) )
118 m_files.emplace_back( wxFileName::DirName( dirname ) );
120 return wxDIR_CONTINUE;
129 wxString gitignore =
path + wxT(
".gitignore" );
131 if( wxFileExists( gitignore ) )
133 wxFileInputStream input( gitignore );
134 wxTextInputStream
text( input, wxT(
"\x9" ), wxConvUTF8 );
136 while( input.IsOk() && !input.Eof() )
138 wxString line =
text.ReadLine();
140 line.Trim().Trim(
false );
142 if( line.IsEmpty() || line.StartsWith( wxT(
"#" ) ) )
148 m_files.emplace_back( wxFileName( gitignore ) );
155 wxString gitattributes =
path + wxT(
".gitattributes" );
157 if( wxFileExists( gitattributes ) )
158 m_files.emplace_back( wxFileName( gitattributes ) );
168 for(
const wxString& pattern : it->second )
170 bool dirOnly = pattern.EndsWith( wxT(
"/" ) );
171 wxString pat = dirOnly ? pattern.substr( 0, pattern.length() - 1 ) : pattern;
173 if( dirOnly && !isDir )
176 if( wxMatchWild( pat,
name ) )
191 std::vector<wxFileName> files;
195 dir.Traverse( sink, wxEmptyString, ( wxDIR_FILES | wxDIR_DIRS ) );
229 bool multipleProjectFilesFound =
false;
231 for( wxFileName& file : srcFiles )
235 if( !basename.IsEmpty() && basename != file.GetName() )
236 multipleProjectFilesFound =
true;
238 basename = file.GetName();
242 if( multipleProjectFilesFound )
245 for( wxFileName& srcFile : srcFiles )
248 wxFileName destFile = srcFile;
251 wxString
name = destFile.GetName();
252 name.Replace( basename, aNewProjectPath.GetName() );
253 destFile.SetName(
name );
257 wxString
path = destFile.GetPathWithSep();
258 path.Replace(
m_basePath.GetPathWithSep(), aNewProjectPath.GetPathWithSep() );
259 path.Replace(
SEP + basename +
SEP,
SEP + aNewProjectPath.GetName() +
SEP );
260 path.Replace(
SEP + basename + wxS(
"-" ),
SEP + aNewProjectPath.GetName() + wxS(
"-" ) );
261 destFile.SetPath(
path );
263 aDestFiles.push_back( destFile );
266 return aDestFiles.size();
281 bool multipleProjectFilesFound =
false;
283 for( wxFileName& file : srcFiles )
287 if( !basename.IsEmpty() && basename != file.GetName() )
288 multipleProjectFilesFound =
true;
290 basename = file.GetName();
294 if( multipleProjectFilesFound )
297 for( wxFileName& srcFile : srcFiles )
300 wxFileName destFile = srcFile;
303 wxString currname = destFile.GetName();
309 else if( destFile.GetName().EndsWith(
"-cache" ) || destFile.GetName().EndsWith(
"-rescue" ) )
311 currname.Replace( basename, aNewProjectPath.GetName() );
323 currname.Replace( basename, aNewProjectPath.GetName() );
326 destFile.SetName( currname );
330 wxString destpath = destFile.GetPathWithSep();
331 destpath.Replace(
m_basePath.GetPathWithSep(), aNewProjectPath.GetPathWithSep() );
332 destpath.Replace(
SEP + basename +
SEP,
SEP + aNewProjectPath.GetName() +
SEP );
333 destpath.Replace(
SEP + basename + wxS(
"-" ),
SEP + aNewProjectPath.GetName() + wxS(
"-" ) );
336 if( !wxFileName::DirExists( destpath ) )
338 if( !wxFileName::Mkdir( destpath, 0777, wxPATH_MKDIR_FULL ) )
342 if( !aErrorMsg->empty() )
347 msg.Printf(
_(
"Cannot create folder '%s'." ), destpath );
355 destFile.SetPath( destpath );
357 if( srcFile.FileExists() )
359 if( !wxCopyFile( srcFile.GetFullPath(), destFile.GetFullPath() ) )
363 if( !aErrorMsg->empty() )
368 msg.Printf(
_(
"Cannot copy file '%s'." ), destFile.GetFullPath() );
392 wxFFileInputStream input(
GetHtmlFile().GetFullPath() );
393 wxString separator( wxT(
"\x9" ) );
394 wxTextInputStream
text( input, separator, wxConvUTF8 );
399 bool hasStart =
false;
401 while( input.IsOk() && !input.Eof() && !done )
403 wxString line =
text.ReadLine();
404 wxString upperline = line.Clone().Upper();
406 start = upperline.Find( wxT(
"<TITLE>" ) );
407 finish = upperline.Find( wxT(
"</TITLE>" ) );
408 int length = finish - start - 7;
411 if( start != wxNOT_FOUND )
413 if( finish != wxNOT_FOUND )
415 m_title = line( start + 7, length );
420 m_title = line.Mid( start + 7 );
426 if( finish != wxNOT_FOUND )
428 m_title += line.SubString( 0, finish - 1 );
437 m_title.Replace( wxT(
"\r" ), wxT(
"" ) );
438 m_title.Replace( wxT(
"\n" ), wxT(
"" ) );
450 if( aBaseDir.IsEmpty() )
453 wxFileName templatePath;
454 templatePath.AssignDir( aBaseDir );
456 templatePath.AppendDir( wxT(
"default" ) );
458 if( !templatePath.DirExists() && !templatePath.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
461 wxFileName metaDir = templatePath;
464 if( !metaDir.DirExists() && !metaDir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
467 wxFileName infoFile = metaDir;
470 if( !infoFile.FileExists() )
472 wxFFile
info( infoFile.GetFullPath(), wxT(
"w" ) );
474 if( !
info.IsOpened() )
477 info.Write( wxT(
"<html><head><title>Default</title></head><body>"
478 "<h3>Default KiCad project template.</h3></body></html>" ) );
482 wxFileName proFile = templatePath;
483 proFile.SetFullName( wxT(
"default.kicad_pro" ) );
485 if( !proFile.FileExists() )
487 wxFFile proj( proFile.GetFullPath(), wxT(
"w" ) );
489 if( !proj.IsOpened() )
492 proj.Write( wxT(
"{\n \"meta\": {\n \"version\": 1\n }\n}\n" ) );
496 if( infoFile.FileExists() && proFile.FileExists() )
virtual wxDirTraverseResult OnDir(const wxString &dirname) override
FILE_TRAVERSER(std::vector< wxFileName > &files, const wxString &exclude)
void EnsureGitFiles(const wxString &path)
virtual wxDirTraverseResult OnFile(const wxString &filename) override
std::unordered_map< wxString, std::vector< wxString > > m_gitIgnores
std::vector< wxFileName > & m_files
bool IsIgnored(const wxString &path, const wxString &name, bool isDir)
wxBitmap * GetIcon()
Get the 64px^2 icon for the project template.
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.
wxFileName m_metaHtmlFile
PROJECT_TEMPLATE(const wxString &aPath)
Create a new project instance from aPath.
std::vector< wxFileName > GetFileList()
Get a vector list of filenames for the template.
~PROJECT_TEMPLATE()
Non-virtual destructor (so no derived classes)
wxFileName GetHtmlFile()
Get the full Html filename for the project template.
wxString * GetTitle()
Get the title of the project (extracted from the html title tag)
bool CreateProject(wxFileName &aNewProjectPath, wxString *aErrorMsg=nullptr)
Copies and renames all template files to create a new project.
wxFileName m_metaIconFile
wxString GetPrjDirName()
Get the dir name of the project template (i.e.
static const std::string ProjectFileExtension
static const std::string LegacyProjectFileExtension
static const std::string LegacySymbolLibFileExtension
static const std::string LockFilePrefix
static const std::string DrawingSheetFileExtension
static const std::string LegacySymbolDocumentFileExtension
static const std::string KiCadFootprintLibPathExtension
wxFileName EnsureDefaultProjectTemplate(const wxString &aBaseDir)
Seed the built-in "default" project template under aBaseDir, creating the directory tree and minimal ...
#define METAFILE_ICON
An optional png icon, exactly 64px x 64px which is used in the template selector if present.
#define METADIR
A directory which contains information about the project template and does not get copied.
#define METAFILE_INFO_HTML
A required html formatted file which contains information about the project template.
wxString result
Test unit parsing edge cases and error handling.
Definition of file extensions used in Kicad.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().