Stop showing popup for library load errors
Errors are stored to a vector for display after clicking the warning icon in the toolbar.
This commit is contained in:
@@ -138,6 +138,22 @@ void FOOTPRINT_LIST::DisplayErrors( wxTopLevelWindow* aWindow )
|
||||
}
|
||||
|
||||
|
||||
wxString FOOTPRINT_LIST::GetErrorMessages()
|
||||
{
|
||||
wxString messages;
|
||||
|
||||
while( std::unique_ptr<IO_ERROR> error = PopError() )
|
||||
{
|
||||
if( !messages.IsEmpty() )
|
||||
messages += wxS( "\n" );
|
||||
|
||||
messages += error->Problem();
|
||||
}
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
|
||||
static FOOTPRINT_LIST* get_instance_from_id( KIWAY& aKiway, int aId )
|
||||
{
|
||||
void* ptr = nullptr;
|
||||
|
||||
@@ -1040,6 +1040,26 @@ std::vector<std::pair<wxString, LIB_STATUS>> LIBRARY_MANAGER_ADAPTER::GetLibrary
|
||||
}
|
||||
|
||||
|
||||
wxString LIBRARY_MANAGER_ADAPTER::GetLibraryLoadErrors() const
|
||||
{
|
||||
wxString errors;
|
||||
|
||||
for( const auto& [nickname, status] : GetLibraryStatuses() )
|
||||
{
|
||||
if( status.load_status == LOAD_STATUS::LOAD_ERROR && status.error )
|
||||
{
|
||||
if( !errors.IsEmpty() )
|
||||
errors += wxS( "\n" );
|
||||
|
||||
errors += wxString::Format( _( "Library '%s': %s" ),
|
||||
nickname, status.error->message );
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
void LIBRARY_MANAGER_ADAPTER::ReloadLibraryEntry( const wxString& aNickname,
|
||||
LIBRARY_TABLE_SCOPE aScope )
|
||||
{
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
#include <thread_pool.h>
|
||||
#include <trace_helpers.h>
|
||||
|
||||
#include <widgets/kistatusbar.h>
|
||||
#include <widgets/wx_splash.h>
|
||||
|
||||
#ifdef KICAD_IPC_API
|
||||
@@ -947,6 +948,79 @@ void PGM_BASE::PreloadDesignBlockLibraries( KIWAY* aKiway )
|
||||
}
|
||||
|
||||
|
||||
void PGM_BASE::RegisterLibraryLoadStatusBar( KISTATUSBAR* aStatusBar )
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( m_libraryLoadStatusBarsMutex );
|
||||
|
||||
wxLogTrace( traceLibraries, "RegisterLibraryLoadStatusBar: statusBar=%p", aStatusBar );
|
||||
|
||||
if( std::find( m_libraryLoadStatusBars.begin(), m_libraryLoadStatusBars.end(), aStatusBar )
|
||||
== m_libraryLoadStatusBars.end() )
|
||||
{
|
||||
m_libraryLoadStatusBars.push_back( aStatusBar );
|
||||
wxLogTrace( traceLibraries, " -> registered, total count=%zu",
|
||||
m_libraryLoadStatusBars.size() );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( traceLibraries, " -> already registered" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PGM_BASE::UnregisterLibraryLoadStatusBar( KISTATUSBAR* aStatusBar )
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( m_libraryLoadStatusBarsMutex );
|
||||
|
||||
wxLogTrace( traceLibraries, "UnregisterLibraryLoadStatusBar: statusBar=%p", aStatusBar );
|
||||
|
||||
m_libraryLoadStatusBars.erase(
|
||||
std::remove( m_libraryLoadStatusBars.begin(), m_libraryLoadStatusBars.end(),
|
||||
aStatusBar ),
|
||||
m_libraryLoadStatusBars.end() );
|
||||
|
||||
wxLogTrace( traceLibraries, " -> remaining count=%zu", m_libraryLoadStatusBars.size() );
|
||||
}
|
||||
|
||||
|
||||
void PGM_BASE::AddLibraryLoadMessages( const std::vector<LOAD_MESSAGE>& aMessages )
|
||||
{
|
||||
wxLogTrace( traceLibraries, "AddLibraryLoadMessages: message_count=%zu", aMessages.size() );
|
||||
|
||||
if( aMessages.empty() )
|
||||
return;
|
||||
|
||||
std::lock_guard<std::mutex> lock( m_libraryLoadStatusBarsMutex );
|
||||
|
||||
wxLogTrace( traceLibraries, " -> registered status bars=%zu",
|
||||
m_libraryLoadStatusBars.size() );
|
||||
|
||||
for( KISTATUSBAR* statusBar : m_libraryLoadStatusBars )
|
||||
{
|
||||
if( statusBar )
|
||||
{
|
||||
wxLogTrace( traceLibraries, " -> forwarding to statusBar=%p", statusBar );
|
||||
statusBar->AddLoadWarningMessages( aMessages );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PGM_BASE::ClearLibraryLoadMessages()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( m_libraryLoadStatusBarsMutex );
|
||||
|
||||
wxLogTrace( traceLibraries, "ClearLibraryLoadMessages: status bars=%zu",
|
||||
m_libraryLoadStatusBars.size() );
|
||||
|
||||
for( KISTATUSBAR* statusBar : m_libraryLoadStatusBars )
|
||||
{
|
||||
if( statusBar )
|
||||
statusBar->ClearLoadWarningMessages();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static PGM_BASE* process;
|
||||
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <fmt/core.h>
|
||||
#include <macros.h>
|
||||
#include <string_utils.h>
|
||||
#include <widgets/kistatusbar.h>
|
||||
#include <wx_filename.h>
|
||||
#include <fmt/chrono.h>
|
||||
#include <wx/log.h>
|
||||
@@ -1781,3 +1782,33 @@ int SortVariantNames( const wxString& aLhs, const wxString& aRhs )
|
||||
return StrNumCmp( aLhs, aRhs );
|
||||
}
|
||||
|
||||
|
||||
std::vector<LOAD_MESSAGE> ExtractLibraryLoadErrors( const wxString& aErrorString, int aSeverity )
|
||||
{
|
||||
std::vector<LOAD_MESSAGE> messages;
|
||||
|
||||
if( aErrorString.IsEmpty() )
|
||||
return messages;
|
||||
|
||||
// Errors are separated by newlines. We want to keep:
|
||||
// - Lines starting with "Library '" (library-level errors)
|
||||
// - Lines containing "Expecting" (file error location)
|
||||
// And strip:
|
||||
// - Lines starting with "from " (internal code location info)
|
||||
wxStringTokenizer tokenizer( aErrorString, wxS( "\n" ), wxTOKEN_STRTOK );
|
||||
|
||||
while( tokenizer.HasMoreTokens() )
|
||||
{
|
||||
wxString line = tokenizer.GetNextToken();
|
||||
|
||||
// Skip internal code location lines (e.g., "from pcb_io_kicad_sexpr_parser.cpp : ...")
|
||||
if( line.StartsWith( wxS( "from " ) ) )
|
||||
continue;
|
||||
|
||||
if( line.StartsWith( wxS( "Library '" ) ) || line.Contains( wxS( "Expecting" ) ) )
|
||||
messages.push_back( { line, static_cast<SEVERITY>( aSeverity ) } );
|
||||
}
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <bitmaps.h>
|
||||
#include <reporter.h>
|
||||
#include <dialog_HTML_reporter_base.h>
|
||||
#include <trace_helpers.h>
|
||||
#include <wx/dcclient.h>
|
||||
|
||||
|
||||
@@ -316,42 +317,106 @@ void KISTATUSBAR::SetNotificationCount( int aCount )
|
||||
|
||||
void KISTATUSBAR::SetLoadWarningMessages( const wxString& aMessages )
|
||||
{
|
||||
m_loadWarningMessages.clear();
|
||||
|
||||
wxStringTokenizer tokenizer( aMessages, wxS( "\n" ), wxTOKEN_STRTOK );
|
||||
|
||||
while( tokenizer.HasMoreTokens() )
|
||||
{
|
||||
LOAD_MESSAGE msg;
|
||||
msg.message = tokenizer.GetNextToken();
|
||||
msg.severity = RPT_SEVERITY_WARNING; // Default to warning for font substitutions
|
||||
m_loadWarningMessages.push_back( msg );
|
||||
}
|
||||
std::lock_guard<std::mutex> lock( m_loadWarningMutex );
|
||||
m_loadWarningMessages.clear();
|
||||
|
||||
if( m_warningButton )
|
||||
{
|
||||
m_warningButton->Show( !m_loadWarningMessages.empty() );
|
||||
wxStringTokenizer tokenizer( aMessages, wxS( "\n" ), wxTOKEN_STRTOK );
|
||||
|
||||
if( !m_loadWarningMessages.empty() )
|
||||
while( tokenizer.HasMoreTokens() )
|
||||
{
|
||||
m_warningButton->SetToolTip(
|
||||
wxString::Format( _( "View %zu load message(s)" ),
|
||||
m_loadWarningMessages.size() ) );
|
||||
LOAD_MESSAGE msg;
|
||||
msg.message = tokenizer.GetNextToken();
|
||||
msg.severity = RPT_SEVERITY_WARNING; // Default to warning for font substitutions
|
||||
m_loadWarningMessages.push_back( msg );
|
||||
}
|
||||
|
||||
Layout();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
updateWarningUI();
|
||||
}
|
||||
|
||||
|
||||
void KISTATUSBAR::AddLoadWarningMessages( const std::vector<LOAD_MESSAGE>& aMessages )
|
||||
{
|
||||
wxLogTrace( traceLibraries, "KISTATUSBAR::AddLoadWarningMessages: this=%p, count=%zu",
|
||||
this, aMessages.size() );
|
||||
|
||||
if( aMessages.empty() )
|
||||
return;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( m_loadWarningMutex );
|
||||
m_loadWarningMessages.insert( m_loadWarningMessages.end(), aMessages.begin(), aMessages.end() );
|
||||
wxLogTrace( traceLibraries, " -> total messages now=%zu", m_loadWarningMessages.size() );
|
||||
}
|
||||
|
||||
// Update UI on main thread
|
||||
wxLogTrace( traceLibraries, " -> calling CallAfter for updateWarningUI" );
|
||||
CallAfter( [this]() { updateWarningUI(); } );
|
||||
}
|
||||
|
||||
|
||||
size_t KISTATUSBAR::GetLoadWarningCount() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( m_loadWarningMutex );
|
||||
return m_loadWarningMessages.size();
|
||||
}
|
||||
|
||||
|
||||
void KISTATUSBAR::updateWarningUI()
|
||||
{
|
||||
wxLogTrace( traceLibraries, "KISTATUSBAR::updateWarningUI: this=%p, m_warningButton=%p",
|
||||
this, m_warningButton );
|
||||
|
||||
if( !m_warningButton )
|
||||
{
|
||||
wxLogTrace( traceLibraries, " -> no warning button, returning early" );
|
||||
return;
|
||||
}
|
||||
|
||||
size_t messageCount;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( m_loadWarningMutex );
|
||||
messageCount = m_loadWarningMessages.size();
|
||||
}
|
||||
|
||||
wxLogTrace( traceLibraries, " -> message count=%zu, showing button=%s",
|
||||
messageCount, messageCount > 0 ? "true" : "false" );
|
||||
|
||||
m_warningButton->Show( messageCount > 0 );
|
||||
|
||||
if( messageCount > 0 )
|
||||
{
|
||||
m_warningButton->SetToolTip( wxString::Format( _( "View %zu load message(s)" ), messageCount ) );
|
||||
|
||||
// Show count badge on the warning button
|
||||
m_warningButton->SetShowBadge( true );
|
||||
wxString badgeText = messageCount > 99
|
||||
? wxString( "99+" )
|
||||
: wxString::Format( wxS( "%zu" ), messageCount );
|
||||
m_warningButton->SetBadgeText( badgeText );
|
||||
|
||||
wxLogTrace( traceLibraries, " -> badge set to '%s'", badgeText );
|
||||
}
|
||||
|
||||
Layout();
|
||||
Refresh();
|
||||
wxLogTrace( traceLibraries, " -> Layout and Refresh complete" );
|
||||
}
|
||||
|
||||
|
||||
void KISTATUSBAR::ClearLoadWarningMessages()
|
||||
{
|
||||
m_loadWarningMessages.clear();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( m_loadWarningMutex );
|
||||
m_loadWarningMessages.clear();
|
||||
}
|
||||
|
||||
if( m_warningButton )
|
||||
{
|
||||
m_warningButton->Hide();
|
||||
m_warningButton->SetShowBadge( false );
|
||||
m_warningButton->SetBadgeText( wxEmptyString );
|
||||
Layout();
|
||||
Refresh();
|
||||
}
|
||||
@@ -360,12 +425,19 @@ void KISTATUSBAR::ClearLoadWarningMessages()
|
||||
|
||||
void KISTATUSBAR::onLoadWarningsIconClick( wxCommandEvent& aEvent )
|
||||
{
|
||||
if( m_loadWarningMessages.empty() )
|
||||
// Copy messages under lock to avoid holding lock during modal dialog
|
||||
std::vector<LOAD_MESSAGE> messages;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( m_loadWarningMutex );
|
||||
messages = m_loadWarningMessages;
|
||||
}
|
||||
|
||||
if( messages.empty() )
|
||||
return;
|
||||
|
||||
DIALOG_HTML_REPORTER dlg( GetParent(), wxID_ANY, _( "Load Messages" ) );
|
||||
|
||||
for( const LOAD_MESSAGE& msg : m_loadWarningMessages )
|
||||
for( const LOAD_MESSAGE& msg : messages )
|
||||
dlg.m_Reporter->Report( msg.message, msg.severity );
|
||||
|
||||
dlg.m_Reporter->Flush();
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <tool/editor_conditions.h>
|
||||
#include <tool/tool_dispatcher.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <widgets/kistatusbar.h>
|
||||
#include <widgets/wx_progress_reporters.h>
|
||||
|
||||
#include <cvpcb_association.h>
|
||||
@@ -908,7 +909,10 @@ bool CVPCB_MAINFRAME::LoadFootprintFiles()
|
||||
m_FootprintsList->ReadFootprintFiles( adapter, nullptr, &progressReporter );
|
||||
|
||||
if( m_FootprintsList->GetErrorCount() )
|
||||
m_FootprintsList->DisplayErrors( this );
|
||||
{
|
||||
if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( GetStatusBar() ) )
|
||||
statusBar->SetLoadWarningMessages( m_FootprintsList->GetErrorMessages() );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -308,7 +308,8 @@ FOOTPRINT* DISPLAY_FOOTPRINTS_FRAME::GetFootprint( const wxString& aFootprintNam
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Error loading footprint" ), ioe.What() );
|
||||
aReporter.Report( wxString::Format( _( "Error loading footprint: %s" ), ioe.What() ),
|
||||
RPT_SEVERITY_ERROR );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <pgm_base.h>
|
||||
#include <libraries/symbol_library_adapter.h>
|
||||
#include <widgets/sch_design_block_pane.h>
|
||||
#include <widgets/kistatusbar.h>
|
||||
#include <wx/log.h>
|
||||
#include <trace_helpers.h>
|
||||
|
||||
@@ -1089,12 +1090,25 @@ void SCH_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
|
||||
break;
|
||||
|
||||
case MAIL_RELOAD_LIB:
|
||||
{
|
||||
if( m_designBlocksPane && m_designBlocksPane->IsShown() )
|
||||
{
|
||||
m_designBlocksPane->RefreshLibs();
|
||||
SyncView();
|
||||
}
|
||||
|
||||
// Show any symbol library load errors in the status bar
|
||||
if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( GetStatusBar() ) )
|
||||
{
|
||||
SYMBOL_LIBRARY_ADAPTER* adapter = PROJECT_SCH::SymbolLibAdapter( &Prj() );
|
||||
wxString errors = adapter->GetLibraryLoadErrors();
|
||||
|
||||
if( !errors.IsEmpty() )
|
||||
statusBar->SetLoadWarningMessages( errors );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:;
|
||||
|
||||
|
||||
@@ -50,11 +50,14 @@
|
||||
#include <symbol_editor_settings.h>
|
||||
#include <sexpr/sexpr.h>
|
||||
#include <sexpr/sexpr_parser.h>
|
||||
#include <string_utils.h>
|
||||
#include <trace_helpers.h>
|
||||
#include <thread_pool.h>
|
||||
#include <kiface_ids.h>
|
||||
#include <widgets/kistatusbar.h>
|
||||
#include <netlist_exporters/netlist_exporter_kicad.h>
|
||||
#include <wx/ffile.h>
|
||||
#include <wx/tokenzr.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
|
||||
#include <schematic.h>
|
||||
@@ -482,6 +485,8 @@ void IFACE::PreloadLibraries( KIWAY* aKiway )
|
||||
if( m_libraryPreloadInProgress.load() )
|
||||
return;
|
||||
|
||||
Pgm().ClearLibraryLoadMessages();
|
||||
|
||||
m_libraryPreloadBackgroundJob =
|
||||
Pgm().GetBackgroundJobMonitor().Create( _( "Loading Symbol Libraries" ) );
|
||||
|
||||
@@ -530,6 +535,26 @@ void IFACE::PreloadLibraries( KIWAY* aKiway )
|
||||
|
||||
adapter->BlockUntilLoaded();
|
||||
|
||||
// Collect library load errors for async reporting
|
||||
wxString errors = adapter->GetLibraryLoadErrors();
|
||||
|
||||
wxLogTrace( traceLibraries, "eeschema PreloadLibraries: errors.IsEmpty()=%d, length=%zu",
|
||||
errors.IsEmpty(), errors.length() );
|
||||
|
||||
std::vector<LOAD_MESSAGE> messages =
|
||||
ExtractLibraryLoadErrors( errors, RPT_SEVERITY_ERROR );
|
||||
|
||||
if( !messages.empty() )
|
||||
{
|
||||
wxLogTrace( traceLibraries, " -> collected %zu messages, calling AddLibraryLoadMessages",
|
||||
messages.size() );
|
||||
Pgm().AddLibraryLoadMessages( messages );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( traceLibraries, " -> no errors from symbol libraries" );
|
||||
}
|
||||
|
||||
Pgm().GetBackgroundJobMonitor().Remove( m_libraryPreloadBackgroundJob );
|
||||
m_libraryPreloadBackgroundJob.reset();
|
||||
m_libraryPreloadInProgress.store( false );
|
||||
|
||||
@@ -641,7 +641,7 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
||||
}
|
||||
|
||||
// Update all symbol library links for all sheets.
|
||||
schematic.UpdateSymbolLinks();
|
||||
schematic.UpdateSymbolLinks( &loadReporter );
|
||||
|
||||
m_infoBar->RemoveAllButtons();
|
||||
m_infoBar->AddCloseButton();
|
||||
|
||||
@@ -537,7 +537,7 @@ SCH_SHEET* SCH_IO_ALTIUM::LoadSchematicFile( const wxString& aFileName, SCHEMATI
|
||||
m_errorMessages.clear();
|
||||
|
||||
SCH_SCREENS allSheets( m_rootSheet );
|
||||
allSheets.UpdateSymbolLinks(); // Update all symbol library links for all sheets.
|
||||
allSheets.UpdateSymbolLinks( &LOAD_INFO_REPORTER::GetInstance() ); // Update all symbol library links for all sheets.
|
||||
allSheets.ClearEditFlags();
|
||||
|
||||
// Set up the default netclass wire & bus width based on imported wires & buses.
|
||||
|
||||
@@ -476,7 +476,7 @@ SCH_SHEET* SCH_IO_EAGLE::LoadSchematicFile( const wxString& aFileName, SCHEMATIC
|
||||
m_pi->SaveLibrary( getLibFileName().GetFullPath() );
|
||||
|
||||
SCH_SCREENS allSheets( m_rootSheet );
|
||||
allSheets.UpdateSymbolLinks(); // Update all symbol library links for all sheets.
|
||||
allSheets.UpdateSymbolLinks( &LOAD_INFO_REPORTER::GetInstance() ); // Update all symbol library links for all sheets.
|
||||
|
||||
return m_rootSheet;
|
||||
}
|
||||
|
||||
@@ -593,7 +593,7 @@ LIB_SYMBOL* SCH_IO_KICAD_SEXPR_PARSER::parseLibSymbol( LIB_SYMBOL_MAP& aSymbolLi
|
||||
}
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
wxLogError( e.What() );
|
||||
m_parseWarnings.push_back( e.What() );
|
||||
}
|
||||
|
||||
SyncLineReaderWith( embeddedFilesParser );
|
||||
@@ -3012,7 +3012,7 @@ void SCH_IO_KICAD_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet, bool aIsCopya
|
||||
}
|
||||
catch( const PARSE_ERROR& e )
|
||||
{
|
||||
wxLogError( e.What() );
|
||||
m_parseWarnings.push_back( e.What() );
|
||||
}
|
||||
|
||||
SyncLineReaderWith( embeddedFilesParser );
|
||||
|
||||
@@ -113,6 +113,12 @@ public:
|
||||
|
||||
int GetParsedRequiredVersion() const { return m_requiredVersion; }
|
||||
|
||||
/**
|
||||
* Return any non-fatal parse warnings that occurred during parsing.
|
||||
* These are errors that were handled gracefully but should be reported to the user.
|
||||
*/
|
||||
const std::vector<wxString>& GetParseWarnings() const { return m_parseWarnings; }
|
||||
|
||||
private:
|
||||
// Group membership info refers to other Uuids in the file.
|
||||
// We don't want to rely on group declarations being last in the file, so
|
||||
@@ -276,6 +282,8 @@ private:
|
||||
int m_maxError;
|
||||
|
||||
std::vector<GROUP_INFO> m_groupInfos;
|
||||
|
||||
std::vector<wxString> m_parseWarnings; ///< Non-fatal warnings collected during parsing
|
||||
};
|
||||
|
||||
#endif // SCH_IO_KICAD_SEXPR_PARSER_H_
|
||||
|
||||
@@ -226,6 +226,11 @@ public:
|
||||
return error;
|
||||
}
|
||||
|
||||
void PushError( std::unique_ptr<IO_ERROR> aError )
|
||||
{
|
||||
m_errors.move_push( std::move( aError ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all the footprints provided by the combination of aTable and aNickname.
|
||||
*
|
||||
@@ -243,6 +248,12 @@ public:
|
||||
|
||||
void DisplayErrors( wxTopLevelWindow* aCaller = nullptr );
|
||||
|
||||
/**
|
||||
* Returns all accumulated errors as a newline-separated string for display in the
|
||||
* status bar. This consumes the errors (pops them from the queue).
|
||||
*/
|
||||
wxString GetErrorMessages();
|
||||
|
||||
FOOTPRINT_LIBRARY_ADAPTER* GetAdapter() const { return m_adapter; }
|
||||
|
||||
/**
|
||||
|
||||
@@ -148,6 +148,9 @@ public:
|
||||
/// Returns a list of all library nicknames and their status (even if they failed to load)
|
||||
std::vector<std::pair<wxString, LIB_STATUS>> GetLibraryStatuses() const;
|
||||
|
||||
/// Returns all library load errors as newline-separated strings for display
|
||||
wxString GetLibraryLoadErrors() const;
|
||||
|
||||
void ReloadLibraryEntry( const wxString& aNickname,
|
||||
LIBRARY_TABLE_SCOPE aScope = LIBRARY_TABLE_SCOPE::BOTH );
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <exception>
|
||||
#include <map>
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <search_stack.h>
|
||||
@@ -49,6 +50,8 @@ class wxWindow;
|
||||
class wxSplashScreen;
|
||||
class wxSingleInstanceChecker;
|
||||
|
||||
class KISTATUSBAR;
|
||||
struct LOAD_MESSAGE;
|
||||
struct BACKGROUND_JOB;
|
||||
class BACKGROUND_JOBS_MONITOR;
|
||||
class NOTIFICATIONS_MANAGER;
|
||||
@@ -360,6 +363,28 @@ public:
|
||||
*/
|
||||
void PreloadDesignBlockLibraries( KIWAY* aKiway );
|
||||
|
||||
/**
|
||||
* Register a status bar to receive library load warning messages.
|
||||
* Multiple status bars can be registered (one per open frame).
|
||||
*/
|
||||
void RegisterLibraryLoadStatusBar( KISTATUSBAR* aStatusBar );
|
||||
|
||||
/**
|
||||
* Unregister a status bar from receiving library load warning messages.
|
||||
*/
|
||||
void UnregisterLibraryLoadStatusBar( KISTATUSBAR* aStatusBar );
|
||||
|
||||
/**
|
||||
* Add library load messages to all registered status bars.
|
||||
* Thread-safe - can be called from background threads.
|
||||
*/
|
||||
void AddLibraryLoadMessages( const std::vector<LOAD_MESSAGE>& aMessages );
|
||||
|
||||
/**
|
||||
* Clear library load messages from all registered status bars.
|
||||
*/
|
||||
void ClearLibraryLoadMessages();
|
||||
|
||||
/**
|
||||
* wxWidgets on MSW tends to crash if you spool up more than one print job at a time.
|
||||
*/
|
||||
@@ -432,6 +457,9 @@ protected:
|
||||
std::future<void> m_libraryPreloadReturn;
|
||||
std::atomic_bool m_libraryPreloadInProgress;
|
||||
std::atomic_bool m_libraryPreloadAbort;
|
||||
|
||||
std::vector<KISTATUSBAR*> m_libraryLoadStatusBars;
|
||||
mutable std::mutex m_libraryLoadStatusBarsMutex;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -511,4 +511,17 @@ KICOMMON_API wxString GetDefaultVariantName();
|
||||
|
||||
KICOMMON_API int SortVariantNames( const wxString& aLhs, const wxString& aRhs );
|
||||
|
||||
struct LOAD_MESSAGE;
|
||||
|
||||
/**
|
||||
* Parse library load error messages, extracting user-facing information while
|
||||
* stripping internal code locations.
|
||||
*
|
||||
* @param aErrorString is the raw error string from GetLibraryLoadErrors()
|
||||
* @param aSeverity is the severity to assign to all extracted messages
|
||||
* @return vector of LOAD_MESSAGE with cleaned error text
|
||||
*/
|
||||
KICOMMON_API std::vector<LOAD_MESSAGE> ExtractLibraryLoadErrors( const wxString& aErrorString,
|
||||
int aSeverity );
|
||||
|
||||
#endif // STRING_UTILS_H
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <kicommon.h>
|
||||
#include <optional>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <widgets/report_severity.h>
|
||||
|
||||
@@ -116,11 +117,23 @@ public:
|
||||
void SetLoadWarningMessages( const wxString& aMessages );
|
||||
void ClearLoadWarningMessages();
|
||||
|
||||
/**
|
||||
* Add warning/error messages thread-safely.
|
||||
* Can be called from any thread. UI update is deferred to main thread.
|
||||
*/
|
||||
void AddLoadWarningMessages( const std::vector<LOAD_MESSAGE>& aMessages );
|
||||
|
||||
/**
|
||||
* Get current message count (thread-safe).
|
||||
*/
|
||||
size_t GetLoadWarningCount() const;
|
||||
|
||||
private:
|
||||
void onSize( wxSizeEvent& aEvent );
|
||||
void onBackgroundProgressClick( wxMouseEvent& aEvent );
|
||||
void onNotificationsIconClick( wxCommandEvent& aEvent );
|
||||
void onLoadWarningsIconClick( wxCommandEvent& aEvent );
|
||||
void updateWarningUI(); ///< Update warning button visibility and badge (main thread only)
|
||||
|
||||
enum class FIELD
|
||||
{
|
||||
@@ -139,6 +152,7 @@ private:
|
||||
wxStaticText* m_backgroundTxt;
|
||||
BITMAP_BUTTON* m_notificationsButton;
|
||||
BITMAP_BUTTON* m_warningButton;
|
||||
mutable std::mutex m_loadWarningMutex; ///< Protects m_loadWarningMessages
|
||||
std::vector<LOAD_MESSAGE> m_loadWarningMessages;
|
||||
int m_normalFieldsCount;
|
||||
STYLE_FLAGS m_styleFlags;
|
||||
|
||||
@@ -172,6 +172,7 @@ KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent, const wxString& titl
|
||||
CreateStatusBar( 2 );
|
||||
Pgm().GetBackgroundJobMonitor().RegisterStatusBar( (KISTATUSBAR*) GetStatusBar() );
|
||||
Pgm().GetNotificationsManager().RegisterStatusBar( (KISTATUSBAR*) GetStatusBar() );
|
||||
Pgm().RegisterLibraryLoadStatusBar( (KISTATUSBAR*) GetStatusBar() );
|
||||
GetStatusBar()->SetFont( KIUI::GetStatusFont( this ) );
|
||||
|
||||
// Give an icon
|
||||
@@ -324,6 +325,7 @@ KICAD_MANAGER_FRAME::~KICAD_MANAGER_FRAME()
|
||||
|
||||
Pgm().GetBackgroundJobMonitor().UnregisterStatusBar( (KISTATUSBAR*) GetStatusBar() );
|
||||
Pgm().GetNotificationsManager().UnregisterStatusBar( (KISTATUSBAR*) GetStatusBar() );
|
||||
Pgm().UnregisterLibraryLoadStatusBar( (KISTATUSBAR*) GetStatusBar() );
|
||||
|
||||
// Shutdown all running tools
|
||||
if( m_toolManager )
|
||||
@@ -383,7 +385,10 @@ void KICAD_MANAGER_FRAME::onNotebookPageCloseRequest( wxAuiNotebookEvent& evt )
|
||||
wxStatusBar* KICAD_MANAGER_FRAME::OnCreateStatusBar( int number, long style, wxWindowID id,
|
||||
const wxString& name )
|
||||
{
|
||||
return new KISTATUSBAR( number, this, id );
|
||||
return new KISTATUSBAR( number, this, id,
|
||||
static_cast<KISTATUSBAR::STYLE_FLAGS>(
|
||||
KISTATUSBAR::NOTIFICATION_ICON | KISTATUSBAR::CANCEL_BUTTON
|
||||
| KISTATUSBAR::WARNING_ICON ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -57,6 +57,9 @@
|
||||
#include <trace_helpers.h>
|
||||
#include <netlist_reader/netlist_reader.h>
|
||||
#include <widgets/pcb_design_block_pane.h>
|
||||
#include <widgets/kistatusbar.h>
|
||||
#include <project_pcb.h>
|
||||
#include <footprint_library_adapter.h>
|
||||
#include <wx/log.h>
|
||||
|
||||
/* Execute a remote command sent via a socket on port KICAD_PCB_PORT_SERVICE_NUMBER
|
||||
@@ -726,8 +729,21 @@ void PCB_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
|
||||
break;
|
||||
|
||||
case MAIL_RELOAD_LIB:
|
||||
{
|
||||
m_designBlocksPane->RefreshLibs();
|
||||
|
||||
// Show any footprint library load errors in the status bar
|
||||
if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( GetStatusBar() ) )
|
||||
{
|
||||
FOOTPRINT_LIBRARY_ADAPTER* adapter = PROJECT_PCB::FootprintLibAdapter( &Prj() );
|
||||
wxString errors = adapter->GetLibraryLoadErrors();
|
||||
|
||||
if( !errors.IsEmpty() )
|
||||
statusBar->SetLoadWarningMessages( errors );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// many many others.
|
||||
default:
|
||||
|
||||
+3
-9
@@ -31,7 +31,6 @@
|
||||
#include <kidialog.h>
|
||||
#include <core/arraydim.h>
|
||||
#include <thread_pool.h>
|
||||
#include <dialog_HTML_reporter_base.h>
|
||||
#include <gestfich.h>
|
||||
#include <local_history.h>
|
||||
#include <pcb_edit_frame.h>
|
||||
@@ -623,7 +622,6 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
||||
std::placeholders::_1 ) );
|
||||
}
|
||||
|
||||
DIALOG_HTML_REPORTER errorReporter( this );
|
||||
bool failedLoad = false;
|
||||
|
||||
try
|
||||
@@ -660,8 +658,10 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
||||
// measure the time to load a BOARD.
|
||||
int64_t startTime = GetRunningMicroSecs();
|
||||
#endif
|
||||
// Use loadReporter for import issues - they will be shown in the status bar
|
||||
// warning icon instead of a modal dialog
|
||||
if( config()->m_System.show_import_issues )
|
||||
pi->SetReporter( errorReporter.m_Reporter );
|
||||
pi->SetReporter( &loadReporter );
|
||||
else
|
||||
pi->SetReporter( &NULL_REPORTER::GetInstance() );
|
||||
|
||||
@@ -718,12 +718,6 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
||||
// compiled.
|
||||
Raise();
|
||||
|
||||
if( errorReporter.m_Reporter->HasMessage() )
|
||||
{
|
||||
errorReporter.m_Reporter->Flush(); // Build HTML messages
|
||||
errorReporter.ShowModal();
|
||||
}
|
||||
|
||||
// Skip (possibly expensive) connectivity build here; we build it below after load
|
||||
SetBoard( loadedBoard, false, &progressReporter );
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
#include <tools/pcb_group_tool.h>
|
||||
#include <tools/position_relative_tool.h>
|
||||
#include <widgets/appearance_controls.h>
|
||||
#include <widgets/kistatusbar.h>
|
||||
#include <widgets/lib_tree.h>
|
||||
#include <widgets/panel_selection_filter.h>
|
||||
#include <widgets/pcb_properties_panel.h>
|
||||
@@ -1151,7 +1152,10 @@ void FOOTPRINT_EDIT_FRAME::initLibraryTree()
|
||||
progressReporter.Show( false );
|
||||
|
||||
if( GFootprintList.GetErrorCount() )
|
||||
GFootprintList.DisplayErrors( this );
|
||||
{
|
||||
if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( GetStatusBar() ) )
|
||||
statusBar->SetLoadWarningMessages( GFootprintList.GetErrorMessages() );
|
||||
}
|
||||
|
||||
m_adapter = FP_TREE_SYNCHRONIZING_ADAPTER::Create( this, footprints );
|
||||
auto adapter = static_cast<FP_TREE_SYNCHRONIZING_ADAPTER*>( m_adapter.get() );
|
||||
|
||||
@@ -45,20 +45,32 @@ void FOOTPRINT_INFO_IMPL::load()
|
||||
FOOTPRINT_LIBRARY_ADAPTER* adapter = m_owner->GetAdapter();
|
||||
wxCHECK( adapter, /* void */ );
|
||||
|
||||
std::unique_ptr<FOOTPRINT> footprint( adapter->LoadFootprint( m_nickname, m_fpname, false ) );
|
||||
|
||||
if( footprint == nullptr ) // Should happen only with malformed/broken libraries
|
||||
try
|
||||
{
|
||||
std::unique_ptr<FOOTPRINT> footprint( adapter->LoadFootprint( m_nickname, m_fpname, false ) );
|
||||
|
||||
if( footprint == nullptr ) // Should happen only with malformed/broken libraries
|
||||
{
|
||||
m_pad_count = 0;
|
||||
m_unique_pad_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pad_count = footprint->GetPadCount( DO_NOT_INCLUDE_NPTH );
|
||||
m_unique_pad_count = footprint->GetUniquePadCount( DO_NOT_INCLUDE_NPTH );
|
||||
m_keywords = footprint->GetKeywords();
|
||||
m_doc = footprint->GetLibDescription();
|
||||
}
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
// Store error in the owner's error list for later display
|
||||
if( m_owner )
|
||||
m_owner->PushError( std::make_unique<IO_ERROR>( ioe ) );
|
||||
|
||||
m_pad_count = 0;
|
||||
m_unique_pad_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pad_count = footprint->GetPadCount( DO_NOT_INCLUDE_NPTH );
|
||||
m_unique_pad_count = footprint->GetUniquePadCount( DO_NOT_INCLUDE_NPTH );
|
||||
m_keywords = footprint->GetKeywords();
|
||||
m_doc = footprint->GetLibDescription();
|
||||
}
|
||||
|
||||
m_loaded = true;
|
||||
}
|
||||
|
||||
@@ -364,12 +364,20 @@ FOOTPRINT* FOOTPRINT_LIBRARY_ADAPTER::LoadFootprint( const wxString& aNickname,
|
||||
{
|
||||
if( std::optional<const LIB_DATA*> lib = fetchIfLoaded( aNickname ) )
|
||||
{
|
||||
if( FOOTPRINT* footprint = pcbplugin( *lib )->FootprintLoad( getUri( ( *lib )->row ), aName ) )
|
||||
try
|
||||
{
|
||||
LIB_ID id = footprint->GetFPID();
|
||||
id.SetLibNickname( ( *lib )->row->Nickname() );
|
||||
footprint->SetFPID( id );
|
||||
return footprint;
|
||||
if( FOOTPRINT* footprint = pcbplugin( *lib )->FootprintLoad( getUri( ( *lib )->row ), aName ) )
|
||||
{
|
||||
LIB_ID id = footprint->GetFPID();
|
||||
id.SetLibNickname( ( *lib )->row->Nickname() );
|
||||
footprint->SetFPID( id );
|
||||
return footprint;
|
||||
}
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
wxLogTrace( traceLibraries, "LoadFootprint: error loading %s:%s: %s",
|
||||
aNickname, aName, ioe.What() );
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <kiway.h>
|
||||
#include <kiway_express.h>
|
||||
#include <netlist_reader/pcb_netlist.h>
|
||||
#include <widgets/kistatusbar.h>
|
||||
#include <widgets/msgpanel.h>
|
||||
#include <widgets/wx_listbox.h>
|
||||
#include <widgets/wx_aui_utils.h>
|
||||
@@ -492,7 +493,8 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateFootprintList()
|
||||
|
||||
if( fp_info_list->GetErrorCount() )
|
||||
{
|
||||
fp_info_list->DisplayErrors( this );
|
||||
if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( GetStatusBar() ) )
|
||||
statusBar->SetLoadWarningMessages( fp_info_list->GetErrorMessages() );
|
||||
|
||||
// For footprint libraries that support one footprint per file, there may have been
|
||||
// valid footprints read so show the footprints that loaded properly.
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <string_utils.h>
|
||||
#include <footprint.h>
|
||||
#include <footprint_library_adapter.h>
|
||||
#include <trace_helpers.h>
|
||||
#include <wx/log.h>
|
||||
|
||||
|
||||
@@ -126,7 +127,8 @@ public:
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
wxLogError( _( "Error loading footprint %s from library '%s'." ) + wxS( "\n%s" ),
|
||||
// Log to trace instead of error to avoid popup dialogs
|
||||
wxLogTrace( traceLibraries, "Error loading footprint %s from library '%s': %s",
|
||||
m_lib_id.GetLibItemName().wx_str(),
|
||||
m_lib_id.GetLibNickname().wx_str(),
|
||||
ioe.What() );
|
||||
|
||||
@@ -190,6 +190,17 @@ void FP_CACHE::Load()
|
||||
|
||||
footprint->SetFPID( LIB_ID( wxEmptyString, fpName ) );
|
||||
m_footprints.insert( fpName, new FP_CACHE_ENTRY( footprint, fn ) );
|
||||
|
||||
// Collect any non-fatal parse warnings
|
||||
for( const wxString& warning : parser.GetParseWarnings() )
|
||||
{
|
||||
if( !cacheError.IsEmpty() )
|
||||
cacheError += wxT( "\n\n" );
|
||||
|
||||
cacheError += wxString::Format( _( "Warning in file '%s'" ) + '\n',
|
||||
fn.GetFullPath() );
|
||||
cacheError += warning;
|
||||
}
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
#include <progress_reporter.h>
|
||||
#include <board_stackup_manager/stackup_predefined_prms.h>
|
||||
#include <pgm_base.h>
|
||||
#include <trace_helpers.h>
|
||||
|
||||
// For some reason wxWidgets is built with wxUSE_BASE64 unset so expose the wxWidgets
|
||||
// base64 code. Needed for PCB_REFERENCE_IMAGE
|
||||
@@ -1173,7 +1174,7 @@ BOARD* PCB_IO_KICAD_SEXPR_PARSER::parseBOARD_unchecked()
|
||||
}
|
||||
catch( const PARSE_ERROR& e )
|
||||
{
|
||||
wxLogError( e.What() );
|
||||
m_parseWarnings.push_back( e.What() );
|
||||
}
|
||||
|
||||
SyncLineReaderWith( embeddedFilesParser );
|
||||
@@ -5306,7 +5307,7 @@ FOOTPRINT* PCB_IO_KICAD_SEXPR_PARSER::parseFOOTPRINT_unchecked( wxArrayString* a
|
||||
}
|
||||
catch( const PARSE_ERROR& e )
|
||||
{
|
||||
wxLogError( e.What() );
|
||||
m_parseWarnings.push_back( e.What() );
|
||||
}
|
||||
|
||||
SyncLineReaderWith( embeddedFilesParser );
|
||||
|
||||
@@ -136,6 +136,12 @@ public:
|
||||
*/
|
||||
bool IsValidBoardHeader();
|
||||
|
||||
/**
|
||||
* Return any non-fatal parse warnings that occurred during parsing.
|
||||
* These are errors that were handled gracefully but should be reported to the user.
|
||||
*/
|
||||
const std::vector<wxString>& GetParseWarnings() const { return m_parseWarnings; }
|
||||
|
||||
private:
|
||||
|
||||
// Group membership info refers to other Uuids in the file.
|
||||
@@ -449,6 +455,8 @@ private:
|
||||
std::vector<GENERATOR_INFO> m_generatorInfos;
|
||||
|
||||
std::function<bool( wxString aTitle, int aIcon, wxString aMsg, wxString aAction )> m_queryUserCallback;
|
||||
|
||||
std::vector<wxString> m_parseWarnings; ///< Non-fatal warnings collected during parsing
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -62,7 +62,12 @@
|
||||
#include <panel_3D_raytracing_options.h>
|
||||
#include <project_pcb.h>
|
||||
#include <python_scripting.h>
|
||||
#include <string_utils.h>
|
||||
#include <thread_pool.h>
|
||||
#include <trace_helpers.h>
|
||||
#include <widgets/kistatusbar.h>
|
||||
|
||||
#include <wx/tokenzr.h>
|
||||
|
||||
#include "invoke_pcb_dialog.h"
|
||||
#include <wildcards_and_files_ext.h>
|
||||
@@ -611,6 +616,8 @@ void IFACE::PreloadLibraries( KIWAY* aKiway )
|
||||
if( m_libraryPreloadInProgress.load() )
|
||||
return;
|
||||
|
||||
Pgm().ClearLibraryLoadMessages();
|
||||
|
||||
m_libraryPreloadBackgroundJob =
|
||||
Pgm().GetBackgroundJobMonitor().Create( _( "Loading Footprint Libraries" ) );
|
||||
|
||||
@@ -659,9 +666,47 @@ void IFACE::PreloadLibraries( KIWAY* aKiway )
|
||||
|
||||
adapter->BlockUntilLoaded();
|
||||
|
||||
// Collect and report library load errors from adapter
|
||||
wxString errors = adapter->GetLibraryLoadErrors();
|
||||
|
||||
wxLogTrace( traceLibraries, "pcbnew PreloadLibraries: adapter errors.IsEmpty()=%d, length=%zu",
|
||||
errors.IsEmpty(), errors.length() );
|
||||
|
||||
if( !errors.IsEmpty() )
|
||||
{
|
||||
std::vector<LOAD_MESSAGE> messages = ExtractLibraryLoadErrors( errors, RPT_SEVERITY_ERROR );
|
||||
|
||||
wxLogTrace( traceLibraries, " -> adapter: collected %zu messages", messages.size() );
|
||||
|
||||
if( !messages.empty() )
|
||||
Pgm().AddLibraryLoadMessages( messages );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( traceLibraries, " -> no errors from footprint adapter" );
|
||||
}
|
||||
|
||||
// TODO: Remove once fp-info-cache isn't a thing
|
||||
GFootprintList.ReadFootprintFiles( adapter, nullptr, reporter.get() );
|
||||
|
||||
// Also collect errors from GFootprintList
|
||||
wxLogTrace( traceLibraries, " -> GFootprintList.GetErrorCount()=%u", GFootprintList.GetErrorCount() );
|
||||
|
||||
if( GFootprintList.GetErrorCount() > 0 )
|
||||
{
|
||||
std::vector<LOAD_MESSAGE> messages =
|
||||
ExtractLibraryLoadErrors( GFootprintList.GetErrorMessages(), RPT_SEVERITY_ERROR );
|
||||
|
||||
wxLogTrace( traceLibraries, " -> GFootprintList: collected %zu messages", messages.size() );
|
||||
|
||||
if( !messages.empty() )
|
||||
Pgm().AddLibraryLoadMessages( messages );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( traceLibraries, " -> no errors from GFootprintList" );
|
||||
}
|
||||
|
||||
Pgm().GetBackgroundJobMonitor().Remove( m_libraryPreloadBackgroundJob );
|
||||
m_libraryPreloadBackgroundJob.reset();
|
||||
m_libraryPreloadInProgress.store( false );
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <kiface_base.h>
|
||||
#include <tool/actions.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <widgets/kistatusbar.h>
|
||||
|
||||
// When a new footprint is selected, a custom event is sent, for instance to update
|
||||
// 3D viewer. So define a FP_SELECTION_EVENT event
|
||||
@@ -79,7 +80,11 @@ PANEL_FOOTPRINT_CHOOSER::PANEL_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aFrame, wxTopL
|
||||
delete progressReporter;
|
||||
|
||||
if( GFootprintList.GetErrorCount() )
|
||||
GFootprintList.DisplayErrors( aParent );
|
||||
{
|
||||
// Show errors in status bar instead of popup dialog
|
||||
if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( aFrame->GetStatusBar() ) )
|
||||
statusBar->SetLoadWarningMessages( GFootprintList.GetErrorMessages() );
|
||||
}
|
||||
|
||||
m_adapter = FP_TREE_MODEL_ADAPTER::Create( aFrame, footprints );
|
||||
FP_TREE_MODEL_ADAPTER* adapter = static_cast<FP_TREE_MODEL_ADAPTER*>( m_adapter.get() );
|
||||
|
||||
Reference in New Issue
Block a user