diff --git a/common/widgets/progress_reporter_base.cpp b/common/widgets/progress_reporter_base.cpp index a4103846fc..dbb214fdfb 100644 --- a/common/widgets/progress_reporter_base.cpp +++ b/common/widgets/progress_reporter_base.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2017 CERN - * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors. * * Author: Tomasz Wlostowski * @@ -121,7 +121,7 @@ bool PROGRESS_REPORTER_BASE::KeepRefreshing( bool aWait ) return false; } - wxMilliSleep( 20 ); + wxMilliSleep( 33 /* 30 FPS refresh rate */ ); } return true; diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index 52a11230ba..473fc65b54 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -175,7 +175,7 @@ set( EESCHEMA_SRCS fields_grid_table.cpp files-io.cpp generate_alias_info.cpp - getpart.cpp + picksymbol.cpp hierarch.cpp lib_shape.cpp lib_item.cpp diff --git a/eeschema/getpart.cpp b/eeschema/picksymbol.cpp similarity index 88% rename from eeschema/getpart.cpp rename to eeschema/picksymbol.cpp index 5c9736acaa..cd394e5f95 100644 --- a/eeschema/getpart.cpp +++ b/eeschema/picksymbol.cpp @@ -105,7 +105,10 @@ PICKED_SYMBOL SCH_BASE_FRAME::PickSymbolFromLibTree( const SCHLIB_FILTER* aFilte Pgm().GetSettingsManager().GetAppSettings(); Pgm().GetSettingsManager().GetAppSettings(); - wxObjectDataPtr adapter = SYMBOL_TREE_MODEL_ADAPTER::Create( this, libs ); + wxObjectDataPtr dataPtr + = SYMBOL_TREE_MODEL_ADAPTER::Create( this, libs ); + SYMBOL_TREE_MODEL_ADAPTER* modelAdapter + = static_cast( dataPtr.get() ); bool loaded = false; if( aFilter ) @@ -117,14 +120,14 @@ PICKED_SYMBOL SCH_BASE_FRAME::PickSymbolFromLibTree( const SCHLIB_FILTER* aFilte if( libs->HasLibrary( liblist[ii], true ) ) { loaded = true; - static_cast( adapter.get() )->AddLibrary( liblist[ii] ); + modelAdapter->AddLibrary( liblist[ii] ); } } - adapter->AssignIntrinsicRanks(); + modelAdapter->AssignIntrinsicRanks(); if( aFilter->GetFilterPowerSymbols() ) - adapter->SetFilter( SYMBOL_TREE_MODEL_ADAPTER::SYM_FILTER_POWER ); + modelAdapter->SetFilter( SYMBOL_TREE_MODEL_ADAPTER::SYM_FILTER_POWER ); } std::vector< LIB_TREE_ITEM* > history_list; @@ -138,29 +141,34 @@ PICKED_SYMBOL SCH_BASE_FRAME::PickSymbolFromLibTree( const SCHLIB_FILTER* aFilte history_list.push_back( symbol ); } - adapter->DoAddLibrary( wxT( "-- " ) + _( "Recently Used" ) + " --", wxEmptyString, history_list, - true ); + modelAdapter->DoAddLibrary( wxT( "-- " ) + _( "Recently Used" ) + wxT( " --" ), wxEmptyString, + history_list, true ); if( !aHistoryList.empty() ) - adapter->SetPreselectNode( aHistoryList[0].LibId, aHistoryList[0].Unit ); + modelAdapter->SetPreselectNode( aHistoryList[0].LibId, aHistoryList[0].Unit ); const std::vector< wxString > libNicknames = libs->GetLogicalLibs(); if( !loaded ) - static_cast( adapter.get() )->AddLibraries( libNicknames, - this ); + { + if( !modelAdapter->AddLibraries( libNicknames, this ) ) + { + // loading cancelled by user + return PICKED_SYMBOL(); + } + } if( aHighlight && aHighlight->IsValid() ) - adapter->SetPreselectNode( *aHighlight, /* aUnit */ 0 ); + modelAdapter->SetPreselectNode( *aHighlight, /* aUnit */ 0 ); wxString dialogTitle; - if( adapter->GetFilter() == SYMBOL_TREE_MODEL_ADAPTER::SYM_FILTER_POWER ) - dialogTitle.Printf( _( "Choose Power Symbol (%d items loaded)" ), adapter->GetItemCount() ); + if( modelAdapter->GetFilter() == SYMBOL_TREE_MODEL_ADAPTER::SYM_FILTER_POWER ) + dialogTitle.Printf( _( "Choose Power Symbol (%d items loaded)" ), dataPtr->GetItemCount() ); else - dialogTitle.Printf( _( "Choose Symbol (%d items loaded)" ), adapter->GetItemCount() ); + dialogTitle.Printf( _( "Choose Symbol (%d items loaded)" ), dataPtr->GetItemCount() ); - DIALOG_CHOOSE_SYMBOL dlg( this, dialogTitle, adapter, aConvert, aAllowFields, aShowFootprints, + DIALOG_CHOOSE_SYMBOL dlg( this, dialogTitle, dataPtr, aConvert, aAllowFields, aShowFootprints, aUseLibBrowser ); if( dlg.ShowModal() == wxID_CANCEL ) diff --git a/eeschema/symbol_async_loader.cpp b/eeschema/symbol_async_loader.cpp index fc40552bca..f7eb5a3974 100644 --- a/eeschema/symbol_async_loader.cpp +++ b/eeschema/symbol_async_loader.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2021 Jon Evans - * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -35,8 +35,7 @@ SYMBOL_ASYNC_LOADER::SYMBOL_ASYNC_LOADER( const std::vector& aNickname m_onlyPowerSymbols( aOnlyPowerSymbols ), m_output( aOutput ), m_reporter( aReporter ), - m_nextLibrary( 0 ), - m_canceled( false ) + m_nextLibrary( 0 ) { wxASSERT( m_table ); m_threadCount = std::max( 1, std::thread::hardware_concurrency() ); @@ -48,7 +47,7 @@ SYMBOL_ASYNC_LOADER::SYMBOL_ASYNC_LOADER( const std::vector& aNickname SYMBOL_ASYNC_LOADER::~SYMBOL_ASYNC_LOADER() { - Abort(); + Join(); } @@ -88,13 +87,6 @@ bool SYMBOL_ASYNC_LOADER::Join() } -void SYMBOL_ASYNC_LOADER::Abort() -{ - m_canceled.store( true ); - Join(); -} - - bool SYMBOL_ASYNC_LOADER::Done() { return m_nextLibrary.load() >= m_nicknames.size(); @@ -110,11 +102,15 @@ std::vector SYMBOL_ASYNC_LOADER::worker() for( size_t libraryIndex = m_nextLibrary++; libraryIndex < m_nicknames.size(); libraryIndex = m_nextLibrary++ ) { - if( m_canceled.load() ) + const wxString& nickname = m_nicknames[libraryIndex]; + + if( m_reporter ) + m_reporter->AdvancePhase( wxString::Format( _( "Loading library %s..." ), nickname ) ); + + if( m_reporter && m_reporter->IsCancelled() ) break; - const wxString& nickname = m_nicknames[libraryIndex]; - LOADED_PAIR pair( nickname, {} ); + LOADED_PAIR pair( nickname, {} ); try { @@ -129,9 +125,6 @@ std::vector SYMBOL_ASYNC_LOADER::worker() std::lock_guard lock( m_errorMutex ); m_errors += msg; } - - if( m_reporter ) - m_reporter->AdvancePhase( wxString::Format( _( "Loading library %s..." ), nickname ) ); } return ret; diff --git a/eeschema/symbol_async_loader.h b/eeschema/symbol_async_loader.h index 7a1257b626..3051366cc8 100644 --- a/eeschema/symbol_async_loader.h +++ b/eeschema/symbol_async_loader.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2021 Jon Evans - * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -62,11 +62,6 @@ public: */ bool Join(); - /** - * Cancels a load in-progress - */ - void Abort(); - ///< Return true if loading is done bool Done(); @@ -97,7 +92,6 @@ private: size_t m_threadCount; std::atomic m_nextLibrary; - std::atomic_bool m_canceled; wxString m_errors; std::mutex m_errorMutex; diff --git a/eeschema/symbol_editor/symbol_edit_frame.cpp b/eeschema/symbol_editor/symbol_edit_frame.cpp index 93c2f77d4e..4e191d207f 100644 --- a/eeschema/symbol_editor/symbol_edit_frame.cpp +++ b/eeschema/symbol_editor/symbol_edit_frame.cpp @@ -127,13 +127,20 @@ SYMBOL_EDIT_FRAME::SYMBOL_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : LoadSettings( m_settings ); m_libMgr = new SYMBOL_LIBRARY_MANAGER( *this ); + bool loadingCancelled = false; - // Preload libraries before using SyncLibraries the first time, as the preload is threaded - WX_PROGRESS_REPORTER reporter( this, _( "Loading Symbol Libraries" ), - m_libMgr->GetLibraryCount(), true ); - m_libMgr->Preload( reporter ); + { + // Preload libraries before using SyncLibraries the first time, as the preload is + // multi-threaded + WX_PROGRESS_REPORTER reporter( this, _( "Loading Symbol Libraries" ), + m_libMgr->GetLibraryCount(), true ); + m_libMgr->Preload( reporter ); - SyncLibraries( false ); + loadingCancelled = reporter.IsCancelled(); + wxSafeYield(); + } + + SyncLibraries( false, loadingCancelled ); m_treePane = new SYMBOL_TREE_PANE( this, m_libMgr ); resolveCanvasType(); @@ -235,6 +242,9 @@ SYMBOL_EDIT_FRAME::SYMBOL_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : // Ensure the window is on top Raise(); + + if( loadingCancelled ) + ShowInfoBarWarning( _( "Symbol library loading was cancelled by user." ) ); } @@ -922,7 +932,8 @@ wxString SYMBOL_EDIT_FRAME::getTargetLib() const } -void SYMBOL_EDIT_FRAME::SyncLibraries( bool aShowProgress, const wxString& aForceRefresh ) +void SYMBOL_EDIT_FRAME::SyncLibraries( bool aShowProgress, bool aPreloadCancelled, + const wxString& aForceRefresh ) { LIB_ID selected; @@ -941,7 +952,7 @@ void SYMBOL_EDIT_FRAME::SyncLibraries( bool aShowProgress, const wxString& aForc libName ) ); } ); } - else + else if( !aPreloadCancelled ) { m_libMgr->Sync( aForceRefresh, [&]( int progress, int max, const wxString& libName ) diff --git a/eeschema/symbol_editor/symbol_edit_frame.h b/eeschema/symbol_editor/symbol_edit_frame.h index 5f6d7f8bf9..c9a20b5e4c 100644 --- a/eeschema/symbol_editor/symbol_edit_frame.h +++ b/eeschema/symbol_editor/symbol_edit_frame.h @@ -296,7 +296,8 @@ public: * Synchronize the library manager to the symbol library table, and then the symbol tree * to the library manager. Optionally displays a progress dialog. */ - void SyncLibraries( bool aShowProgress, const wxString& aForceRefresh = wxEmptyString ); + void SyncLibraries( bool aShowProgress, bool aPreloadCancelled = false, + const wxString& aForceRefresh = wxEmptyString ); /** * Filter, sort, and redisplay the library tree. diff --git a/eeschema/symbol_editor/symbol_editor.cpp b/eeschema/symbol_editor/symbol_editor.cpp index 3755dd8c9e..3ddb1c8641 100644 --- a/eeschema/symbol_editor/symbol_editor.cpp +++ b/eeschema/symbol_editor/symbol_editor.cpp @@ -1119,7 +1119,7 @@ bool SYMBOL_EDIT_FRAME::saveLibrary( const wxString& aLibrary, bool aNewFile ) if( resyncLibTree ) { FreezeLibraryTree(); - SyncLibraries( true, forceRefresh ); + SyncLibraries( true, false, forceRefresh ); ThawLibraryTree(); } } diff --git a/eeschema/symbol_editor/symbol_library_manager.cpp b/eeschema/symbol_editor/symbol_library_manager.cpp index 07a728bede..2afa0025c5 100644 --- a/eeschema/symbol_editor/symbol_library_manager.cpp +++ b/eeschema/symbol_editor/symbol_library_manager.cpp @@ -74,8 +74,6 @@ void SYMBOL_LIBRARY_MANAGER::Sync( const wxString& aForceRefresh, void SYMBOL_LIBRARY_MANAGER::Preload( PROGRESS_REPORTER& aReporter ) { - const int progressIntervalMillis = 60; - SYMBOL_ASYNC_LOADER loader( symTable()->GetLogicalLibs(), symTable(), false, nullptr, &aReporter ); @@ -85,19 +83,13 @@ void SYMBOL_LIBRARY_MANAGER::Preload( PROGRESS_REPORTER& aReporter ) while( !loader.Done() ) { - aReporter.KeepRefreshing(); + if( !aReporter.KeepRefreshing() ) + break; - wxMilliSleep( progressIntervalMillis ); + wxMilliSleep( 33 /* 30 FPS refresh rate */ ); } - if( aReporter.IsCancelled() ) - { - loader.Abort(); - } - else - { - loader.Join(); - } + loader.Join(); if( !loader.GetErrors().IsEmpty() ) { @@ -116,7 +108,7 @@ void SYMBOL_LIBRARY_MANAGER::Preload( PROGRESS_REPORTER& aReporter ) bool SYMBOL_LIBRARY_MANAGER::HasModifications() const { - for( const auto& lib : m_libs ) + for( const std::pair& lib : m_libs ) { if( lib.second.IsModified() ) return true; @@ -130,7 +122,7 @@ int SYMBOL_LIBRARY_MANAGER::GetHash() const { int hash = symTable()->GetModifyHash(); - for( const auto& lib : m_libs ) + for( const std::pair& lib : m_libs ) hash += lib.second.GetHash(); return hash; @@ -144,7 +136,7 @@ int SYMBOL_LIBRARY_MANAGER::GetLibraryHash( const wxString& aLibrary ) const if( libBufIt != m_libs.end() ) return libBufIt->second.GetHash(); - auto row = GetLibrary( aLibrary ); + SYMBOL_LIB_TABLE_ROW* row = GetLibrary( aLibrary ); // return -1 if library does not exist or 0 if not modified return row ? std::hash{}( aLibrary.ToStdString() + @@ -156,7 +148,7 @@ wxArrayString SYMBOL_LIBRARY_MANAGER::GetLibraryNames() const { wxArrayString res; - for( const auto& libName : symTable()->GetLogicalLibs() ) + for( const wxString& libName : symTable()->GetLogicalLibs() ) res.Add( libName ); return res; diff --git a/eeschema/symbol_tree_model_adapter.cpp b/eeschema/symbol_tree_model_adapter.cpp index d0361b5280..87f0650d6d 100644 --- a/eeschema/symbol_tree_model_adapter.cpp +++ b/eeschema/symbol_tree_model_adapter.cpp @@ -3,7 +3,7 @@ * * Copyright (C) 2017 Chris Pavlina * Copyright (C) 2014 Henner Zeller - * Copyright (C) 2014-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2014-2022 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -35,7 +35,7 @@ bool SYMBOL_TREE_MODEL_ADAPTER::m_show_progress = true; -#define PROGRESS_INTERVAL_MILLIS 66 +#define PROGRESS_INTERVAL_MILLIS 33 // 30 FPS refresh rate wxObjectDataPtr @@ -56,7 +56,7 @@ SYMBOL_TREE_MODEL_ADAPTER::~SYMBOL_TREE_MODEL_ADAPTER() {} -void SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( const std::vector& aNicknames, +bool SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( const std::vector& aNicknames, wxWindow* aParent ) { std::unique_ptr prg = nullptr; @@ -82,20 +82,18 @@ void SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( const std::vector& aNick while( !loader.Done() ) { - if( prg ) - prg->KeepRefreshing(); + if( prg && !prg->KeepRefreshing() ) + break; wxMilliSleep( PROGRESS_INTERVAL_MILLIS ); } - if( prg && prg->IsCancelled() ) - { - loader.Abort(); - } - else - { - loader.Join(); - } + loader.Join(); + + bool cancelled = false; + + if( prg ) + cancelled = prg->IsCancelled(); if( !loader.GetErrors().IsEmpty() ) { @@ -134,6 +132,8 @@ void SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( const std::vector& aNick prg.reset(); m_show_progress = false; } + + return !cancelled; } diff --git a/eeschema/symbol_tree_model_adapter.h b/eeschema/symbol_tree_model_adapter.h index 4690d74470..ef19cfbf04 100644 --- a/eeschema/symbol_tree_model_adapter.h +++ b/eeschema/symbol_tree_model_adapter.h @@ -3,7 +3,7 @@ * * Copyright (C) 2017 Chris Pavlina * Copyright (C) 2014 Henner Zeller - * Copyright (C) 2014-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2014-2022 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -49,8 +49,9 @@ public: * * @param aNicknames is the list of library nicknames * @param aParent is the parent window to display the progress dialog + * @return false if loading was cancelled by the user */ - void AddLibraries( const std::vector& aNicknames, wxWindow* aParent ); + bool AddLibraries( const std::vector& aNicknames, wxWindow* aParent ); void AddLibrary( wxString const& aLibNickname ); diff --git a/eeschema/symbol_viewer_frame.cpp b/eeschema/symbol_viewer_frame.cpp index 5406218987..3028990991 100644 --- a/eeschema/symbol_viewer_frame.cpp +++ b/eeschema/symbol_viewer_frame.cpp @@ -835,11 +835,16 @@ void SYMBOL_VIEWER_FRAME::OnSelectSymbol( wxCommandEvent& aEvent ) // Container doing search-as-you-type. SYMBOL_LIB_TABLE* libs = Prj().SchSymbolLibTable(); - wxObjectDataPtr adapter = - SYMBOL_TREE_MODEL_ADAPTER::Create( this, libs ); + wxObjectDataPtr dataPtr + = SYMBOL_TREE_MODEL_ADAPTER::Create( this, libs ); + SYMBOL_TREE_MODEL_ADAPTER* modelAdapter + = static_cast( dataPtr.get() ); - const auto libNicknames = libs->GetLogicalLibs(); - static_cast( adapter.get() )->AddLibraries( libNicknames, this ); + if( !modelAdapter->AddLibraries( libs->GetLogicalLibs(), this ) ) + { + // loading cancelled by user + return; + } LIB_SYMBOL* current = GetSelectedSymbol(); LIB_ID id; @@ -848,13 +853,13 @@ void SYMBOL_VIEWER_FRAME::OnSelectSymbol( wxCommandEvent& aEvent ) if( current ) { id = current->GetLibId(); - adapter->SetPreselectNode( id, unit ); + modelAdapter->SetPreselectNode( id, unit ); } wxString dialogTitle; - dialogTitle.Printf( _( "Choose Symbol (%d items loaded)" ), adapter->GetItemCount() ); + dialogTitle.Printf( _( "Choose Symbol (%d items loaded)" ), modelAdapter->GetItemCount() ); - DIALOG_CHOOSE_SYMBOL dlg( this, dialogTitle, adapter, m_convert, false, false, false ); + DIALOG_CHOOSE_SYMBOL dlg( this, dialogTitle, dataPtr, m_convert, false, false, false ); if( dlg.ShowQuasiModal() == wxID_CANCEL ) return; diff --git a/pcbnew/footprint_info_impl.cpp b/pcbnew/footprint_info_impl.cpp index bfae62a4aa..f350ffcf62 100644 --- a/pcbnew/footprint_info_impl.cpp +++ b/pcbnew/footprint_info_impl.cpp @@ -143,7 +143,7 @@ bool FOOTPRINT_LIST_IMPL::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxStri if( m_progress_reporter && !m_progress_reporter->KeepRefreshing() ) m_cancelled = true; - wxMilliSleep( 20 ); + wxMilliSleep( 33 /* 30 FPS refresh rate */); } if( m_cancelled ) @@ -326,7 +326,7 @@ bool FOOTPRINT_LIST_IMPL::joinWorkers() if( m_progress_reporter && !m_progress_reporter->KeepRefreshing() ) m_cancelled = true; - wxMilliSleep( 30 ); + wxMilliSleep( 33 /* 30 FPS refresh rate */ ); } for( auto& thr : threads ) diff --git a/pcbnew/fp_tree_synchronizing_adapter.cpp b/pcbnew/fp_tree_synchronizing_adapter.cpp index 6d689301fc..09de73ee12 100644 --- a/pcbnew/fp_tree_synchronizing_adapter.cpp +++ b/pcbnew/fp_tree_synchronizing_adapter.cpp @@ -64,7 +64,7 @@ bool FP_TREE_SYNCHRONIZING_ADAPTER::IsContainer( const wxDataViewItem& aItem ) c } -#define PROGRESS_INTERVAL_MILLIS 66 +#define PROGRESS_INTERVAL_MILLIS 33 // 30 FPS refresh rate void FP_TREE_SYNCHRONIZING_ADAPTER::Sync() {