Improve error reporting for lib table rows.

This commit is contained in:
Jeff Young
2025-11-23 22:36:37 +00:00
parent 3c2f6c5b8d
commit 8f8f05a944
17 changed files with 345 additions and 264 deletions
+79 -72
View File
@@ -67,8 +67,7 @@ LIBRARY_RESULT<IO_BASE*> DESIGN_BLOCK_LIBRARY_ADAPTER::createPlugin( const LIBRA
if( type == DESIGN_BLOCK_IO_MGR::DESIGN_BLOCK_FILE_UNKNOWN )
{
wxLogTrace( traceLibraries, "Sym: Plugin type %s is unknown!", row->Type() );
wxString msg =
wxString::Format( _( "Unknown library type %s " ), row->Type() );
wxString msg = wxString::Format( _( "Unknown library type %s " ), row->Type() );
return tl::unexpected( LIBRARY_ERROR( msg ) );
}
@@ -85,6 +84,32 @@ IO_BASE* DESIGN_BLOCK_LIBRARY_ADAPTER::plugin( const LIB_DATA* aRow )
}
/// Loads or reloads the given library, if it exists
std::optional<LIB_STATUS> DESIGN_BLOCK_LIBRARY_ADAPTER::LoadOne( LIB_DATA* aLib )
{
wxArrayString dummyList;
std::lock_guard lock ( aLib->mutex );
aLib->status.load_status = LOAD_STATUS::LOADING;
std::map<std::string, UTF8> options = aLib->row->GetOptionsMap();
try
{
dbplugin( aLib )->DesignBlockEnumerate( dummyList, getUri( aLib->row ), false, &options );
wxLogTrace( traceLibraries, "DB: %s: library enumerated %zu items", aLib->row->Nickname(), dummyList.size() );
aLib->status.load_status = LOAD_STATUS::LOADED;
}
catch( IO_ERROR& e )
{
aLib->status.load_status = LOAD_STATUS::LOAD_ERROR;
aLib->status.error = LIBRARY_ERROR( { e.What() } );
wxLogTrace( traceLibraries, "DB: %s: plugin threw exception: %s", aLib->row->Nickname(), e.What() );
}
return aLib->status;
}
void DESIGN_BLOCK_LIBRARY_ADAPTER::AsyncLoad()
{
// TODO(JE) library tables - how much of this can be shared with other library types?
@@ -116,20 +141,20 @@ void DESIGN_BLOCK_LIBRARY_ADAPTER::AsyncLoad()
thread_pool& tp = GetKiCadThreadPool();
auto check =
[]( const wxString& aLib, std::map<wxString, LIB_DATA>& aMap, std::mutex& aMutex )
{
std::lock_guard lock( aMutex );
if( aMap.contains( aLib ) )
[]( const wxString& aLib, std::map<wxString, LIB_DATA>& aMap, std::mutex& aMutex )
{
if( aMap[aLib].status.load_status == LOAD_STATUS::LOADED )
return true;
std::lock_guard lock( aMutex );
aMap.erase( aLib );
}
if( aMap.contains( aLib ) )
{
if( aMap[aLib].status.load_status == LOAD_STATUS::LOADED )
return true;
return false;
};
aMap.erase( aLib );
}
return false;
};
std::set<wxString> libNamesCurrentlyValid;
@@ -154,71 +179,53 @@ void DESIGN_BLOCK_LIBRARY_ADAPTER::AsyncLoad()
}
m_futures.emplace_back( tp.submit_task(
[this, nickname, scope]()
{
if( m_abort.load() )
return;
LIBRARY_RESULT<LIB_DATA*> result = loadIfNeeded( nickname );
if( result.has_value() )
[this, nickname, scope]()
{
LIB_DATA* lib = *result;
wxArrayString dummyList;
std::lock_guard lock ( lib->mutex );
lib->status.load_status = LOAD_STATUS::LOADING;
if( m_abort.load() )
return;
std::map<std::string, UTF8> options = lib->row->GetOptionsMap();
LIBRARY_RESULT<LIB_DATA*> result = loadIfNeeded( nickname );
try
if( result.has_value() )
{
dbplugin( lib )->DesignBlockEnumerate( dummyList, getUri( lib->row ), false, &options );
wxLogTrace( traceLibraries, "DB: %s: library enumerated %zu items", nickname, dummyList.size() );
lib->status.load_status = LOAD_STATUS::LOADED;
LoadOne( *result );
}
catch( IO_ERROR& e )
else
{
lib->status.load_status = LOAD_STATUS::LOAD_ERROR;
lib->status.error = LIBRARY_ERROR( { e.What() } );
wxLogTrace( traceLibraries, "DB: %s: plugin threw exception: %s", nickname, e.What() );
}
}
else
{
switch( scope )
{
case LIBRARY_TABLE_SCOPE::GLOBAL:
{
std::lock_guard lock( GlobalLibraryMutex );
switch( scope )
{
case LIBRARY_TABLE_SCOPE::GLOBAL:
{
std::lock_guard lock( GlobalLibraryMutex );
GlobalLibraries[nickname].status = LIB_STATUS( {
.load_status = LOAD_STATUS::LOAD_ERROR,
.error = result.error()
} );
GlobalLibraries[nickname].status = LIB_STATUS( {
.load_status = LOAD_STATUS::LOAD_ERROR,
.error = result.error()
} );
break;
break;
}
case LIBRARY_TABLE_SCOPE::PROJECT:
{
wxLogTrace( traceLibraries, "DB: project library error: %s: %s", nickname, result.error().message );
std::lock_guard lock( m_libraries_mutex );
m_libraries[nickname].status = LIB_STATUS( {
.load_status = LOAD_STATUS::LOAD_ERROR,
.error = result.error()
} );
break;
}
default:
wxFAIL_MSG( "Unexpected library table scope" );
}
}
case LIBRARY_TABLE_SCOPE::PROJECT:
{
wxLogTrace( traceLibraries, "DB: project library error: %s: %s", nickname, result.error().message );
std::lock_guard lock( m_libraries_mutex );
m_libraries[nickname].status = LIB_STATUS( {
.load_status = LOAD_STATUS::LOAD_ERROR,
.error = result.error()
} );
break;
}
default:
wxFAIL_MSG( "Unexpected library table scope" );
}
}
++m_loadCount;
}, BS::pr::lowest ) );
++m_loadCount;
}, BS::pr::lowest ) );
}
// Cleanup libraries that were removed from the table
@@ -262,8 +269,7 @@ std::vector<DESIGN_BLOCK*> DESIGN_BLOCK_LIBRARY_ADAPTER::GetDesignBlocks( const
}
catch( IO_ERROR& e )
{
wxLogTrace( traceLibraries, "DB: Exception enumerating library %s: %s",
lib->row->Nickname(), e.What() );
wxLogTrace( traceLibraries, "DB: Exception enumerating library %s: %s", lib->row->Nickname(), e.What() );
}
for( const wxString& blockName : blockNames )
@@ -304,7 +310,7 @@ std::vector<wxString> DESIGN_BLOCK_LIBRARY_ADAPTER::GetDesignBlockNames( const w
DESIGN_BLOCK* DESIGN_BLOCK_LIBRARY_ADAPTER::LoadDesignBlock( const wxString& aNickname,
const wxString& aDesignBlockName, bool aKeepUUID )
const wxString& aDesignBlockName, bool aKeepUUID )
{
if( std::optional<const LIB_DATA*> maybeLib = fetchIfLoaded( aNickname ) )
{
@@ -350,7 +356,8 @@ const DESIGN_BLOCK* DESIGN_BLOCK_LIBRARY_ADAPTER::GetEnumeratedDesignBlock( cons
DESIGN_BLOCK_LIBRARY_ADAPTER::SAVE_T DESIGN_BLOCK_LIBRARY_ADAPTER::SaveDesignBlock( const wxString& aNickname,
const DESIGN_BLOCK* aDesignBlock, bool aOverwrite )
const DESIGN_BLOCK* aDesignBlock,
bool aOverwrite )
{
if( std::optional<const LIB_DATA*> maybeLib = fetchIfLoaded( aNickname ) )
{
+2
View File
@@ -42,6 +42,8 @@ public:
void AsyncLoad() override;
std::optional<LIB_STATUS> LoadOne( LIB_DATA* aLib ) override;
// Currently unused for design blocks
std::optional<LIB_STATUS> GetLibraryStatus( const wxString& aNickname ) const override { return std::nullopt; }
@@ -19,7 +19,7 @@ PANEL_DESIGN_BLOCK_LIB_TABLE_BASE::PANEL_DESIGN_BLOCK_LIB_TABLE_BASE( wxWindow*
m_notebook = new wxAuiNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_NB_CLOSE_ON_ALL_TABS|wxAUI_NB_DEFAULT_STYLE );
bMainSizer->Add( m_notebook, 1, wxEXPAND | wxALL, 5 );
bMainSizer->Add( m_notebook, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
wxBoxSizer* bButtonsSizer;
bButtonsSizer = new wxBoxSizer( wxHORIZONTAL );
@@ -59,7 +59,7 @@ PANEL_DESIGN_BLOCK_LIB_TABLE_BASE::PANEL_DESIGN_BLOCK_LIB_TABLE_BASE( wxWindow*
bButtonsSizer->Add( m_migrate_libs_button, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
bMainSizer->Add( bButtonsSizer, 0, wxEXPAND|wxALL, 8 );
bMainSizer->Add( bButtonsSizer, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 8 );
wxStaticText* stPathsLabel;
stPathsLabel = new wxStaticText( this, wxID_ANY, _("Available path substitutions:"), wxDefaultPosition, wxDefaultSize, 0 );
@@ -62,7 +62,7 @@
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND | wxALL</property>
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
<property name="proportion">1</property>
<object class="wxAuiNotebook" expanded="true">
<property name="BottomDockable">1</property>
@@ -123,7 +123,7 @@
</object>
<object class="sizeritem" expanded="true">
<property name="border">8</property>
<property name="flag">wxEXPAND|wxALL</property>
<property name="flag">wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
+8 -27
View File
@@ -469,38 +469,19 @@ bool LIB_TABLE_GRID_TRICKS::VerifyTable( WX_GRID* aGrid, std::function<void( int
wxString uri = model->GetValue( r, COL_URI ).Trim( false ).Trim();
unsigned illegalCh = 0;
if( !nick || !uri )
if( !uri )
{
if( !nick && !uri )
msg = _( "A library table row nickname and path cells are empty." );
else if( !nick )
msg = _( "A library table row nickname cell is empty." );
else
msg = _( "A library table row path cell is empty." );
wxMessageDialog badCellDlg( topLevelParent, msg, _( "Invalid Row Definition" ),
wxYES_NO | wxCENTER | wxICON_QUESTION | wxYES_DEFAULT );
badCellDlg.SetExtendedMessage( _( "Empty cells will result in all rows that are "
"invalid to be removed from the table." ) );
badCellDlg.SetYesNoLabels( wxMessageDialog::ButtonLabel( _( "Remove Invalid Cells" ) ),
wxMessageDialog::ButtonLabel( _( "Cancel Table Update" ) ) );
if( badCellDlg.ShowModal() == wxID_NO )
return false;
// Delete the "empty" row, where empty means missing nick or uri.
// This also updates the UI which could be slow, but there should only be a few
// rows to delete, unless the user fell asleep on the Add Row
// button.
// Silently nuke rows that have no libraray URI
model->DeleteRows( r, 1 );
}
else if( ( illegalCh = LIB_ID::FindIllegalLibraryNameChar( nick ) ) )
else if( !nick || ( illegalCh = LIB_ID::FindIllegalLibraryNameChar( nick ) ) )
{
msg = wxString::Format( _( "Illegal character '%c' in nickname '%s'." ),
illegalCh,
nick );
if( !nick )
msg = _( "Library must have a nickname." );
else
msg = wxString::Format( _( "Illegal character '%c' in nickname '%s'." ), illegalCh, nick );
aErrorHandler( r, 1 );
aErrorHandler( r, COL_NICKNAME );
wxMessageDialog errdlg( topLevelParent, msg, _( "Library Nickname Error" ) );
errdlg.ShowModal();
+100 -70
View File
@@ -54,6 +54,10 @@ LIB_TABLE_GRID_DATA_MODEL::LIB_TABLE_GRID_DATA_MODEL( DIALOG_SHIM* aDialog, WX_G
m_warningAttr->SetReadOnly();
m_warningAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
m_noStatusAttr = new wxGridCellAttr;
m_noStatusAttr->SetReadOnly();
m_noStatusAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
m_editSettingsAttr = new wxGridCellAttr;
m_editSettingsAttr->SetRenderer( new GRID_BITMAP_BUTTON_RENDERER( KiBitmapBundle( BITMAPS::config ) ) );
m_editSettingsAttr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
@@ -72,55 +76,66 @@ LIB_TABLE_GRID_DATA_MODEL::~LIB_TABLE_GRID_DATA_MODEL()
m_typesEditor->DecRef();
m_boolAttr->DecRef();
m_warningAttr->DecRef();
m_noStatusAttr->DecRef();
m_editSettingsAttr->DecRef();
m_openTableAttr->DecRef();
}
bool LIB_TABLE_GRID_DATA_MODEL::badCoords( int aRow, int aCol )
{
if( aRow < 0 || aRow >= (int) size() )
return true;
if( aCol < 0 || aCol >= GetNumberCols() )
return true;
return false;
}
wxString LIB_TABLE_GRID_DATA_MODEL::GetValue( int aRow, int aCol )
{
wxCHECK( aRow >= 0, wxEmptyString );
size_t row = static_cast<size_t>( aRow );
if( badCoords( aRow, aCol ) )
return wxEmptyString;
if( row < size() )
const LIBRARY_TABLE_ROW& r = at( aRow );
switch( aCol )
{
const LIBRARY_TABLE_ROW& r = at( row );
case COL_NICKNAME: return UnescapeString( r.Nickname() );
case COL_URI: return r.URI();
case COL_TYPE: return r.Type();
case COL_OPTIONS: return r.Options();
case COL_DESCR: return r.Description();
case COL_ENABLED: return r.Disabled() ? wxT( "0" ) : wxT( "1" );
case COL_VISIBLE: return r.Hidden() ? wxT( "0" ) : wxT( "1" );
switch( aCol )
{
case COL_NICKNAME: return UnescapeString( r.Nickname() );
case COL_URI: return r.URI();
case COL_TYPE: return r.Type();
case COL_OPTIONS: return r.Options();
case COL_DESCR: return r.Description();
case COL_ENABLED: return r.Disabled() ? wxT( "0" ) : wxT( "1" );
case COL_VISIBLE: return r.Hidden() ? wxT( "0" ) : wxT( "1" );
case COL_STATUS:
if( !r.IsOk() )
return r.ErrorDescription();
case COL_STATUS:
if( !r.IsOk() )
return r.ErrorDescription();
if( std::optional<LIBRARY_ERROR> error = m_adapter->LibraryError( r.Nickname() ) )
return error->message;
if( std::optional<LIBRARY_ERROR> error = m_adapter->LibraryError( r.Nickname() ) )
return error->message;
if( m_adapter->SupportsConfigurationDialog( r.Nickname() ) )
return _( "Edit settings" );
else if( r.Type() == LIBRARY_TABLE_ROW::TABLE_TYPE_NAME )
return _( "Open library table" );
if( m_adapter->SupportsConfigurationDialog( r.Nickname() ) )
return _( "Edit settings" );
else if( r.Type() == LIBRARY_TABLE_ROW::TABLE_TYPE_NAME )
return _( "Open library table" );
return wxEmptyString;
return wxEmptyString;
default:
return wxEmptyString;
}
default:
return wxEmptyString;
}
return wxEmptyString;
}
wxGridCellAttr* LIB_TABLE_GRID_DATA_MODEL::GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind )
{
if( badCoords( aRow, aCol ) )
return enhanceAttr( nullptr, aRow, aCol, aKind );
LIBRARY_TABLE_ROW& tableRow = at( aRow );
switch( aCol )
@@ -162,7 +177,8 @@ wxGridCellAttr* LIB_TABLE_GRID_DATA_MODEL::GetAttr( int aRow, int aCol, wxGridCe
return enhanceAttr( m_openTableAttr, aRow, aCol, aKind );
}
return enhanceAttr( nullptr, aRow, aCol, aKind );
m_noStatusAttr->IncRef();
return enhanceAttr( m_noStatusAttr, aRow, aCol, aKind );
case COL_NICKNAME:
case COL_OPTIONS:
@@ -175,32 +191,30 @@ wxGridCellAttr* LIB_TABLE_GRID_DATA_MODEL::GetAttr( int aRow, int aCol, wxGridCe
bool LIB_TABLE_GRID_DATA_MODEL::CanGetValueAs( int aRow, int aCol, const wxString& aTypeName )
{
if( aRow < static_cast<int>( size() ) )
if( badCoords( aRow, aCol ) )
return false;
switch( aCol )
{
switch( aCol )
{
case COL_ENABLED:
case COL_VISIBLE:
return aTypeName == wxGRID_VALUE_BOOL;
case COL_ENABLED:
case COL_VISIBLE:
return aTypeName == wxGRID_VALUE_BOOL;
default:
return aTypeName == wxGRID_VALUE_STRING;
}
default:
return aTypeName == wxGRID_VALUE_STRING;
}
return false;
}
bool LIB_TABLE_GRID_DATA_MODEL::GetValueAsBool( int aRow, int aCol )
{
wxCHECK( aRow >= 0, false );
size_t row = static_cast<size_t>( aRow );
if( badCoords( aRow, aCol ) )
return false;
if( row < size() && aCol == COL_ENABLED )
return !at( row ).Disabled();
else if( row < size() && aCol == COL_VISIBLE )
return !at( row ).Hidden();
if( aCol == COL_ENABLED )
return !at( aRow ).Disabled();
else if( aCol == COL_VISIBLE )
return !at( aRow ).Hidden();
else
return false;
}
@@ -208,36 +222,50 @@ bool LIB_TABLE_GRID_DATA_MODEL::GetValueAsBool( int aRow, int aCol )
void LIB_TABLE_GRID_DATA_MODEL::SetValue( int aRow, int aCol, const wxString& aValue )
{
wxCHECK( aRow >= 0, /* void */ );
size_t row = static_cast<size_t>( aRow );
if( badCoords( aRow, aCol ) )
return;
if( row < size() )
LIBRARY_TABLE_ROW& r = at( aRow );
switch( aCol )
{
LIBRARY_TABLE_ROW& r = at( row );
case COL_NICKNAME: r.SetNickname( EscapeString( aValue, CTX_LIBID ) ); break;
case COL_URI: r.SetURI( aValue ); break;
case COL_TYPE: r.SetType( aValue ); break;
case COL_OPTIONS: r.SetOptions( aValue ); break;
case COL_DESCR: r.SetDescription( aValue ); break;
case COL_ENABLED: r.SetDisabled( aValue == wxT( "0" ) ); break;
case COL_VISIBLE: r.SetHidden( aValue == wxT( "0" ) ); break;
case COL_STATUS: break;
}
switch( aCol )
{
case COL_NICKNAME: r.SetNickname( EscapeString( aValue, CTX_LIBID ) ); break;
case COL_URI: r.SetURI( aValue ); break;
case COL_TYPE: r.SetType( aValue ); break;
case COL_OPTIONS: r.SetOptions( aValue ); break;
case COL_DESCR: r.SetDescription( aValue ); break;
case COL_ENABLED: r.SetDisabled( aValue == wxT( "0" ) ); break;
case COL_VISIBLE: r.SetHidden( aValue == wxT( "0" ) ); break;
case COL_STATUS: break;
}
if( aCol == COL_URI || aCol == COL_TYPE || aCol == COL_OPTIONS )
{
GetView()->CallAfter(
[this, aRow, aCol]()
{
if( badCoords( aRow, aCol ) )
return;
LIBRARY_TABLE_ROW& r = at( aRow );
m_adapter->CheckTableRow( r );
GetView()->RefreshBlock( aRow, COL_STATUS, aRow, COL_STATUS );
} );
}
}
void LIB_TABLE_GRID_DATA_MODEL::SetValueAsBool( int aRow, int aCol, bool aValue )
{
wxCHECK( aRow >= 0, /* void */ );
size_t row = static_cast<size_t>( aRow );
if( badCoords( aRow, aCol ) )
return;
if( row < size() && aCol == COL_ENABLED )
at( row ).SetDisabled( !aValue );
else if( row < size() && aCol == COL_VISIBLE )
at( row ).SetHidden( !aValue );
if( aCol == COL_ENABLED )
at( aRow ).SetDisabled( !aValue );
else if( aCol == COL_VISIBLE )
at( aRow ).SetHidden( !aValue );
}
@@ -357,7 +385,8 @@ LIBRARY_TABLE_ROWS_ITER LIB_TABLE_GRID_DATA_MODEL::begin()
}
LIBRARY_TABLE_ROWS_ITER LIB_TABLE_GRID_DATA_MODEL::insert( LIBRARY_TABLE_ROWS_ITER aIterator, const LIBRARY_TABLE_ROW& aRow )
LIBRARY_TABLE_ROWS_ITER LIB_TABLE_GRID_DATA_MODEL::insert( LIBRARY_TABLE_ROWS_ITER aIterator,
const LIBRARY_TABLE_ROW& aRow )
{
return m_table.Rows().insert( aIterator, aRow );
}
@@ -369,7 +398,8 @@ void LIB_TABLE_GRID_DATA_MODEL::push_back( const LIBRARY_TABLE_ROW& aRow )
}
LIBRARY_TABLE_ROWS_ITER LIB_TABLE_GRID_DATA_MODEL::erase( LIBRARY_TABLE_ROWS_ITER aFirst, LIBRARY_TABLE_ROWS_ITER aLast )
LIBRARY_TABLE_ROWS_ITER LIB_TABLE_GRID_DATA_MODEL::erase( LIBRARY_TABLE_ROWS_ITER aFirst,
LIBRARY_TABLE_ROWS_ITER aLast )
{
return m_table.Rows().erase( aFirst, aLast );
}
+65 -35
View File
@@ -780,6 +780,36 @@ void LIBRARY_MANAGER_ADAPTER::GlobalTablesChanged( std::initializer_list<LIBRARY
globalLibs().clear();
}
}
void LIBRARY_MANAGER_ADAPTER::CheckTableRow( LIBRARY_TABLE_ROW& aRow )
{
abortLoad();
LIBRARY_RESULT<IO_BASE*> plugin = createPlugin( &aRow );
if( plugin.has_value() )
{
LIB_DATA lib;
lib.row = &aRow;
lib.plugin.reset( *plugin );
std::optional<LIB_STATUS> status = LoadOne( &lib );
if( status.has_value() )
{
aRow.SetOk( status.value().load_status == LOAD_STATUS::LOADED );
if( status.value().error.has_value() )
aRow.SetErrorDescription( status.value().error.value().message );
}
}
else
{
aRow.SetOk( false );
aRow.SetErrorDescription( plugin.error().message );
}
}
@@ -1035,48 +1065,48 @@ std::optional<LIB_DATA*> LIBRARY_MANAGER_ADAPTER::fetchIfLoaded(
LIBRARY_RESULT<LIB_DATA*> LIBRARY_MANAGER_ADAPTER::loadIfNeeded( const wxString& aNickname )
{
auto tryLoadFromScope =
[&]( LIBRARY_TABLE_SCOPE aScope, std::map<wxString, LIB_DATA>& aTarget,
std::mutex& aMutex ) -> LIBRARY_RESULT<LIB_DATA*>
{
bool present = false;
[&]( LIBRARY_TABLE_SCOPE aScope, std::map<wxString, LIB_DATA>& aTarget,
std::mutex& aMutex ) -> LIBRARY_RESULT<LIB_DATA*>
{
std::lock_guard lock( aMutex );
present = aTarget.contains( aNickname ) && aTarget.at( aNickname ).plugin;
}
bool present = false;
if( !present )
{
if( auto result = m_manager.GetRow( Type(), aNickname, aScope ) )
{
const LIBRARY_TABLE_ROW* row = *result;
wxLogTrace( traceLibraries, "Library %s (%s) not yet loaded, will attempt...",
aNickname, magic_enum::enum_name( aScope ) );
if( LIBRARY_RESULT<IO_BASE*> plugin = createPlugin( row ); plugin.has_value() )
{
std::lock_guard lock( aMutex );
aTarget[ row->Nickname() ].status.load_status = LOAD_STATUS::LOADING;
aTarget[ row->Nickname() ].row = row;
aTarget[ row->Nickname() ].plugin.reset( *plugin );
return &aTarget.at( aNickname );
}
else
{
return tl::unexpected( plugin.error() );
}
std::lock_guard lock( aMutex );
present = aTarget.contains( aNickname ) && aTarget.at( aNickname ).plugin;
}
return nullptr;
}
if( !present )
{
if( auto result = m_manager.GetRow( Type(), aNickname, aScope ) )
{
const LIBRARY_TABLE_ROW* row = *result;
wxLogTrace( traceLibraries, "Library %s (%s) not yet loaded, will attempt...",
aNickname, magic_enum::enum_name( aScope ) );
return &aTarget.at( aNickname );
};
if( LIBRARY_RESULT<IO_BASE*> plugin = createPlugin( row ); plugin.has_value() )
{
std::lock_guard lock( aMutex );
LIBRARY_RESULT<LIB_DATA*> result =
tryLoadFromScope( LIBRARY_TABLE_SCOPE::PROJECT, m_libraries, m_libraries_mutex );
aTarget[ row->Nickname() ].status.load_status = LOAD_STATUS::LOADING;
aTarget[ row->Nickname() ].row = row;
aTarget[ row->Nickname() ].plugin.reset( *plugin );
return &aTarget.at( aNickname );
}
else
{
return tl::unexpected( plugin.error() );
}
}
return nullptr;
}
return &aTarget.at( aNickname );
};
LIBRARY_RESULT<LIB_DATA*> result = tryLoadFromScope( LIBRARY_TABLE_SCOPE::PROJECT, m_libraries,
m_libraries_mutex );
if( !result.has_value() || *result )
return result;
@@ -19,7 +19,7 @@ PANEL_SYM_LIB_TABLE_BASE::PANEL_SYM_LIB_TABLE_BASE( wxWindow* parent, wxWindowID
m_notebook = new wxAuiNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_NB_CLOSE_ON_ALL_TABS|wxAUI_NB_DEFAULT_STYLE );
bMainSizer->Add( m_notebook, 1, wxEXPAND | wxALL, 5 );
bMainSizer->Add( m_notebook, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
wxBoxSizer* bButtonsSizer;
bButtonsSizer = new wxBoxSizer( wxHORIZONTAL );
@@ -65,7 +65,7 @@ PANEL_SYM_LIB_TABLE_BASE::PANEL_SYM_LIB_TABLE_BASE( wxWindow* parent, wxWindowID
bButtonsSizer->Add( m_convertLegacy, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
bMainSizer->Add( bButtonsSizer, 0, wxEXPAND|wxALL, 3 );
bMainSizer->Add( bButtonsSizer, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 3 );
bMainSizer->Add( 0, 5, 0, wxEXPAND, 5 );
@@ -62,7 +62,7 @@
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND | wxALL</property>
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
<property name="proportion">1</property>
<object class="wxAuiNotebook" expanded="true">
<property name="BottomDockable">1</property>
@@ -124,7 +124,7 @@
</object>
<object class="sizeritem" expanded="true">
<property name="border">3</property>
<property name="flag">wxEXPAND|wxALL</property>
<property name="flag">wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
+33 -24
View File
@@ -64,34 +64,43 @@ SCH_IO* SYMBOL_LIBRARY_ADAPTER::schplugin( const LIB_DATA* aRow )
}
std::optional<LIB_STATUS> SYMBOL_LIBRARY_ADAPTER::LoadOne( const wxString& aNickname )
/// Loads or reloads the given library, if it exists
std::optional<LIB_STATUS> SYMBOL_LIBRARY_ADAPTER::LoadOne( LIB_DATA* aLib )
{
if( LIBRARY_RESULT<LIB_DATA*> result = loadIfNeeded( aNickname ); result.has_value() )
std::lock_guard lock ( aLib->mutex );
aLib->status.load_status = LOAD_STATUS::LOADING;
std::map<std::string, UTF8> options = aLib->row->GetOptionsMap();
try
{
LIB_DATA* lib = *result;
std::lock_guard lock ( lib->mutex );
lib->status.load_status = LOAD_STATUS::LOADING;
std::map<std::string, UTF8> options = lib->row->GetOptionsMap();
try
{
wxArrayString dummyList;
schplugin( lib )->EnumerateSymbolLib( dummyList, getUri( lib->row ), &options );
wxLogTrace( traceLibraries, "Sym: %s: library enumerated %zu items", aNickname, dummyList.size() );
lib->status.load_status = LOAD_STATUS::LOADED;
}
catch( IO_ERROR& e )
{
lib->status.load_status = LOAD_STATUS::LOAD_ERROR;
lib->status.error = LIBRARY_ERROR( { e.What() } );
wxLogTrace( traceLibraries, "Sym: %s: plugin threw exception: %s", aNickname, e.What() );
}
return lib->status;
wxArrayString dummyList;
schplugin( aLib )->EnumerateSymbolLib( dummyList, getUri( aLib->row ), &options );
wxLogTrace( traceLibraries, "Sym: %s: library enumerated %zu items", aLib->row->Nickname(), dummyList.size() );
aLib->status.load_status = LOAD_STATUS::LOADED;
}
catch( IO_ERROR& e )
{
aLib->status.load_status = LOAD_STATUS::LOAD_ERROR;
aLib->status.error = LIBRARY_ERROR( { e.What() } );
wxLogTrace( traceLibraries, "Sym: %s: plugin threw exception: %s", aLib->row->Nickname(), e.What() );
}
return std::nullopt;
return aLib->status;
}
std::optional<LIB_STATUS> SYMBOL_LIBRARY_ADAPTER::LoadOne( const wxString& nickname )
{
LIBRARY_RESULT<LIB_DATA*> result = loadIfNeeded( nickname );
if( result.has_value() )
return LoadOne( *result );
return LIB_STATUS{
.load_status = LOAD_STATUS::LOAD_ERROR,
.error = LIBRARY_ERROR( { result.error() } )
};
}
@@ -61,6 +61,9 @@ public:
void AsyncLoad() override;
/// Loads or reloads the given library, if it exists
std::optional<LIB_STATUS> LoadOne( LIB_DATA* aLib ) override;
/// Loads or reloads the given library, if it exists
std::optional<LIB_STATUS> LoadOne( const wxString& aNickname );
+3
View File
@@ -97,6 +97,8 @@ public:
LIBRARY_MANAGER_ADAPTER* Adapter() const { return m_adapter; }
protected:
bool badCoords( int aRow, int aCol );
virtual wxString getFileTypes( WX_GRID* aGrid, int aRow ) = 0;
virtual LIBRARY_TABLE_ROW& at( size_t aIndex );
@@ -121,6 +123,7 @@ protected:
wxGridCellAttr* m_typesEditor;
wxGridCellAttr* m_boolAttr;
wxGridCellAttr* m_warningAttr;
wxGridCellAttr* m_noStatusAttr;
wxGridCellAttr* m_editSettingsAttr;
wxGridCellAttr* m_openTableAttr;
+4
View File
@@ -128,9 +128,13 @@ public:
/// Notify the adapter that the global library tables have changed
void GlobalTablesChanged( std::initializer_list<LIBRARY_TABLE_TYPE> aChangedTables = {} );
void CheckTableRow( LIBRARY_TABLE_ROW& aRow );
/// Loads all available libraries for this adapter type in the background
virtual void AsyncLoad() = 0;
virtual std::optional<LIB_STATUS> LoadOne( LIB_DATA* aLib ) = 0;
/// Returns async load progress between 0.0 and 1.0, or nullopt if load is not in progress
std::optional<float> AsyncLoadProgress() const;
+2 -2
View File
@@ -19,7 +19,7 @@ PANEL_FP_LIB_TABLE_BASE::PANEL_FP_LIB_TABLE_BASE( wxWindow* parent, wxWindowID i
m_notebook = new wxAuiNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_NB_CLOSE_ON_ALL_TABS|wxAUI_NB_DEFAULT_STYLE );
bMainSizer->Add( m_notebook, 1, wxEXPAND | wxALL, 5 );
bMainSizer->Add( m_notebook, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
wxBoxSizer* bButtonsSizer;
bButtonsSizer = new wxBoxSizer( wxHORIZONTAL );
@@ -65,7 +65,7 @@ PANEL_FP_LIB_TABLE_BASE::PANEL_FP_LIB_TABLE_BASE( wxWindow* parent, wxWindowID i
bButtonsSizer->Add( m_migrate_libs_button, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
bMainSizer->Add( bButtonsSizer, 0, wxEXPAND|wxALL, 8 );
bMainSizer->Add( bButtonsSizer, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 8 );
wxStaticText* stPathsLabel;
stPathsLabel = new wxStaticText( this, wxID_ANY, _("Available path substitutions:"), wxDefaultPosition, wxDefaultSize, 0 );
+2 -2
View File
@@ -62,7 +62,7 @@
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND | wxALL</property>
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
<property name="proportion">1</property>
<object class="wxAuiNotebook" expanded="true">
<property name="BottomDockable">1</property>
@@ -124,7 +124,7 @@
</object>
<object class="sizeritem" expanded="true">
<property name="border">8</property>
<property name="flag">wxEXPAND|wxALL</property>
<property name="flag">wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
+33 -24
View File
@@ -180,34 +180,43 @@ void FOOTPRINT_LIBRARY_ADAPTER::AsyncLoad()
}
std::optional<LIB_STATUS> FOOTPRINT_LIBRARY_ADAPTER::LoadOne( const wxString& aNickname )
/// Loads or reloads the given library, if it exists
std::optional<LIB_STATUS> FOOTPRINT_LIBRARY_ADAPTER::LoadOne( LIB_DATA* aLib )
{
if( LIBRARY_RESULT<LIB_DATA*> result = loadIfNeeded( aNickname ); result.has_value() )
std::lock_guard lock ( aLib->mutex );
aLib->status.load_status = LOAD_STATUS::LOADING;
std::map<std::string, UTF8> options = aLib->row->GetOptionsMap();
try
{
LIB_DATA* lib = *result;
std::lock_guard lock ( lib->mutex );
lib->status.load_status = LOAD_STATUS::LOADING;
std::map<std::string, UTF8> options = lib->row->GetOptionsMap();
try
{
wxArrayString dummyList;
pcbplugin( lib )->FootprintEnumerate( dummyList, getUri( lib->row ), true, &options );
wxLogTrace( traceLibraries, "Sym: %s: library enumerated %zu items", aNickname, dummyList.size() );
lib->status.load_status = LOAD_STATUS::LOADED;
}
catch( IO_ERROR& e )
{
lib->status.load_status = LOAD_STATUS::LOAD_ERROR;
lib->status.error = LIBRARY_ERROR( { e.What() } );
wxLogTrace( traceLibraries, "Sym: %s: plugin threw exception: %s", aNickname, e.What() );
}
return lib->status;
wxArrayString dummyList;
pcbplugin( aLib )->FootprintEnumerate( dummyList, getUri( aLib->row ), false, &options );
wxLogTrace( traceLibraries, "Sym: %s: library enumerated %zu items", aLib->row->Nickname(), dummyList.size() );
aLib->status.load_status = LOAD_STATUS::LOADED;
}
catch( IO_ERROR& e )
{
aLib->status.load_status = LOAD_STATUS::LOAD_ERROR;
aLib->status.error = LIBRARY_ERROR( { e.What() } );
wxLogTrace( traceLibraries, "Sym: %s: plugin threw exception: %s", aLib->row->Nickname(), e.What() );
}
return std::nullopt;
return aLib->status;
}
std::optional<LIB_STATUS> FOOTPRINT_LIBRARY_ADAPTER::LoadOne( const wxString& nickname )
{
LIBRARY_RESULT<LIB_DATA*> result = loadIfNeeded( nickname );
if( result.has_value() )
return LoadOne( *result );
return LIB_STATUS{
.load_status = LOAD_STATUS::LOAD_ERROR,
.error = LIBRARY_ERROR( { result.error() } )
};
}
+3
View File
@@ -48,6 +48,9 @@ public:
void AsyncLoad() override;
/// Loads or reloads the given library, if it exists
std::optional<LIB_STATUS> LoadOne( LIB_DATA* aLib ) override;
/// Loads or reloads the given library, if it exists
std::optional<LIB_STATUS> LoadOne( const wxString& aNickname );