3D file name resolver improvements.
* Paths defined via pcbnew->Preferences->Configure Paths are now included in the 3D file browser's drop-down list except for KICAD_PTEMPLATES, KIGITHUB, KISYSMOD, any paths resembling a URL, and any non-existent paths. When an absolute path is shortened using one of these path aliases, let's say 'KISYS3DMOD' then the name appears in the pcb file as "${KISYS3DMOD}/blah.wrl". If a user defines and actual environment variable with the same name, then that user defined variable will have precedence over the internally defined variable. * Paths relative to the current project directory are no longer represented as "some/path/to/file.wrl". For compatibility with previous KiCad versions it shall always be stored as ${KIPRJMOD}/some/path/to/file.wrl. * Various restrictions on alias path values have been removed since the imposed restrictions could result in corrupted user data as aliases are silently dropped. * Overall the patch should improve back-compatibility by providing a ${ENV_VAR} mechanism for supporting different model root directories and ensuring that paths relative to KIPRJMOD are expressed in a way that is compatible with earlier KiCad versions. This allows users more flexibility and the ability to work in a way that ensures 3D model files can be correctly resolved in earlier versions of KiCad. Users who do not care about back-compatibility may prefer to use the newer alias system.
This commit is contained in:
parent
32fc9198c3
commit
6120472d60
|
@ -686,6 +686,13 @@ bool S3D_CACHE::SetProjectDir( const wxString& aProjDir )
|
|||
}
|
||||
|
||||
|
||||
void S3D_CACHE::SetProgramBase( PGM_BASE* aBase )
|
||||
{
|
||||
m_FNResolver->SetProgramBase( aBase );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
wxString S3D_CACHE::GetProjectDir( void )
|
||||
{
|
||||
return m_FNResolver->GetProjectDir();
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "plugins/3dapi/c3dmodel.h"
|
||||
|
||||
|
||||
class PGM_BASE;
|
||||
class S3D_CACHE;
|
||||
class S3D_CACHE_ENTRY;
|
||||
class SCENEGRAPH;
|
||||
|
@ -138,6 +139,14 @@ public:
|
|||
*/
|
||||
bool SetProjectDir( const wxString& aProjDir );
|
||||
|
||||
/**
|
||||
* Function SetProgramBase
|
||||
* sets the filename resolver's pointer to the application's
|
||||
* PGM_BASE instance; the pointer is used to extract the
|
||||
* local env vars.
|
||||
*/
|
||||
void SetProgramBase( PGM_BASE* aBase );
|
||||
|
||||
/**
|
||||
* Function GetProjectDir
|
||||
* returns the current project's working directory
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <wx/thread.h>
|
||||
#include <pgm_base.h>
|
||||
#include "3d_cache_wrapper.h"
|
||||
|
||||
static wxCriticalSection lock3D_wrapper;
|
||||
|
@ -57,6 +58,7 @@ S3D_CACHE* PROJECT::Get3DCacheManager( bool updateProjDir )
|
|||
wxFileName cfgpath;
|
||||
cfgpath.AssignDir( GetKicadConfigPath() );
|
||||
cfgpath.AppendDir( wxT( "3d" ) );
|
||||
cache->SetProgramBase( &Pgm() );
|
||||
cache->Set3DConfigDir( cfgpath.GetFullPath() );
|
||||
SetElem( ELEM_3DCACHE, cw );
|
||||
updateProjDir = true;
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <wx/thread.h>
|
||||
#include <wx/utils.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <pgm_base.h>
|
||||
|
||||
#include "3d_filename_resolver.h"
|
||||
|
||||
|
@ -54,6 +55,7 @@ static bool getHollerith( const std::string& aString, size_t& aIndex, wxString&
|
|||
S3D_FILENAME_RESOLVER::S3D_FILENAME_RESOLVER()
|
||||
{
|
||||
m_errflags = 0;
|
||||
m_pgm = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -86,7 +88,7 @@ bool S3D_FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgCh
|
|||
if( false == projdir.DirExists() )
|
||||
return false;
|
||||
|
||||
wxString path = projdir.GetPath();
|
||||
m_curProjDir = projdir.GetPath();
|
||||
|
||||
if( flgChanged )
|
||||
*flgChanged = false;
|
||||
|
@ -96,7 +98,7 @@ bool S3D_FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgCh
|
|||
S3D_ALIAS al;
|
||||
al.m_alias = _( "(DEFAULT)" );
|
||||
al.m_pathvar = _( "${PROJDIR}" );
|
||||
al.m_pathexp = path;
|
||||
al.m_pathexp = m_curProjDir;
|
||||
al.m_description = _( "Current project directory" );
|
||||
m_Paths.push_back( al );
|
||||
m_NameMap.clear();
|
||||
|
@ -107,9 +109,9 @@ bool S3D_FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgCh
|
|||
}
|
||||
else
|
||||
{
|
||||
if( m_Paths.front().m_pathexp.Cmp( path ) )
|
||||
if( m_Paths.front().m_pathexp.Cmp( m_curProjDir ) )
|
||||
{
|
||||
m_Paths.front().m_pathexp = path;
|
||||
m_Paths.front().m_pathexp = m_curProjDir;
|
||||
m_NameMap.clear();
|
||||
|
||||
if( flgChanged )
|
||||
|
@ -138,10 +140,22 @@ bool S3D_FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgCh
|
|||
|
||||
wxString S3D_FILENAME_RESOLVER::GetProjectDir( void )
|
||||
{
|
||||
if( m_Paths.empty() )
|
||||
return wxEmptyString;
|
||||
return m_curProjDir;
|
||||
}
|
||||
|
||||
return m_Paths.front().m_pathexp;
|
||||
|
||||
void S3D_FILENAME_RESOLVER::SetProgramBase( PGM_BASE* aBase )
|
||||
{
|
||||
m_pgm = aBase;
|
||||
|
||||
if( NULL == m_pgm || m_Paths.empty() )
|
||||
return;
|
||||
|
||||
// recreate the path list
|
||||
m_Paths.clear();
|
||||
createPathList();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -157,15 +171,61 @@ bool S3D_FILENAME_RESOLVER::createPathList( void )
|
|||
// the user may change this later with a call to SetProjectDir()
|
||||
|
||||
S3D_ALIAS lpath;
|
||||
lpath.m_alias = _( "(DEFAULT)" );
|
||||
lpath.m_pathvar = _( "${PROJDIR}" );
|
||||
lpath.m_description = _( "Current project directory" );
|
||||
lpath.m_alias = _( "${KIPRJMOD}" );
|
||||
lpath.m_pathvar = _( "${KIPRJMOD}" );
|
||||
lpath.m_pathexp = m_curProjDir;
|
||||
m_Paths.push_back( lpath );
|
||||
wxFileName fndummy;
|
||||
wxUniChar psep = fndummy.GetPathSeparator();
|
||||
|
||||
lpath.m_alias = wxT( "KISYS3DMOD" );
|
||||
lpath.m_pathvar = wxT( "${KISYS3DMOD}" );
|
||||
lpath.m_description = _( "Legacy 3D environment path" );
|
||||
addPath( lpath );
|
||||
// iterate over the list of internally defined ENV VARs
|
||||
// and add existing paths to the resolver
|
||||
if( m_pgm )
|
||||
{
|
||||
ENV_VAR_MAP_CITER mS = m_pgm->GetLocalEnvVariables().begin();
|
||||
ENV_VAR_MAP_CITER mE = m_pgm->GetLocalEnvVariables().end();
|
||||
|
||||
while( mS != mE )
|
||||
{
|
||||
// filter out URLs, template directories, and known system paths
|
||||
if( mS->first == wxString( "KICAD_PTEMPLATES" )
|
||||
|| mS->first == wxString( "KIGITHUB" )
|
||||
|| mS->first == wxString( "KISYSMOD" ) )
|
||||
{
|
||||
++mS;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( wxString::npos != mS->second.GetValue().find( wxString( "://" ) ) )
|
||||
{
|
||||
++mS;
|
||||
continue;
|
||||
}
|
||||
|
||||
fndummy.Assign( mS->second.GetValue(), "" );
|
||||
|
||||
if( !fndummy.DirExists() )
|
||||
{
|
||||
++mS;
|
||||
continue;
|
||||
}
|
||||
|
||||
wxString tmp( "${" );
|
||||
tmp.Append( mS->first );
|
||||
tmp.Append( "}" );
|
||||
|
||||
lpath.m_alias = tmp;
|
||||
lpath.m_pathvar = tmp;
|
||||
lpath.m_pathexp = mS->second.GetValue();
|
||||
|
||||
if( !lpath.m_pathexp.empty() && psep == *lpath.m_pathexp.rbegin() )
|
||||
lpath.m_pathexp.erase( --lpath.m_pathexp.end() );
|
||||
|
||||
m_Paths.push_back( lpath );
|
||||
|
||||
++mS;
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_ConfigDir.empty() )
|
||||
readPathList();
|
||||
|
@ -191,7 +251,9 @@ bool S3D_FILENAME_RESOLVER::createPathList( void )
|
|||
|
||||
bool S3D_FILENAME_RESOLVER::UpdatePathList( std::vector< S3D_ALIAS >& aPathList )
|
||||
{
|
||||
while( m_Paths.size() > 2 )
|
||||
wxUniChar envMarker( '$' );
|
||||
|
||||
while( !m_Paths.empty() && envMarker != *m_Paths.back().m_alias.rbegin() )
|
||||
m_Paths.pop_back();
|
||||
|
||||
size_t nI = aPathList.size();
|
||||
|
@ -258,6 +320,11 @@ wxString S3D_FILENAME_RESOLVER::ResolvePath( const wxString& aFileName )
|
|||
|
||||
return tname;
|
||||
}
|
||||
else if( resolveVirtualEnv( aFileName, tname ) )
|
||||
{
|
||||
m_NameMap.insert( std::pair< wxString, wxString > ( aFileName, tname ) );
|
||||
return tname;
|
||||
}
|
||||
|
||||
if( !( m_errflags & ERRFLG_ENVPATH ) )
|
||||
{
|
||||
|
@ -276,7 +343,8 @@ wxString S3D_FILENAME_RESOLVER::ResolvePath( const wxString& aFileName )
|
|||
|
||||
// check the path relative to the current project directory;
|
||||
// note: this is not necessarily the same as the current working
|
||||
// directory, which has already been checked
|
||||
// directory, which has already been checked. This case accounts
|
||||
// for partial paths which do not contain ${KIPRJMOD}.
|
||||
if( !sPL->m_pathexp.empty() )
|
||||
{
|
||||
wxFileName fpath( wxFileName::DirName( sPL->m_pathexp ) );
|
||||
|
@ -295,28 +363,33 @@ wxString S3D_FILENAME_RESOLVER::ResolvePath( const wxString& aFileName )
|
|||
}
|
||||
}
|
||||
|
||||
++sPL; // skip to item 2: KISYS3DMOD
|
||||
|
||||
// check if the path is relative to KISYS3DMOD but lacking
|
||||
// the "KISYS3DMOD:" alias tag
|
||||
if( !sPL->m_pathexp.empty() )
|
||||
// ${ENV_VAR} paths have already been checked; skip all but
|
||||
// ${KISYS3DMOD}, since legacy behavior was to check if paths
|
||||
// were relative to ${KISYS3DMOD}
|
||||
while( sPL != ePL && sPL->m_alias.StartsWith( "${" ) )
|
||||
{
|
||||
wxFileName fpath( wxFileName::DirName( sPL->m_pathexp ) );
|
||||
wxString fullPath = fpath.GetPathWithSep() + tname;
|
||||
|
||||
if( wxFileName::FileExists( fullPath ) )
|
||||
if( sPL->m_alias == "${KISYS3DMOD}" )
|
||||
{
|
||||
wxFileName tmp( fullPath );
|
||||
wxFileName fpath( wxFileName::DirName( sPL->m_pathexp ) );
|
||||
wxString fullPath = fpath.GetPathWithSep() + tname;
|
||||
|
||||
if( tmp.Normalize() )
|
||||
tname = tmp.GetFullPath();
|
||||
if( wxFileName::FileExists( fullPath ) )
|
||||
{
|
||||
wxFileName tmp( fullPath );
|
||||
|
||||
m_NameMap.insert( std::pair< wxString, wxString > ( aFileName, tname ) );
|
||||
if( tmp.Normalize() )
|
||||
tname = tmp.GetFullPath();
|
||||
|
||||
return tname;
|
||||
m_NameMap.insert( std::pair< wxString, wxString > ( aFileName, tname ) );
|
||||
|
||||
return tname;
|
||||
}
|
||||
}
|
||||
|
||||
++sPL;
|
||||
}
|
||||
|
||||
// at this point the filename must contain an alias or else it is invalid
|
||||
wxString alias; // the alias portion of the short filename
|
||||
wxString relpath; // the path relative to the alias
|
||||
|
||||
|
@ -324,8 +397,10 @@ wxString S3D_FILENAME_RESOLVER::ResolvePath( const wxString& aFileName )
|
|||
{
|
||||
if( !( m_errflags & ERRFLG_RELPATH ) )
|
||||
{
|
||||
// this can happen if the file was intended to be relative to
|
||||
// ${KISYS3DMOD} but ${KISYS3DMOD} not set or incorrect.
|
||||
m_errflags |= ERRFLG_RELPATH;
|
||||
wxString errmsg = _( "[3D File Resolver] No such path; ensure KISYS3DMOD is correctly defined" );
|
||||
wxString errmsg = _( "[3D File Resolver] No such path" );
|
||||
errmsg.append( "\n" );
|
||||
errmsg.append( tname );
|
||||
wxLogTrace( MASK_3D_RESOLVER, "%s\n", errmsg.ToUTF8() );
|
||||
|
@ -378,7 +453,6 @@ bool S3D_FILENAME_RESOLVER::addPath( const S3D_ALIAS& aPath )
|
|||
wxCriticalSectionLocker lock( lock3D_resolver );
|
||||
|
||||
S3D_ALIAS tpath = aPath;
|
||||
tpath.m_duplicate = false;
|
||||
|
||||
#ifdef _WIN32
|
||||
while( tpath.m_pathvar.EndsWith( wxT( "\\" ) ) )
|
||||
|
@ -424,83 +498,6 @@ bool S3D_FILENAME_RESOLVER::addPath( const S3D_ALIAS& aPath )
|
|||
|
||||
while( sPL != ePL )
|
||||
{
|
||||
// aliases with the same m_pathvar are forbidden and the
|
||||
// user must be forced to fix the problem in order to
|
||||
// obtain good filename resolution
|
||||
if( !sPL->m_pathvar.empty() && !tpath.m_pathvar.empty()
|
||||
&& !tpath.m_pathvar.Cmp( sPL->m_pathvar ) )
|
||||
{
|
||||
wxString msg = _( "This alias: " );
|
||||
msg.append( tpath.m_alias );
|
||||
msg.append( wxT( "\n" ) );
|
||||
msg.append( _( "This path: " ) );
|
||||
msg.append( tpath.m_pathvar );
|
||||
msg.append( wxT( "\n" ) );
|
||||
msg.append( _( "Existing alias: " ) );
|
||||
msg.append( sPL->m_alias );
|
||||
msg.append( wxT( "\n" ) );
|
||||
msg.append( _( "Existing path: " ) );
|
||||
msg.append( sPL->m_pathvar );
|
||||
wxMessageBox( msg, _( "Bad alias (duplicate path)" ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// aliases with the same m_pathexp are acceptable (one or both
|
||||
// aliases being tested may be expanded variables) but when shortening
|
||||
// names the preference is for (a) a fully specified path in m_pathvar
|
||||
// then (b) the more senior alias in the list
|
||||
if( !sPL->m_pathexp.empty() && !tpath.m_pathexp.empty() )
|
||||
{
|
||||
if( !tpath.m_pathexp.Cmp( sPL->m_pathexp ) )
|
||||
{
|
||||
wxString msg = _( "This alias: " );
|
||||
msg.append( tpath.m_alias );
|
||||
msg.append( wxT( "\n" ) );
|
||||
msg.append( _( "Existing alias: " ) );
|
||||
msg.append( sPL->m_alias );
|
||||
msg.append( wxT( "\n" ) );
|
||||
msg.append( _( "This path: " ) );
|
||||
msg.append( tpath.m_pathexp );
|
||||
msg.append( wxT( "\n" ) );
|
||||
msg.append( _( "Existing path: " ) );
|
||||
msg.append( sPL->m_pathexp );
|
||||
msg.append( wxT( "\n" ) );
|
||||
msg.append( _( "This full path: " ) );
|
||||
msg.append( tpath.m_pathexp );
|
||||
msg.append( wxT( "\n" ) );
|
||||
msg.append( _( "Existing full path: " ) );
|
||||
msg.append( sPL->m_pathexp );
|
||||
wxMessageBox( msg, _( "Bad alias (duplicate path)" ) );
|
||||
|
||||
if( tpath.m_pathvar.StartsWith( wxT( "${" ) ) )
|
||||
tpath.m_duplicate = true;
|
||||
else if( sPL->m_pathvar.StartsWith( wxT( "${" ) ) )
|
||||
sPL->m_duplicate = true;
|
||||
|
||||
}
|
||||
|
||||
if( ( tpath.m_pathexp.find( sPL->m_pathexp ) != wxString::npos
|
||||
|| sPL->m_pathexp.find( tpath.m_pathexp ) != wxString::npos )
|
||||
&& tpath.m_pathexp.Cmp( sPL->m_pathexp ) )
|
||||
{
|
||||
wxString msg = _( "This alias: " );
|
||||
msg.append( tpath.m_alias );
|
||||
msg.append( wxT( "\n" ) );
|
||||
msg.append( _( "This path: " ) );
|
||||
msg.append( tpath.m_pathexp );
|
||||
msg.append( wxT( "\n" ) );
|
||||
msg.append( _( "Existing alias: " ) );
|
||||
msg.append( sPL->m_alias );
|
||||
msg.append( wxT( "\n" ) );
|
||||
msg.append( _( "Existing path: " ) );
|
||||
msg.append( sPL->m_pathexp );
|
||||
wxMessageBox( msg, _( "Bad alias (common path)" ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( !tpath.m_alias.Cmp( sPL->m_alias ) )
|
||||
{
|
||||
wxString msg = _( "Alias: " );
|
||||
|
@ -519,8 +516,6 @@ bool S3D_FILENAME_RESOLVER::addPath( const S3D_ALIAS& aPath )
|
|||
++sPL;
|
||||
}
|
||||
|
||||
// Note: at this point we may still have duplicated paths
|
||||
|
||||
m_Paths.push_back( tpath );
|
||||
return true;
|
||||
}
|
||||
|
@ -572,7 +567,6 @@ bool S3D_FILENAME_RESOLVER::readPathList( void )
|
|||
|
||||
int lineno = 0;
|
||||
S3D_ALIAS al;
|
||||
al.m_duplicate = false;
|
||||
size_t idx;
|
||||
int vnum = 0; // version number
|
||||
|
||||
|
@ -647,11 +641,18 @@ bool S3D_FILENAME_RESOLVER::writePathList( void )
|
|||
return false;
|
||||
}
|
||||
|
||||
// skip all ${ENV_VAR} alias names
|
||||
std::list< S3D_ALIAS >::const_iterator sPL = m_Paths.begin();
|
||||
std::list< S3D_ALIAS >::const_iterator ePL = m_Paths.end();
|
||||
|
||||
while( sPL != ePL && sPL->m_alias.StartsWith( "${" ) )
|
||||
++sPL;
|
||||
|
||||
wxFileName cfgpath( m_ConfigDir, S3D_RESOLVER_CONFIG );
|
||||
wxString cfgname = cfgpath.GetFullPath();
|
||||
std::ofstream cfgFile;
|
||||
|
||||
if( m_Paths.empty() || 1 == m_Paths.size() )
|
||||
if( sPL == ePL )
|
||||
{
|
||||
wxMessageDialog md( NULL,
|
||||
_( "3D search path list is empty;\ncontinue to write empty file?" ),
|
||||
|
@ -692,23 +693,10 @@ bool S3D_FILENAME_RESOLVER::writePathList( void )
|
|||
}
|
||||
|
||||
cfgFile << "#V" << CFGFILE_VERSION << "\n";
|
||||
std::list< S3D_ALIAS >::const_iterator sPL = m_Paths.begin();
|
||||
std::list< S3D_ALIAS >::const_iterator ePL = m_Paths.end();
|
||||
|
||||
// the first entry is the current project dir; we never add the implicit
|
||||
// project dir to the path list in the configuration file
|
||||
++sPL;
|
||||
std::string tstr;
|
||||
|
||||
while( sPL != ePL )
|
||||
{
|
||||
// never write the KISYS3DMOD entry
|
||||
if( !sPL->m_alias.Cmp( wxT( "KISYS3DMOD") ) )
|
||||
{
|
||||
++sPL;
|
||||
continue;
|
||||
}
|
||||
|
||||
tstr = sPL->m_alias.ToUTF8();
|
||||
cfgFile << "\"" << tstr.size() << ":" << tstr << "\",";
|
||||
tstr = sPL->m_pathvar.ToUTF8();
|
||||
|
@ -733,6 +721,50 @@ bool S3D_FILENAME_RESOLVER::writePathList( void )
|
|||
}
|
||||
|
||||
|
||||
bool S3D_FILENAME_RESOLVER::resolveVirtualEnv( const wxString& aFileName, wxString& aFullPath )
|
||||
{
|
||||
aFullPath.clear();
|
||||
|
||||
if( !aFileName.StartsWith( "${" ) )
|
||||
return false;
|
||||
|
||||
size_t eDelim = aFileName.find( '}' );
|
||||
|
||||
if( eDelim == wxString::npos || eDelim + 2 >= aFileName.length() )
|
||||
return false;
|
||||
|
||||
wxString tPath = aFileName.substr( 0, eDelim + 1 );
|
||||
|
||||
std::list< S3D_ALIAS >::const_iterator sPL = m_Paths.begin();
|
||||
std::list< S3D_ALIAS >::const_iterator ePL = m_Paths.end();
|
||||
|
||||
while( sPL != ePL )
|
||||
{
|
||||
if( !sPL->m_alias.StartsWith( "${" ) )
|
||||
return false;
|
||||
|
||||
if( sPL->m_alias == tPath )
|
||||
{
|
||||
tPath.Append( aFileName.substr( eDelim + 2 ) );
|
||||
wxFileName tFile( tPath );
|
||||
tFile.Normalize();
|
||||
|
||||
if( tFile.FileExists() )
|
||||
{
|
||||
aFullPath = tFile.GetFullPath();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
++sPL;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
wxString S3D_FILENAME_RESOLVER::ShortenPath( const wxString& aFullPathName )
|
||||
{
|
||||
wxString fname = aFullPathName;
|
||||
|
@ -745,32 +777,11 @@ wxString S3D_FILENAME_RESOLVER::ShortenPath( const wxString& aFullPathName )
|
|||
std::list< S3D_ALIAS >::const_iterator eL = m_Paths.end();
|
||||
size_t idx;
|
||||
|
||||
// test for files within the current project directory
|
||||
// and KISYS3DMOD directory
|
||||
for( int i = 0; i < 2 && sL != eL; ++i )
|
||||
{
|
||||
if( !sL->m_pathexp.empty() )
|
||||
{
|
||||
wxFileName fpath( sL->m_pathexp, wxT( "" ) );
|
||||
wxString fps = fpath.GetPathWithSep();
|
||||
|
||||
idx = fname.find( fps );
|
||||
|
||||
if( std::string::npos != idx && 0 == idx )
|
||||
{
|
||||
fname = fname.substr( fps.size() );
|
||||
return fname;
|
||||
}
|
||||
}
|
||||
|
||||
++sL;
|
||||
}
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
// undefined paths and duplicates do not participate
|
||||
// in the file name shortening procedure
|
||||
if( sL->m_pathexp.empty() || sL->m_duplicate )
|
||||
// undefined paths do not participate in the
|
||||
// file name shortening procedure
|
||||
if( sL->m_pathexp.empty() )
|
||||
{
|
||||
++sL;
|
||||
continue;
|
||||
|
@ -791,10 +802,21 @@ wxString S3D_FILENAME_RESOLVER::ShortenPath( const wxString& aFullPathName )
|
|||
fname.Replace( wxT( "\\" ), wxT( "/" ) );
|
||||
#endif
|
||||
|
||||
tname = ":";
|
||||
tname.append( sL->m_alias );
|
||||
tname.append( ":" );
|
||||
tname.append( fname );
|
||||
if( sL->m_alias.StartsWith( "${" ) )
|
||||
{
|
||||
// old style ENV_VAR
|
||||
tname = sL->m_alias;
|
||||
tname.Append( "/" );
|
||||
tname.append( fname );
|
||||
}
|
||||
else
|
||||
{
|
||||
// new style alias
|
||||
tname = ":";
|
||||
tname.append( sL->m_alias );
|
||||
tname.append( ":" );
|
||||
tname.append( fname );
|
||||
}
|
||||
|
||||
return tname;
|
||||
}
|
||||
|
|
|
@ -39,9 +39,10 @@
|
|||
#include <wx/string.h>
|
||||
#include "str_rsort.h"
|
||||
|
||||
class PGM_BASE;
|
||||
|
||||
struct S3D_ALIAS
|
||||
{
|
||||
bool m_duplicate;
|
||||
wxString m_alias; // alias to the base path
|
||||
wxString m_pathvar; // base path as stored in the config file
|
||||
wxString m_pathexp; // expanded base path
|
||||
|
@ -56,6 +57,8 @@ private:
|
|||
// mapping of (short) file names to resolved names
|
||||
std::map< wxString, wxString, S3D::rsort_wxString > m_NameMap;
|
||||
int m_errflags;
|
||||
PGM_BASE* m_pgm;
|
||||
wxString m_curProjDir;
|
||||
|
||||
/**
|
||||
* Function createPathList
|
||||
|
@ -95,6 +98,14 @@ private:
|
|||
*/
|
||||
bool writePathList( void );
|
||||
|
||||
/**
|
||||
* Function resolveVirtualEnv
|
||||
* extracts the ${ENV_VAR} component of aFileName and puts a
|
||||
* resolved path in aFullPath if the ${ENV_VAR} exists in the
|
||||
* alias list and the referenced file exists.
|
||||
*/
|
||||
bool resolveVirtualEnv( const wxString& aFileName, wxString& aFullPath );
|
||||
|
||||
public:
|
||||
S3D_FILENAME_RESOLVER();
|
||||
|
||||
|
@ -120,6 +131,13 @@ public:
|
|||
bool SetProjectDir( const wxString& aProjDir, bool* flgChanged = NULL );
|
||||
wxString GetProjectDir( void );
|
||||
|
||||
/**
|
||||
* Function SetProgramBase
|
||||
* sets a pointer to the application's PGM_BASE instance;
|
||||
* the pointer is used to extract the local env vars.
|
||||
*/
|
||||
void SetProgramBase( PGM_BASE* aBase );
|
||||
|
||||
|
||||
/**
|
||||
* Function UpdatePathList
|
||||
|
|
|
@ -42,33 +42,35 @@ DLG_3D_PATH_CONFIG::DLG_3D_PATH_CONFIG( wxWindow* aParent, S3D_FILENAME_RESOLVER
|
|||
m_aliasValidator.SetCharExcludes( wxT( "{}[]()%~<>\"='`;:.,&?/\\|$" ) );
|
||||
|
||||
const std::list< S3D_ALIAS >* rpaths = m_resolver->GetPaths();
|
||||
std::list< S3D_ALIAS >::const_iterator rI = rpaths->begin();
|
||||
std::list< S3D_ALIAS >::const_iterator rE = rpaths->end();
|
||||
size_t listsize = rpaths->size();
|
||||
size_t listidx = 0;
|
||||
|
||||
if( listsize > 0 )
|
||||
m_curdir = rpaths->front().m_pathexp;
|
||||
while( rI != rE && (*rI).m_alias.StartsWith( "${" ) )
|
||||
{
|
||||
++listidx;
|
||||
++rI;
|
||||
}
|
||||
|
||||
if( listsize < 3 )
|
||||
if( listidx < listsize )
|
||||
m_curdir = (*rI).m_pathexp;
|
||||
else
|
||||
return;
|
||||
|
||||
listsize = listsize - 2 - m_Aliases->GetNumberRows();
|
||||
listsize = listsize - listidx - m_Aliases->GetNumberRows();
|
||||
|
||||
// note: if the list allocation fails we have bigger problems
|
||||
// and there is no point in trying to notify the user here
|
||||
if( listsize > 0 && !m_Aliases->InsertRows( 0, listsize ) )
|
||||
return;
|
||||
|
||||
std::list< S3D_ALIAS >::const_iterator sL = rpaths->begin();
|
||||
std::list< S3D_ALIAS >::const_iterator eL = rpaths->end();
|
||||
int nitems = 0;
|
||||
|
||||
// skip the current project dir and KISYS3DMOD
|
||||
++sL;
|
||||
++sL;
|
||||
wxGridCellTextEditor* pEdAlias;
|
||||
|
||||
while( sL != eL )
|
||||
while( rI != rE )
|
||||
{
|
||||
m_Aliases->SetCellValue( nitems, 0, sL->m_alias );
|
||||
m_Aliases->SetCellValue( nitems, 0, rI->m_alias );
|
||||
|
||||
if( 0 == nitems )
|
||||
{
|
||||
|
@ -83,12 +85,12 @@ DLG_3D_PATH_CONFIG::DLG_3D_PATH_CONFIG( wxWindow* aParent, S3D_FILENAME_RESOLVER
|
|||
m_Aliases->SetCellEditor( nitems, 0, pEdAlias );
|
||||
}
|
||||
|
||||
m_Aliases->SetCellValue( nitems, 1, sL->m_pathvar );
|
||||
m_Aliases->SetCellValue( nitems++, 2, sL->m_description );
|
||||
m_Aliases->SetCellValue( nitems, 1, rI->m_pathvar );
|
||||
m_Aliases->SetCellValue( nitems++, 2, rI->m_description );
|
||||
|
||||
// TODO: implement a wxGridCellEditor which invokes a wxDirDialog
|
||||
|
||||
++sL;
|
||||
++rI;
|
||||
}
|
||||
|
||||
m_Aliases->AutoSize();
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <set>
|
||||
#include "dlg_select_3dmodel.h"
|
||||
#include "project.h"
|
||||
#include "3d_cache/3d_info.h"
|
||||
|
@ -240,12 +241,20 @@ void DLG_SELECT_3DMODEL::updateDirChoiceList( void )
|
|||
std::list< S3D_ALIAS > const* md = m_resolver->GetPaths();
|
||||
std::list< S3D_ALIAS >::const_iterator sL = md->begin();
|
||||
std::list< S3D_ALIAS >::const_iterator eL = md->end();
|
||||
std::vector< wxString > cl;
|
||||
std::set< wxString > cl;
|
||||
wxString prjDir;
|
||||
|
||||
// extract the current project dir
|
||||
if( sL != eL )
|
||||
{
|
||||
prjDir = sL->m_pathexp;
|
||||
++sL;
|
||||
}
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
if( !sL->m_pathexp.empty() && !sL->m_duplicate )
|
||||
cl.push_back( sL->m_pathexp );
|
||||
if( !sL->m_pathexp.empty() && sL->m_pathexp.compare( prjDir ) )
|
||||
cl.insert( sL->m_pathexp );
|
||||
|
||||
++sL;
|
||||
}
|
||||
|
@ -253,7 +262,19 @@ void DLG_SELECT_3DMODEL::updateDirChoiceList( void )
|
|||
if( !cl.empty() )
|
||||
{
|
||||
dirChoices->Clear();
|
||||
dirChoices->Append( (int)cl.size(), &cl[0] );
|
||||
|
||||
if( !prjDir.empty() )
|
||||
dirChoices->Append( prjDir );
|
||||
|
||||
std::set< wxString >::const_iterator sI = cl.begin();
|
||||
std::set< wxString >::const_iterator eI = cl.end();
|
||||
|
||||
while( sI != eI )
|
||||
{
|
||||
dirChoices->Append( *sI );
|
||||
++sI;
|
||||
}
|
||||
|
||||
dirChoices->Select( 0 );
|
||||
}
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ DIALOG_MODULE_BOARD_EDITOR::DIALOG_MODULE_BOARD_EDITOR( PCB_EDIT_FRAME* aParent
|
|||
m_OrientValueCtrl->SetValidator( m_OrientValidator );
|
||||
m_OrientValidator.SetWindow( m_OrientValueCtrl );
|
||||
|
||||
aParent->Prj().Get3DCacheManager()->GetResolver()->SetProgramBase( &Pgm() );
|
||||
m_PreviewPane = new PANEL_PREV_3D( m_Panel3D, aParent->Prj().Get3DCacheManager() );
|
||||
bLowerSizer3D->Add( m_PreviewPane, 1, wxEXPAND, 5 );
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include <module_editor_frame.h>
|
||||
#include <dialog_edit_module_for_Modedit.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <pgm_base.h>
|
||||
#include "3d_cache/dialogs/panel_prev_model.h"
|
||||
#include "3d_cache/dialogs/3d_cache_dialogs.h"
|
||||
#include "3d_cache/3d_cache.h"
|
||||
|
@ -70,6 +71,7 @@ DIALOG_MODULE_MODULE_EDITOR::DIALOG_MODULE_MODULE_EDITOR( FOOTPRINT_EDIT_FRAME*
|
|||
icon.CopyFromBitmap( KiBitmap( icon_modedit_xpm ) );
|
||||
SetIcon( icon );
|
||||
|
||||
aParent->Prj().Get3DCacheManager()->GetResolver()->SetProgramBase( &Pgm() );
|
||||
m_PreviewPane = new PANEL_PREV_3D( m_Panel3D, aParent->Prj().Get3DCacheManager() );
|
||||
bLowerSizer3D->Add( m_PreviewPane, 1, wxEXPAND, 5 );
|
||||
|
||||
|
|
Loading…
Reference in New Issue