More performance enhancements.
Be more intelligent about sorting lib tree items. (Footprint entries, for instance, come out of an already-sorted list.) Don't recreate menus twice when laoding Footprint Editor. More pervasive use of WX_FILENAME to avoid expensive calls to wxFileName::SplitPath() and string concatenation. For POSIX kernels do all the work on the file-system side so we don't have to keep converting back and forth between encodings.
This commit is contained in:
parent
9e84c3fc3b
commit
be1d6113d6
|
@ -534,121 +534,240 @@ bool std::less<wxPoint>::operator()( const wxPoint& aA, const wxPoint& aB ) cons
|
|||
|
||||
|
||||
//
|
||||
// A cover of wxFileName::SetFullName() which avoids expensive calls to wxFileName::SplitPath().
|
||||
// A wrapper around a wxFileName which avoids expensive calls to wxFileName::SplitPath()
|
||||
// and string concatenations by caching the path and filename locally and only resolving
|
||||
// the wxFileName when it has to.
|
||||
//
|
||||
WX_FILENAME::WX_FILENAME( const wxString& aPath, const wxString& aFilename ) :
|
||||
m_fn( aPath, aFilename ),
|
||||
m_path( aPath ),
|
||||
m_fullName( aFilename )
|
||||
{ }
|
||||
|
||||
|
||||
void WX_FILENAME::SetFullName( const wxString& aFileNameAndExtension )
|
||||
{
|
||||
m_fullName = aFileNameAndExtension;
|
||||
}
|
||||
|
||||
|
||||
wxString WX_FILENAME::GetName() const
|
||||
{
|
||||
size_t dot = m_fullName.find_last_of( wxT( '.' ) );
|
||||
return m_fullName.substr( 0, dot );
|
||||
}
|
||||
|
||||
|
||||
wxString WX_FILENAME::GetFullName() const
|
||||
{
|
||||
return m_fullName;
|
||||
}
|
||||
|
||||
|
||||
wxString WX_FILENAME::GetPath() const
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
|
||||
wxString WX_FILENAME::GetFullPath() const
|
||||
{
|
||||
return m_path + wxT( '/' ) + m_fullName;
|
||||
}
|
||||
|
||||
|
||||
// Write locally-cached values to the wxFileName. MUST be called before using m_fn.
|
||||
void WX_FILENAME::resolve()
|
||||
{
|
||||
size_t dot = m_fullName.find_last_of( wxT( '.' ) );
|
||||
m_fn.SetName( m_fullName.substr( 0, dot ) );
|
||||
m_fn.SetExt( m_fullName.substr( dot + 1 ) );
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// An alernative to wxFileName::GetModificationTime() which avoids multiple calls to stat() on
|
||||
// POSIX kernels.
|
||||
//
|
||||
long long WX_FILENAME::GetTimestamp()
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
resolve();
|
||||
|
||||
if( m_fn.FileExists() )
|
||||
return m_fn.GetModificationTime().GetValue().GetValue();
|
||||
#else
|
||||
// By stat-ing the file ourselves we save wxWidgets from doing it three times:
|
||||
// Exists( wxFILE_EXISTS_SYMLINK ), FileExists(), and finally GetModificationTime()
|
||||
struct stat fn_stat;
|
||||
wxLstat( GetFullPath(), &fn_stat );
|
||||
|
||||
// Timestamp the source file, not the symlink
|
||||
if( S_ISLNK( fn_stat.st_mode ) ) // wxFILE_EXISTS_SYMLINK
|
||||
{
|
||||
char buffer[ PATH_MAX + 1 ];
|
||||
ssize_t pathLen = readlink( TO_UTF8( GetFullPath() ), buffer, PATH_MAX );
|
||||
|
||||
if( pathLen > 0 )
|
||||
{
|
||||
buffer[ pathLen ] = '\0';
|
||||
wxString srcPath = m_path + wxT( '/' ) + wxString::FromUTF8( buffer );
|
||||
wxLstat( srcPath, &fn_stat );
|
||||
}
|
||||
}
|
||||
|
||||
if( S_ISREG( fn_stat.st_mode ) ) // wxFileExists()
|
||||
return fn_stat.st_mtime * 1000;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef __WINDOWS__
|
||||
|
||||
//
|
||||
// A version of wxDir which avoids expensive calls to wxFileName::wxFileName().
|
||||
// A copy of wxMatchWild (attributed to <dalewis@cs.Buffalo.EDU>) modified to use
|
||||
// POSIX-file-system-encoded inputs.
|
||||
//
|
||||
WX_DIR::WX_DIR( const wxString& aDirPath ) :
|
||||
m_dirpath( aDirPath )
|
||||
bool matchWild( const char* pat, const char* text, bool dot_special )
|
||||
{
|
||||
m_dir = NULL;
|
||||
|
||||
// throw away the trailing slashes
|
||||
size_t n = m_dirpath.length();
|
||||
|
||||
while ( n > 0 && m_dirpath[--n] == '/' )
|
||||
;
|
||||
|
||||
m_dirpath.Truncate(n + 1);
|
||||
|
||||
m_dir = opendir( m_dirpath.fn_str() );
|
||||
}
|
||||
|
||||
|
||||
bool WX_DIR::IsOpened() const
|
||||
{
|
||||
return m_dir != nullptr;
|
||||
}
|
||||
|
||||
|
||||
WX_DIR::~WX_DIR()
|
||||
{
|
||||
if ( m_dir )
|
||||
closedir( m_dir );
|
||||
}
|
||||
|
||||
|
||||
bool WX_DIR::GetFirst( wxString *filename, const wxString& filespec )
|
||||
{
|
||||
m_filespec = filespec;
|
||||
|
||||
rewinddir( m_dir );
|
||||
return GetNext( filename );
|
||||
}
|
||||
|
||||
|
||||
bool WX_DIR::GetNext(wxString *filename) const
|
||||
{
|
||||
dirent *dirEntry = NULL;
|
||||
wxString dirEntryName;
|
||||
bool matches = false;
|
||||
|
||||
while ( !matches )
|
||||
if ( !*text )
|
||||
{
|
||||
dirEntry = readdir( m_dir );
|
||||
|
||||
if ( !dirEntry )
|
||||
return false;
|
||||
|
||||
#if wxUSE_UNICODE
|
||||
dirEntryName = wxString( dirEntry->d_name, *wxConvFileName );
|
||||
#else
|
||||
dirEntryName = dirEntry->d_name;
|
||||
#endif
|
||||
|
||||
matches = wxMatchWild( m_filespec, dirEntryName );
|
||||
/* Match if both are empty. */
|
||||
return !*pat;
|
||||
}
|
||||
|
||||
*filename = dirEntryName;
|
||||
const char *m = pat,
|
||||
*n = text,
|
||||
*ma = NULL,
|
||||
*na = NULL;
|
||||
int just = 0,
|
||||
acount = 0,
|
||||
count = 0;
|
||||
|
||||
return true;
|
||||
if (dot_special && (*n == '.'))
|
||||
{
|
||||
/* Never match so that hidden Unix files
|
||||
* are never found. */
|
||||
return false;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (*m == '*')
|
||||
{
|
||||
ma = ++m;
|
||||
na = n;
|
||||
just = 1;
|
||||
acount = count;
|
||||
}
|
||||
else if (*m == '?')
|
||||
{
|
||||
m++;
|
||||
if (!*n++)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*m == '\\')
|
||||
{
|
||||
m++;
|
||||
/* Quoting "nothing" is a bad thing */
|
||||
if (!*m)
|
||||
return false;
|
||||
}
|
||||
if (!*m)
|
||||
{
|
||||
/*
|
||||
* If we are out of both strings or we just
|
||||
* saw a wildcard, then we can say we have a
|
||||
* match
|
||||
*/
|
||||
if (!*n)
|
||||
return true;
|
||||
if (just)
|
||||
return true;
|
||||
just = 0;
|
||||
goto not_matched;
|
||||
}
|
||||
/*
|
||||
* We could check for *n == NULL at this point, but
|
||||
* since it's more common to have a character there,
|
||||
* check to see if they match first (m and n) and
|
||||
* then if they don't match, THEN we can check for
|
||||
* the NULL of n
|
||||
*/
|
||||
just = 0;
|
||||
if (*m == *n)
|
||||
{
|
||||
m++;
|
||||
count++;
|
||||
n++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
not_matched:
|
||||
|
||||
/*
|
||||
* If there are no more characters in the
|
||||
* string, but we still need to find another
|
||||
* character (*m != NULL), then it will be
|
||||
* impossible to match it
|
||||
*/
|
||||
if (!*n)
|
||||
return false;
|
||||
|
||||
if (ma)
|
||||
{
|
||||
m = ma;
|
||||
n = ++na;
|
||||
count = acount;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
long long TimestampDir( const wxString& aDirPath, const wxString& aFilespec )
|
||||
{
|
||||
long long timestamp = 0;
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
// wxFileName construction is egregiously slow. Construct it once and just swap out
|
||||
// the filename thereafter.
|
||||
WX_FILENAME fn( aDirPath, wxT( "dummyName" ) );
|
||||
wxDir dir( aDirPath );
|
||||
wxString fullname;
|
||||
|
||||
if( dir.IsOpened() )
|
||||
{
|
||||
if( dir.GetFirst( &fullname, filespec ) )
|
||||
{
|
||||
do
|
||||
{
|
||||
fn.SetFullName( fullname );
|
||||
timestamp += fn.GetTimestamp();
|
||||
}
|
||||
while( dir.GetNext( &fullname ) );
|
||||
}
|
||||
}
|
||||
#else
|
||||
// POSIX version. Save time by not converting between encodings -- do everything on
|
||||
// the file-system side.
|
||||
std::string filespec( aFilespec.fn_str() );
|
||||
std::string dir_path( aDirPath.fn_str() );
|
||||
|
||||
DIR* dir = opendir( dir_path.c_str() );
|
||||
|
||||
if( dir )
|
||||
{
|
||||
for( dirent* dir_entry = readdir( dir ); dir_entry; dir_entry = readdir( dir ) )
|
||||
{
|
||||
if( !matchWild( filespec.c_str(), dir_entry->d_name, true ) )
|
||||
continue;
|
||||
|
||||
std::string entry_path = dir_path + '/' + dir_entry->d_name;
|
||||
struct stat entry_stat;
|
||||
|
||||
wxCRT_Lstat( entry_path.c_str(), &entry_stat );
|
||||
|
||||
// Timestamp the source file, not the symlink
|
||||
if( S_ISLNK( entry_stat.st_mode ) ) // wxFILE_EXISTS_SYMLINK
|
||||
{
|
||||
char buffer[ PATH_MAX + 1 ];
|
||||
ssize_t pathLen = readlink( entry_path.c_str(), buffer, PATH_MAX );
|
||||
|
||||
if( pathLen > 0 )
|
||||
{
|
||||
buffer[ pathLen ] = '\0';
|
||||
entry_path = dir_path + buffer;
|
||||
|
||||
wxCRT_Lstat( entry_path.c_str(), &entry_stat );
|
||||
}
|
||||
}
|
||||
|
||||
if( S_ISREG( entry_stat.st_mode ) ) // wxFileExists()
|
||||
timestamp += entry_stat.st_mtime * 1000;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -23,12 +23,6 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @file footprint_info.cpp
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Functions to read footprint libraries and fill m_footprints by available footprints names
|
||||
* and their documentation (comments and keywords)
|
||||
|
@ -156,7 +150,6 @@ FOOTPRINT_LIST* FOOTPRINT_LIST::GetInstance( KIWAY& aKiway )
|
|||
|
||||
FOOTPRINT_ASYNC_LOADER::FOOTPRINT_ASYNC_LOADER() : m_list( nullptr )
|
||||
{
|
||||
m_started = false;
|
||||
m_total_libs = 0;
|
||||
}
|
||||
|
||||
|
@ -177,8 +170,6 @@ void FOOTPRINT_ASYNC_LOADER::SetList( FOOTPRINT_LIST* aList )
|
|||
void FOOTPRINT_ASYNC_LOADER::Start(
|
||||
FP_LIB_TABLE* aTable, wxString const* aNickname, unsigned aNThreads )
|
||||
{
|
||||
m_started = true;
|
||||
|
||||
// Capture the FP_LIB_TABLE into m_last_table. Formatting it as a string instead of storing the
|
||||
// raw data avoids having to pull in the FP-specific parts.
|
||||
STRING_FORMATTER sof;
|
||||
|
@ -210,17 +201,3 @@ void FOOTPRINT_ASYNC_LOADER::Abort()
|
|||
m_list = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FOOTPRINT_ASYNC_LOADER::SetCompletionCallback( std::function<void()> aCallback )
|
||||
{
|
||||
m_completion_cb = std::move(aCallback);
|
||||
}
|
||||
|
||||
|
||||
bool FOOTPRINT_ASYNC_LOADER::IsSameTable( FP_LIB_TABLE* aOther )
|
||||
{
|
||||
STRING_FORMATTER sof;
|
||||
aOther->Format( &sof, 0 );
|
||||
return m_last_table == sof.GetString();
|
||||
}
|
||||
|
|
|
@ -142,15 +142,15 @@ BOX2D STROKE_FONT::computeBoundingBox( const GLYPH& aGLYPH, const VECTOR2D& aGLY
|
|||
|
||||
std::deque<VECTOR2D> boundingPoints;
|
||||
|
||||
boundingPoints.push_back( VECTOR2D( aGLYPHBoundingX.x, 0 ) );
|
||||
boundingPoints.push_back( VECTOR2D( aGLYPHBoundingX.y, 0 ) );
|
||||
boundingPoints.emplace_back( VECTOR2D( aGLYPHBoundingX.x, 0 ) );
|
||||
boundingPoints.emplace_back( VECTOR2D( aGLYPHBoundingX.y, 0 ) );
|
||||
|
||||
for( GLYPH::const_iterator pointListIt = aGLYPH.begin(); pointListIt != aGLYPH.end(); ++pointListIt )
|
||||
{
|
||||
for( std::deque<VECTOR2D>::const_iterator pointIt = pointListIt->begin();
|
||||
pointIt != pointListIt->end(); ++pointIt )
|
||||
{
|
||||
boundingPoints.push_back( VECTOR2D( aGLYPHBoundingX.x, pointIt->y ) );
|
||||
boundingPoints.emplace_back( VECTOR2D( aGLYPHBoundingX.x, pointIt->y ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include <make_unique.h>
|
||||
#include <utility>
|
||||
#include <pgm_base.h>
|
||||
|
||||
#include <kicad_string.h>
|
||||
|
||||
// Each node gets this lowest score initially, without any matches applied.
|
||||
// Matches will then increase this score depending on match quality. This way,
|
||||
|
@ -59,19 +59,29 @@ void LIB_TREE_NODE::ResetScore()
|
|||
}
|
||||
|
||||
|
||||
void LIB_TREE_NODE::AssignIntrinsicRanks()
|
||||
void LIB_TREE_NODE::AssignIntrinsicRanks( bool presorted )
|
||||
{
|
||||
std::vector<LIB_TREE_NODE*> sort_buf;
|
||||
|
||||
for( auto const& node: Children )
|
||||
sort_buf.push_back( &*node );
|
||||
if( presorted )
|
||||
{
|
||||
int max = Children.size() - 1;
|
||||
|
||||
std::sort( sort_buf.begin(), sort_buf.end(),
|
||||
[]( LIB_TREE_NODE* a, LIB_TREE_NODE* b ) -> bool
|
||||
{ return a->MatchName > b->MatchName; } );
|
||||
for( int i = 0; i <= max; ++i )
|
||||
Children[i]->IntrinsicRank = max - i;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( auto const& node: Children )
|
||||
sort_buf.push_back( &*node );
|
||||
|
||||
for( int i = 0; i < (int) sort_buf.size(); ++i )
|
||||
sort_buf[i]->IntrinsicRank = i;
|
||||
std::sort( sort_buf.begin(), sort_buf.end(),
|
||||
[]( LIB_TREE_NODE* a, LIB_TREE_NODE* b ) -> bool
|
||||
{ return StrNumCmp( a->Name, b->Name, INT_MAX, true ) > 0; } );
|
||||
|
||||
for( int i = 0; i < (int) sort_buf.size(); ++i )
|
||||
sort_buf[i]->IntrinsicRank = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -108,7 +118,7 @@ LIB_TREE_NODE::LIB_TREE_NODE()
|
|||
Type( INVALID ),
|
||||
IntrinsicRank( 0 ),
|
||||
Score( kLowestDefaultScore ),
|
||||
SearchTextNormalized( false ),
|
||||
Normalized( false ),
|
||||
Unit( 0 ),
|
||||
IsRoot( false )
|
||||
{}
|
||||
|
@ -146,14 +156,15 @@ LIB_TREE_NODE_LIB_ID::LIB_TREE_NODE_LIB_ID( LIB_TREE_NODE* aParent, LIB_TREE_ITE
|
|||
Type = LIBID;
|
||||
Parent = aParent;
|
||||
|
||||
LibId = aItem->GetLibId();
|
||||
LibId.SetLibNickname( aItem->GetLibNickname() );
|
||||
LibId.SetLibItemName( aItem->GetName () );
|
||||
|
||||
Name = aItem->GetName();
|
||||
Desc = aItem->GetDescription();
|
||||
|
||||
MatchName = aItem->GetName().Lower();
|
||||
MatchName = aItem->GetName();
|
||||
SearchText = aItem->GetSearchText();
|
||||
SearchTextNormalized = false;
|
||||
Normalized = false;
|
||||
|
||||
IsRoot = aItem->IsRoot();
|
||||
|
||||
|
@ -182,7 +193,7 @@ void LIB_TREE_NODE_LIB_ID::Update( LIB_TREE_ITEM* aItem )
|
|||
Desc = aItem->GetDescription();
|
||||
|
||||
SearchText = aItem->GetSearchText();
|
||||
SearchTextNormalized = false;
|
||||
Normalized = false;
|
||||
|
||||
IsRoot = aItem->IsRoot();
|
||||
Children.clear();
|
||||
|
@ -197,10 +208,11 @@ void LIB_TREE_NODE_LIB_ID::UpdateScore( EDA_COMBINED_MATCHER& aMatcher )
|
|||
if( Score <= 0 )
|
||||
return; // Leaf nodes without scores are out of the game.
|
||||
|
||||
if( !SearchTextNormalized )
|
||||
if( !Normalized )
|
||||
{
|
||||
MatchName = MatchName.Lower();
|
||||
SearchText = SearchText.Lower();
|
||||
SearchTextNormalized = true;
|
||||
Normalized = true;
|
||||
}
|
||||
|
||||
// Keywords and description we only count if the match string is at
|
||||
|
|
|
@ -98,7 +98,7 @@ public:
|
|||
wxString Desc; ///< Description to be displayed
|
||||
wxString MatchName; ///< Normalized name for matching
|
||||
wxString SearchText; ///< Descriptive text to search
|
||||
bool SearchTextNormalized; ///< Support for lazy normalization.
|
||||
bool Normalized; ///< Support for lazy normalization.
|
||||
|
||||
|
||||
LIB_ID LibId; ///< LIB_ID determined by the parent library nickname and alias name.
|
||||
|
@ -122,7 +122,7 @@ public:
|
|||
* Store intrinsic ranks on all children of this node. See IntrinsicRank
|
||||
* member doc for more information.
|
||||
*/
|
||||
void AssignIntrinsicRanks();
|
||||
void AssignIntrinsicRanks( bool presorted = false );
|
||||
|
||||
/**
|
||||
* Sort child nodes quickly and recursively (IntrinsicRanks must have been set).
|
||||
|
|
|
@ -107,15 +107,15 @@ void LIB_TREE_MODEL_ADAPTER::SetPreselectNode( LIB_ID const& aLibId, int aUnit )
|
|||
|
||||
|
||||
void LIB_TREE_MODEL_ADAPTER::DoAddLibrary( wxString const& aNodeName, wxString const& aDesc,
|
||||
std::vector<LIB_TREE_ITEM*> const& aItemList )
|
||||
std::vector<LIB_TREE_ITEM*> const& aItemList,
|
||||
bool presorted )
|
||||
{
|
||||
auto& lib_node = m_tree.AddLib( aNodeName, aDesc );
|
||||
|
||||
for( auto item: aItemList )
|
||||
lib_node.AddItem( item );
|
||||
|
||||
lib_node.AssignIntrinsicRanks();
|
||||
m_tree.AssignIntrinsicRanks();
|
||||
lib_node.AssignIntrinsicRanks( presorted );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -151,7 +151,13 @@ public:
|
|||
* @param aItemList list of components
|
||||
*/
|
||||
void DoAddLibrary( wxString const& aNodeName, wxString const& aDesc,
|
||||
std::vector<LIB_TREE_ITEM*> const& aItemList );
|
||||
std::vector<LIB_TREE_ITEM*> const& aItemList, bool presorted );
|
||||
|
||||
|
||||
/**
|
||||
* Sort the tree and assign ranks after adding libraries.
|
||||
*/
|
||||
void AssignIntrinsicRanks() { m_tree.AssignIntrinsicRanks(); }
|
||||
|
||||
/**
|
||||
* Set the search string provided by the user.
|
||||
|
|
|
@ -70,7 +70,8 @@ wxBitmap COLOR_SWATCH::MakeBitmap( COLOR4D aColor, COLOR4D aBackground, wxSize a
|
|||
static std::unique_ptr<wxStaticBitmap> makeColorSwatch( wxWindow* aParent, COLOR4D aColor,
|
||||
COLOR4D aBackground, int aID )
|
||||
{
|
||||
wxSize size = aParent->ConvertDialogToPixels( SWATCH_SIZE_DU );
|
||||
static wxSize size = aParent->ConvertDialogToPixels( SWATCH_SIZE_DU );
|
||||
|
||||
wxBitmap bitmap = COLOR_SWATCH::MakeBitmap( aColor, aBackground, size );
|
||||
auto ret = std::make_unique<wxStaticBitmap>( aParent, aID, bitmap );
|
||||
|
||||
|
|
|
@ -145,7 +145,11 @@ wxString LIB_ALIAS::GetUnitReference( int aUnit )
|
|||
|
||||
wxString LIB_ALIAS::GetSearchText()
|
||||
{
|
||||
wxString text = GetKeyWords() + wxT( " " ) + GetDescription();
|
||||
// Matches are scored by offset from front of string, so inclusion of this spacer
|
||||
// discounts matches found after it.
|
||||
static const wxString discount( wxT( " " ) );
|
||||
|
||||
wxString text = GetKeyWords() + discount + GetDescription();
|
||||
|
||||
// If a footprint is defined for the part, add it to the serach string
|
||||
if( shared )
|
||||
|
@ -153,7 +157,7 @@ wxString LIB_ALIAS::GetSearchText()
|
|||
wxString footprint = shared->GetFootprintField().GetText();
|
||||
|
||||
if( !footprint.IsEmpty() )
|
||||
text += wxT( " " ) + footprint;
|
||||
text += discount + footprint;
|
||||
}
|
||||
|
||||
return text;
|
||||
|
|
|
@ -123,21 +123,21 @@ public:
|
|||
description = aDescription;
|
||||
}
|
||||
|
||||
wxString GetDescription() override { return description; }
|
||||
const wxString& GetDescription() override { return description; }
|
||||
|
||||
void SetKeyWords( const wxString& aKeyWords )
|
||||
{
|
||||
keyWords = aKeyWords;
|
||||
}
|
||||
|
||||
wxString GetKeyWords() const { return keyWords; }
|
||||
const wxString& GetKeyWords() const { return keyWords; }
|
||||
|
||||
void SetDocFileName( const wxString& aDocFileName )
|
||||
{
|
||||
docFileName = aDocFileName;
|
||||
}
|
||||
|
||||
wxString GetDocFileName() const { return docFileName; }
|
||||
const wxString& GetDocFileName() const { return docFileName; }
|
||||
|
||||
wxString GetSearchText() override;
|
||||
|
||||
|
|
|
@ -133,6 +133,8 @@ SCH_BASE_FRAME::COMPONENT_SELECTION SCH_BASE_FRAME::SelectComponentFromLibTree(
|
|||
}
|
||||
}
|
||||
|
||||
adapter->AssignIntrinsicRanks();
|
||||
|
||||
if( aFilter->GetFilterPowerParts() )
|
||||
adapter->SetFilter( SYMBOL_TREE_MODEL_ADAPTER::CMP_FILTER_POWER );
|
||||
|
||||
|
@ -150,7 +152,7 @@ SCH_BASE_FRAME::COMPONENT_SELECTION SCH_BASE_FRAME::SelectComponentFromLibTree(
|
|||
history_list.push_back( alias );
|
||||
}
|
||||
|
||||
adapter->DoAddLibrary( "-- " + _( "Recently Used" ) + " --", wxEmptyString, history_list );
|
||||
adapter->DoAddLibrary( "-- " + _( "Recently Used" ) + " --", wxEmptyString, history_list, true );
|
||||
adapter->SetPreselectNode( aHistoryList[0].LibId, aHistoryList[0].Unit );
|
||||
}
|
||||
|
||||
|
|
|
@ -76,6 +76,8 @@ void SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( const std::vector<wxString>& aNick
|
|||
ii++;
|
||||
}
|
||||
|
||||
m_tree.AssignIntrinsicRanks();
|
||||
|
||||
if( prg )
|
||||
{
|
||||
prg->Destroy();
|
||||
|
@ -105,8 +107,7 @@ void SYMBOL_TREE_MODEL_ADAPTER::AddLibrary( wxString const& aLibNickname )
|
|||
if( alias_list.size() > 0 )
|
||||
{
|
||||
comp_list.assign( alias_list.begin(), alias_list.end() );
|
||||
DoAddLibrary( aLibNickname, m_libs->GetDescription( aLibNickname ), comp_list );
|
||||
m_tree.AssignIntrinsicRanks();
|
||||
DoAddLibrary( aLibNickname, m_libs->GetDescription( aLibNickname ), comp_list, false );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -102,9 +102,10 @@ void SYMBOL_TREE_SYNCHRONIZING_ADAPTER::Sync( bool aForce, std::function<void(in
|
|||
|
||||
auto& lib_node = m_tree.AddLib( libName, library->GetDescr() );
|
||||
updateLibrary( lib_node );
|
||||
m_tree.AssignIntrinsicRanks();
|
||||
}
|
||||
}
|
||||
|
||||
m_tree.AssignIntrinsicRanks();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -383,65 +383,35 @@ namespace std
|
|||
|
||||
|
||||
/**
|
||||
* A wrapper around a wxFileName which is much more performant with a (very) limited API.
|
||||
* A wrapper around a wxFileName which is much more performant with a subset of the API.
|
||||
*/
|
||||
class WX_FILENAME
|
||||
{
|
||||
public:
|
||||
WX_FILENAME( const wxString& aPath, const wxString& aFilename ) :
|
||||
m_fn( aPath, aFilename ),
|
||||
m_path( aPath ),
|
||||
m_fullName( aFilename )
|
||||
{ }
|
||||
WX_FILENAME( const wxString& aPath, const wxString& aFilename );
|
||||
|
||||
// Avoid wxFileName's expensive path concatenation.
|
||||
wxString GetFullPath() { return m_path + wxT( '/' ) + m_fullName; }
|
||||
|
||||
wxString GetName() { return m_fn.GetName(); }
|
||||
|
||||
// Avoid wxFileName's expensive calls to wxFileName::SplitPath().
|
||||
void SetFullName( const wxString& aFileNameAndExtension );
|
||||
|
||||
wxString GetName() const;
|
||||
wxString GetFullName() const;
|
||||
wxString GetPath() const;
|
||||
wxString GetFullPath() const;
|
||||
|
||||
// Avoid multiple calls to stat() on POSIX kernels.
|
||||
long long GetTimestamp();
|
||||
|
||||
operator wxFileName() const { return m_fn; }
|
||||
|
||||
private:
|
||||
// Write cached values to the wrapped wxFileName. MUST be called before using m_fn.
|
||||
void resolve();
|
||||
|
||||
wxFileName m_fn;
|
||||
wxString m_path;
|
||||
wxString m_fullName;
|
||||
};
|
||||
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#define WX_DIR wxDir
|
||||
#else
|
||||
// For POSIX kernels we implement our own version which avoids expensive calls to
|
||||
// wxFileName::wxFileName().
|
||||
class WX_DIR
|
||||
{
|
||||
public:
|
||||
WX_DIR( const wxString& dir );
|
||||
~WX_DIR();
|
||||
long long TimestampDir( const wxString& aDirPath, const wxString& aFilespec );
|
||||
|
||||
// returns true if the directory was successfully opened
|
||||
bool IsOpened() const;
|
||||
|
||||
bool GetFirst( wxString *filename, const wxString& filespec );
|
||||
|
||||
// get next file in the enumeration started with GetFirst()
|
||||
bool GetNext( wxString *filename ) const;
|
||||
|
||||
private:
|
||||
DIR* m_dir;
|
||||
|
||||
wxString m_dirpath;
|
||||
wxString m_filespec;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS( WX_DIR );
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -92,13 +92,13 @@ public:
|
|||
return LIB_ID( m_nickname, m_fpname );
|
||||
}
|
||||
|
||||
wxString GetDescription() override
|
||||
const wxString& GetDescription() override
|
||||
{
|
||||
ensure_loaded();
|
||||
return m_doc;
|
||||
}
|
||||
|
||||
wxString GetKeywords()
|
||||
const wxString& GetKeywords()
|
||||
{
|
||||
ensure_loaded();
|
||||
return m_keywords;
|
||||
|
@ -106,7 +106,11 @@ public:
|
|||
|
||||
wxString GetSearchText() override
|
||||
{
|
||||
return GetKeywords() + wxT( " " ) + GetDescription();
|
||||
// Matches are scored by offset from front of string, so inclusion of this spacer
|
||||
// discounts matches found after it.
|
||||
static const wxString discount( wxT( " " ) );
|
||||
|
||||
return GetKeywords() + discount + GetDescription();
|
||||
}
|
||||
|
||||
unsigned GetPadCount()
|
||||
|
@ -154,8 +158,8 @@ protected:
|
|||
wxString m_nickname; ///< library as known in FP_LIB_TABLE
|
||||
wxString m_fpname; ///< Module name.
|
||||
int m_num; ///< Order number in the display list.
|
||||
int m_pad_count; ///< Number of pads
|
||||
int m_unique_pad_count; ///< Number of unique pads
|
||||
unsigned m_pad_count; ///< Number of pads
|
||||
unsigned m_unique_pad_count; ///< Number of unique pads
|
||||
wxString m_doc; ///< Footprint description.
|
||||
wxString m_keywords; ///< Footprint keywords.
|
||||
};
|
||||
|
@ -313,10 +317,8 @@ class APIEXPORT FOOTPRINT_ASYNC_LOADER
|
|||
friend class FOOTPRINT_LIST_IMPL;
|
||||
|
||||
FOOTPRINT_LIST* m_list;
|
||||
std::function<void()> m_completion_cb;
|
||||
std::string m_last_table;
|
||||
|
||||
bool m_started; ///< True if Start() has been called - does not reset
|
||||
int m_total_libs;
|
||||
|
||||
public:
|
||||
|
@ -364,21 +366,6 @@ public:
|
|||
*/
|
||||
void Abort();
|
||||
|
||||
/**
|
||||
* Set a callback to receive notice when loading is complete.
|
||||
*
|
||||
* Callback MUST be threadsafe, and must be set before calling Start
|
||||
* if you want to use it (it is safe not to set it at all).
|
||||
*/
|
||||
void SetCompletionCallback( std::function<void()> aCallback );
|
||||
|
||||
/**
|
||||
* Return true if the given table is the same as the last table loaded.
|
||||
* Useful for checking if the table has been modified and needs to be
|
||||
* reloaded.
|
||||
*/
|
||||
bool IsSameTable( FP_LIB_TABLE* aOther );
|
||||
|
||||
/**
|
||||
* Default number of worker threads. Determined empirically (by dickelbeck):
|
||||
* More than 6 is not significantly faster, less than 6 is likely slower.
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
virtual const wxString& GetName() const = 0;
|
||||
virtual wxString GetLibNickname() const = 0;
|
||||
|
||||
virtual wxString GetDescription() { return wxEmptyString; }
|
||||
virtual const wxString& GetDescription() = 0;
|
||||
|
||||
virtual wxString GetSearchText() { return wxEmptyString; }
|
||||
|
||||
|
|
|
@ -270,12 +270,19 @@ FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent,
|
|||
initLibraryTree();
|
||||
m_treePane = new FOOTPRINT_TREE_PANE( this );
|
||||
|
||||
ReCreateMenuBar();
|
||||
// ReCreateMenuBar(); // UseGalCanvas() will do this for us.
|
||||
ReCreateHToolbar();
|
||||
ReCreateAuxiliaryToolbar();
|
||||
ReCreateVToolbar();
|
||||
ReCreateOptToolbar();
|
||||
|
||||
m_Layers->ReFill();
|
||||
m_Layers->ReFillRender();
|
||||
|
||||
GetScreen()->m_Active_Layer = F_SilkS;
|
||||
m_Layers->SelectLayer( F_SilkS );
|
||||
m_Layers->OnLayerSelected();
|
||||
|
||||
if( m_canvas )
|
||||
m_canvas->SetEnableBlockCommands( true );
|
||||
|
||||
|
@ -334,16 +341,6 @@ FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent,
|
|||
GetGalCanvas()->GetGAL()->SetAxesEnabled( true );
|
||||
UseGalCanvas( aBackend != EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE );
|
||||
|
||||
if( m_auimgr.GetPane( "m_LayersManagerToolBar" ).IsShown() )
|
||||
{
|
||||
m_Layers->ReFill();
|
||||
m_Layers->ReFillRender();
|
||||
|
||||
GetScreen()->m_Active_Layer = F_SilkS;
|
||||
m_Layers->SelectLayer( F_SilkS );
|
||||
m_Layers->OnLayerSelected();
|
||||
}
|
||||
|
||||
m_auimgr.Update();
|
||||
updateTitle();
|
||||
|
||||
|
|
|
@ -49,8 +49,10 @@ void FP_TREE_MODEL_ADAPTER::AddLibraries()
|
|||
{
|
||||
const FP_LIB_TABLE_ROW* library = m_libs->FindRow( libName );
|
||||
|
||||
DoAddLibrary( libName, library->GetDescr(), getFootprints( libName ) );
|
||||
DoAddLibrary( libName, library->GetDescr(), getFootprints( libName ), true );
|
||||
}
|
||||
|
||||
m_tree.AssignIntrinsicRanks();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -69,16 +69,21 @@ void FP_TREE_SYNCHRONIZING_ADAPTER::Sync()
|
|||
}
|
||||
|
||||
// Look for new libraries
|
||||
size_t count = m_libMap.size();
|
||||
|
||||
for( const auto& libName : m_libs->GetLogicalLibs() )
|
||||
{
|
||||
if( m_libMap.count( libName ) == 0 )
|
||||
{
|
||||
const FP_LIB_TABLE_ROW* library = m_libs->FindRow( libName );
|
||||
|
||||
DoAddLibrary( libName, library->GetDescr(), getFootprints( libName ) );
|
||||
DoAddLibrary( libName, library->GetDescr(), getFootprints( libName ), true );
|
||||
m_libMap.insert( libName );
|
||||
}
|
||||
}
|
||||
|
||||
if( m_libMap.size() > count )
|
||||
m_tree.AssignIntrinsicRanks();
|
||||
}
|
||||
|
||||
|
||||
|
@ -92,7 +97,7 @@ void FP_TREE_SYNCHRONIZING_ADAPTER::updateLibrary( LIB_TREE_NODE_LIB& aLibNode )
|
|||
{
|
||||
std::vector<LIB_TREE_ITEM*> footprints = getFootprints( aLibNode.Name );
|
||||
|
||||
// remove the common part from the aliases list
|
||||
// remove the common part from the footprints list
|
||||
for( auto nodeIt = aLibNode.Children.begin(); nodeIt != aLibNode.Children.end(); )
|
||||
{
|
||||
// Since the list is sorted we can use a binary search to speed up searches within
|
||||
|
@ -119,7 +124,7 @@ void FP_TREE_SYNCHRONIZING_ADAPTER::updateLibrary( LIB_TREE_NODE_LIB& aLibNode )
|
|||
}
|
||||
}
|
||||
|
||||
// now the aliases list contains only new aliases that need to be added to the tree
|
||||
// now the footprint list contains only new aliases that need to be added to the tree
|
||||
for( auto footprint : footprints )
|
||||
aLibNode.AddItem( footprint );
|
||||
|
||||
|
|
|
@ -133,9 +133,9 @@ public:
|
|||
};
|
||||
|
||||
|
||||
wxString GenerateFootprintInfo( FP_LIB_TABLE* aSymLibTable, LIB_ID const& aLibId )
|
||||
wxString GenerateFootprintInfo( FP_LIB_TABLE* aFpLibTable, LIB_ID const& aLibId )
|
||||
{
|
||||
FOOTPRINT_INFO_GENERATOR gen( aSymLibTable, aLibId );
|
||||
FOOTPRINT_INFO_GENERATOR gen( aFpLibTable, aLibId );
|
||||
gen.GenerateHtml();
|
||||
return gen.GetHtml();
|
||||
}
|
||||
|
|
|
@ -108,20 +108,19 @@ static inline long parseInt( const wxString& aValue, double aScalar )
|
|||
*/
|
||||
class GPCB_FPL_CACHE_ITEM
|
||||
{
|
||||
wxFileName m_file_name; ///< The the full file name and path of the footprint to cache.
|
||||
WX_FILENAME m_filename; ///< The the full file name and path of the footprint to cache.
|
||||
std::unique_ptr<MODULE> m_module;
|
||||
|
||||
public:
|
||||
GPCB_FPL_CACHE_ITEM( MODULE* aModule, const wxFileName& aFileName );
|
||||
GPCB_FPL_CACHE_ITEM( MODULE* aModule, const WX_FILENAME& aFileName );
|
||||
|
||||
wxString GetName() const { return m_file_name.GetDirs().Last(); }
|
||||
wxFileName GetFileName() const { return m_file_name; }
|
||||
MODULE* GetModule() const { return m_module.get(); }
|
||||
WX_FILENAME GetFileName() const { return m_filename; }
|
||||
MODULE* GetModule() const { return m_module.get(); }
|
||||
};
|
||||
|
||||
|
||||
GPCB_FPL_CACHE_ITEM::GPCB_FPL_CACHE_ITEM( MODULE* aModule, const wxFileName& aFileName ) :
|
||||
m_file_name( aFileName ),
|
||||
GPCB_FPL_CACHE_ITEM::GPCB_FPL_CACHE_ITEM( MODULE* aModule, const WX_FILENAME& aFileName ) :
|
||||
m_filename( aFileName ),
|
||||
m_module( aModule )
|
||||
{
|
||||
}
|
||||
|
@ -225,7 +224,7 @@ void GPCB_FPL_CACHE::Load()
|
|||
// Note: like our .pretty footprint libraries, the gpcb footprint libraries are folders,
|
||||
// and the footprints are the .fp files inside this folder.
|
||||
|
||||
WX_DIR dir( m_lib_path.GetPath() );
|
||||
wxDir dir( m_lib_path.GetPath() );
|
||||
|
||||
if( !dir.IsOpened() )
|
||||
{
|
||||
|
@ -233,21 +232,21 @@ void GPCB_FPL_CACHE::Load()
|
|||
m_lib_path.GetPath().GetData() ) );
|
||||
}
|
||||
|
||||
wxString fpFileName;
|
||||
wxString wildcard = wxT( "*." ) + GedaPcbFootprintLibFileExtension;
|
||||
wxString fullName;
|
||||
wxString fileSpec = wxT( "*." ) + GedaPcbFootprintLibFileExtension;
|
||||
|
||||
// wxFileName construction is egregiously slow. Construct it once and just swap out
|
||||
// the filename.
|
||||
WX_FILENAME fn( m_lib_path.GetPath(), wxT( "dummy." ) + GedaPcbFootprintLibFileExtension );
|
||||
// the filename thereafter.
|
||||
WX_FILENAME fn( m_lib_path.GetPath(), wxT( "dummyName" ) );
|
||||
|
||||
if( !dir.GetFirst( &fpFileName, wildcard ) )
|
||||
if( !dir.GetFirst( &fullName, fileSpec ) )
|
||||
return;
|
||||
|
||||
wxString cacheErrorMsg;
|
||||
|
||||
do
|
||||
{
|
||||
fn.SetFullName( fpFileName );
|
||||
fn.SetFullName( fullName );
|
||||
|
||||
// Queue I/O errors so only files that fail to parse don't get loaded.
|
||||
try
|
||||
|
@ -260,7 +259,7 @@ void GPCB_FPL_CACHE::Load()
|
|||
|
||||
// The footprint name is the file name without the extension.
|
||||
footprint->SetFPID( LIB_ID( wxEmptyString, fn.GetName() ) );
|
||||
m_modules.insert( name, new GPCB_FPL_CACHE_ITEM( footprint, fn.GetName() ) );
|
||||
m_modules.insert( name, new GPCB_FPL_CACHE_ITEM( footprint, fn ) );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
|
@ -269,7 +268,7 @@ void GPCB_FPL_CACHE::Load()
|
|||
|
||||
cacheErrorMsg += ioe.What();
|
||||
}
|
||||
} while( dir.GetNext( &fpFileName ) );
|
||||
} while( dir.GetNext( &fullName ) );
|
||||
|
||||
if( !cacheErrorMsg.IsEmpty() )
|
||||
THROW_IO_ERROR( cacheErrorMsg );
|
||||
|
@ -306,30 +305,9 @@ bool GPCB_FPL_CACHE::IsModified()
|
|||
|
||||
long long GPCB_FPL_CACHE::GetTimestamp( const wxString& aLibPath )
|
||||
{
|
||||
long long files_timestamp = 0;
|
||||
wxString fileSpec = wxT( "*." ) + GedaPcbFootprintLibFileExtension;
|
||||
|
||||
// wxFileName construction is egregiously slow. Construct it once and just swap out
|
||||
// the filename.
|
||||
WX_FILENAME fn( aLibPath, wxT( "dummy." ) + GedaPcbFootprintLibFileExtension );
|
||||
|
||||
WX_DIR dir( aLibPath );
|
||||
|
||||
if( dir.IsOpened() )
|
||||
{
|
||||
wxString fpFileName;
|
||||
wxString wildcard = wxT( "*." ) + GedaPcbFootprintLibFileExtension;
|
||||
|
||||
if( dir.GetFirst( &fpFileName, wildcard ) )
|
||||
{
|
||||
do
|
||||
{
|
||||
fn.SetFullName( fpFileName );
|
||||
files_timestamp += fn.GetTimestamp();
|
||||
} while( dir.GetNext( &fpFileName ) );
|
||||
}
|
||||
}
|
||||
|
||||
return files_timestamp;
|
||||
return TimestampDir( aLibPath, fileSpec );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -85,24 +85,21 @@ void filterNetClass( const BOARD& aBoard, NETCLASS& aNetClass )
|
|||
*/
|
||||
class FP_CACHE_ITEM
|
||||
{
|
||||
wxFileName m_file_name; ///< The the full file name and path of the footprint to cache.
|
||||
WX_FILENAME m_filename;
|
||||
std::unique_ptr<MODULE> m_module;
|
||||
|
||||
public:
|
||||
FP_CACHE_ITEM( MODULE* aModule, const wxFileName& aFileName );
|
||||
FP_CACHE_ITEM( MODULE* aModule, const WX_FILENAME& aFileName );
|
||||
|
||||
const wxString& GetName() const { return m_file_name.GetDirs().Last(); }
|
||||
const wxFileName& GetFileName() const { return m_file_name; }
|
||||
|
||||
const MODULE* GetModule() const { return m_module.get(); }
|
||||
const WX_FILENAME& GetFileName() const { return m_filename; }
|
||||
const MODULE* GetModule() const { return m_module.get(); }
|
||||
};
|
||||
|
||||
|
||||
FP_CACHE_ITEM::FP_CACHE_ITEM( MODULE* aModule, const wxFileName& aFileName ) :
|
||||
FP_CACHE_ITEM::FP_CACHE_ITEM( MODULE* aModule, const WX_FILENAME& aFileName ) :
|
||||
m_filename( aFileName ),
|
||||
m_module( aModule )
|
||||
{
|
||||
m_file_name = aFileName;
|
||||
}
|
||||
{ }
|
||||
|
||||
|
||||
typedef boost::ptr_map< wxString, FP_CACHE_ITEM > MODULE_MAP;
|
||||
|
@ -207,11 +204,11 @@ void FP_CACHE::Save( MODULE* aModule )
|
|||
if( aModule && aModule != it->second->GetModule() )
|
||||
continue;
|
||||
|
||||
wxFileName fn = it->second->GetFileName();
|
||||
WX_FILENAME fn = it->second->GetFileName();
|
||||
|
||||
wxString tempFileName =
|
||||
#ifdef USE_TMP_FILE
|
||||
fn.CreateTempFileName( fn.GetPath() );
|
||||
wxFileName::CreateTempFileName( fn.GetPath() );
|
||||
#else
|
||||
fn.GetFullPath();
|
||||
#endif
|
||||
|
@ -244,7 +241,7 @@ void FP_CACHE::Save( MODULE* aModule )
|
|||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
#endif
|
||||
m_cache_timestamp += fn.GetModificationTime().GetValue().GetValue();
|
||||
m_cache_timestamp += fn.GetTimestamp();
|
||||
}
|
||||
|
||||
m_cache_timestamp += m_lib_path.GetModificationTime().GetValue().GetValue();
|
||||
|
@ -260,7 +257,7 @@ void FP_CACHE::Load()
|
|||
m_cache_dirty = false;
|
||||
m_cache_timestamp = 0;
|
||||
|
||||
WX_DIR dir( m_lib_raw_path );
|
||||
wxDir dir( m_lib_raw_path );
|
||||
|
||||
if( !dir.IsOpened() )
|
||||
{
|
||||
|
@ -269,20 +266,20 @@ void FP_CACHE::Load()
|
|||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
|
||||
wxString fpFileName;
|
||||
wxString wildcard = wxT( "*." ) + KiCadFootprintFileExtension;
|
||||
wxString fullName;
|
||||
wxString fileSpec = wxT( "*." ) + KiCadFootprintFileExtension;
|
||||
|
||||
// wxFileName construction is egregiously slow. Construct it once and just swap out
|
||||
// the filename.
|
||||
WX_FILENAME fn( m_lib_raw_path, wxT( "dummy." ) + KiCadFootprintFileExtension );
|
||||
// the filename thereafter.
|
||||
WX_FILENAME fn( m_lib_raw_path, wxT( "dummyName" ) );
|
||||
|
||||
if( dir.GetFirst( &fpFileName, wildcard ) )
|
||||
if( dir.GetFirst( &fullName, fileSpec ) )
|
||||
{
|
||||
wxString cacheError;
|
||||
|
||||
do
|
||||
{
|
||||
fn.SetFullName( fpFileName );
|
||||
fn.SetFullName( fullName );
|
||||
|
||||
// Queue I/O errors so only files that fail to parse don't get loaded.
|
||||
try
|
||||
|
@ -292,8 +289,6 @@ void FP_CACHE::Load()
|
|||
m_owner->m_parser->SetLineReader( &reader );
|
||||
|
||||
MODULE* footprint = (MODULE*) m_owner->m_parser->Parse();
|
||||
|
||||
// The footprint name is the file name without the extension.
|
||||
wxString fpName = fn.GetName();
|
||||
|
||||
footprint->SetFPID( LIB_ID( wxEmptyString, fpName ) );
|
||||
|
@ -308,7 +303,7 @@ void FP_CACHE::Load()
|
|||
|
||||
cacheError += ioe.What();
|
||||
}
|
||||
} while( dir.GetNext( &fpFileName ) );
|
||||
} while( dir.GetNext( &fullName ) );
|
||||
|
||||
if( !cacheError.IsEmpty() )
|
||||
THROW_IO_ERROR( cacheError );
|
||||
|
@ -351,30 +346,9 @@ bool FP_CACHE::IsModified()
|
|||
|
||||
long long FP_CACHE::GetTimestamp( const wxString& aLibPath )
|
||||
{
|
||||
long long files_timestamp = 0;
|
||||
wxString fileSpec = wxT( "*." ) + KiCadFootprintFileExtension;
|
||||
|
||||
// wxFileName construction is egregiously slow. Construct it once and just
|
||||
// swap out the filename for each file.
|
||||
WX_FILENAME fn( aLibPath, wxT( "dummy." ) + KiCadFootprintFileExtension );
|
||||
|
||||
WX_DIR dir( aLibPath );
|
||||
|
||||
if( dir.IsOpened() )
|
||||
{
|
||||
wxString fpFileName;
|
||||
wxString wildcard = wxT( "*." ) + KiCadFootprintFileExtension;
|
||||
|
||||
if( dir.GetFirst( &fpFileName, wildcard ) )
|
||||
{
|
||||
do
|
||||
{
|
||||
fn.SetFullName( fpFileName );
|
||||
files_timestamp += fn.GetTimestamp();
|
||||
} while( dir.GetNext( &fpFileName ) );
|
||||
}
|
||||
}
|
||||
|
||||
return files_timestamp;
|
||||
return TimestampDir( aLibPath, fileSpec );
|
||||
}
|
||||
|
||||
|
||||
|
@ -2120,14 +2094,15 @@ void PCB_IO::FootprintSave( const wxString& aLibraryPath, const MODULE* aFootpri
|
|||
fn.GetFullPath() ) );
|
||||
}
|
||||
|
||||
wxString fullPath = fn.GetFullPath();
|
||||
wxString fullName = fn.GetFullName();
|
||||
MODULE_CITER it = mods.find( footprintName );
|
||||
|
||||
if( it != mods.end() )
|
||||
{
|
||||
wxLogTrace( traceKicadPcbPlugin, wxT( "Removing footprint library file '%s'." ),
|
||||
fn.GetFullPath().GetData() );
|
||||
wxLogTrace( traceKicadPcbPlugin, wxT( "Removing footprint file '%s'." ), fullPath );
|
||||
mods.erase( footprintName );
|
||||
wxRemoveFile( fn.GetFullPath() );
|
||||
wxRemoveFile( fullPath );
|
||||
}
|
||||
|
||||
// I need my own copy for the cache
|
||||
|
@ -2142,9 +2117,8 @@ void PCB_IO::FootprintSave( const wxString& aLibraryPath, const MODULE* aFootpri
|
|||
if( module->GetLayer() != F_Cu )
|
||||
module->Flip( module->GetPosition() );
|
||||
|
||||
wxLogTrace( traceKicadPcbPlugin, wxT( "Creating s-expression footprint file: %s." ),
|
||||
fn.GetFullPath().GetData() );
|
||||
mods.insert( footprintName, new FP_CACHE_ITEM( module, fn ) );
|
||||
wxLogTrace( traceKicadPcbPlugin, wxT( "Creating s-expr footprint file '%s'." ), fullPath );
|
||||
mods.insert( footprintName, new FP_CACHE_ITEM( module, WX_FILENAME( fullPath, fullName ) ) );
|
||||
m_cache->Save( module );
|
||||
}
|
||||
|
||||
|
|
|
@ -207,7 +207,7 @@ MODULE* PCB_BASE_FRAME::SelectFootprintFromLibTree( bool aAllowBrowser )
|
|||
for( auto const& item : s_ModuleHistoryList )
|
||||
historyInfos.push_back( GFootprintList.GetModuleInfo( item ) );
|
||||
|
||||
adapter->DoAddLibrary( "-- " + _( "Recently Used" ) + " --", wxEmptyString, historyInfos );
|
||||
adapter->DoAddLibrary( "-- " + _( "Recently Used" ) + " --", wxEmptyString, historyInfos, true );
|
||||
|
||||
if( !historyInfos.empty() )
|
||||
adapter->SetPreselectNode( historyInfos[0]->GetLibId(), 0 );
|
||||
|
|
|
@ -113,7 +113,6 @@ PCB_LAYER_WIDGET::PCB_LAYER_WIDGET( PCB_BASE_FRAME* aParent, wxWindow* aFocusOwn
|
|||
{
|
||||
m_alwaysShowActiveCopperLayer = false;
|
||||
m_fp_editor_mode = aFpEditorMode;
|
||||
ReFillRender();
|
||||
|
||||
// Update default tabs labels
|
||||
SetLayersManagerTabsText();
|
||||
|
|
Loading…
Reference in New Issue