Work in progress: transition to new 3D name resolution with nicknames

This commit is contained in:
Cirilo Bernardo 2016-01-15 11:28:28 +11:00
parent d519df22ca
commit 2ed89c29d2
7 changed files with 496 additions and 173 deletions

View File

@ -51,16 +51,6 @@
#define CACHE_CONFIG_NAME wxT( "cache.cfg" ) #define CACHE_CONFIG_NAME wxT( "cache.cfg" )
void display(unsigned char* hash)
{
std::cout << "SHA1: " << std::hex;
for(int i = 0; i < 20; ++i)
{
std::cout << ((hash[i] & 0x000000F0) >> 4)
<< (hash[i] & 0x0000000F);
}
std::cout << std::endl; // Das wars
}
static const wxString sha1ToWXString( const unsigned char* aSHA1Sum ) static const wxString sha1ToWXString( const unsigned char* aSHA1Sum )
{ {
@ -91,7 +81,6 @@ static const wxString sha1ToWXString( const unsigned char* aSHA1Sum )
} }
sha1[j] = 0; sha1[j] = 0;
std::cerr << "XXX: SHA1: " << sha1 << "\n";
return wxString::FromUTF8Unchecked( sha1 ); return wxString::FromUTF8Unchecked( sha1 );
} }
@ -265,7 +254,7 @@ SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName, S3D_CACHE_ENTRY**
if( !getSHA1( aFileName, sha1sum ) || m_CacheDir.empty() ) if( !getSHA1( aFileName, sha1sum ) || m_CacheDir.empty() )
{ {
// just in case we can't get an MD5 sum (for example, on access issues) // just in case we can't get an hash digest (for example, on access issues)
// or we do not have a configured cache file directory, we create an // or we do not have a configured cache file directory, we create an
// entry to prevent further attempts at loading the file // entry to prevent further attempts at loading the file
S3D_CACHE_ENTRY* ep = new S3D_CACHE_ENTRY; S3D_CACHE_ENTRY* ep = new S3D_CACHE_ENTRY;
@ -381,8 +370,6 @@ bool S3D_CACHE::getSHA1( const wxString& aFileName, unsigned char* aSHA1Sum )
aSHA1Sum[idx] = tmp & 0xff; aSHA1Sum[idx] = tmp & 0xff;
} }
display( aSHA1Sum );
return true; return true;
} }
@ -712,3 +699,28 @@ S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName )
return mp; return mp;
} }
wxString S3D_CACHE::GetModelHash( const wxString& aModelFileName )
{
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFileName );
if( full3Dpath.empty() || !wxFileName::FileExists( full3Dpath ) )
return wxEmptyString;
// check cache if file is already loaded
std::map< wxString, S3D_CACHE_ENTRY*, S3D::rsort_wxString >::iterator mi;
mi = m_CacheMap.find( full3Dpath );
if( mi != m_CacheMap.end() )
return mi->second->GetCacheBaseName();
// a cache item does not exist; search the Filename->Cachename map
S3D_CACHE_ENTRY* cp = NULL;
checkCache( full3Dpath, &cp );
if( NULL != cp )
return cp->GetCacheBaseName();
return wxEmptyString;
}

View File

@ -182,7 +182,7 @@ public:
*/ */
void ClosePlugins( void ); void ClosePlugins( void );
/** /**
* Function GetModel * Function GetModel
* attempts to load the scene data for a model and to translate it * attempts to load the scene data for a model and to translate it
* into an S3D_MODEL structure for display by a renderer * into an S3D_MODEL structure for display by a renderer
@ -191,6 +191,8 @@ public:
* @return is a pointer to the render data or NULL if not available * @return is a pointer to the render data or NULL if not available
*/ */
S3DMODEL* GetModel( const wxString& aModelFileName ); S3DMODEL* GetModel( const wxString& aModelFileName );
wxString GetModelHash( const wxString& aModelFileName );
}; };
#endif // CACHE_3D_H #endif // CACHE_3D_H

View File

@ -25,13 +25,28 @@
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <fstream> #include <fstream>
#include <sstream>
#include <wx/filename.h> #include <wx/filename.h>
#include <wx/utils.h> #include <wx/utils.h>
#include <wx/msgdlg.h>
#include "3d_filename_resolver.h" #include "3d_filename_resolver.h"
#define S3D_RESOLVER_CONFIG wxT( "3Dresolver.cfg" ) #define S3D_RESOLVER_CONFIG wxT( "3Dresolver.cfg" )
// flag bits used to track different one-off messages to users
#define ERRFLG_NODIR (1)
#define ERRFLG_RELPATH (2)
static bool getHollerith( const std::string& aString, size_t& aIndex, wxString& aResult );
S3D_FILENAME_RESOLVER::S3D_FILENAME_RESOLVER()
{
m_errflags = 0;
}
bool S3D_FILENAME_RESOLVER::Set3DConfigDir( const wxString& aConfigDir ) bool S3D_FILENAME_RESOLVER::Set3DConfigDir( const wxString& aConfigDir )
{ {
@ -69,7 +84,13 @@ bool S3D_FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgCh
if( m_Paths.empty() ) if( m_Paths.empty() )
{ {
m_Paths.push_back( path ); S3D_ALIAS al;
al.m_alias = _( "(DEFAULT)" );
al.m_pathvar = _( "${PROJDIR}" );
al.m_pathexp = path;
al.m_description = _( "Current project directory" );
m_Paths.push_back( al );
m_NameMap.clear();
if( flgChanged ) if( flgChanged )
*flgChanged = true; *flgChanged = true;
@ -77,10 +98,9 @@ bool S3D_FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgCh
} }
else else
{ {
if( m_Paths.front().Cmp( path ) ) if( m_Paths.front().m_pathexp.Cmp( path ) )
{ {
m_Paths.pop_front(); m_Paths.front().m_pathexp = path;
m_Paths.push_front( path );
m_NameMap.clear(); m_NameMap.clear();
if( flgChanged ) if( flgChanged )
@ -95,7 +115,8 @@ bool S3D_FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgCh
#ifdef DEBUG #ifdef DEBUG
std::cout << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; std::cout << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cout << " * [INFO] changed project dir to " << m_Paths.front().ToUTF8() << "\n"; std::cout << " * [INFO] changed project dir to ";
std::cout << m_Paths.front().m_pathexp.ToUTF8() << "\n";
#endif #endif
return true; return true;
@ -107,7 +128,7 @@ wxString S3D_FILENAME_RESOLVER::GetProjectDir( void )
if( m_Paths.empty() ) if( m_Paths.empty() )
return wxEmptyString; return wxEmptyString;
return m_Paths.front(); return m_Paths.front().m_pathexp;
} }
@ -122,11 +143,27 @@ bool S3D_FILENAME_RESOLVER::createPathList( void )
// default; since CWD is not necessarily what we really want, // default; since CWD is not necessarily what we really want,
// the user may change this later with a call to SetProjectDir() // the user may change this later with a call to SetProjectDir()
if( !addPath( wxFileName::GetCwd() ) ) S3D_ALIAS lpath;
m_Paths.push_back( wxEmptyString ); lpath.m_alias = _( "(DEFAULT)" );
lpath.m_pathvar = _( "(PROJECT DIR)" );
lpath.m_pathexp = wxFileName::GetCwd();
lpath.m_description = _( "Current project directory" );
m_Paths.push_back( lpath );
if( wxGetEnv( wxT( "KISYS3DMOD" ), &kmod ) ) if( wxGetEnv( wxT( "KISYS3DMOD" ), &kmod ) && !kmod.empty() )
addPath( kmod ); {
wxFileName tmp( kmod );
wxString kpath = tmp.GetFullPath();
if( tmp.Normalize() && lpath.m_pathexp.Cmp( kpath ) )
{
lpath.m_alias = wxT( "KISYS3DMOD" );
lpath.m_pathvar = wxT( "${KISYS3DMOD}" );
lpath.m_pathexp = kpath;
lpath.m_description = _( "Legacy 3D environment path" );
addPath( lpath );
}
}
if( !m_ConfigDir.empty() ) if( !m_ConfigDir.empty() )
readPathList(); readPathList();
@ -136,12 +173,12 @@ bool S3D_FILENAME_RESOLVER::createPathList( void )
#ifdef DEBUG #ifdef DEBUG
std::cout << " * [3D model] search paths:\n"; std::cout << " * [3D model] search paths:\n";
std::list< wxString >::const_iterator sPL = m_Paths.begin(); std::list< S3D_ALIAS >::const_iterator sPL = m_Paths.begin();
std::list< wxString >::const_iterator ePL = m_Paths.end(); std::list< S3D_ALIAS >::const_iterator ePL = m_Paths.end();
while( sPL != ePL ) while( sPL != ePL )
{ {
std::cout << " + '" << (*sPL).ToUTF8() << "'\n"; std::cout << " + '" << (*sPL).m_pathexp.ToUTF8() << "'\n";
++sPL; ++sPL;
} }
#endif #endif
@ -150,7 +187,7 @@ bool S3D_FILENAME_RESOLVER::createPathList( void )
} }
bool S3D_FILENAME_RESOLVER::UpdatePathList( std::vector< wxString >& aPathList ) bool S3D_FILENAME_RESOLVER::UpdatePathList( std::vector< S3D_ALIAS >& aPathList )
{ {
while( m_Paths.size() > 1 ) while( m_Paths.size() > 1 )
m_Paths.pop_back(); m_Paths.pop_back();
@ -172,61 +209,125 @@ wxString S3D_FILENAME_RESOLVER::ResolvePath( const wxString& aFileName )
if( m_Paths.empty() ) if( m_Paths.empty() )
createPathList(); createPathList();
// first attempt to use the name as specified: // look up the filename in the internal filename map
wxString aResolvedName; std::map< wxString, wxString, S3D::rsort_wxString >::iterator mi;
wxString fname; mi = m_NameMap.find( aFileName );
if( mi != m_NameMap.end() )
return mi->second;
// first attempt to use the name as specified:
wxString tname = aFileName;
#ifdef _WIN32
// translate from KiCad's internal UNIX-like path to MSWin paths
tname.Replace( wxT( "/" ), wxT( "\\" ) );
#endif
if( wxFileName::FileExists( tname ) )
{
wxFileName tmp( tname );
if( tmp.Normalize() )
tname = tmp.GetFullPath();
m_NameMap.insert( std::pair< wxString, wxString > ( aFileName, tname ) );
std::cerr << "XXX: RESOLVER LINE " << __LINE__ << "\n";
return tname;
}
// at this point aFileName:
// a. is a legacy ${} shortened name
// b. an aliased shortened name
// c. cannot be determined
// normalize paths with "${VARNAME}" to support legacy behavior
if( aFileName.StartsWith( wxT( "${" ) ) ) if( aFileName.StartsWith( wxT( "${" ) ) )
{ {
wxFileName tmp( aFileName ); wxFileName tmp( aFileName );
if( tmp.Normalize() ) if( tmp.Normalize() )
fname = tmp.GetFullPath();
else
fname = aFileName;
}
else
{ {
fname = aFileName; tname = tmp.GetFullPath();
m_NameMap.insert( std::pair< wxString, wxString > ( aFileName, tname ) );
std::cerr << "XXX: RESOLVER LINE " << __LINE__ << "\n";
return tname;
} }
#ifdef _WIN32 std::cerr << "XXX: RESOLVER LINE " << __LINE__ << "\n";
// translate from KiCad's internal UNIX-like path to MSWin paths
fname.Replace( wxT( "/" ), wxT( "\\" ) );
#endif
if( checkRealPath( fname, aResolvedName ) ) // XXX - no such path - consider showing the user a pop-up message
return aResolvedName; return wxEmptyString;
}
// look up the filename in the internal filename map std::list< S3D_ALIAS >::const_iterator sPL = m_Paths.begin();
std::map< wxString, wxString, S3D::rsort_wxString >::iterator mi; std::list< S3D_ALIAS >::const_iterator ePL = m_Paths.end();
mi = m_NameMap.find( fname );
if( mi != m_NameMap.end() ) // check the path relative to the current dir
return mi->second; do
{
wxFileName fpath( wxFileName::DirName( sPL->m_pathexp ) );
wxString fullPath = fpath.GetPathWithSep() + tname;
std::list< wxString >::const_iterator sPL = m_Paths.begin(); if( wxFileName::FileExists( fullPath ) )
std::list< wxString >::const_iterator ePL = m_Paths.end(); {
wxFileName tmp( fullPath );
if( tmp.Normalize() )
tname = tmp.GetFullPath();
m_NameMap.insert( std::pair< wxString, wxString > ( aFileName, tname ) );
std::cerr << "XXX: RESOLVER LINE " << __LINE__ << "\n";
return tname;
}
} while( 0 );
++sPL;
wxString alias; // the alias portion of the short filename
wxString relpath; // the path relative to the alias
if( !SplitAlias( aFileName, alias, relpath ) )
{
std::cerr << "XXX: RESOLVER LINE " << __LINE__ << "\n";
// XXX - no such path - consider showing the user a pop-up message
return wxEmptyString;
}
while( sPL != ePL ) while( sPL != ePL )
{ {
wxFileName fpath( wxFileName::DirName( *sPL ) ); if( !sPL->m_alias.Cmp( alias ) )
wxFileName filename( fname );
// we can only attempt a search if the filename is incomplete
if( filename.IsRelative() )
{ {
wxString fullPath = fpath.GetPathWithSep() + fname; wxFileName fpath( wxFileName::DirName( sPL->m_pathexp ) );
wxString fullPath = fpath.GetPathWithSep() + relpath;
if( checkRealPath( fullPath, aResolvedName ) ) if( wxFileName::FileExists( fullPath ) )
return aResolvedName; {
wxFileName tmp( fullPath );
if( tmp.Normalize() )
tname = tmp.GetFullPath();
m_NameMap.insert( std::pair< wxString, wxString > ( aFileName, tname ) );
std::cerr << "XXX: RESOLVER LINE " << __LINE__ << "\n";
return tname;
}
} }
++sPL; ++sPL;
} }
std::cerr << "XXX: RESOLVER LINE " << __LINE__ << "\n";
// XXX - no such path - consider showing the user a pop-up message
wxString errmsg = _( "filename could not be resolved" ); wxString errmsg = _( "filename could not be resolved" );
std::cerr << " * [3D Model] " << errmsg.ToUTF8() << " '"; std::cerr << " * [3D Model] " << errmsg.ToUTF8() << " '";
std::cerr << aFileName.ToUTF8() << "'\n"; std::cerr << aFileName.ToUTF8() << "'\n";
@ -235,52 +336,113 @@ wxString S3D_FILENAME_RESOLVER::ResolvePath( const wxString& aFileName )
} }
bool S3D_FILENAME_RESOLVER::checkRealPath( const wxString& aFileName, bool S3D_FILENAME_RESOLVER::addPath( const S3D_ALIAS& aPath )
wxString& aResolvedName )
{ {
aResolvedName.clear(); if( aPath.m_alias.empty() || aPath.m_pathvar.empty() )
wxFileName fname( aFileName );
fname.Normalize();
if( !fname.FileExists() )
return false; return false;
aResolvedName = fname.GetFullPath(); wxFileName path( aPath.m_pathvar, wxT( "" ) );
m_NameMap.insert( std::pair< wxString, wxString > ( aFileName, aResolvedName ) );
return true;
}
bool S3D_FILENAME_RESOLVER::addPath( const wxString& aPath )
{
if( aPath.empty() )
return false;
wxFileName path( aPath, wxT( "" ) );
path.Normalize(); path.Normalize();
S3D_ALIAS tpath = aPath;
if( !path.DirExists() ) if( !path.DirExists() )
tpath.m_pathexp.clear();
else
tpath.m_pathexp = path.GetFullPath();
wxString pname = path.GetPath();
std::list< S3D_ALIAS >::const_iterator sPL = m_Paths.begin();
std::list< S3D_ALIAS >::const_iterator ePL = m_Paths.end();
while( sPL != ePL )
{ {
wxString errmsg = _( "invalid path" ); if( !sPL->m_pathvar.empty() && !tpath.m_pathvar.empty()
std::cerr << " * [3D Model] " << errmsg.ToUTF8() << " '" << path.GetPath().ToUTF8() << "'\n"; && !tpath.m_pathvar.Cmp( sPL->m_pathvar ) )
{
wxString msg = _T( "This alias: " );
msg.append( tpath.m_alias );
msg.append( wxT( "\n" ) );
msg.append( _T( "This path: " ) );
msg.append( tpath.m_pathvar );
msg.append( wxT( "\n" ) );
msg.append( _T( "Existing alias: " ) );
msg.append( sPL->m_alias );
msg.append( wxT( "\n" ) );
msg.append( _T( "Existing path: " ) );
msg.append( sPL->m_pathvar );
wxMessageBox( msg, _T( "Bad alias (duplicate path)" ) );
return false; return false;
} }
wxString pname = path.GetPath(); if( !sPL->m_pathexp.empty() && !tpath.m_pathexp.empty() )
std::list< wxString >::const_iterator sPL = m_Paths.begin();
std::list< wxString >::const_iterator ePL = m_Paths.end();
while( sPL != ePL )
{ {
if( !pname.Cmp( *sPL ) ) if( !tpath.m_pathexp.Cmp( sPL->m_pathexp ) )
return true; {
wxString msg = _T( "This alias: " );
msg.append( tpath.m_alias );
msg.append( wxT( "\n" ) );
msg.append( _T( "Existing alias: " ) );
msg.append( sPL->m_alias );
msg.append( wxT( "\n" ) );
msg.append( _T( "This path: " ) );
msg.append( tpath.m_pathexp );
msg.append( wxT( "\n" ) );
msg.append( _T( "Existing path: " ) );
msg.append( sPL->m_pathexp );
msg.append( wxT( "\n" ) );
msg.append( _T( "This full path: " ) );
msg.append( tpath.m_pathexp );
msg.append( wxT( "\n" ) );
msg.append( _T( "Existing full path: " ) );
msg.append( sPL->m_pathexp );
wxMessageBox( msg, _T( "Bad alias (duplicate path)" ) );
return false;
}
if( tpath.m_pathexp.find( sPL->m_pathexp ) != wxString::npos
|| sPL->m_pathexp.find( tpath.m_pathexp ) != wxString::npos )
{
wxString msg = _T( "This alias: " );
msg.append( tpath.m_alias );
msg.append( wxT( "\n" ) );
msg.append( _T( "This path: " ) );
msg.append( tpath.m_pathexp );
msg.append( wxT( "\n" ) );
msg.append( _T( "Existing alias: " ) );
msg.append( sPL->m_alias );
msg.append( wxT( "\n" ) );
msg.append( _T( "Existing path: " ) );
msg.append( sPL->m_pathexp );
wxMessageBox( msg, _T( "Bad alias (common path)" ) );
return false;
}
}
if( !tpath.m_alias.Cmp( sPL->m_alias ) )
{
wxString msg = _T( "Alias: " );
msg.append( tpath.m_alias );
msg.append( wxT( "\n" ) );
msg.append( _T( "This path: " ) );
msg.append( tpath.m_pathvar );
msg.append( wxT( "\n" ) );
msg.append( _T( "Existing path: " ) );
msg.append( sPL->m_pathvar );
wxMessageBox( msg, _T( "Bad alias (duplicate name)" ) );
return false;
}
++sPL; ++sPL;
} }
m_Paths.push_back( pname ); // Note: at this point we may still have duplicated paths
m_Paths.push_back( tpath );
return true; return true;
} }
@ -324,7 +486,8 @@ bool S3D_FILENAME_RESOLVER::readPathList( void )
} }
int lineno = 0; int lineno = 0;
bool mod = false; // set to true if there are non-existent paths in the file S3D_ALIAS al;
size_t idx;
while( cfgFile.good() ) while( cfgFile.good() )
{ {
@ -340,42 +503,22 @@ bool S3D_FILENAME_RESOLVER::readPathList( void )
continue; continue;
} }
std::string::size_type spos = cfgLine.find_first_of( '"', 0 ); idx = 0;
if( std::string::npos == spos ) if( !getHollerith( cfgLine, idx, al.m_alias ) )
{ continue;
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
wxString errmsg = _( "missing opening quote mark in config file" );
std::cerr << " * " << errmsg.ToUTF8() << " '" << cfgname.ToUTF8() << "'\n";
}
cfgLine.erase( 0, spos + 1 ); if( !getHollerith( cfgLine, idx, al.m_pathvar ) )
continue;
spos = cfgLine.find_last_of( '"' ); if( !getHollerith( cfgLine, idx, al.m_description ) )
continue;
if( std::string::npos == spos ) addPath( al );
{
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
wxString errmsg = _( "missing closing quote mark in config file" );
std::cerr << " * " << errmsg.ToUTF8() << " '" << cfgname.ToUTF8() << "'\n";
}
cfgLine.erase( spos );
if( !addPath( cfgLine ) )
{
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
wxString errmsg = _( "invalid path in config file" );
std::cerr << " * " << errmsg.ToUTF8() << " '" << cfgname.ToUTF8() << "'\n";
mod = true;
}
} }
cfgFile.close(); cfgFile.close();
if( mod )
writePathList();
if( m_Paths.size() != nitems ) if( m_Paths.size() != nitems )
return true; return true;
@ -410,16 +553,22 @@ bool S3D_FILENAME_RESOLVER::writePathList( void )
return false; return false;
} }
std::list< wxString >::const_iterator sPL = m_Paths.begin(); std::list< S3D_ALIAS >::const_iterator sPL = m_Paths.begin();
std::list< wxString >::const_iterator ePL = m_Paths.end(); std::list< S3D_ALIAS >::const_iterator ePL = m_Paths.end();
// the first entry is the current project dir; we never add a project dir // the first entry is the current project dir; we never add the implicit
// to the path list in the configuration file // project dir to the path list in the configuration file
++sPL; ++sPL;
std::string tstr;
while( sPL != ePL ) while( sPL != ePL )
{ {
cfgFile << "\"" << sPL->ToUTF8() << "\"\n"; tstr = sPL->m_alias.ToUTF8();
cfgFile << "\"" << tstr.size() << ":" << tstr << "\",";
tstr = sPL->m_pathvar.ToUTF8();
cfgFile << "\"" << tstr.size() << ":" << tstr << "\",";
tstr = sPL->m_description.ToUTF8();
cfgFile << "\"" << tstr.size() << ":" << tstr << "\"\n";
++sPL; ++sPL;
} }
@ -440,23 +589,56 @@ wxString S3D_FILENAME_RESOLVER::ShortenPath( const wxString& aFullPathName )
if( m_Paths.empty() ) if( m_Paths.empty() )
createPathList(); createPathList();
std::list< wxString >::const_iterator sL = m_Paths.begin(); std::list< S3D_ALIAS >::const_iterator sL = m_Paths.begin();
std::list< wxString >::const_iterator eL = m_Paths.end(); std::list< S3D_ALIAS >::const_iterator eL = m_Paths.end();
size_t idx;
// test for files within the current project directory
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 ) while( sL != eL )
{ {
wxFileName fpath( *sL, wxT( "" ) ); if( sL->m_pathexp.empty() )
wxString fps = fpath.GetPathWithSep(); {
++sL;
continue;
}
if( std::string::npos != fname.find( fps ) ) wxFileName fpath( sL->m_pathexp, wxT( "" ) );
wxString fps = fpath.GetPathWithSep();
wxString tname;
idx = fname.find( fps );
if( std::string::npos != idx && 0 == idx )
{ {
fname = fname.substr( fps.size() ); fname = fname.substr( fps.size() );
#ifdef _WIN32 #ifdef _WIN32
// ensure only the '/' separator is used in the internal name
fname.Replace( wxT( "\\" ), wxT( "/" ) ); fname.Replace( wxT( "\\" ), wxT( "/" ) );
#endif #endif
return fname; tname = ":";
tname.append( sL->m_alias );
tname.append( ":" );
tname.append( fname );
return tname;
} }
++sL; ++sL;
@ -475,7 +657,114 @@ wxString S3D_FILENAME_RESOLVER::ShortenPath( const wxString& aFullPathName )
const std::list< wxString >* S3D_FILENAME_RESOLVER::GetPaths( void ) const std::list< S3D_ALIAS >* S3D_FILENAME_RESOLVER::GetPaths( void )
{ {
return &m_Paths; return &m_Paths;
} }
bool S3D_FILENAME_RESOLVER::SplitAlias( const wxString& aFileName,
wxString& anAlias, wxString& aRelPath )
{
anAlias.clear();
aRelPath.clear();
if( !aFileName.StartsWith( wxT( ":" ) ) )
return false;
size_t tagpos = aFileName.find( wxT( ":" ), 1 );
if( wxString::npos == tagpos || 1 == tagpos )
return false;
if( tagpos + 1 >= aFileName.length() )
return false;
anAlias = aFileName.substr( 1, tagpos - 1 );
aRelPath = aFileName.substr( tagpos + 1 );
return true;
}
static bool getHollerith( const std::string& aString, size_t& aIndex, wxString& aResult )
{
aResult.clear();
if( aIndex < 0 || aIndex >= aString.size() )
{
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
wxString errmsg = _( "bad Hollerith string on line" );
std::cerr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'\n";
return false;
}
size_t i2 = aString.find( '"', aIndex );
if( std::string::npos == i2 )
{
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
wxString errmsg = _( "missing opening quote mark in config file" );
std::cerr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'\n";
return false;
}
++i2;
if( i2 >= aString.size() )
{
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
wxString errmsg = _( "invalid entry (unexpected end of line)" );
std::cerr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'\n";
return false;
}
std::string tnum;
while( aString[i2] >= '0' && aString[i2] <= '9' )
tnum.append( 1, aString[i2++] );
if( tnum.empty() || aString[i2++] != ':' )
{
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
wxString errmsg = _( "bad Hollerith string on line" );
std::cerr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'\n";
return false;
}
std::istringstream istr;
istr.str( tnum );
size_t nchars;
istr >> nchars;
if( (i2 + nchars) >= aString.size() )
{
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
wxString errmsg = _( "invalid entry (unexpected end of line)" );
std::cerr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'\n";
return false;
}
if( nchars > 0 )
{
aResult = aString.substr( i2, nchars );
i2 += nchars;
}
if( aString[i2] != '"' )
{
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
wxString errmsg = _( "missing closing quote mark in config file" );
std::cerr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'\n";
return false;
}
aIndex = i2 + 1;
return true;
}

View File

@ -39,26 +39,22 @@
#include <wx/string.h> #include <wx/string.h>
#include "str_rsort.h" #include "str_rsort.h"
struct S3D_ALIAS
{
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
wxString m_description; // description of the aliased path
};
class S3D_FILENAME_RESOLVER class S3D_FILENAME_RESOLVER
{ {
private: private:
wxString m_ConfigDir; // 3D configuration directory wxString m_ConfigDir; // 3D configuration directory
std::list< wxString > m_Paths; // list of base paths to search from std::list< S3D_ALIAS > m_Paths; // list of base paths to search from
// mapping of (short) file names to resolved names // mapping of (short) file names to resolved names
std::map< wxString, wxString, S3D::rsort_wxString > m_NameMap; std::map< wxString, wxString, S3D::rsort_wxString > m_NameMap;
int m_errflags;
/**
* Function checkRealPath
* checks if a file exists, is a regular file, and retrieves
* the canonical name and extension.
*
* @param aFileName [in] is the file name and path to be checked
* @param aResolvedName [out] is the canonical resolved filename
* @param aFileExtension [out] is the file's extension string
* @return true if the file was found and is a regular file
*/
bool checkRealPath( const wxString& aFileName, wxString& aResolvedName );
/** /**
* Function createPathList * Function createPathList
@ -75,10 +71,10 @@ private:
* Function addPath * Function addPath
* checks that a path is valid and adds it to the search list * checks that a path is valid and adds it to the search list
* *
* @param aPath is the path to be checked and added * @param aPath is the alias set to be checked and added
* @return true if aPath is valid * @return true if aPath is valid
*/ */
bool addPath( const wxString& aPath ); bool addPath( const S3D_ALIAS& aPath );
/** /**
* Function readPathList * Function readPathList
@ -99,6 +95,8 @@ private:
bool writePathList( void ); bool writePathList( void );
public: public:
S3D_FILENAME_RESOLVER();
/** /**
* Function Set3DConfigDir * Function Set3DConfigDir
* sets the user's configuration directory * sets the user's configuration directory
@ -127,7 +125,7 @@ public:
* clears the current path list and substitutes the given path * clears the current path list and substitutes the given path
* list, updating the path configuration file on success. * list, updating the path configuration file on success.
*/ */
bool UpdatePathList( std::vector< wxString >& aPathList ); bool UpdatePathList( std::vector< S3D_ALIAS >& aPathList );
/** /**
* Function ResolvePath * Function ResolvePath
@ -159,7 +157,15 @@ public:
* *
* @return pointer to the internal path list * @return pointer to the internal path list
*/ */
const std::list< wxString >* GetPaths( void ); const std::list< S3D_ALIAS >* GetPaths( void );
/**
* Function SplitAlias
* returns true if the given name contains an alias and
* populates the string anAlias with the alias and aRelPath
* with the relative path.
*/
bool SplitAlias( const wxString& aFileName, wxString& anAlias, wxString& aRelPath );
}; };
#endif // FILENAME_RESOLVER_3D_H #endif // FILENAME_RESOLVER_3D_H

View File

@ -100,9 +100,9 @@ DLG_CFG_3DPATH::DLG_CFG_3DPATH( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResol
if( resolver ) if( resolver )
{ {
const std::list< wxString >* pl = resolver->GetPaths(); const std::list< S3D_ALIAS >* pl = resolver->GetPaths();
std::list< wxString >::const_iterator sL = pl->begin(); std::list< S3D_ALIAS >::const_iterator sL = pl->begin();
std::list< wxString >::const_iterator eL = pl->end(); std::list< S3D_ALIAS >::const_iterator eL = pl->end();
// always skip the first entry which is the current project dir // always skip the first entry which is the current project dir
if( sL != eL ) if( sL != eL )
@ -113,7 +113,7 @@ DLG_CFG_3DPATH::DLG_CFG_3DPATH( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResol
while( sL != eL ) while( sL != eL )
{ {
m_paths.push_back( *sL ); m_paths.push_back( *sL );
pathList->InsertItem( i, *sL ); pathList->InsertItem( i, sL->m_alias );
++i; ++i;
++sL; ++sL;
} }
@ -130,8 +130,10 @@ DLG_CFG_3DPATH::DLG_CFG_3DPATH( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResol
bool DLG_CFG_3DPATH::TransferDataFromWindow() bool DLG_CFG_3DPATH::TransferDataFromWindow()
{ {
if( resolver && resolver->UpdatePathList( m_paths ) ) // NOTE: This dialog is to be deprecated
return true;
//if( resolver && resolver->UpdatePathList( m_paths ) )
// return true;
return false; return false;
} }
@ -139,6 +141,9 @@ bool DLG_CFG_3DPATH::TransferDataFromWindow()
void DLG_CFG_3DPATH::EditPath( wxCommandEvent& event ) void DLG_CFG_3DPATH::EditPath( wxCommandEvent& event )
{ {
// NOTE: This dialog is to be deprecated
/*
long nItem = pathList->GetFirstSelected(); long nItem = pathList->GetFirstSelected();
wxString tmpname = m_paths[ nItem ]; wxString tmpname = m_paths[ nItem ];
@ -164,6 +169,7 @@ void DLG_CFG_3DPATH::EditPath( wxCommandEvent& event )
} }
delete dd; delete dd;
*/
return; return;
} }
@ -171,6 +177,9 @@ void DLG_CFG_3DPATH::EditPath( wxCommandEvent& event )
void DLG_CFG_3DPATH::AddPath( wxCommandEvent& event ) void DLG_CFG_3DPATH::AddPath( wxCommandEvent& event )
{ {
// NOTE: This dialog is to be deprecated
/*
wxDirDialog* dd = new wxDirDialog( this, _( "Add a 3D model directory" ) ); wxDirDialog* dd = new wxDirDialog( this, _( "Add a 3D model directory" ) );
if( wxID_OK == dd->ShowModal() ) if( wxID_OK == dd->ShowModal() )
@ -188,6 +197,7 @@ void DLG_CFG_3DPATH::AddPath( wxCommandEvent& event )
} }
delete dd; delete dd;
*/
return; return;
} }
@ -195,6 +205,9 @@ void DLG_CFG_3DPATH::AddPath( wxCommandEvent& event )
void DLG_CFG_3DPATH::DeletePath( wxCommandEvent& event ) void DLG_CFG_3DPATH::DeletePath( wxCommandEvent& event )
{ {
// NOTE: This dialog is to be deprecated
/*
long nItem = pathList->GetFirstSelected(); long nItem = pathList->GetFirstSelected();
if( -1 == nItem ) if( -1 == nItem )
@ -216,6 +229,7 @@ void DLG_CFG_3DPATH::DeletePath( wxCommandEvent& event )
deleteButton->Enable( false ); deleteButton->Enable( false );
pathList->Select( -1 ); pathList->Select( -1 );
} }
*/
return; return;
} }

View File

@ -43,7 +43,7 @@ private:
wxButton* deleteButton; wxButton* deleteButton;
S3D_FILENAME_RESOLVER* resolver; S3D_FILENAME_RESOLVER* resolver;
std::vector< wxString > m_paths; std::vector< S3D_ALIAS > m_paths;
public: public:
DLG_CFG_3DPATH( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver ); DLG_CFG_3DPATH( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver );

View File

@ -350,14 +350,14 @@ void PANEL_PREV_3D::updateDirChoiceList( void )
if( NULL == m_FileDlg || NULL == m_ModelManager || NULL == dirChoices ) if( NULL == m_FileDlg || NULL == m_ModelManager || NULL == dirChoices )
return; return;
std::list< wxString > const* md = m_ModelManager->GetResolver()->GetPaths(); std::list< S3D_ALIAS > const* md = m_ModelManager->GetResolver()->GetPaths();
std::list< wxString >::const_iterator sL = md->begin(); std::list< S3D_ALIAS >::const_iterator sL = md->begin();
std::list< wxString >::const_iterator eL = md->end(); std::list< S3D_ALIAS >::const_iterator eL = md->end();
std::vector< wxString > cl; std::vector< wxString > cl;
while( sL != eL ) while( sL != eL )
{ {
cl.push_back( *sL ); cl.push_back( sL->m_pathexp );
++sL; ++sL;
} }