From 829c23643719c269a3d731ef31c7cb5965c946a5 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Thu, 25 Jan 2018 23:49:04 +0000 Subject: [PATCH] Symbol library load performance enhancements. 1) Edit Symbol gets similar fix as Place Symbol 2) progress dialog updating reduced to once every 50ms 3) SearchText gets lazy normalization 4) TypeNames get lazy translation 5) default fieldNames get translated a single time per language change These fixes reduce first-load-time of both Edit Symbol and Place Symbol by about 2/3, and second-load-time of Edit Symbol to near-instantaneous. --- eeschema/cmp_tree_model.cpp | 24 +++++++++++++++++++++--- eeschema/cmp_tree_model.h | 2 ++ eeschema/lib_arc.cpp | 1 - eeschema/lib_arc.h | 5 +++++ eeschema/lib_bezier.cpp | 1 - eeschema/lib_bezier.h | 4 ++++ eeschema/lib_circle.cpp | 1 - eeschema/lib_circle.h | 4 ++++ eeschema/lib_draw_item.cpp | 3 +-- eeschema/lib_draw_item.h | 8 +++++--- eeschema/lib_field.cpp | 2 -- eeschema/lib_field.h | 5 +++++ eeschema/lib_manager.cpp | 13 +++++++------ eeschema/lib_manager_adapter.cpp | 18 ++++++++++++++++-- eeschema/lib_pin.cpp | 1 - eeschema/lib_pin.h | 5 +++++ eeschema/lib_polyline.cpp | 1 - eeschema/lib_polyline.h | 4 ++++ eeschema/lib_rectangle.cpp | 1 - eeschema/lib_rectangle.h | 5 +++++ eeschema/lib_text.cpp | 1 - eeschema/lib_text.h | 5 +++++ eeschema/template_fieldnames.cpp | 31 ++++++++++++++++++++++++++----- 23 files changed, 115 insertions(+), 30 deletions(-) diff --git a/eeschema/cmp_tree_model.cpp b/eeschema/cmp_tree_model.cpp index 605e44b823..a8308fbd43 100644 --- a/eeschema/cmp_tree_model.cpp +++ b/eeschema/cmp_tree_model.cpp @@ -25,6 +25,7 @@ #include #include #include +#include // Each node gets this lowest score initially, without any matches applied. @@ -114,13 +115,24 @@ CMP_TREE_NODE::CMP_TREE_NODE() CMP_TREE_NODE_UNIT::CMP_TREE_NODE_UNIT( CMP_TREE_NODE* aParent, int aUnit ) { + static void* locale = nullptr; + static wxString namePrefix; + + // Fetching translations can take a surprising amount of time when loading libraries, + // so only do it when necessary. + if( Pgm().GetLocale() != locale ) + { + namePrefix = _( "Unit" ); + locale = Pgm().GetLocale(); + } + Parent = aParent; Type = UNIT; Unit = aUnit; LibId = aParent->LibId; - Name = _( "Unit" ) + " " + LIB_PART::SubReference( aUnit, false ); + Name = namePrefix + " " + LIB_PART::SubReference( aUnit, false ); Desc = wxEmptyString; MatchName = wxEmptyString; @@ -158,7 +170,7 @@ void CMP_TREE_NODE_LIB_ID::Update( LIB_ALIAS* aAlias ) // Search text spaces out keywords and description to penalize description // matches - earlier matches are worth more. MatchName = aAlias->GetName().Lower(); - SearchText = (aAlias->GetKeyWords() + " " + Desc).Lower(); + SearchText = (aAlias->GetKeyWords() + " " + Desc); // Extract default footprint text LIB_PART* part = aAlias->GetPart(); @@ -177,7 +189,7 @@ void CMP_TREE_NODE_LIB_ID::Update( LIB_ALIAS* aAlias ) if( !footprint.IsEmpty() ) { SearchText += " "; - SearchText += footprint.Lower(); + SearchText += footprint; } Children.clear(); @@ -195,6 +207,12 @@ void CMP_TREE_NODE_LIB_ID::UpdateScore( EDA_COMBINED_MATCHER& aMatcher ) if( Score <= 0 ) return; // Leaf nodes without scores are out of the game. + if( !SearchTextNormalized ) + { + SearchText = SearchText.Lower(); + SearchTextNormalized = true; + } + // Keywords and description we only count if the match string is at // least two characters long. That avoids spurious, low quality // matches. Most abbreviations are at three characters long. diff --git a/eeschema/cmp_tree_model.h b/eeschema/cmp_tree_model.h index e9e04cb7e5..30788e13d0 100644 --- a/eeschema/cmp_tree_model.h +++ b/eeschema/cmp_tree_model.h @@ -100,6 +100,8 @@ 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. + LIB_ID LibId; ///< LIB_ID determined by the parent library nickname and alias name. int Unit; ///< Actual unit, or zero diff --git a/eeschema/lib_arc.cpp b/eeschema/lib_arc.cpp index 0b5531e6db..88d8edf97a 100644 --- a/eeschema/lib_arc.cpp +++ b/eeschema/lib_arc.cpp @@ -92,7 +92,6 @@ LIB_ARC::LIB_ARC( LIB_PART* aParent ) : LIB_ITEM( LIB_ARC_T, aParent ) m_Width = 0; m_Fill = NO_FILL; m_isFillable = true; - m_typeName = _( "Arc" ); m_editState = 0; m_lastEditState = 0; m_editCenterDistance = 0.0; diff --git a/eeschema/lib_arc.h b/eeschema/lib_arc.h index 9bd050b98b..886d464d15 100644 --- a/eeschema/lib_arc.h +++ b/eeschema/lib_arc.h @@ -91,6 +91,11 @@ public: return wxT( "LIB_ARC" ); } + wxString GetTypeName() override + { + return _( "Arc" ); + } + bool HitTest( const wxPoint& aPosition ) const override; bool HitTest( const wxPoint& aPosition, int aThreshold, const TRANSFORM& aTransform ) const override; diff --git a/eeschema/lib_bezier.cpp b/eeschema/lib_bezier.cpp index 2039049e76..916b610483 100644 --- a/eeschema/lib_bezier.cpp +++ b/eeschema/lib_bezier.cpp @@ -47,7 +47,6 @@ LIB_BEZIER::LIB_BEZIER( LIB_PART* aParent ) : m_Fill = NO_FILL; m_Width = 0; m_isFillable = true; - m_typeName = _( "Bezier" ); } diff --git a/eeschema/lib_bezier.h b/eeschema/lib_bezier.h index 7e649d59de..919a7f37f1 100644 --- a/eeschema/lib_bezier.h +++ b/eeschema/lib_bezier.h @@ -58,6 +58,10 @@ public: return wxT( "LIB_BEZIER" ); } + wxString GetTypeName() override + { + return _( "Bezier" ); + } void AddPoint( const wxPoint& aPoint ) { m_BezierPoints.push_back( aPoint ); } diff --git a/eeschema/lib_circle.cpp b/eeschema/lib_circle.cpp index 2ba1570083..e2f1bd31eb 100644 --- a/eeschema/lib_circle.cpp +++ b/eeschema/lib_circle.cpp @@ -50,7 +50,6 @@ LIB_CIRCLE::LIB_CIRCLE( LIB_PART* aParent ) : m_Width = 0; m_Fill = NO_FILL; m_isFillable = true; - m_typeName = _( "Circle" ); } diff --git a/eeschema/lib_circle.h b/eeschema/lib_circle.h index 41c02794ed..1a2740285d 100644 --- a/eeschema/lib_circle.h +++ b/eeschema/lib_circle.h @@ -56,6 +56,10 @@ public: return wxT( "LIB_CIRCLE" ); } + wxString GetTypeName() override + { + return _( "Circle" ); + } bool HitTest( const wxPoint& aPosition ) const override; diff --git a/eeschema/lib_draw_item.cpp b/eeschema/lib_draw_item.cpp index c9e16b0e06..efd9986af4 100644 --- a/eeschema/lib_draw_item.cpp +++ b/eeschema/lib_draw_item.cpp @@ -52,7 +52,6 @@ LIB_ITEM::LIB_ITEM( KICAD_T aType, m_Convert = aConvert; m_Fill = aFillType; m_Parent = (EDA_ITEM*) aComponent; - m_typeName = _( "Undefined" ); m_isFillable = false; m_eraseLastDrawItem = false; } @@ -62,7 +61,7 @@ void LIB_ITEM::GetMsgPanelInfo( MSG_PANEL_ITEMS& aList ) { wxString msg; - aList.push_back( MSG_PANEL_ITEM( _( "Type" ), m_typeName, CYAN ) ); + aList.push_back( MSG_PANEL_ITEM( _( "Type" ), GetTypeName(), CYAN ) ); if( m_Unit == 0 ) msg = _( "All" ); diff --git a/eeschema/lib_draw_item.h b/eeschema/lib_draw_item.h index 650c4f8a50..28549177ba 100644 --- a/eeschema/lib_draw_item.h +++ b/eeschema/lib_draw_item.h @@ -128,8 +128,6 @@ protected: */ FILL_T m_Fill; - wxString m_typeName; ///< Name of object displayed in the message panel. - wxPoint m_initialPos; ///< Temporary position when moving an existing item. wxPoint m_initialCursorPos; ///< Initial cursor position at the beginning of a move. @@ -148,7 +146,11 @@ public: virtual ~LIB_ITEM() { } - wxString GetTypeName() { return m_typeName; } + /** + * Provide a user-consumable name of the object type. Perform localization when + * called so that run-time language selection works. + */ + virtual wxString GetTypeName() = 0; /** * Begin an editing a component library draw item in \a aEditMode at \a aPosition. diff --git a/eeschema/lib_field.cpp b/eeschema/lib_field.cpp index d8fef90fb2..1260fbb7f3 100644 --- a/eeschema/lib_field.cpp +++ b/eeschema/lib_field.cpp @@ -84,8 +84,6 @@ void LIB_FIELD::Init( int id ) SetTextWidth( GetDefaultTextSize() ); SetTextHeight( GetDefaultTextSize() ); - m_typeName = _( "Field" ); - SetTextAngle( TEXT_ANGLE_HORIZ ); // constructor already did this. m_rotate = false; diff --git a/eeschema/lib_field.h b/eeschema/lib_field.h index e64af1e067..f622729ed1 100644 --- a/eeschema/lib_field.h +++ b/eeschema/lib_field.h @@ -100,6 +100,11 @@ public: return wxT( "LIB_FIELD" ); } + wxString GetTypeName() override + { + return _( "Field" ); + } + /** * Object constructor initialization helper. */ diff --git a/eeschema/lib_manager.cpp b/eeschema/lib_manager.cpp index e9ec9a6c75..fc82ed2f42 100644 --- a/eeschema/lib_manager.cpp +++ b/eeschema/lib_manager.cpp @@ -288,14 +288,15 @@ std::list LIB_MANAGER::GetAliases( const wxString& aLibrary ) const } else { - wxArrayString symbols; + std::vector aliases; - try { - symTable()->EnumerateSymbolLib( aLibrary, symbols ); + try + { + symTable()->LoadSymbolLib( aliases, aLibrary ); + } + catch( IO_ERROR& ) {} - for( const auto& symbol : symbols ) - ret.push_back( symTable()->LoadSymbol( aLibrary, symbol ) ); - } catch( IO_ERROR& e ) {} + std::copy( aliases.begin(), aliases.end(), std::back_inserter( ret ) ); } return ret; diff --git a/eeschema/lib_manager_adapter.cpp b/eeschema/lib_manager_adapter.cpp index 2a01db656f..0f753bb6cc 100644 --- a/eeschema/lib_manager_adapter.cpp +++ b/eeschema/lib_manager_adapter.cpp @@ -54,8 +54,12 @@ bool LIB_MANAGER_ADAPTER::IsContainer( const wxDataViewItem& aItem ) const } +#define PROGRESS_INTERVAL_MILLIS 50 + void LIB_MANAGER_ADAPTER::Sync( bool aForce, std::function aProgressCallback ) { + wxLongLong nextUpdate = wxGetUTCTimeMillis() + PROGRESS_INTERVAL_MILLIS; + int libMgrHash = m_libMgr->GetHash(); if( !aForce && m_lastSyncHash == libMgrHash ) @@ -68,7 +72,12 @@ void LIB_MANAGER_ADAPTER::Sync( bool aForce, std::functionget()->Name; - aProgressCallback( i++, max, name ); + + if( wxGetUTCTimeMillis() > nextUpdate ) + { + aProgressCallback( i++, max, name ); + nextUpdate = wxGetUTCTimeMillis() + PROGRESS_INTERVAL_MILLIS; + } if( !m_libMgr->LibraryExists( name ) ) { @@ -88,7 +97,12 @@ void LIB_MANAGER_ADAPTER::Sync( bool aForce, std::function nextUpdate ) + { + aProgressCallback( i++, max, libName ); + nextUpdate = wxGetUTCTimeMillis() + PROGRESS_INTERVAL_MILLIS; + } + auto& lib_node = m_tree.AddLib( libName ); updateLibrary( lib_node ); m_tree.AssignIntrinsicRanks(); diff --git a/eeschema/lib_pin.cpp b/eeschema/lib_pin.cpp index 8af8d385d6..52ef34c826 100644 --- a/eeschema/lib_pin.cpp +++ b/eeschema/lib_pin.cpp @@ -154,7 +154,6 @@ LIB_PIN::LIB_PIN( LIB_PART* aParent ) : m_numTextSize = LIB_EDIT_FRAME::GetPinNumDefaultSize(); m_nameTextSize = LIB_EDIT_FRAME::GetPinNameDefaultSize(); m_width = 0; - m_typeName = _( "Pin" ); } diff --git a/eeschema/lib_pin.h b/eeschema/lib_pin.h index d3dfda010a..79605da585 100644 --- a/eeschema/lib_pin.h +++ b/eeschema/lib_pin.h @@ -110,6 +110,11 @@ public: return wxT( "LIB_PIN" ); } + wxString GetTypeName() override + { + return _( "Pin" ); + } + #if defined(DEBUG) void Show( int nestLevel, std::ostream& os ) const override; #endif diff --git a/eeschema/lib_polyline.cpp b/eeschema/lib_polyline.cpp index 28b61daa18..761688a54d 100644 --- a/eeschema/lib_polyline.cpp +++ b/eeschema/lib_polyline.cpp @@ -48,7 +48,6 @@ LIB_POLYLINE::LIB_POLYLINE( LIB_PART* aParent ) : m_Fill = NO_FILL; m_Width = 0; m_isFillable = true; - m_typeName = _( "PolyLine" ); m_ModifyIndex = 0; } diff --git a/eeschema/lib_polyline.h b/eeschema/lib_polyline.h index f7ae53950d..2a6bba10be 100644 --- a/eeschema/lib_polyline.h +++ b/eeschema/lib_polyline.h @@ -57,6 +57,10 @@ public: return wxT( "LIB_POLYLINE" ); } + wxString GetTypeName() override + { + return _( "PolyLine" ); + } void AddPoint( const wxPoint& aPoint ); diff --git a/eeschema/lib_rectangle.cpp b/eeschema/lib_rectangle.cpp index 1be9cfa561..e1a92fbd29 100644 --- a/eeschema/lib_rectangle.cpp +++ b/eeschema/lib_rectangle.cpp @@ -48,7 +48,6 @@ LIB_RECTANGLE::LIB_RECTANGLE( LIB_PART* aParent ) : m_Width = 0; m_Fill = NO_FILL; m_isFillable = true; - m_typeName = _( "Rectangle" ); m_isHeightLocked = false; m_isWidthLocked = false; m_isStartPointSelected = false; diff --git a/eeschema/lib_rectangle.h b/eeschema/lib_rectangle.h index 3909c41027..5c85b7931b 100644 --- a/eeschema/lib_rectangle.h +++ b/eeschema/lib_rectangle.h @@ -59,6 +59,11 @@ public: return wxT( "LIB_RECTANGLE" ); } + wxString GetTypeName() override + { + return _( "Rectangle" ); + } + void SetEndPosition( const wxPoint& aPosition ) { m_End = aPosition; } bool HitTest( const wxPoint& aPosition ) const override; diff --git a/eeschema/lib_text.cpp b/eeschema/lib_text.cpp index 671f21e188..ba29349124 100644 --- a/eeschema/lib_text.cpp +++ b/eeschema/lib_text.cpp @@ -48,7 +48,6 @@ LIB_TEXT::LIB_TEXT( LIB_PART * aParent ) : EDA_TEXT() { SetTextSize( wxSize( 50, 50 ) ); - m_typeName = _( "Text" ); m_rotate = false; m_updateText = false; } diff --git a/eeschema/lib_text.h b/eeschema/lib_text.h index 42096ab041..bad432168d 100644 --- a/eeschema/lib_text.h +++ b/eeschema/lib_text.h @@ -65,6 +65,11 @@ public: return wxT( "LIB_TEXT" ); } + wxString GetTypeName() override + { + return _( "Text" ); + } + /** * Sets the text item string to \a aText. * diff --git a/eeschema/template_fieldnames.cpp b/eeschema/template_fieldnames.cpp index 01fbaec352..1505fd7100 100644 --- a/eeschema/template_fieldnames.cpp +++ b/eeschema/template_fieldnames.cpp @@ -26,33 +26,54 @@ #include #include #include +#include using namespace TFIELD_T; + const wxString TEMPLATE_FIELDNAME::GetDefaultFieldName( int aFieldNdx ) { + static void* locale = nullptr; + static wxString referenceDefault; + static wxString valueDefault; + static wxString footprintDefault; + static wxString datasheetDefault; + static wxString fieldDefault; + + // Fetching translations can take a surprising amount of time when loading libraries, + // so only do it when necessary. + if( Pgm().GetLocale() != locale ) + { + referenceDefault = _( "Reference" ); + valueDefault = _( "Value" ); + footprintDefault = _( "Footprint" ); + datasheetDefault = _( "Datasheet" ); + fieldDefault = _( "Field" ); + locale = Pgm().GetLocale(); + } + // Fixed values for the first few default fields used by EESCHEMA // (mandatory fields) switch( aFieldNdx ) { case REFERENCE: - return _( "Reference" ); // The component reference, R1, C1, etc. + return referenceDefault; // The component reference, R1, C1, etc. case VALUE: - return _( "Value" ); // The component value + name + return valueDefault; // The component value + name case FOOTPRINT: - return _( "Footprint" ); // The footprint for use with Pcbnew + return footprintDefault; // The footprint for use with Pcbnew case DATASHEET: - return _( "Datasheet" ); // Link to a datasheet for component + return datasheetDefault; // Link to a datasheet for component default: break; } // Other fields are use fields, give a default name: - wxString fieldName = _( "Field" ); + wxString fieldName = fieldDefault; fieldName << aFieldNdx; return fieldName; }