Load schematic libraries in the background when the editor is started

This commit is contained in:
Jon Evans
2025-10-15 22:18:49 -04:00
parent ee6bda1699
commit 413f095faf
12 changed files with 250 additions and 60 deletions
+10 -1
View File
@@ -211,6 +211,15 @@ void BACKGROUND_JOB_REPORTER::AdvancePhase()
}
void BACKGROUND_JOB_REPORTER::SetCurrentProgress( double aProgress )
{
PROGRESS_REPORTER_BASE::SetCurrentProgress( aProgress );
m_job->m_maxProgress = 1000;
m_job->m_currentProgress = ( 1000 * aProgress );
m_monitor->jobUpdated( m_job );
}
BACKGROUND_JOBS_MONITOR::BACKGROUND_JOBS_MONITOR()
{
@@ -341,8 +350,8 @@ void BACKGROUND_JOBS_MONITOR::jobUpdated( std::shared_ptr<BACKGROUND_JOB> aJob )
[=]()
{
statusBar->ShowBackgroundProgressBar();
statusBar->SetBackgroundProgress( aJob->m_currentProgress );
statusBar->SetBackgroundProgressMax( aJob->m_maxProgress );
statusBar->SetBackgroundProgress( aJob->m_currentProgress );
statusBar->SetBackgroundStatusText( aJob->m_status );
} );
}
+22 -6
View File
@@ -63,6 +63,7 @@
#include <view/view.h>
#include <drawing_sheet/ds_draw_item.h>
#include <view/view_controls.h>
#include <widgets/kistatusbar.h>
#include <widgets/msgpanel.h>
#include <widgets/properties_panel.h>
#include <widgets/net_inspector_panel.h>
@@ -724,10 +725,15 @@ void EDA_DRAW_FRAME::OnSize( wxSizeEvent& SizeEv )
void EDA_DRAW_FRAME::updateStatusBarWidths()
{
wxWindow* stsbar = GetStatusBar();
int spacer = KIUI::GetTextSize( wxT( "M" ), stsbar ).x * 2;
constexpr int numLocalFields = 8;
int dims[] = {
wxStatusBar* stsbar = GetStatusBar();
int spacer = KIUI::GetTextSize( wxT( "M" ), stsbar ).x * 2;
// Note this is a KISTATUSBAR and there are fields to the right of the ones we know about
int totalFields = stsbar->GetFieldsCount();
std::vector<int> dims = {
// remainder of status bar on far left is set to a default or whatever is left over.
-1,
@@ -756,10 +762,20 @@ void EDA_DRAW_FRAME::updateStatusBarWidths()
KIUI::GetTextSize( _( "Constrain to H, V, 45" ), stsbar ).x
};
for( size_t ii = 1; ii < arrayDim( dims ); ii++ )
dims[ii] += spacer;
for( int& dim : dims )
dim += spacer;
SetStatusWidths( arrayDim( dims ), dims );
for( int idx = numLocalFields; idx < totalFields; ++idx )
dims.emplace_back( stsbar->GetStatusWidth( idx ) );
SetStatusWidths( dims.size(), dims.data() );
}
wxStatusBar* EDA_DRAW_FRAME::OnCreateStatusBar( int number, long style, wxWindowID id,
const wxString& name )
{
return new KISTATUSBAR( number, this, id, KISTATUSBAR::STYLE_FLAGS::NONE );
}
+2
View File
@@ -520,6 +520,8 @@ bool PGM_BASE::InitPgm( bool aHeadless, bool aSkipPyInit, bool aIsUnitTest )
m_plugin_manager->ReloadPlugins();
#endif
m_library_manager->LoadGlobalTables();
// This sets the maximum tooltip display duration to 10s (up from 5) but only affects
// Windows as other platforms display tooltips while the mouse is not moving
if( !aHeadless )
+108 -50
View File
@@ -36,51 +36,65 @@
#include <bitmaps.h>
#include <wx/dcclient.h>
#define FIELD_OFFSET_BGJOB_TEXT 0
#define FIELD_OFFSET_BGJOB_GAUGE 1
#define FIELD_OFFSET_BGJOB_CANCEL 2
#define FIELD_OFFSET_NOTIFICATION_BUTTON 3
KISTATUSBAR::KISTATUSBAR( int aNumberFields, wxWindow* parent, wxWindowID id ) :
KISTATUSBAR::KISTATUSBAR( int aNumberFields, wxWindow* parent, wxWindowID id, STYLE_FLAGS aFlags ) :
wxStatusBar( parent, id ),
m_normalFieldsCount( aNumberFields )
m_backgroundStopButton( nullptr ),
m_notificationsButton( nullptr ),
m_normalFieldsCount( aNumberFields ),
m_styleFlags( aFlags )
{
#ifdef __WXOSX__
// we need +1 extra field on OSX to offset from the rounded corner on the right
// OSX doesn't use resize grippers like the other platforms and the statusbar field
// includes the rounded part
const int ExtraFields = 5;
int extraFields = 4;
#else
const int ExtraFields = 4;
int extraFields = 3;
#endif
SetFieldsCount( aNumberFields + ExtraFields );
int* widths = new int[aNumberFields + ExtraFields];
bool showNotification = ( m_styleFlags & NOTIFICATION_ICON );
bool showCancel = ( m_styleFlags & CANCEL_BUTTON );
if( showCancel )
extraFields++;
if( showNotification )
extraFields++;
SetFieldsCount( aNumberFields + extraFields );
int* widths = new int[aNumberFields + extraFields];
for( int i = 0; i < aNumberFields; i++ )
widths[i] = -1;
widths[aNumberFields + FIELD_OFFSET_BGJOB_TEXT] = -1; // background status text field
// (variable size)
widths[aNumberFields + FIELD_OFFSET_BGJOB_GAUGE] = 75; // background progress button
widths[aNumberFields + FIELD_OFFSET_BGJOB_CANCEL] = 20; // background stop button
widths[aNumberFields + FIELD_OFFSET_NOTIFICATION_BUTTON] = 20; // notifications button
if( std::optional<int> idx = fieldIndex( FIELD::BGJOB_LABEL ) )
widths[aNumberFields + *idx] = -1; // background status text field (variable size)
if( std::optional<int> idx = fieldIndex( FIELD::BGJOB_GAUGE ) )
widths[aNumberFields + *idx] = 75; // background progress button
if( std::optional<int> idx = fieldIndex( FIELD::BGJOB_CANCEL ) )
widths[aNumberFields + *idx] = 20; // background stop button
if( std::optional<int> idx = fieldIndex( FIELD::NOTIFICATION ) )
widths[aNumberFields + *idx] = 20; // notifications button
#ifdef __WXOSX__
// offset from the right edge
widths[aNumberFields + ExtraFields - 1] = 10;
widths[aNumberFields + extraFields - 1] = 10;
#endif
SetStatusWidths( aNumberFields + ExtraFields, widths );
SetStatusWidths( aNumberFields + extraFields, widths );
delete[] widths;
int* styles = new int[aNumberFields + extraFields];
int* styles = new int[aNumberFields + ExtraFields];
for( int i = 0; i < aNumberFields + ExtraFields; i++ )
for( int i = 0; i < aNumberFields + extraFields; i++ )
styles[i] = wxSB_FLAT;
SetStatusStyles( aNumberFields + ExtraFields, styles );
SetStatusStyles( aNumberFields + extraFields, styles );
delete[] styles;
m_backgroundTxt = new wxStaticText( this, wxID_ANY, wxT( "" ) );
@@ -88,18 +102,24 @@ KISTATUSBAR::KISTATUSBAR( int aNumberFields, wxWindow* parent, wxWindowID id ) :
m_backgroundProgressBar = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize,
wxGA_HORIZONTAL | wxGA_SMOOTH );
m_backgroundStopButton = new wxButton( this, wxID_ANY, "X", wxDefaultPosition, wxDefaultSize,
wxBU_EXACTFIT );
m_notificationsButton = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition,
if( showCancel )
{
m_backgroundStopButton = new wxButton( this, wxID_ANY, "X", wxDefaultPosition,
wxDefaultSize, wxBU_EXACTFIT );
}
m_notificationsButton->SetPadding( 0 );
m_notificationsButton->SetBitmap( KiBitmapBundle( BITMAPS::notifications ) );
m_notificationsButton->SetShowBadge( true );
m_notificationsButton->SetBitmapCentered( true );
if( showNotification )
{
m_notificationsButton = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition,
wxDefaultSize, wxBU_EXACTFIT );
m_notificationsButton->Bind( wxEVT_BUTTON, &KISTATUSBAR::onNotificationsIconClick, this );
m_notificationsButton->SetPadding( 0 );
m_notificationsButton->SetBitmap( KiBitmapBundle( BITMAPS::notifications ) );
m_notificationsButton->SetShowBadge( true );
m_notificationsButton->SetBitmapCentered( true );
m_notificationsButton->Bind( wxEVT_BUTTON, &KISTATUSBAR::onNotificationsIconClick, this );
}
Bind( wxEVT_SIZE, &KISTATUSBAR::onSize, this );
m_backgroundProgressBar->Bind( wxEVT_LEFT_DOWN, &KISTATUSBAR::onBackgroundProgressClick, this );
@@ -111,7 +131,9 @@ KISTATUSBAR::KISTATUSBAR( int aNumberFields, wxWindow* parent, wxWindowID id ) :
KISTATUSBAR::~KISTATUSBAR()
{
m_notificationsButton->Unbind( wxEVT_BUTTON, &KISTATUSBAR::onNotificationsIconClick, this );
if( m_notificationsButton )
m_notificationsButton->Unbind( wxEVT_BUTTON, &KISTATUSBAR::onNotificationsIconClick, this );
Unbind( wxEVT_SIZE, &KISTATUSBAR::onSize, this );
m_backgroundProgressBar->Unbind( wxEVT_LEFT_DOWN, &KISTATUSBAR::onBackgroundProgressClick,
this );
@@ -120,6 +142,7 @@ KISTATUSBAR::~KISTATUSBAR()
void KISTATUSBAR::onNotificationsIconClick( wxCommandEvent& aEvent )
{
wxCHECK( m_notificationsButton, /* void */ );
wxPoint pos = m_notificationsButton->GetScreenPosition();
wxRect r;
@@ -141,36 +164,44 @@ void KISTATUSBAR::onBackgroundProgressClick( wxMouseEvent& aEvent )
Pgm().GetBackgroundJobMonitor().ShowList( this, pos );
}
void KISTATUSBAR::onSize( wxSizeEvent& aEvent )
{
wxRect r;
GetFieldRect( m_normalFieldsCount + FIELD_OFFSET_BGJOB_TEXT, r );
GetFieldRect( m_normalFieldsCount + *fieldIndex( FIELD::BGJOB_LABEL ), r );
int x = r.GetLeft();
int y = r.GetTop();
m_backgroundTxt->SetPosition( { x, y } );
GetFieldRect( m_normalFieldsCount + FIELD_OFFSET_BGJOB_GAUGE, r );
GetFieldRect( m_normalFieldsCount + *fieldIndex( FIELD::BGJOB_GAUGE ), r );
x = r.GetLeft();
y = r.GetTop();
int w = r.GetWidth();
int h = r.GetHeight();
constexpr int b = 5;
wxSize buttonSize( 0, 0 );
auto buttonSize = m_backgroundStopButton->GetEffectiveMinSize();
m_backgroundStopButton->SetPosition( { x + w - buttonSize.GetWidth(), y } );
m_backgroundStopButton->SetSize( buttonSize.GetWidth(), h );
if( m_backgroundStopButton )
{
buttonSize = m_backgroundStopButton->GetEffectiveMinSize();
m_backgroundStopButton->SetPosition( { x + w - buttonSize.GetWidth(), y } );
m_backgroundStopButton->SetSize( buttonSize.GetWidth(), h );
}
m_backgroundProgressBar->SetPosition( { x, y } );
m_backgroundProgressBar->SetSize( w - buttonSize.GetWidth() - b, h );
GetFieldRect( m_normalFieldsCount + FIELD_OFFSET_NOTIFICATION_BUTTON, r );
x = r.GetLeft();
y = r.GetTop();
h = r.GetHeight();
buttonSize = m_notificationsButton->GetEffectiveMinSize();
m_notificationsButton->SetPosition( { x, y } );
m_notificationsButton->SetSize( buttonSize.GetWidth() + 6, h );
if( m_notificationsButton )
{
GetFieldRect( m_normalFieldsCount + *fieldIndex( FIELD::NOTIFICATION ), r );
x = r.GetLeft();
y = r.GetTop();
h = r.GetHeight();
buttonSize = m_notificationsButton->GetEffectiveMinSize();
m_notificationsButton->SetPosition( { x, y } );
m_notificationsButton->SetSize( buttonSize.GetWidth() + 6, h );
}
}
@@ -178,17 +209,17 @@ void KISTATUSBAR::ShowBackgroundProgressBar( bool aCancellable )
{
m_backgroundProgressBar->Show();
if( aCancellable )
m_backgroundStopButton->Show();
else
m_backgroundStopButton->Hide();
if( m_backgroundStopButton )
m_backgroundStopButton->Show( aCancellable );
}
void KISTATUSBAR::HideBackgroundProgressBar()
{
m_backgroundProgressBar->Hide();
m_backgroundStopButton->Hide();
if( m_backgroundStopButton )
m_backgroundStopButton->Hide();
}
@@ -210,8 +241,9 @@ void KISTATUSBAR::SetBackgroundStatusText( const wxString& aTxt )
}
void KISTATUSBAR::SetNotificationCount(int aCount)
void KISTATUSBAR::SetNotificationCount( int aCount )
{
wxCHECK( m_notificationsButton, /* void */ );
wxString cnt = "";
if( aCount > 0 )
@@ -246,3 +278,29 @@ void KISTATUSBAR::SetEllipsedTextField( const wxString& aText, int aFieldId )
SetStatusText( etext, aFieldId );
}
std::optional<int> KISTATUSBAR::fieldIndex( FIELD aField ) const
{
switch( aField )
{
case FIELD::BGJOB_LABEL: return 0;
case FIELD::BGJOB_GAUGE: return 1;
case FIELD::BGJOB_CANCEL:
{
if( m_styleFlags & CANCEL_BUTTON )
return 2;
break;
}
case FIELD::NOTIFICATION:
{
if( m_styleFlags & ( CANCEL_BUTTON | NOTIFICATION_ICON ) )
return 3;
else if( m_styleFlags & NOTIFICATION_ICON )
return 2;
}
}
return std::nullopt;
}
@@ -287,6 +287,7 @@ void SYMBOL_LIBRARY_MANAGER_ADAPTER::AsyncLoad()
{
lib->plugin->EnumerateSymbolLib( dummyList, getUri( lib->row ),
lib->row->OptionsMap().get() );
//std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
lib->status.load_status = LOAD_STATUS::LOADED;
}
catch( IO_ERROR& e )
+62 -1
View File
@@ -24,6 +24,7 @@
#include <advanced_config.h>
#include <base_units.h>
#include <background_jobs_monitor.h>
#include <kiway.h>
#include <lib_tree_model_adapter.h>
#include <pgm_base.h>
@@ -45,11 +46,13 @@
#include <preview_items/selection_area.h>
#include <project_sch.h>
#include <libraries/legacy_symbol_library.h>
#include <libraries/symbol_library_manager_adapter.h>
#include <symbol_lib_table.h>
#include <sch_base_frame.h>
#include <dialogs/dialog_sch_find.h>
#include <design_block.h>
#include <design_block_lib_table.h>
#include <thread_pool.h>
#include <tool/actions.h>
#include <tool/action_toolbar.h>
#include <tool/tool_manager.h>
@@ -113,7 +116,8 @@ 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_inSymChangeTimerEvent( false ),
m_libraryPreloadInProgress( false )
{
m_findReplaceData = std::make_unique<SCH_SEARCH_DATA>();
@@ -134,6 +138,8 @@ SCH_BASE_FRAME::SCH_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aWindo
}
} );
Pgm().GetBackgroundJobMonitor().RegisterStatusBar( (KISTATUSBAR*) GetStatusBar() );
m_watcherDebounceTimer.Bind( wxEVT_TIMER, &SCH_BASE_FRAME::OnSymChangeDebounceTimer, this );
}
@@ -263,6 +269,61 @@ void SCH_BASE_FRAME::UpdateStatusBar()
}
void SCH_BASE_FRAME::PreloadLibraries()
{
if( m_libraryPreloadInProgress )
return;
m_libraryPreloadBackgroundJob =
Pgm().GetBackgroundJobMonitor().Create( _( "Loading Symbol Libraries" ) );
auto preload =
[this]() -> void
{
std::shared_ptr<BACKGROUND_JOB_REPORTER> reporter =
m_libraryPreloadBackgroundJob->m_reporter;
SYMBOL_LIBRARY_MANAGER_ADAPTER adapter( Pgm().GetLibraryManager(), Prj() );
constexpr static int interval = 250;
constexpr static int timeLimit = 20000;
int elapsed = 0;
reporter->Report( _( "Loading Symbol Libraries" ) );
adapter.AsyncLoad();
while( true )
{
std::this_thread::sleep_for( std::chrono::milliseconds( interval ) );
if( std::optional<float> loadStatus = adapter.AsyncLoadProgress();
loadStatus.has_value() )
{
reporter->SetCurrentProgress( *loadStatus );
if( loadStatus >= 1 )
break;
}
elapsed += interval;
if( elapsed > timeLimit )
break;
}
adapter.BlockUntilLoaded();
Pgm().GetBackgroundJobMonitor().Remove( m_libraryPreloadBackgroundJob );
m_libraryPreloadBackgroundJob.reset();
m_libraryPreloadInProgress = false;
};
thread_pool& tp = GetKiCadThreadPool();
m_libraryPreloadInProgress = true;
m_libraryPreloadReturn = tp.submit( preload );
}
LIB_SYMBOL* SCH_BASE_FRAME::GetLibSymbol( const LIB_ID& aLibId, bool aUseCacheLib,
bool aShowErrorMsg )
{
+7
View File
@@ -33,6 +33,7 @@
#include <stddef.h>
#include <utility>
#include <future>
#include <vector>
#include <wx/event.h>
#include <wx/datetime.h>
@@ -65,6 +66,7 @@ class SPNAV_2D_PLUGIN;
class PANEL_SCH_SELECTION_FILTER;
class DIALOG_SCH_FIND;
struct BACKGROUND_JOB;
#ifdef wxHAS_INOTIFY
#define wxFileSystemWatcher wxInotifyFileSystemWatcher
@@ -156,6 +158,7 @@ public:
void UpdateStatusBar() override;
void PreloadLibraries();
/**
* Call the library viewer to select symbol to import into schematic.
@@ -341,6 +344,10 @@ private:
#else
std::unique_ptr<SPNAV_2D_PLUGIN> m_spaceMouse;
#endif
std::shared_ptr<BACKGROUND_JOB> m_libraryPreloadBackgroundJob;
std::future<void> m_libraryPreloadReturn;
bool m_libraryPreloadInProgress;
};
#endif // SCH_BASE_FRAME_H_
+3
View File
@@ -452,6 +452,9 @@ 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<SCH_ITEM*>& aItems )
+3 -1
View File
@@ -60,6 +60,8 @@ public:
void SetNumPhases( int aNumPhases ) override;
void SetCurrentProgress( double aProgress ) override;
private:
bool updateUI() override;
@@ -142,4 +144,4 @@ private:
mutable std::shared_mutex m_mutex;
};
#endif
#endif
+7
View File
@@ -349,6 +349,13 @@ public:
*/
virtual void OnPageSettingsChange() {}
/** Create the status line (like a wxStatusBar). This is actually a KISTATUSBAR status bar.
* the specified number of fields is the extra number of fields, not the full field count.
* @return a KISTATUSBAR (derived from wxStatusBar)
*/
wxStatusBar* OnCreateStatusBar( int number, long style, wxWindowID id,
const wxString& name ) override;
/**
* Update the status bar information.
*
+1
View File
@@ -28,6 +28,7 @@
#define PROGRESS_REPORTER_H
#include <kicommon.h>
#include <wx/wx.h>
/**
* A progress reporter interface for use in multi-threaded environments. The various advancement
+24 -1
View File
@@ -26,6 +26,7 @@
#define KISTATUSBAR_H
#include <kicommon.h>
#include <optional>
class wxGauge;
class wxButton;
@@ -44,7 +45,18 @@ class BITMAP_BUTTON;
class KICOMMON_API KISTATUSBAR : public wxStatusBar
{
public:
KISTATUSBAR( int aNumberFields, wxWindow* parent, wxWindowID id );
enum STYLE_FLAGS : int
{
NONE = 0x00,
NOTIFICATION_ICON = 0x01,
CANCEL_BUTTON = 0x02,
};
static constexpr auto DEFAULT_STYLE =
static_cast<STYLE_FLAGS>( NOTIFICATION_ICON | CANCEL_BUTTON );
KISTATUSBAR( int aNumberFields, wxWindow* parent, wxWindowID id,
STYLE_FLAGS aFlags = DEFAULT_STYLE );
~KISTATUSBAR();
@@ -93,12 +105,23 @@ private:
void onBackgroundProgressClick( wxMouseEvent& aEvent );
void onNotificationsIconClick( wxCommandEvent& aEvent );
enum class FIELD
{
BGJOB_LABEL,
BGJOB_GAUGE,
BGJOB_CANCEL,
NOTIFICATION
};
std::optional<int> fieldIndex( FIELD aField ) const;
private:
wxGauge* m_backgroundProgressBar;
wxButton* m_backgroundStopButton;
wxStaticText* m_backgroundTxt;
BITMAP_BUTTON* m_notificationsButton;
int m_normalFieldsCount;
STYLE_FLAGS m_styleFlags;
};
#endif