From 38f21a215ef8f0ab60688d72576d9734d0e605db Mon Sep 17 00:00:00 2001 From: Jon Evans Date: Wed, 2 Jul 2025 17:54:17 -0400 Subject: [PATCH] Move background load of libraries to kiface --- common/background_jobs_monitor.cpp | 4 ++ common/kiway.cpp | 7 +++ eeschema/eeschema.cpp | 87 +++++++++++++++++++++++++++++- eeschema/files-io.cpp | 6 ++- eeschema/sch_base_frame.cpp | 79 +++------------------------ eeschema/sch_base_frame.h | 10 ---- eeschema/sch_edit_frame.cpp | 10 ++-- include/kiway.h | 4 ++ kicad/kicad_manager_frame.cpp | 8 +++ qa/tests/api/test_api_module.cpp | 6 --- qa/tests/pcbnew/test_module.cpp | 4 -- 11 files changed, 127 insertions(+), 98 deletions(-) diff --git a/common/background_jobs_monitor.cpp b/common/background_jobs_monitor.cpp index 647fc1fd94..3f698f590a 100644 --- a/common/background_jobs_monitor.cpp +++ b/common/background_jobs_monitor.cpp @@ -373,6 +373,10 @@ void BACKGROUND_JOBS_MONITOR::jobUpdated( std::shared_ptr aJob ) void BACKGROUND_JOBS_MONITOR::RegisterStatusBar( KISTATUSBAR* aStatusBar ) { m_statusBars.push_back( aStatusBar ); + + // Make sure the newly-registered bar gets the active job, if any + if( !m_jobs.empty() ) + jobUpdated( m_jobs.front() ); } diff --git a/common/kiway.cpp b/common/kiway.cpp index bb3aeca55b..b942237d47 100644 --- a/common/kiway.cpp +++ b/common/kiway.cpp @@ -647,6 +647,13 @@ void KIWAY::ProjectChanged() top->ProjectChanged(); } + // Cancel an in-progress load of libraries; handled through the schematic and PCB ifaces + if ( KIFACE* schface = KiFACE( KIWAY::FACE_SCH ) ) + schface->ProjectChanged(); + + if ( KIFACE* pcbface = KiFACE( KIWAY::FACE_PCB ) ) + pcbface->ProjectChanged(); + for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i ) { KIWAY_PLAYER* frame = GetPlayerFrame( ( FRAME_T )i ); diff --git a/eeschema/eeschema.cpp b/eeschema/eeschema.cpp index ce9d550e98..33e995acef 100644 --- a/eeschema/eeschema.cpp +++ b/eeschema/eeschema.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -34,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -45,11 +47,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -170,7 +174,8 @@ static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER IFACE( const char* aName, KIWAY::FACE_T aType ) : KIFACE_BASE( aName, aType ), - UNITS_PROVIDER( schIUScale, EDA_UNITS::MM ) + UNITS_PROVIDER( schIUScale, EDA_UNITS::MM ), + m_libraryPreloadInProgress( false ) {} bool OnKifaceStart( PGM_BASE* aProgram, int aCtlBits, KIWAY* aKiway ) override; @@ -193,6 +198,10 @@ static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER { // only run this under single_top, not under a project manager. frame->CreateServer( KICAD_SCH_PORT_SERVICE_NUMBER ); + + // Preload libraries, since this won't have been started by the manager + wxCHECK( aKiway, frame ); + Kiface().PreloadLibraries( &aKiway->Prj() ); } return frame; @@ -401,11 +410,18 @@ static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER bool HandleJobConfig( JOB* aJob, wxWindow* aParent ) override; + void PreloadLibraries( PROJECT* aProject ) override; + void ProjectChanged() override; + private: bool loadGlobalLibTable(); bool loadGlobalDesignBlockLibTable(); std::unique_ptr m_jobHandler; + std::shared_ptr m_libraryPreloadBackgroundJob; + std::future m_libraryPreloadReturn; + std::atomic_bool m_libraryPreloadInProgress; + std::atomic_bool m_libraryPreloadAbort; } kiface( "eeschema", KIWAY::FACE_SCH ); @@ -470,6 +486,75 @@ void IFACE::Reset() } +void IFACE::PreloadLibraries( PROJECT* aProject ) +{ + constexpr static int interval = 150; + constexpr static int timeLimit = 120000; + + if( m_libraryPreloadInProgress.load() ) + return; + + m_libraryPreloadBackgroundJob = + Pgm().GetBackgroundJobMonitor().Create( _( "Loading Symbol Libraries" ) ); + + auto preload = + [this, aProject]() -> void + { + std::shared_ptr reporter = + m_libraryPreloadBackgroundJob->m_reporter; + + SYMBOL_LIBRARY_MANAGER_ADAPTER* adapter = PROJECT_SCH::SymbolLibManager( aProject ); + + int elapsed = 0; + + reporter->Report( _( "Loading Symbol Libraries" ) ); + adapter->AsyncLoad(); + + while( true ) + { + if( m_libraryPreloadAbort.load() ) + { + m_libraryPreloadAbort.store( false ); + break; + } + + std::this_thread::sleep_for( std::chrono::milliseconds( interval ) ); + + if( std::optional loadStatus = adapter->AsyncLoadProgress() ) + { + float progress = *loadStatus; + reporter->SetCurrentProgress( progress ); + + if( progress >= 1 ) + break; + } + + elapsed += interval; + + if( elapsed > timeLimit ) + break; + } + + adapter->BlockUntilLoaded(); + + Pgm().GetBackgroundJobMonitor().Remove( m_libraryPreloadBackgroundJob ); + m_libraryPreloadBackgroundJob.reset(); + m_libraryPreloadInProgress.store( false ); + }; + + thread_pool& tp = GetKiCadThreadPool(); + m_libraryPreloadInProgress.store( true ); + m_libraryPreloadReturn = tp.submit_task( preload ); +} + + +void IFACE::ProjectChanged() +{ + if( m_libraryPreloadInProgress.load() ) + m_libraryPreloadAbort.store( true ); +} + + bool IFACE::loadGlobalLibTable() { wxFileName fn = SYMBOL_LIB_TABLE::GetGlobalTableFileName(); diff --git a/eeschema/files-io.cpp b/eeschema/files-io.cpp index 07b7cf630f..520afbc238 100644 --- a/eeschema/files-io.cpp +++ b/eeschema/files-io.cpp @@ -715,7 +715,11 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector& aFileSet, in GetCanvas()->DisplaySheet( GetCurrentSheet().LastScreen() ); // Trigger a library load to handle any project-specific libraries - CallAfter( [&]() { PreloadLibraries(); } ); + CallAfter( [&]() + { + KIFACE *schface = Kiway().KiFACE( KIWAY::FACE_SCH ); + schface->PreloadLibraries( &Prj() ); + } ); return true; } diff --git a/eeschema/sch_base_frame.cpp b/eeschema/sch_base_frame.cpp index 47c4ea1d46..c0cafd3901 100644 --- a/eeschema/sch_base_frame.cpp +++ b/eeschema/sch_base_frame.cpp @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -117,8 +118,7 @@ SCH_BASE_FRAME::SCH_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aWindo m_selectionFilterPanel( nullptr ), m_findReplaceDialog( nullptr ), m_base_frame_defaults( nullptr, "base_Frame_defaults" ), - m_inSymChangeTimerEvent( false ), - m_libraryPreloadInProgress( false ) + m_inSymChangeTimerEvent( false ) { m_findReplaceData = std::make_unique(); @@ -139,7 +139,7 @@ SCH_BASE_FRAME::SCH_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aWindo } } ); - Pgm().GetBackgroundJobMonitor().RegisterStatusBar( (KISTATUSBAR*) GetStatusBar() ); + Pgm().GetBackgroundJobMonitor().RegisterStatusBar( static_cast( GetStatusBar() ) ); m_watcherDebounceTimer.Bind( wxEVT_TIMER, &SCH_BASE_FRAME::OnSymChangeDebounceTimer, this ); } @@ -147,7 +147,9 @@ SCH_BASE_FRAME::SCH_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aWindo /// Needs to be in the cpp file to encode the sizeof() for std::unique_ptr SCH_BASE_FRAME::~SCH_BASE_FRAME() -{} +{ + Pgm().GetBackgroundJobMonitor().UnregisterStatusBar( static_cast( GetStatusBar() ) ); +} void SCH_BASE_FRAME::doCloseWindow() @@ -270,75 +272,6 @@ void SCH_BASE_FRAME::UpdateStatusBar() } -void SCH_BASE_FRAME::ProjectChanged() -{ - m_libraryPreloadRestart.store( true ); - m_libraryPreloadAbort.store( true ); -} - - -void SCH_BASE_FRAME::PreloadLibraries() -{ - constexpr static int interval = 150; - constexpr static int timeLimit = 60000; - - if( m_libraryPreloadInProgress.load() ) - return; - - m_libraryPreloadBackgroundJob = - Pgm().GetBackgroundJobMonitor().Create( _( "Loading Symbol Libraries" ) ); - - auto preload = - [this]() -> void - { - std::shared_ptr reporter = - m_libraryPreloadBackgroundJob->m_reporter; - - SYMBOL_LIBRARY_MANAGER_ADAPTER* adapter = PROJECT_SCH::SymbolLibManager( &Prj() ); - - int elapsed = 0; - - reporter->Report( _( "Loading Symbol Libraries" ) ); - adapter->AsyncLoad(); - - while( true ) - { - if( m_libraryPreloadAbort.load() ) - { - m_libraryPreloadAbort.store( false ); - break; - } - - std::this_thread::sleep_for( std::chrono::milliseconds( interval ) ); - - if( std::optional loadStatus = adapter->AsyncLoadProgress() ) - { - float progress = *loadStatus; - reporter->SetCurrentProgress( progress ); - - if( progress >= 1 ) - break; - } - - elapsed += interval; - - if( elapsed > timeLimit ) - break; - } - - adapter->BlockUntilLoaded(); - - Pgm().GetBackgroundJobMonitor().Remove( m_libraryPreloadBackgroundJob ); - m_libraryPreloadBackgroundJob.reset(); - m_libraryPreloadInProgress.store( false ); - }; - - thread_pool& tp = GetKiCadThreadPool(); - m_libraryPreloadInProgress.store( true ); - m_libraryPreloadReturn = tp.submit_task( preload ); -} - - LIB_SYMBOL* SCH_BASE_FRAME::GetLibSymbol( const LIB_ID& aLibId, bool aUseCacheLib, bool aShowErrorMsg ) { diff --git a/eeschema/sch_base_frame.h b/eeschema/sch_base_frame.h index 7b4b963966..0089b4139d 100644 --- a/eeschema/sch_base_frame.h +++ b/eeschema/sch_base_frame.h @@ -134,8 +134,6 @@ public: void LoadSettings( APP_SETTINGS_BASE* aCfg ) override; void SaveSettings( APP_SETTINGS_BASE* aCfg ) override; - void ProjectChanged() override; - SCH_RENDER_SETTINGS* GetRenderSettings(); COLOR4D GetDrawBgColor() const override; @@ -161,8 +159,6 @@ public: void UpdateStatusBar() override; - void PreloadLibraries(); - /** * Call the library viewer to select symbol to import into schematic. * If the library viewer is currently running, it is closed and reopened in modal mode. @@ -338,12 +334,6 @@ private: #else std::unique_ptr m_spaceMouse; #endif - - std::shared_ptr m_libraryPreloadBackgroundJob; - std::future m_libraryPreloadReturn; - std::atomic_bool m_libraryPreloadInProgress; - std::atomic_bool m_libraryPreloadAbort; - std::atomic_bool m_libraryPreloadRestart; }; #endif // SCH_BASE_FRAME_H_ diff --git a/eeschema/sch_edit_frame.cpp b/eeschema/sch_edit_frame.cpp index f7dc8169a6..c98d2d1eff 100644 --- a/eeschema/sch_edit_frame.cpp +++ b/eeschema/sch_edit_frame.cpp @@ -452,9 +452,6 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : Bind( EDA_EVT_CLOSE_DIALOG_BOOK_REPORTER, &SCH_EDIT_FRAME::onCloseSymbolDiffDialog, this ); Bind( EDA_EVT_CLOSE_ERC_DIALOG, &SCH_EDIT_FRAME::onCloseErcDialog, this ); Bind( EDA_EVT_CLOSE_DIALOG_SYMBOL_FIELDS_TABLE, &SCH_EDIT_FRAME::onCloseSymbolFieldsTableDialog, this ); - - // TODO(JE) should this happen later? - PreloadLibraries(); } void SCH_EDIT_FRAME::StartCrossProbeFlash( const std::vector& aItems ) @@ -1410,6 +1407,13 @@ void SCH_EDIT_FRAME::LoadProject() OpenProjectFiles( std::vector( 1, dlg.GetPath() ) ); m_mruPath = Prj().GetProjectPath(); } + + // Since we know we're single-top here: trigger library reload + CallAfter( [&]() + { + KIFACE *schface = Kiway().KiFACE( KIWAY::FACE_SCH ); + schface->PreloadLibraries( &Prj() ); + } ); } diff --git a/include/kiway.h b/include/kiway.h index ee066674de..e0793169d3 100644 --- a/include/kiway.h +++ b/include/kiway.h @@ -252,6 +252,10 @@ struct KIFACE { return 0; } + + virtual void PreloadLibraries( PROJECT* aProject ) {} + + virtual void ProjectChanged() {} }; diff --git a/kicad/kicad_manager_frame.cpp b/kicad/kicad_manager_frame.cpp index 73df304c01..319b5317ae 100644 --- a/kicad/kicad_manager_frame.cpp +++ b/kicad/kicad_manager_frame.cpp @@ -847,6 +847,14 @@ void KICAD_MANAGER_FRAME::LoadProject( const wxFileName& aProjectFileName ) m_openSavedWindows = true; KIPLATFORM::ENV::AddToRecentDocs( aProjectFileName.GetFullPath() ); + + // Now that we have a new project, trigger a library preload, which will load in any + // project-specific symbol and footprint libraries into the manager + CallAfter( [&]() + { + KIFACE *schface = Kiway().KiFACE( KIWAY::FACE_SCH ); + schface->PreloadLibraries( &Prj() ); + } ); } diff --git a/qa/tests/api/test_api_module.cpp b/qa/tests/api/test_api_module.cpp index 3925a9825a..987a6de9fb 100644 --- a/qa/tests/api/test_api_module.cpp +++ b/qa/tests/api/test_api_module.cpp @@ -46,12 +46,6 @@ bool init_unit_test() wxSetAssertHandler( &KI_TEST::wxAssertThrower ); Pgm().InitPgm( true, true, true ); - - const MOCK_PGM_BASE& program = static_cast( Pgm() ); - - MOCK_EXPECT( program.GetCommonSettings ) - .returns( Pgm().GetSettingsManager().GetCommonSettings() ); - Pgm().GetSettingsManager().LoadProject( "" ); } diff --git a/qa/tests/pcbnew/test_module.cpp b/qa/tests/pcbnew/test_module.cpp index 5d105b0716..963e6c8784 100644 --- a/qa/tests/pcbnew/test_module.cpp +++ b/qa/tests/pcbnew/test_module.cpp @@ -59,10 +59,6 @@ bool init_unit_test() Pgm().GetSettingsManager().Load(); const MOCK_PGM_BASE& program = static_cast( Pgm() ); - - MOCK_EXPECT( program.GetCommonSettings ) - .returns( Pgm().GetSettingsManager().GetCommonSettings() ); - Pgm().GetSettingsManager().LoadProject( "" ); }