Symbol Fields Table: make non-modal

Fixes: https://gitlab.com/kicad/code/kicad/-/issues/2141
This commit is contained in:
Mike Williams 2023-08-14 10:41:28 -04:00
parent 1c52a60270
commit dc103b88d1
7 changed files with 230 additions and 24 deletions

View File

@ -54,6 +54,8 @@
#include <fields_data_model.h>
#include "eda_list_dialog.h"
wxDEFINE_EVENT( EDA_EVT_CLOSE_DIALOG_SYMBOL_FIELDS_TABLE, wxCommandEvent );
#ifdef __WXMAC__
#define COLUMN_MARGIN 5
#else
@ -298,6 +300,9 @@ DIALOG_SYMBOL_FIELDS_TABLE::DIALOG_SYMBOL_FIELDS_TABLE( SCH_EDIT_FRAME* parent )
m_cbBomFmtPresets->Bind( wxEVT_CHOICE, &DIALOG_SYMBOL_FIELDS_TABLE::onBomFmtPresetChanged, this );
m_fieldsCtrl->Bind( wxEVT_DATAVIEW_ITEM_VALUE_CHANGED,
&DIALOG_SYMBOL_FIELDS_TABLE::OnColLabelChange, this );
// Start listening for schematic changes
m_parent->Schematic().AddListener( this );
}
@ -415,26 +420,6 @@ void DIALOG_SYMBOL_FIELDS_TABLE::SetupAllColumnProperties()
DIALOG_SYMBOL_FIELDS_TABLE::~DIALOG_SYMBOL_FIELDS_TABLE()
{
savePresetsToSchematic();
EESCHEMA_SETTINGS* cfg = m_parent->eeconfig();
cfg->m_FieldEditorPanel.width = GetSize().x;
cfg->m_FieldEditorPanel.height = GetSize().y;
cfg->m_FieldEditorPanel.page = m_nbPages->GetSelection();
cfg->m_FieldEditorPanel.export_filename = m_outputFileName->GetValue();
cfg->m_FieldEditorPanel.selection_mode = m_radioSelect->GetSelection();
cfg->m_FieldEditorPanel.scope = m_radioScope->GetSelection();
for( int i = 0; i < m_grid->GetNumberCols(); i++ )
{
if( m_grid->IsColShown( i ) )
{
std::string fieldName( m_dataModel->GetColFieldName( i ).ToUTF8() );
cfg->m_FieldEditorPanel.field_widths[fieldName] = m_grid->GetColSize( i );
}
}
// Disconnect Events
m_grid->Disconnect( wxEVT_GRID_COL_SORT,
wxGridEventHandler( DIALOG_SYMBOL_FIELDS_TABLE::OnColSort ), nullptr,
@ -1250,7 +1235,37 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnClose( wxCloseEvent& event )
}
}
event.Skip();
// Stop listening to schematic events
m_parent->Schematic().RemoveListener( this );
// Save all our settings since we're really closing
savePresetsToSchematic();
EESCHEMA_SETTINGS* cfg = m_parent->eeconfig();
cfg->m_FieldEditorPanel.width = GetSize().x;
cfg->m_FieldEditorPanel.height = GetSize().y;
cfg->m_FieldEditorPanel.page = m_nbPages->GetSelection();
cfg->m_FieldEditorPanel.export_filename = m_outputFileName->GetValue();
cfg->m_FieldEditorPanel.selection_mode = m_radioSelect->GetSelection();
cfg->m_FieldEditorPanel.scope = m_radioScope->GetSelection();
for( int i = 0; i < m_grid->GetNumberCols(); i++ )
{
if( m_grid->IsColShown( i ) )
{
std::string fieldName( m_dataModel->GetColFieldName( i ).ToUTF8() );
cfg->m_FieldEditorPanel.field_widths[fieldName] = m_grid->GetColSize( i );
}
}
m_parent->FocusOnItem( nullptr );
wxCommandEvent* evt = new wxCommandEvent( EDA_EVT_CLOSE_DIALOG_SYMBOL_FIELDS_TABLE, wxID_ANY );
wxWindow* parent = GetParent();
if( parent )
wxQueueEvent( parent, evt );
}
@ -2004,3 +2019,79 @@ void DIALOG_SYMBOL_FIELDS_TABLE::savePresetsToSchematic()
m_schSettings.m_BomFmtPresets = fmts;
m_schSettings.m_BomFmtSettings = GetCurrentBomFmtSettings();
}
void DIALOG_SYMBOL_FIELDS_TABLE::OnSchItemsAdded( SCHEMATIC& aSch,
std::vector<SCH_ITEM*>& aSchItem )
{
for( SCH_ITEM* item : aSchItem )
{
if( item->Type() == SCH_SYMBOL_T )
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
// Add all fields again in case this symbol has a new one
for( SCH_FIELD& field : symbol->GetFields() )
AddField( field.GetCanonicalName(), field.GetName(), true, false, true );
m_dataModel->AddReferences( *symbol, getSymbolReferences( symbol ) );
}
}
m_dataModel->RebuildRows();
}
void DIALOG_SYMBOL_FIELDS_TABLE::OnSchItemsRemoved( SCHEMATIC& aSch,
std::vector<SCH_ITEM*>& aSchItem )
{
for( SCH_ITEM* item : aSchItem )
if( item->Type() == SCH_SYMBOL_T )
m_dataModel->RemoveSymbol( *static_cast<SCH_SYMBOL*>( item ) );
m_dataModel->RebuildRows();
}
void DIALOG_SYMBOL_FIELDS_TABLE::OnSchItemsChanged( SCHEMATIC& aSch,
std::vector<SCH_ITEM*>& aSchItem )
{
for( SCH_ITEM* item : aSchItem )
{
if( item->Type() == SCH_SYMBOL_T )
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
// Add all fields again in case this symbol has a new one
for( SCH_FIELD& field : symbol->GetFields() )
AddField( field.GetCanonicalName(), field.GetName(), true, false, true );
m_dataModel->UpdateReferences( *symbol, getSymbolReferences( symbol ) );
}
}
m_dataModel->RebuildRows();
}
SCH_REFERENCE_LIST DIALOG_SYMBOL_FIELDS_TABLE::getSymbolReferences( SCH_SYMBOL* aSymbol )
{
SCH_SHEET_LIST sheets = m_parent->Schematic().GetSheets();
SCH_REFERENCE_LIST allRefs;
SCH_REFERENCE_LIST symbolRefs;
sheets.GetSymbols( allRefs );
for( size_t i = 0; i < allRefs.GetCount(); i++ )
{
SCH_REFERENCE& ref = allRefs[i];
if( ref.GetSymbol() == aSymbol )
{
ref.Split(); // Figures out if we are annotated or not
symbolRefs.AddItem( ref );
}
}
return symbolRefs;
}

View File

@ -28,7 +28,9 @@
#include <dialog_symbol_fields_table_base.h>
#include <sch_reference_list.h>
#include <schematic.h>
wxDECLARE_EVENT( EDA_EVT_CLOSE_DIALOG_SYMBOL_FIELDS_TABLE, wxCommandEvent );
class SCHEMATIC_SETTINGS;
struct BOM_PRESET;
@ -37,7 +39,7 @@ class SCH_EDIT_FRAME;
class FIELDS_EDITOR_GRID_DATA_MODEL;
class DIALOG_SYMBOL_FIELDS_TABLE : public DIALOG_SYMBOL_FIELDS_TABLE_BASE
class DIALOG_SYMBOL_FIELDS_TABLE : public DIALOG_SYMBOL_FIELDS_TABLE_BASE, public SCHEMATIC_LISTENER
{
public:
DIALOG_SYMBOL_FIELDS_TABLE( SCH_EDIT_FRAME* parent );
@ -103,7 +105,13 @@ private:
void ApplyBomFmtPreset( const wxString& aPresetName );
void ApplyBomFmtPreset( const BOM_FMT_PRESET& aPreset );
void OnSchItemsAdded( SCHEMATIC& aSch, std::vector<SCH_ITEM*>& aSchItem ) override;
void OnSchItemsRemoved( SCHEMATIC& aSch, std::vector<SCH_ITEM*>& aSchItem ) override;
void OnSchItemsChanged( SCHEMATIC& aSch, std::vector<SCH_ITEM*>& aSchItem ) override;
private:
SCH_REFERENCE_LIST getSymbolReferences( SCH_SYMBOL* aSymbol );
void syncBomPresetSelection();
void rebuildBomPresetsWidget();
void updateBomPresetSelection( const wxString& aName );

View File

@ -880,3 +880,51 @@ wxString FIELDS_EDITOR_GRID_DATA_MODEL::Export( const BOM_FMT_PRESET& settings )
return out;
}
void FIELDS_EDITOR_GRID_DATA_MODEL::AddReferences( const SCH_SYMBOL& aSymbol,
const SCH_REFERENCE_LIST& aRefs )
{
// Update the fields of every reference
for( const SCH_FIELD& field : aSymbol.GetFields() )
m_dataStore[aSymbol.m_Uuid][field.GetCanonicalName()] = field.GetText();
for( const SCH_REFERENCE& ref : aRefs )
if( !m_symbolsList.Contains( ref ) )
m_symbolsList.AddItem( ref );
}
void FIELDS_EDITOR_GRID_DATA_MODEL::RemoveSymbol( const SCH_SYMBOL& aSymbol )
{
// The schematic event listener passes us the item after it has been removed,
// so we can't just work with a SCH_REFERENCE_LIST like the other handlers as the
// references are already gone. Instead we need to prune our list.
m_dataStore[aSymbol.m_Uuid].clear();
// Remove all refs that match this symbol using remove_if
m_symbolsList.erase( std::remove_if( m_symbolsList.begin(), m_symbolsList.end(),
[aSymbol]( const SCH_REFERENCE& ref ) -> bool
{
return ref.GetSymbol()->m_Uuid == aSymbol.m_Uuid;
} ),
m_symbolsList.end() );
}
void FIELDS_EDITOR_GRID_DATA_MODEL::UpdateReferences( const SCH_SYMBOL& aSymbol,
const SCH_REFERENCE_LIST& aRefs )
{
wxCHECK_RET( m_dataStore.count( aSymbol.m_Uuid ) == 1,
"Trying to update a symbol that doesn't exist" );
// Update the fields of every reference. Do this by iterating through the data model
// colums; we must have all fields in the symbol added to the data model at this point,
// and some of the data model columns may be variables that are not present in the symbol
for( const DATA_MODEL_COL& col : m_cols )
updateDataStoreSymbolField( aSymbol, col.m_fieldName );
for( const SCH_REFERENCE& ref : aRefs )
if( !m_symbolsList.Contains( ref ) )
m_symbolsList.AddItem( ref );
}

View File

@ -210,6 +210,11 @@ public:
BOM_PRESET GetBomSettings();
wxString Export( const BOM_FMT_PRESET& settings );
void AddReferences( const SCH_SYMBOL& aSymbol, const SCH_REFERENCE_LIST& aRefs );
void RemoveSymbol( const SCH_SYMBOL& aSymbol );
void UpdateReferences( const SCH_SYMBOL& aSymbol, const SCH_REFERENCE_LIST& aRefs );
private:
static bool cmp( const DATA_MODEL_ROW& lhGroup, const DATA_MODEL_ROW& rhGroup,
FIELDS_EDITOR_GRID_DATA_MODEL* dataModel, int sortCol, bool ascending );
@ -231,6 +236,8 @@ private:
void Sort();
SCH_REFERENCE_LIST getSymbolReferences( SCH_SYMBOL* aSymbol );
void storeReferenceFields( SCH_REFERENCE& aRef );
void updateDataStoreSymbolField( const SCH_SYMBOL& aSymbol, const wxString& aFieldName );

View File

@ -30,6 +30,7 @@
#include <dialogs/dialog_erc.h>
#include <dialogs/dialog_schematic_find.h>
#include <dialogs/dialog_book_reporter.h>
#include <dialogs/dialog_symbol_fields_table.h>
#include <eeschema_id.h>
#include <executable_names.h>
#include <gestfich.h>
@ -125,6 +126,7 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE, SCH_EDIT_FRAME_NAME ),
m_ercDialog( nullptr ),
m_diffSymbolDialog( nullptr ),
m_symbolFieldsTableDialog( nullptr ),
m_netNavigator( nullptr ),
m_highlightedConnChanged( false )
{
@ -378,6 +380,8 @@ 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 );
}
@ -918,6 +922,12 @@ bool SCH_EDIT_FRAME::canCloseWindow( wxCloseEvent& aEvent )
if( !Kiway().PlayerClose( FRAME_SIMULATOR, false ) ) // Can close the simulator?
return false;
if( m_symbolFieldsTableDialog
&& !m_symbolFieldsTableDialog->Close( false ) ) // Can close the symbol fields table?
{
return false;
}
// We may have gotten multiple events; don't clean up twice
if( !Schematic().IsValid() )
return false;
@ -954,6 +964,8 @@ void SCH_EDIT_FRAME::doCloseWindow()
// Close modeless dialogs. They're trouble when they get destroyed after the frame.
Unbind( EDA_EVT_CLOSE_DIALOG_BOOK_REPORTER, &SCH_EDIT_FRAME::onCloseSymbolDiffDialog, this );
Unbind( EDA_EVT_CLOSE_ERC_DIALOG, &SCH_EDIT_FRAME::onCloseErcDialog, this );
Unbind( EDA_EVT_CLOSE_DIALOG_SYMBOL_FIELDS_TABLE,
&SCH_EDIT_FRAME::onCloseSymbolFieldsTableDialog, this );
m_netNavigator->Unbind( wxEVT_TREE_SEL_CHANGING, &SCH_EDIT_FRAME::onNetNavigatorSelChanging,
this );
m_netNavigator->Unbind( wxEVT_TREE_SEL_CHANGED, &SCH_EDIT_FRAME::onNetNavigatorSelection,
@ -981,6 +993,12 @@ void SCH_EDIT_FRAME::doCloseWindow()
m_ercDialog = nullptr;
}
if( m_symbolFieldsTableDialog )
{
m_symbolFieldsTableDialog->Destroy();
m_symbolFieldsTableDialog = nullptr;
}
// Shutdown all running tools
if( m_toolManager )
{
@ -2215,6 +2233,25 @@ void SCH_EDIT_FRAME::onCloseErcDialog( wxCommandEvent& aEvent )
}
DIALOG_SYMBOL_FIELDS_TABLE* SCH_EDIT_FRAME::GetSymbolFieldsTableDialog()
{
if( !m_symbolFieldsTableDialog )
m_symbolFieldsTableDialog = new DIALOG_SYMBOL_FIELDS_TABLE( this );
return m_symbolFieldsTableDialog;
}
void SCH_EDIT_FRAME::onCloseSymbolFieldsTableDialog( wxCommandEvent& aEvent )
{
if( m_symbolFieldsTableDialog )
{
m_symbolFieldsTableDialog->Destroy();
m_symbolFieldsTableDialog = nullptr;
}
}
void SCH_EDIT_FRAME::AddSchematicChangeListener( wxEvtHandler* aListener )
{
auto it = std::find( m_schematicChangeListeners.begin(), m_schematicChangeListeners.end(),

View File

@ -58,6 +58,7 @@ class SCHEMATIC;
class SCH_COMMIT;
class DIALOG_BOOK_REPORTER;
class DIALOG_ERC;
class DIALOG_SYMBOL_FIELDS_TABLE;
class DIALOG_SCH_FIND;
class RESCUER;
class HIERARCHY_PANE;
@ -824,6 +825,8 @@ public:
DIALOG_ERC* GetErcDialog();
DIALOG_SYMBOL_FIELDS_TABLE* GetSymbolFieldsTableDialog();
wxTreeCtrl* GetNetNavigator() { return m_netNavigator; }
const SCH_ITEM* GetSelectedNetNavigatorItem() const;
@ -896,6 +899,8 @@ protected:
void onCloseErcDialog( wxCommandEvent& aEvent );
void onCloseSymbolFieldsTableDialog( wxCommandEvent& aEvent );
void unitsChangeRefresh() override;
private:
@ -998,6 +1003,8 @@ private:
DIALOG_ERC* m_ercDialog;
DIALOG_BOOK_REPORTER* m_diffSymbolDialog;
HIERARCHY_PANE* m_hierarchy;
DIALOG_SYMBOL_FIELDS_TABLE* m_symbolFieldsTableDialog;
wxTreeCtrl* m_netNavigator;

View File

@ -2052,8 +2052,16 @@ int SCH_EDITOR_CONTROL::ShowCvpcb( const TOOL_EVENT& aEvent )
int SCH_EDITOR_CONTROL::EditSymbolFields( const TOOL_EVENT& aEvent )
{
DIALOG_SYMBOL_FIELDS_TABLE dlg( m_frame );
dlg.ShowQuasiModal();
DIALOG_SYMBOL_FIELDS_TABLE* dlg = m_frame->GetSymbolFieldsTableDialog();
wxCHECK( dlg, 0 );
// Needed at least on Windows. Raise() is not enough
dlg->Show( true );
// Bring it to the top if already open. Dual monitor users need this.
dlg->Raise();
return 0;
}