diff --git a/common/design_block_io.cpp b/common/design_block_io.cpp index 912c4acada..e25acbad2e 100644 --- a/common/design_block_io.cpp +++ b/common/design_block_io.cpp @@ -74,8 +74,10 @@ DESIGN_BLOCK_IO_MGR::DESIGN_BLOCK_FILE_T DESIGN_BLOCK_IO_MGR::GuessPluginTypeFromLibPath( const wxString& aLibPath, int aCtl ) { if( IO_RELEASER<DESIGN_BLOCK_IO>( FindPlugin( KICAD_SEXP ) )->CanReadLibrary( aLibPath ) - && aCtl != KICTL_NONKICAD_ONLY ) + && aCtl != KICTL_NONKICAD_ONLY ) + { return KICAD_SEXP; + } return DESIGN_BLOCK_IO_MGR::FILE_TYPE_NONE; } diff --git a/eeschema/erc/erc.cpp b/eeschema/erc/erc.cpp index 777019f0f9..dd1372b9df 100644 --- a/eeschema/erc/erc.cpp +++ b/eeschema/erc/erc.cpp @@ -1387,8 +1387,8 @@ int ERC_TESTER::TestLibSymbolIssues() wxCHECK2( libSymbolInSchematic, continue ); - wxString libName = symbol->GetLibId().GetLibNickname(); - LIB_TABLE_ROW* libTableRow = libTable->FindRow( libName, true ); + wxString libName = symbol->GetLibId().GetLibNickname(); + const LIB_TABLE_ROW* libTableRow = libTable->FindRow( libName, true ); if( !libTableRow ) { @@ -1411,7 +1411,7 @@ int ERC_TESTER::TestLibSymbolIssues() { std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES ); ercItem->SetItems( symbol ); - msg.Printf( _( "The library '%s' is not enabled in the current configuration" ), + msg.Printf( _( "The symbol library '%s' is not enabled in the current configuration" ), UnescapeString( libName ) ); ercItem->SetErrorMessage( msg ); @@ -1420,6 +1420,22 @@ int ERC_TESTER::TestLibSymbolIssues() continue; } + else if( !libTableRow->LibraryExists() ) + { + if( m_settings.IsTestEnabled( ERCE_LIB_SYMBOL_ISSUES ) ) + { + std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES ); + ercItem->SetItems( symbol ); + msg.Printf( _( "The symbol library '%s' was not found at '%s'." ), + UnescapeString( libName ), + libTableRow->GetFullURI( true ) ); + ercItem->SetErrorMessage( msg ); + + markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) ); + } + + continue; + } wxString symbolName = symbol->GetLibId().GetLibItemName(); LIB_SYMBOL* libSymbol = SchGetLibSymbol( symbol->GetLibId(), libTable ); diff --git a/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr.cpp b/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr.cpp index 6fa80445f6..1eb23fe2b7 100644 --- a/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr.cpp +++ b/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr.cpp @@ -1697,9 +1697,7 @@ void SCH_IO_KICAD_SEXPR::SaveLibrary( const wxString& aLibraryPath, wxString oldFileName = m_cache->GetFileName(); if( !m_cache->IsFile( aLibraryPath ) ) - { m_cache->SetFileName( aLibraryPath ); - } // This is a forced save. m_cache->SetModified(); @@ -1708,6 +1706,18 @@ void SCH_IO_KICAD_SEXPR::SaveLibrary( const wxString& aLibraryPath, } +bool SCH_IO_KICAD_SEXPR::CanReadLibrary( const wxString& aLibraryPath ) const +{ + if( !SCH_IO::CanReadLibrary( aLibraryPath ) ) + return false; + + // Above just checks for proper extension; now check that it actually exists + + wxFileName fn( aLibraryPath ); + return fn.IsOk() && fn.FileExists(); +} + + bool SCH_IO_KICAD_SEXPR::IsLibraryWritable( const wxString& aLibraryPath ) { wxFileName fn( aLibraryPath ); @@ -1785,7 +1795,6 @@ std::vector<LIB_SYMBOL*> SCH_IO_KICAD_SEXPR::ParseLibSymbols( std::string& aSymb void SCH_IO_KICAD_SEXPR::FormatLibSymbol( LIB_SYMBOL* symbol, OUTPUTFORMATTER & formatter ) { - LOCALE_IO toggle; // toggles on, then off, the C locale. SCH_IO_KICAD_SEXPR_LIB_CACHE::SaveSymbol( symbol, formatter ); } diff --git a/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr.h b/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr.h index 43816daa7b..ec44df1b3b 100644 --- a/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr.h +++ b/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr.h @@ -125,6 +125,8 @@ public: void SaveLibrary( const wxString& aLibraryPath, const std::map<std::string, UTF8>* aProperties = nullptr ) override; + bool CanReadLibrary( const wxString& aLibraryPath ) const override; + bool IsLibraryWritable( const wxString& aLibraryPath ) override; void GetAvailableSymbolFields( std::vector<wxString>& aNames ) override; diff --git a/eeschema/symbol_lib_table.h b/eeschema/symbol_lib_table.h index cdfbff340d..202540ebb5 100644 --- a/eeschema/symbol_lib_table.h +++ b/eeschema/symbol_lib_table.h @@ -115,6 +115,14 @@ public: plugin->GetDefaultSymbolFields( aNames ); } + bool LibraryExists() const override + { + if( plugin ) + return plugin->CanReadLibrary( GetFullURI( true ) ); + + return false; + } + SCH_IO_MGR::SCH_FILE_T GetFileType() { return type; } protected: diff --git a/include/design_block_lib_table.h b/include/design_block_lib_table.h index cfb831e6ce..dbbfbbfbc7 100644 --- a/include/design_block_lib_table.h +++ b/include/design_block_lib_table.h @@ -69,6 +69,14 @@ public: */ void SetType( const wxString& aType ) override; + bool LibraryExists() const override + { + if( plugin ) + return plugin->CanReadLibrary( GetFullURI( true ) ); + + return false; + } + DESIGN_BLOCK_IO_MGR::DESIGN_BLOCK_FILE_T GetFileType() { return type; } protected: diff --git a/include/fp_lib_table.h b/include/fp_lib_table.h index 5850d9d354..8f355eebd2 100644 --- a/include/fp_lib_table.h +++ b/include/fp_lib_table.h @@ -67,7 +67,7 @@ public: */ void SetType( const wxString& aType ) override; - bool LibraryExists() const; + bool LibraryExists() const override; PCB_IO_MGR::PCB_FILE_T GetFileType() { return type; } diff --git a/include/io/io_base.h b/include/io/io_base.h index 34514d28e6..3388c2c410 100644 --- a/include/io/io_base.h +++ b/include/io/io_base.h @@ -114,9 +114,6 @@ public: /** * Checks if this IO object can read the specified library file/directory. * If not overridden, extension check is used. - * - * @note This is not a check that the file system object is readable by the user, - * but a check that this IO object can parse the given library. */ virtual bool CanReadLibrary( const wxString& aFileName ) const; diff --git a/include/lib_table_base.h b/include/lib_table_base.h index 3ba27e02b3..d3b94783f1 100644 --- a/include/lib_table_base.h +++ b/include/lib_table_base.h @@ -188,6 +188,8 @@ public: void SetVisible( bool aVisible = true ) { visible = aVisible; } + virtual bool LibraryExists() const = 0; + virtual bool Refresh() { return false; } /** diff --git a/pcbnew/drc/drc_test_provider_library_parity.cpp b/pcbnew/drc/drc_test_provider_library_parity.cpp index 39d8f1bf39..3a8da66edc 100644 --- a/pcbnew/drc/drc_test_provider_library_parity.cpp +++ b/pcbnew/drc/drc_test_provider_library_parity.cpp @@ -837,10 +837,10 @@ bool DRC_TEST_PROVIDER_LIBRARY_PARITY::Run() if( !reportProgress( ii++, (int) board->Footprints().size(), progressDelta ) ) return false; // DRC cancelled - LIB_ID fpID = footprint->GetFPID(); - wxString libName = fpID.GetLibNickname(); - wxString fpName = fpID.GetLibItemName(); - const FP_LIB_TABLE_ROW* libTableRow = nullptr; + LIB_ID fpID = footprint->GetFPID(); + wxString libName = fpID.GetLibNickname(); + wxString fpName = fpID.GetLibItemName(); + const LIB_TABLE_ROW* libTableRow = nullptr; if( libName.IsEmpty() ) { @@ -862,7 +862,7 @@ bool DRC_TEST_PROVIDER_LIBRARY_PARITY::Run() { std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_LIB_FOOTPRINT_ISSUES ); msg.Printf( _( "The current configuration does not include the footprint library '%s'." ), - libName ); + UnescapeString( libName ) ); drcItem->SetErrorMessage( msg ); drcItem->SetItems( footprint ); reportViolation( drcItem, footprint->GetCenter(), UNDEFINED_LAYER ); @@ -876,7 +876,7 @@ bool DRC_TEST_PROVIDER_LIBRARY_PARITY::Run() { std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_LIB_FOOTPRINT_ISSUES ); msg.Printf( _( "The footprint library '%s' is not enabled in the current configuration." ), - libName ); + UnescapeString( libName ) ); drcItem->SetErrorMessage( msg ); drcItem->SetItems( footprint ); reportViolation( drcItem, footprint->GetCenter(), UNDEFINED_LAYER ); @@ -889,8 +889,9 @@ bool DRC_TEST_PROVIDER_LIBRARY_PARITY::Run() if( !m_drcEngine->IsErrorLimitExceeded( DRCE_LIB_FOOTPRINT_ISSUES ) ) { std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_LIB_FOOTPRINT_ISSUES ); - msg.Printf( _( "The footprint library '%s' was not found." ), - libName ); + msg.Printf( _( "The footprint library '%s' was not found at '%s'." ), + UnescapeString( libName ), + libTableRow->GetFullURI( true ) ); drcItem->SetErrorMessage( msg ); drcItem->SetItems( footprint ); reportViolation( drcItem, footprint->GetCenter(), UNDEFINED_LAYER ); diff --git a/pcbnew/pcb_io/pcb_io.h b/pcbnew/pcb_io/pcb_io.h index cb07d6ad8c..3562bf268d 100644 --- a/pcbnew/pcb_io/pcb_io.h +++ b/pcbnew/pcb_io/pcb_io.h @@ -126,7 +126,8 @@ public: * possible. */ virtual BOARD* LoadBoard( const wxString& aFileName, BOARD* aAppendToMe, - const std::map<std::string, UTF8>* aProperties = nullptr, PROJECT* aProject = nullptr ); + const std::map<std::string, UTF8>* aProperties = nullptr, + PROJECT* aProject = nullptr ); /** * Return a container with the cached library footprints generated in the last call to @@ -174,7 +175,8 @@ public: * @throw IO_ERROR if the library cannot be found, or footprint cannot be loaded. */ virtual void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath, - bool aBestEfforts, const std::map<std::string, UTF8>* aProperties = nullptr ); + bool aBestEfforts, + const std::map<std::string, UTF8>* aProperties = nullptr ); /** * Generate a timestamp representing all the files in the library (including the library diff --git a/qa/tests/common/test_lib_table.cpp b/qa/tests/common/test_lib_table.cpp index 8d8abfea4c..2645aa6ae9 100644 --- a/qa/tests/common/test_lib_table.cpp +++ b/qa/tests/common/test_lib_table.cpp @@ -83,15 +83,10 @@ public: { } - const wxString GetType() const override - { - return m_type; - } + const wxString GetType() const override { return m_type; } + void SetType( const wxString& aType ) override { m_type = aType; } - void SetType( const wxString& aType ) override - { - m_type = aType; - } + bool LibraryExists() const override { return true; } private: LIB_TABLE_ROW* do_clone() const override