28#include <wx/txtstrm.h> 
   29#include <wx/wfstream.h> 
   31#include <wx/textfile.h> 
   32#include <unordered_map> 
   38#define SEP wxFileName::GetPathSeparator() 
   51    if( !wxFileName::DirExists( 
m_basePath.GetPath() ) )
 
   54        m_title.Printf( 
_( 
"Could not open the template path '%s'" ), aPath );
 
   56    else if( !wxFileName::DirExists( 
m_metaPath.GetPath() ) )
 
   59        m_title.Printf( 
_( 
"Could not find the expected 'meta' directory at '%s'" ), 
m_metaPath.GetPath() );
 
 
   84    virtual wxDirTraverseResult 
OnFile( 
const wxString& filename )
 override 
   86        wxFileName fn( filename );
 
   87        wxString   
path( fn.GetPathWithSep() );
 
   92            return wxDIR_CONTINUE;
 
   94        bool exclude = fn.GetName().Contains( 
"fp-info-cache" )
 
   98            m_files.emplace_back( wxFileName( filename ) );
 
  100        return wxDIR_CONTINUE;
 
 
  103    virtual wxDirTraverseResult 
OnDir( 
const wxString& dirname )
 override 
  105        wxFileName dir( dirname );
 
  106        wxString   parent = dir.GetPathWithSep();
 
  110        if( dir.GetFullName() == wxT( 
".git" ) || 
IsIgnored( parent, dir.GetFullName(), 
true )
 
  111            || dirname.StartsWith( 
m_exclude ) || dirname.EndsWith( 
"-backups" ) )
 
  116        m_files.emplace_back( wxFileName::DirName( dirname ) );
 
  118        return wxDIR_CONTINUE;
 
 
  127        wxString gitignore = 
path + wxT( 
".gitignore" );
 
  129        if( wxFileExists( gitignore ) )
 
  131            wxFileInputStream input( gitignore );
 
  132            wxTextInputStream 
text( input, wxT( 
"\x9" ), wxConvUTF8 );
 
  134            while( input.IsOk() && !input.Eof() )
 
  136                wxString line = 
text.ReadLine();
 
  138                line.Trim().Trim( 
false );
 
  140                if( line.IsEmpty() || line.StartsWith( wxT( 
"#" ) ) )
 
  146            m_files.emplace_back( wxFileName( gitignore ) );
 
  153        wxString gitattributes = 
path + wxT( 
".gitattributes" );
 
  155        if( wxFileExists( gitattributes ) )
 
  156            m_files.emplace_back( wxFileName( gitattributes ) );
 
 
  166        for( 
const wxString& pattern : it->second )
 
  168            bool     dirOnly = pattern.EndsWith( wxT( 
"/" ) );
 
  169            wxString pat = dirOnly ? pattern.substr( 0, pattern.length() - 1 ) : pattern;
 
  171            if( dirOnly && !isDir )
 
  174            if( wxMatchWild( pat, 
name ) )
 
 
 
  189    std::vector<wxFileName> files;
 
  193    dir.Traverse( sink, wxEmptyString, ( wxDIR_FILES | wxDIR_DIRS ) );
 
 
  227    bool     multipleProjectFilesFound = 
false;
 
  229    for( wxFileName& file : srcFiles )
 
  233            if( !basename.IsEmpty() && basename != file.GetName() )
 
  234                multipleProjectFilesFound = 
true;
 
  236            basename = file.GetName();
 
  240    if( multipleProjectFilesFound )
 
  243    for( wxFileName& srcFile : srcFiles )
 
  246        wxFileName destFile = srcFile;
 
  249        wxString 
name = destFile.GetName();
 
  250        name.Replace( basename, aNewProjectPath.GetName() );
 
  251        destFile.SetName( 
name );
 
  254        wxString 
path = destFile.GetPathWithSep();
 
  255        path.Replace( 
m_basePath.GetPathWithSep(), aNewProjectPath.GetPathWithSep() );
 
  256        destFile.SetPath( 
path );
 
  258        aDestFiles.push_back( destFile );
 
  261    return aDestFiles.size();
 
 
  276    bool     multipleProjectFilesFound = 
false;
 
  278    for( wxFileName& file : srcFiles )
 
  282            if( !basename.IsEmpty() && basename != file.GetName() )
 
  283                multipleProjectFilesFound = 
true;
 
  285            basename = file.GetName();
 
  289    if( multipleProjectFilesFound )
 
  292    for( wxFileName& srcFile : srcFiles )
 
  295        wxFileName destFile = srcFile;
 
  298        wxString currname = destFile.GetName();
 
  304        else if( destFile.GetName().EndsWith( 
"-cache" ) || destFile.GetName().EndsWith( 
"-rescue" ) )
 
  306            currname.Replace( basename, aNewProjectPath.GetName() );
 
  318            currname.Replace( basename, aNewProjectPath.GetName() );
 
  321        destFile.SetName( currname );
 
  325        wxString destpath = destFile.GetPathWithSep();
 
  326        destpath.Replace( 
m_basePath.GetPathWithSep(), aNewProjectPath.GetPathWithSep() );
 
  329        if( !wxFileName::DirExists( destpath ) )
 
  331            if( !wxFileName::Mkdir( destpath, 0777, wxPATH_MKDIR_FULL ) )
 
  335                    if( !aErrorMsg->empty() )
 
  340                    msg.Printf( 
_( 
"Cannot create folder '%s'." ), destpath );
 
  348        destFile.SetPath( destpath );
 
  350        if( srcFile.FileExists() && !wxCopyFile( srcFile.GetFullPath(), destFile.GetFullPath() ) )
 
  354                if( !aErrorMsg->empty() )
 
  359                msg.Printf( 
_( 
"Cannot copy file '%s'." ), destFile.GetFullPath() );
 
 
  373    wxFFileInputStream input( 
GetHtmlFile().GetFullPath() );
 
  374    wxString           separator( wxT( 
"\x9" ) );
 
  375    wxTextInputStream  
text( input, separator, wxConvUTF8 );
 
  383        bool hasStart = 
false;
 
  385        while( input.IsOk() && !input.Eof() && !done )
 
  387            wxString line = 
text.ReadLine();
 
  388            wxString upperline = line.Clone().Upper();
 
  390            start = upperline.Find( wxT( 
"<TITLE>" ) );
 
  391            finish = upperline.Find( wxT( 
"</TITLE>" ) );
 
  392            int length = finish - start - 7;
 
  395            if( start != wxNOT_FOUND )
 
  397                if( finish != wxNOT_FOUND )
 
  399                    m_title = line( start + 7, length );
 
  404                    m_title = line.Mid( start + 7 );
 
  410                if( finish != wxNOT_FOUND )
 
  412                    m_title += line.SubString( 0, finish - 1 );
 
  421        m_title.Replace( wxT( 
"\r" ), wxT( 
"" ) );
 
  422        m_title.Replace( wxT( 
"\n" ), wxT( 
"" ) );
 
 
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
 
#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.