39#define CFGFILE_VERSION 1
42#define ERRFLG_ALIAS (1)
43#define ERRFLG_RELPATH (2)
44#define ERRFLG_ENVPATH (4)
46#define MASK_3D_RESOLVER "3D_RESOLVER"
61 if( aConfigDir.empty() )
68 if( !cfgdir.DirExists() )
89 if( !projdir.DirExists() )
100 al.
m_Alias = wxS(
"${KIPRJMOD}" );
125 std::ostringstream ostr;
126 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
127 ostr <<
" * [INFO] changed project dir to ";
128 ostr <<
m_paths.front().m_Pathexp.ToUTF8();
166 lpath.
m_Alias = wxS(
"${KIPRJMOD}" );
171 wxUniChar psep = fndummy.GetPathSeparator();
172 std::list< wxString > epaths;
176 for(
const wxString& currPath : epaths )
178 wxString currPathVarFormat = currPath;
179 currPathVarFormat.Prepend( wxS(
"${" ) );
180 currPathVarFormat.Append( wxS(
"}" ) );
184 if( pathVal.empty() )
190 fndummy.Assign( pathVal,
"" );
205 lpath.
m_Alias = currPathVarFormat;
215 std::list< SEARCH_PATH >::const_iterator sPL =
m_paths.begin();
219 wxLogTrace(
MASK_3D_RESOLVER, wxS(
" + %s : '%s'\n" ), (*sPL).m_Alias.GetData(),
220 (*sPL).m_Pathexp.GetData() );
231 wxUniChar envMarker(
'$' );
233 while( !
m_paths.empty() && envMarker != *
m_paths.back().m_Alias.rbegin() )
247 if( aFileName.empty() )
248 return wxEmptyString;
254 wxString tname = aFileName;
262 wxFileName tmpFN( tname );
266 if( tmpFN.FileExists() )
269 tname = tmpFN.GetFullPath();
273 if( aFileName.StartsWith( wxS(
"${" ) ) || aFileName.StartsWith( wxS(
"$(" ) ) )
281 if( aFileName.StartsWith(
"${" ) || aFileName.StartsWith(
"$(" ) )
286 wxString errmsg =
"[3D File Resolver] No such path; ensure the environment var is defined";
287 errmsg.append(
"\n" );
288 errmsg.append( tname );
289 errmsg.append(
"\n" );
293 return wxEmptyString;
305 if( !
m_paths.begin()->m_Pathexp.empty() && !tname.StartsWith(
":" ) )
307 tmpFN.Assign(
m_paths.begin()->m_Pathexp,
"" );
308 wxString fullPath = tmpFN.GetPathWithSep() + tname;
312 if( wxFileName::FileExists( fullPath ) )
314 tmpFN.Assign( fullPath );
316 tname = tmpFN.GetFullPath();
323 if( !aWorkingPath.IsEmpty() && !tname.StartsWith(
":" ) )
325 wxString tmp = aWorkingPath;
326 tmp.Append( tmpFN.GetPathSeparator() );
330 if( tmpFN.MakeAbsolute() && tmpFN.FileExists() )
332 tname = tmpFN.GetFullPath();
338 if( !tname.StartsWith( wxS(
":" ) ) )
341 wxString fullPath( wxS(
"${KICAD7_3DMODEL_DIR}" ) );
342 fullPath.Append( fpath.GetPathSeparator() );
343 fullPath.Append( tname );
345 fpath.Assign( fullPath );
349 tname = fpath.GetFullPath();
366 wxString errmsg =
"[3D File Resolver] No such path";
367 errmsg.append( wxS(
"\n" ) );
368 errmsg.append( tname );
369 errmsg.append( wxS(
"\n" ) );
373 return wxEmptyString;
379 if(
path.m_Alias.StartsWith( wxS(
"${" ) ) ||
path.m_Alias.StartsWith( wxS(
"$(" ) ) )
382 if(
path.m_Alias == alias && !
path.m_Pathexp.empty() )
384 wxFileName fpath( wxFileName::DirName(
path.m_Pathexp ) );
385 wxString fullPath = fpath.GetPathWithSep() + relpath;
389 if( wxFileName::FileExists( fullPath ) )
393 wxFileName tmp( fullPath );
396 tname = tmp.GetFullPath();
406 wxString errmsg =
"[3D File Resolver] No such path; ensure the path alias is defined";
407 errmsg.append(
"\n" );
408 errmsg.append( tname.substr( 1 ) );
409 errmsg.append(
"\n" );
413 return wxEmptyString;
427 while( tpath.
m_Pathvar.EndsWith( wxT(
"\\" ) ) )
438 if( !
path.DirExists() )
440 if( aPath.
m_Pathvar == wxS(
"${KICAD7_3DMODEL_DIR}" )
442 || aPath.
m_Pathvar == wxS(
"${KISYS3DMOD}" ) || aPath.
m_Pathvar == wxS(
"$(KISYS3DMOD)" ) )
448 wxString msg =
_(
"The given path does not exist" );
449 msg.append( wxT(
"\n" ) );
461 while( tpath.
m_Pathexp.EndsWith( wxT(
"\\" ) ) )
469 std::list< SEARCH_PATH >::iterator sPL =
m_paths.begin();
470 std::list< SEARCH_PATH >::iterator ePL =
m_paths.end();
474 if( tpath.
m_Alias == sPL->m_Alias )
476 wxString msg =
_(
"Alias: " );
478 msg.append( wxT(
"\n" ) );
479 msg.append(
_(
"This path:" ) + wxS(
" " ) );
481 msg.append( wxT(
"\n" ) );
482 msg.append(
_(
"Existing path:" ) + wxS(
" " ) );
483 msg.append( sPL->m_Pathvar );
498 bool useParen =
false;
500 if( aPath.StartsWith( wxS(
"$(" ) ) )
502 else if( !aPath.StartsWith( wxS(
"${" ) ) )
508 pEnd = aPath.find( wxS(
")" ) );
510 pEnd = aPath.find( wxS(
"}" ) );
512 if( pEnd == wxString::npos )
515 wxString envar = aPath.substr( 0, pEnd + 1 );
524 if( sPL->m_Alias == envar )
527 if( !sPL->m_Alias.StartsWith( wxS(
"${" ) ) )
538 wxUniChar psep = tmpFN.GetPathSeparator();
541 if( !tmpFN.DirExists() )
558 wxString fname = aFullPathName;
565 std::list< SEARCH_PATH >::const_iterator sL =
m_paths.begin();
572 if( sL->m_Pathexp.empty() )
581 if( sL->m_Alias.StartsWith( wxS(
"${" ) ) || sL->m_Alias.StartsWith( wxS(
"$(" ) ) )
591 fpath.Assign( tpath, wxT(
"" ) );
595 fpath.Assign( sL->m_Pathexp, wxT(
"" ) );
598 wxString fps = fpath.GetPathWithSep();
601 idx = fname.find( fps );
605 fname = fname.substr( fps.size() );
609 fname.Replace( wxT(
"\\" ), wxT(
"/" ) );
612 if( sL->m_Alias.StartsWith( wxS(
"${" ) ) || sL->m_Alias.StartsWith( wxS(
"$(" ) ) )
616 tname.Append( wxS(
"/" ) );
617 tname.append( fname );
623 tname.append( sL->m_Alias );
624 tname.append( wxS(
"}/" ) );
625 tname.append( fname );
639 fname.Replace( wxT(
"\\" ), wxT(
"/" ) );
654 wxString& anAlias, wxString& aRelPath )
const
659 size_t searchStart = 0;
661 if( aFileName.StartsWith( wxT(
":" ) ) )
664 size_t tagpos = aFileName.find( wxT(
":" ), searchStart );
666 if( tagpos == wxString::npos || tagpos == searchStart )
669 if( tagpos + 1 >= aFileName.length() )
672 anAlias = aFileName.substr( searchStart, tagpos - searchStart );
673 aRelPath = aFileName.substr( tagpos + 1 );
688 if( aFileName.empty() )
691 wxString filename = aFileName;
693 size_t aliasStart = aFileName.StartsWith(
':' ) ? 1 : 0;
694 size_t aliasEnd = aFileName.find(
':', aliasStart );
698 filename.Replace( wxT(
"/" ), wxT(
"\\" ) );
701 if( aliasEnd != wxString::npos )
703 size_t pos1 = filename.find( wxT(
":\\" ) );
705 if( pos1 != wxString::npos && ( pos1 != aliasEnd || pos1 != 1 ) )
709 if( pos1 != wxString::npos )
710 aliasEnd = wxString::npos;
713 filename.Replace( wxT(
"\\" ), wxT(
"/" ) );
717 if( aliasEnd == aFileName.length() -1 )
720 if( aliasEnd != wxString::npos )
723 if( aliasEnd == aliasStart )
726 lpath = filename.substr( aliasStart, aliasEnd );
729 if( wxString::npos != lpath.find_first_of( wxT(
"{}[]()%~<>\"='`;:.,&?/\\|$" ) ) )
733 lpath = aFileName.substr( aliasEnd + 1 );
741 aliasEnd = wxString::npos;
743 if( aFileName.StartsWith( wxS(
"${" ) ) )
744 aliasEnd = aFileName.find(
'}' );
745 else if( aFileName.StartsWith( wxS(
"$(" ) ) )
746 aliasEnd = aFileName.find(
')' );
748 if( aliasEnd != wxString::npos )
749 lpath = aFileName.substr( aliasEnd + 1 );
757 wxString lpath_no_sep = lpath;
759 lpath_no_sep.Replace(
"/",
" " );
760 lpath_no_sep.Replace(
"\\",
" " );
763 if( lpath_no_sep.Length() > 1 && lpath_no_sep[1] ==
':' )
764 lpath_no_sep[1] =
' ';
767 if( wxString::npos != lpath_no_sep.find_first_of( wxFileName::GetForbiddenChars() ) )
781 bool hasKisys3D =
false;
792 if( mS->first == wxS(
"KICAD_PTEMPLATES" )
793 || mS->first.Matches( wxS(
"KICAD*_FOOTPRINT_DIR") ) )
799 if( wxString::npos != mS->second.GetValue().find( wxS(
"://" ) ) )
806 paths.push_back( mS->first );
808 if( mS->first.Matches( wxS(
"KICAD*_3DMODEL_DIR") ) )
815 paths.emplace_back( wxS(
"KICAD7_3DMODEL_DIR") );
bool ValidateFileName(const wxString &aFileName, bool &hasAlias) const
Returns true if the given path is a valid aliased relative path.
bool createPathList(void)
Build the path list using available information such as KICAD7_3DMODEL_DIR and the 3d_path_list confi...
bool addPath(const SEARCH_PATH &aPath)
Check that a path is valid and adds it to the search list.
wxString GetProjectDir() const
bool GetKicadPaths(std::list< wxString > &paths) const
Return a list of path environment variables local to KiCad.
bool Set3DConfigDir(const wxString &aConfigDir)
Set the user's configuration directory for 3D models.
void checkEnvVarPath(const wxString &aPath)
Check the ${ENV_VAR} component of a path and adds it to the resolver's path list if it is not yet in ...
std::list< SEARCH_PATH > m_paths
bool SetProject(PROJECT *aProject, bool *flgChanged=nullptr)
Set the current KiCad project directory as the first entry in the model path list.
void SetProgramBase(PGM_BASE *aBase)
Set a pointer to the application's PGM_BASE instance used to extract the local env vars.
bool SplitAlias(const wxString &aFileName, wxString &anAlias, wxString &aRelPath) const
Return true if the given name contains an alias and populates the string anAlias with the alias and a...
const std::list< SEARCH_PATH > * GetPaths() const
Return a pointer to the internal path list; the items in:load.
wxString ResolvePath(const wxString &aFileName, const wxString &aWorkingPath)
Determines the full path of the given file name.
bool UpdatePathList(const std::vector< SEARCH_PATH > &aPathList)
Clear the current path list and substitutes the given path list and update the path configuration fil...
wxString ShortenPath(const wxString &aFullPathName)
Produce a relative path based on the existing search directories or returns the same path if the path...
Container for data for KiCad programs.
virtual ENV_VAR_MAP & GetLocalEnvVariables() const
Container for project specific data.
virtual const wxString GetProjectPath() const
Return the full path of the project.
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
This file is part of the common library.
static std::mutex mutex_resolver
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
std::map< wxString, ENV_VAR_ITEM >::const_iterator ENV_VAR_MAP_CITER
wxLogTrace helper definitions.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().