KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_lib_fields_table.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2025 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
21
22#include <bitmaps.h>
23#include <common.h>
24#include <confirm.h>
25#include <eda_doc.h>
27#include <grid_tricks.h>
28#include <kiface_base.h>
29#include <kiplatform/ui.h>
30#include <kiway_player.h>
31#include <string_utils.h>
33#include <project_sch.h>
34#include <symbol_edit_frame.h>
40#include <tools/sch_actions.h>
41#include <tool/tool_manager.h>
42#include <trace_helpers.h>
43#include <fields_data_model.h>
45#include <wx/arrstr.h>
46#include <wx/msgdlg.h>
47#include <wx/srchctrl.h>
48
49#include <wx/textdlg.h>
50
52
53#ifdef __WXMAC__
54#define COLUMN_MARGIN 3
55#else
56#define COLUMN_MARGIN 15
57#endif
58
59
61{
62public:
64 GRID_TRICKS( aGrid )
65 {}
66
67protected:
68 void doPopupSelection( wxCommandEvent& event ) override
69 {
70 if( event.GetId() >= GRIDTRICKS_FIRST_SHOWHIDE )
71 m_grid->PostSizeEvent();
72
74 }
75};
76
77
78enum
79{
85};
86
87
89{
90public:
92 VIEW_CONTROLS_GRID_DATA_MODEL* aViewFieldsData,
94 GRID_TRICKS( aGrid ),
95 m_dlg( aParent ),
96 m_viewControlsDataModel( aViewFieldsData ),
97 m_dataModel( aDataModel )
98 {}
99
100protected:
101 void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent ) override
102 {
103 wxMenuItem* revertMenu = menu.Append( MYID_REVERT_ROW, _( "Revert symbol" ), _( "Revert the symbol to its last saved state" ), wxITEM_NORMAL );
104 wxMenuItem* clearMenu = menu.Append( MYID_CLEAR_CELL, _( "Clear cell" ), _( "Clear the cell value" ), wxITEM_NORMAL );
105 menu.AppendSeparator();
106 wxMenuItem* createDerivedSymbolMenu = menu.Append( MYID_CREATE_DERIVED_SYMBOL, _( "Create Derived Symbol" ), _( "Create a new symbol derived from the selected one" ), wxITEM_NORMAL );
107
108 // Get global mouse position and convert to grid client coords
109 wxPoint mousePos = wxGetMousePosition();
110 wxPoint gridPt = m_grid->ScreenToClient( mousePos );
111
112 // Offset by grid header (column label) height so header area doesn't map to a row.
113 int headerHeight = m_grid->GetColLabelSize();
114 gridPt.y -= headerHeight;
115 if ( gridPt.y < 0 )
116 gridPt.y = 0;
117
118 int row = m_grid->YToRow( gridPt.y );
119 int col = m_grid->XToCol( gridPt.x );
120 m_grid->SetGridCursor( row, col );
121
122 revertMenu->Enable( m_dataModel->IsCellEdited( row, col ) );
123 clearMenu->Enable( !m_dataModel->IsCellClear( row, col ) );
124 createDerivedSymbolMenu->Enable( m_dataModel->IsRowSingleSymbol( row ) );
125
126 if( m_dataModel->GetColFieldName( col ) == GetCanonicalFieldName( FIELD_T::FOOTPRINT ) )
127 {
128 menu.Append( MYID_SELECT_FOOTPRINT, _( "Select Footprint..." ), _( "Browse for footprint" ) );
129 menu.AppendSeparator();
130 }
131 else if( m_dataModel->GetColFieldName( col ) == GetCanonicalFieldName( FIELD_T::DATASHEET ) )
132 {
133 menu.Append( MYID_SHOW_DATASHEET, _( "Show Datasheet" ), _( "Show datasheet in browser" ) );
134 menu.AppendSeparator();
135 }
136
137 GRID_TRICKS::showPopupMenu( menu, aEvent );
138 }
139
140 void doPopupSelection( wxCommandEvent& event ) override
141 {
142 int row = m_grid->GetGridCursorRow();
143 int col = m_grid->GetGridCursorCol();
144
145 if( event.GetId() == MYID_REVERT_ROW )
146 {
147 if( m_grid->CommitPendingChanges( false ) )
148 m_dataModel->RevertRow( row );
149
150 if( m_dataModel->IsEdited() )
151 m_dlg->OnModify();
152 else
153 m_dlg->ClearModify();
154
155 m_grid->ForceRefresh();
156 }
157 else if( event.GetId() == MYID_CLEAR_CELL )
158 {
159 if( m_grid->CommitPendingChanges( false ) )
160 m_dataModel->ClearCell( row, col );
161
162 if( m_dataModel->IsEdited() )
163 m_dlg->OnModify();
164 else
165 m_dlg->ClearModify();
166
167 m_grid->ForceRefresh();
168 }
169 else if( event.GetId() == MYID_CREATE_DERIVED_SYMBOL )
170 {
171 EDA_DRAW_FRAME* frame = dynamic_cast<EDA_DRAW_FRAME*>( m_dlg->GetParent() );
172 wxCHECK( frame, /* void */ );
173
174 const LIB_SYMBOL* parentSymbol = m_dataModel->GetSymbolForRow( row );
175
176 wxArrayString symbolNames;
177 m_dataModel->GetSymbolNames( symbolNames );
178
179 auto validator =
180 [&]( const wxString& newName ) -> bool
181 {
182 return symbolNames.Index( newName ) == wxNOT_FOUND;
183 };
184
185 DIALOG_NEW_SYMBOL dlg( frame, symbolNames, parentSymbol->GetName(), validator );
186
187 if( dlg.ShowModal() != wxID_OK )
188 return;
189
190 wxString derivedName = dlg.GetName();
191
192 m_dataModel->CreateDerivedSymbolImmediate( row, col, derivedName );
193
194 if( m_dataModel->IsEdited() )
195 m_dlg->OnModify();
196
197 m_grid->ForceRefresh();
198 }
199 else if( event.GetId() == MYID_SELECT_FOOTPRINT )
200 {
201 // pick a footprint using the footprint picker.
202 wxString fpid = m_grid->GetCellValue( row, col );
203
204 if( KIWAY_PLAYER* frame = m_dlg->Kiway().Player( FRAME_FOOTPRINT_CHOOSER, true, m_dlg ) )
205 {
206 if( frame->ShowModal( &fpid, m_dlg ) )
207 m_grid->SetCellValue( row, col, fpid );
208
209 frame->Destroy();
210 }
211 }
212 else if (event.GetId() == MYID_SHOW_DATASHEET )
213 {
214 wxString datasheet_uri = m_grid->GetCellValue( row, col );
215 GetAssociatedDocument( m_dlg, datasheet_uri, &m_dlg->Prj(), PROJECT_SCH::SchSearchS( &m_dlg->Prj() ) );
216 }
217 else if( event.GetId() >= GRIDTRICKS_FIRST_SHOWHIDE )
218 {
219 if( !m_grid->CommitPendingChanges( false ) )
220 return;
221
222 // Pop-up column order is the order of the shown fields, not the viewControls order
223 col = event.GetId() - GRIDTRICKS_FIRST_SHOWHIDE;
224
225 bool show = !m_dataModel->GetShowColumn( col );
226
227 m_dlg->ShowHideColumn( col, show );
228
229 wxString fieldName = m_dataModel->GetColFieldName( col );
230
231 for( row = 0; row < m_viewControlsDataModel->GetNumberRows(); row++ )
232 {
233 if( m_viewControlsDataModel->GetCanonicalFieldName( row ) == fieldName )
234 m_viewControlsDataModel->SetValueAsBool( row, SHOW_FIELD_COLUMN, show );
235 }
236
237 if( m_viewControlsDataModel->GetView() )
238 m_viewControlsDataModel->GetView()->ForceRefresh();
239 }
240 else
241 {
243 }
244 }
245
249};
250
251
253 DIALOG_LIB_FIELDS_TABLE_BASE( parent, wxID_ANY ),
254 m_parent( parent ),
255 m_scope( aScope ),
256 m_viewControlsDataModel( nullptr ),
257 m_dataModel( nullptr )
258{
260
264
266
268
269 m_viewControlsGrid->UseNativeColHeader( true );
271
272 // must be done after SetTable(), which appears to re-set it
273 m_viewControlsGrid->SetSelectionMode( wxGrid::wxGridSelectCells );
274
275 // add Cut, Copy, and Paste to wxGrid
277
278 wxGridCellAttr* attr = new wxGridCellAttr;
279 attr->SetReadOnly( true );
280 m_viewControlsDataModel->SetColAttr( attr, DISPLAY_NAME_COLUMN );
281
282 attr = new wxGridCellAttr;
283 attr->SetRenderer( new wxGridCellBoolRenderer() );
284 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
285 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
286 m_viewControlsDataModel->SetColAttr( attr, SHOW_FIELD_COLUMN );
287
288 attr = new wxGridCellAttr;
289 attr->SetRenderer( new wxGridCellBoolRenderer() );
290 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
291 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
292 m_viewControlsDataModel->SetColAttr( attr, GROUP_BY_COLUMN );
293
294 // Compress the view controls grid. (We want it to look different from the fields grid.)
295 m_viewControlsGrid->SetDefaultRowSize( m_viewControlsGrid->GetDefaultRowSize() - FromDIP( 4 ) );
296
297 m_filter->SetDescriptiveText( _( "Filter" ) );
298
300
301 m_grid->UseNativeColHeader( true );
302 m_grid->SetTable( m_dataModel, true );
303
304 // must be done after SetTable(), which appears to re-set it
305 m_grid->SetSelectionMode( wxGrid::wxGridSelectCells );
306
307 // add Cut, Copy, and Paste to wxGrid
309 m_dataModel ) );
310
312 m_grid->ClearSelection();
313
315
317
318 SetSize( wxSize( horizPixelsFromDU( 600 ), vertPixelsFromDU( 300 ) ) );
319
320 SYMBOL_EDITOR_SETTINGS::PANEL_LIB_FIELDS_TABLE& cfg = m_parent->libeditconfig()->m_LibFieldEditor;
321
323 // Ensure at least one column is visible otherwise we cannot add columns
324 // because there is no area to right click to get the menu managing the show/hide columns
325 wxString visible_column = m_viewControlsGrid->GetShownColumnsAsString();;
326
327 if( visible_column.IsEmpty() )
328 {
329 visible_column = wxT( "0" );
330 m_viewControlsGrid->ShowHideColumns( visible_column );
331 }
332
333 CallAfter( [this, cfg]()
334 {
335 if( cfg.sidebar_collapsed )
336 {
339 }
340 else
341 {
342 m_splitterMainWindow->SetSashPosition( cfg.sash_pos );
343 }
344 } );
345
346 Center();
347
348 // Connect Events
349 m_grid->Bind( wxEVT_GRID_COL_SORT, &DIALOG_LIB_FIELDS_TABLE::OnColSort, this );
350 m_grid->Bind( wxEVT_GRID_COL_MOVE, &DIALOG_LIB_FIELDS_TABLE::OnColMove, this );
351 m_grid->Bind( wxEVT_GRID_CELL_LEFT_CLICK, &DIALOG_LIB_FIELDS_TABLE::OnTableCellClick, this );
352 m_viewControlsGrid->Bind( wxEVT_GRID_CELL_CHANGED, &DIALOG_LIB_FIELDS_TABLE::OnViewControlsCellChanged, this );
353}
354
355
357{
358 SYMBOL_EDITOR_SETTINGS::PANEL_LIB_FIELDS_TABLE& cfg = m_parent->libeditconfig()->m_LibFieldEditor;
359
360 cfg.view_controls_visible_columns = m_viewControlsGrid->GetShownColumnsAsString();
361
362 cfg.sidebar_collapsed = ( m_splitterMainWindow->GetSashPosition() == 0 );
363
364 if( !cfg.sidebar_collapsed )
365 cfg.sash_pos = m_splitterMainWindow->GetSashPosition();
366
367 for( int i = 0; i < m_grid->GetNumberCols(); i++ )
368 {
369 if( m_grid->IsColShown( i ) )
370 {
371 std::string fieldName( m_dataModel->GetColFieldName( i ).ToUTF8() );
372 cfg.field_widths[fieldName] = m_grid->GetColSize( i );
373 }
374 }
375
376 // Disconnect Events
377 m_grid->Unbind( wxEVT_GRID_COL_SORT, &DIALOG_LIB_FIELDS_TABLE::OnColSort, this );
378 m_grid->Unbind( wxEVT_GRID_COL_MOVE, &DIALOG_LIB_FIELDS_TABLE::OnColMove, this );
379 m_grid->Unbind( wxEVT_GRID_CELL_LEFT_CLICK, &DIALOG_LIB_FIELDS_TABLE::OnTableCellClick, this );
380 m_viewControlsGrid->Unbind( wxEVT_GRID_CELL_CHANGED, &DIALOG_LIB_FIELDS_TABLE::OnViewControlsCellChanged, this );
381
382 // Delete the GRID_TRICKS.
383 m_viewControlsGrid->PopEventHandler( true );
384 m_grid->PopEventHandler( true );
385
386 // we gave ownership of m_viewControlsDataModel & m_dataModel to the wxGrids...
387}
388
389
391{
392 wxGridCellAttr* attr = new wxGridCellAttr;
393 attr->SetReadOnly( false );
394
395 // Set some column types to specific editors
396 if( m_dataModel->GetColFieldName( aCol ) == GetCanonicalFieldName( FIELD_T::FOOTPRINT ) )
397 {
398 // Create symbol netlist for footprint picker
399 wxString symbolNetlist;
400
401 if( !m_symbolsList.empty() )
402 {
403 // Use the first symbol's netlist (all symbols in lib should have similar pin structure)
404 LIB_SYMBOL* symbol = m_symbolsList[0];
405 wxArrayString pins;
406
407 for( SCH_PIN* pin : symbol->GetGraphicalPins( 0 /* all units */, 1 /* single bodyStyle */ ) )
408 pins.push_back( pin->GetNumber() + ' ' + pin->GetShownName() );
409
410 if( !pins.IsEmpty() )
411 symbolNetlist << EscapeString( wxJoin( pins, '\t' ), CTX_LINE );
412
413 symbolNetlist << wxS( "\r" );
414
415 wxArrayString fpFilters = symbol->GetFPFilters();
416 if( !fpFilters.IsEmpty() )
417 symbolNetlist << EscapeString( wxJoin( fpFilters, ' ' ), CTX_LINE );
418
419 symbolNetlist << wxS( "\r" );
420 }
421
422 attr->SetEditor( new GRID_CELL_FPID_EDITOR( this, symbolNetlist ) );
423 m_dataModel->SetColAttr( attr, aCol );
424 }
425 else if( m_dataModel->GetColFieldName( aCol ) == GetCanonicalFieldName( FIELD_T::DATASHEET ) )
426 {
427 // set datasheet column viewer button
428 attr->SetEditor( new GRID_CELL_URL_EDITOR( this, PROJECT_SCH::SchSearchS( &Prj() ) ) );
429 m_dataModel->SetColAttr( attr, aCol );
430 }
431 else if( m_dataModel->ColIsCheck( aCol ) )
432 {
433 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
434 attr->SetRenderer( new GRID_CELL_CHECKBOX_RENDERER() );
435 m_dataModel->SetColAttr( attr, aCol );
436 }
437 else if( IsGeneratedField( m_dataModel->GetColFieldName( aCol ) ) )
438 {
439 attr->SetReadOnly();
440 m_dataModel->SetColAttr( attr, aCol );
441 }
442 else
443 {
444 attr->SetEditor( m_grid->GetDefaultEditor() );
445 m_dataModel->SetColAttr( attr, aCol );
446 }
447}
448
449
451{
452 SYMBOL_EDITOR_SETTINGS* cfg = m_parent->GetSettings();
453 wxSize defaultDlgSize = ConvertDialogToPixels( wxSize( 600, 300 ) );
454
455 // Restore column sorting order and widths
456 m_grid->AutoSizeColumns( false );
457 int sortCol = 0;
458 bool sortAscending = true;
459
460 // Find the VALUE column for initial sorting
461 int valueCol = m_dataModel->GetFieldNameCol( GetCanonicalFieldName( FIELD_T::VALUE ) );
462
463 // Set initial sort to VALUE field (ascending) if no previous sort preference exists
464 if( m_dataModel->GetSortCol() == 0 && valueCol != -1 )
465 {
466 sortCol = valueCol;
467 sortAscending = true;
468 m_dataModel->SetSorting( sortCol, sortAscending );
469 }
470
471 for( int col = 0; col < m_grid->GetNumberCols(); ++col )
472 {
474
475 if( col == m_dataModel->GetSortCol() )
476 {
477 sortCol = col;
478 sortAscending = m_dataModel->GetSortAsc();
479 }
480 }
481
482 // sync m_grid's column visibilities to Show checkboxes in m_viewControlsGrid
483 for( int i = 0; i < m_viewControlsDataModel->GetNumberRows(); ++i )
484 {
485 int col = m_dataModel->GetFieldNameCol( m_viewControlsDataModel->GetCanonicalFieldName( i ) );
486
487 if( col == -1 )
488 continue;
489
490 bool show = m_viewControlsDataModel->GetValueAsBool( i, SHOW_FIELD_COLUMN );
491 m_dataModel->SetShowColumn( col, show );
492
493 if( show )
494 {
495 m_grid->ShowCol( col );
496
497 std::string key( m_dataModel->GetColFieldName( col ).ToUTF8() );
498
499 if( cfg->m_LibFieldEditor.field_widths.count( key )
500 && ( cfg->m_LibFieldEditor.field_widths.at( key ) > 0 ) )
501 {
502 m_grid->SetColSize( col, cfg->m_LibFieldEditor.field_widths.at( key ) );
503 }
504 else
505 {
506 int textWidth = m_dataModel->GetDataWidth( col ) + COLUMN_MARGIN;
507 int maxWidth = defaultDlgSize.x / 3;
508
509 m_grid->SetColSize( col, std::clamp( textWidth, 100, maxWidth ) );
510 }
511 }
512 else
513 {
514 m_grid->HideCol( col );
515 }
516 }
517
518 m_dataModel->SetSorting( sortCol, sortAscending );
519 m_grid->SetSortingColumn( sortCol, sortAscending );
520}
521
522
524{
525 switch( m_scope )
526 {
527 case SCOPE::SCOPE_LIBRARY: m_choiceScope->SetSelection( 0 ); break;
528 case SCOPE::SCOPE_RELATED_SYMBOLS: m_choiceScope->SetSelection( 1 ); break;
529 }
530
531 setScope( m_scope );
532
533 return true;
534}
535
536
537void DIALOG_LIB_FIELDS_TABLE::loadSymbols( const wxArrayString& aSymbolNames )
538{
539 // Clear any existing data
540 m_symbolsList.clear();
541
542 wxString libName = m_parent->GetTreeLIBID().GetLibNickname();
543
544 if( aSymbolNames.IsEmpty() )
545 {
547 wxMessageBox( wxString::Format( _( "No related symbols found in library '%s'." ), libName ) );
548 else
549 wxMessageBox( wxString::Format( _( "No symbols found in library '%s'." ), libName ) );
550
551 return;
552 }
553
554 // Load each symbol from the library manager and add it to our list
555 for( const wxString& symbolName : aSymbolNames )
556 {
557 LIB_SYMBOL* canvasSymbol = m_parent->GetCurSymbol();
558
559 if( canvasSymbol && canvasSymbol->GetLibraryName() == libName && canvasSymbol->GetName() == symbolName )
560 {
561 m_symbolsList.push_back( canvasSymbol );
562 }
563 else
564 {
565 try
566 {
567 if( LIB_SYMBOL* symbol = m_parent->GetLibManager().GetSymbol( symbolName, libName ) )
568 m_symbolsList.push_back( symbol );
569 }
570 catch( const IO_ERROR& ioe )
571 {
572 // Log the error and continue
573 wxLogWarning( wxString::Format( _( "Error loading symbol '%s': %s" ), symbolName, ioe.What() ) );
574 }
575 }
576 }
577
578 if( m_symbolsList.empty() )
579 {
581 wxMessageBox( _( "No related symbols could be loaded from the library." ) );
582 else
583 wxMessageBox( _( "No symbols could be loaded from the library." ) );
584 }
585
586 m_dataModel->SetSymbols( m_symbolsList );
587}
588
589
591{
592 if( !m_grid->CommitPendingChanges() )
593 return false;
594
595 if( !wxDialog::TransferDataFromWindow() )
596 return false;
597
598 bool updateCanvas = false;
599
600 m_dataModel->ApplyData(
601 [&]( LIB_SYMBOL* symbol )
602 {
603 m_parent->GetLibManager().UpdateSymbol( symbol, symbol->GetLibNickname() );
604
605 if( m_parent->GetCurSymbol() == symbol )
606 updateCanvas = true;
607 },
608 [&]()
609 {
610 // Handle newly created derived symbols
611 auto createdSymbols = m_dataModel->GetAndClearCreatedDerivedSymbols();
612
613 wxLogTrace( traceLibFieldTable, "Post-apply handler: found %zu created derived symbols",
614 createdSymbols.size() );
615
616 for( const auto& [symbol, libraryName] : createdSymbols )
617 {
618 if( !libraryName.IsEmpty() )
619 {
620 wxLogTrace( traceLibFieldTable, "Updating symbol '%s' (UUID: %s) in library '%s'",
621 symbol->GetName(), symbol->m_Uuid.AsString(), libraryName );
622 // Update the symbol in the library manager to properly register it
623 m_parent->GetLibManager().UpdateSymbol( symbol, libraryName );
624 }
625 }
626
627 // Sync libraries and refresh tree if there were changes
628 if( !createdSymbols.empty() )
629 {
630 wxLogTrace( traceLibFieldTable, "Syncing libraries due to %zu new symbols", createdSymbols.size() );
631
632 // Store references to the created symbols before sync
633 std::vector<LIB_SYMBOL*> symbolsToPreserve;
634 for( const auto& [symbol, libraryName] : createdSymbols )
635 {
636 symbolsToPreserve.push_back( symbol );
637 }
638
639 // Synchronize libraries to update the tree view
640 m_parent->SyncLibraries( false );
641
642 // Ensure created symbols are still in the symbol list after sync
643 for( LIB_SYMBOL* symbol : symbolsToPreserve )
644 {
645 bool found = false;
646 for( LIB_SYMBOL* existingSymbol : m_symbolsList )
647 {
648 if( existingSymbol->m_Uuid == symbol->m_Uuid )
649 {
650 found = true;
651 break;
652 }
653 }
654 if( !found )
655 {
656 wxLogTrace( traceLibFieldTable, "Re-adding symbol '%s' to list after sync", symbol->GetName() );
657 m_symbolsList.push_back( symbol );
658 }
659 }
660 }
661
662 wxLogTrace( traceLibFieldTable, "Dialog symbol list size after processing: %zu", m_symbolsList.size() );
663 } );
664
665 ClearModify();
666
667 wxLogTrace( traceLibFieldTable, "About to rebuild grid rows to include new symbols" );
669 wxLogTrace( traceLibFieldTable, "Grid rebuild completed" );
670
671 m_parent->RefreshLibraryTree();
672
673 if( updateCanvas )
674 {
675 m_parent->OnModify();
676 m_parent->HardRedraw();
677 }
678
679 return true;
680}
681
682
683void DIALOG_LIB_FIELDS_TABLE::OnAddField(wxCommandEvent& event)
684{
685 wxTextEntryDialog dlg( this, _( "New field name:" ), _( "Add Field" ) );
686
687 if( dlg.ShowModal() != wxID_OK )
688 return;
689
690 wxString fieldName = dlg.GetValue();
691
692 if( fieldName.IsEmpty() )
693 {
694 DisplayError( this, _( "Field must have a name." ) );
695 return;
696 }
697
698 for( int i = 0; i < m_dataModel->GetNumberCols(); ++i )
699 {
700 if( fieldName == m_dataModel->GetColFieldName( i ) )
701 {
702 DisplayError( this, wxString::Format( _( "Field name '%s' already in use." ), fieldName ) );
703 return;
704 }
705 }
706
707 AddField( fieldName, GetGeneratedFieldDisplayName( fieldName ), true, false, true );
708
709 SetupColumnProperties( m_dataModel->GetColsCount() - 1 );
710
711 OnModify();
712}
713
714
715void DIALOG_LIB_FIELDS_TABLE::OnRemoveField(wxCommandEvent& event)
716{
717 m_viewControlsGrid->OnDeleteRows(
718 [&]( int row )
719 {
720 return IsOK( this, wxString::Format( _( "Are you sure you want to remove the field '%s'?" ),
721 m_viewControlsDataModel->GetValue( row, DISPLAY_NAME_COLUMN ) ) );
722 },
723 [&]( int row )
724 {
725 wxString fieldName = m_viewControlsDataModel->GetCanonicalFieldName( row );
726
727 RemoveField( fieldName );
728
729 m_viewControlsDataModel->DeleteRow( row );
730 OnModify();
731 } );
732}
733
734
735void DIALOG_LIB_FIELDS_TABLE::OnRenameField(wxCommandEvent& event)
736{
737 wxArrayInt selectedRows = m_viewControlsGrid->GetSelectedRows();
738
739 if( selectedRows.empty() && m_viewControlsGrid->GetGridCursorRow() >= 0 )
740 selectedRows.push_back( m_viewControlsGrid->GetGridCursorRow() );
741
742 if( selectedRows.empty() )
743 return;
744
745 int row = selectedRows[0];
746
747 wxString fieldName = m_viewControlsDataModel->GetCanonicalFieldName( row );
748
749 int col = m_dataModel->GetFieldNameCol( fieldName );
750 wxCHECK_RET( col != -1, wxS( "Existing field name missing from data model" ) );
751
752 wxTextEntryDialog dlg( this, _( "New field name:" ), _( "Rename Field" ), fieldName );
753
754 if( dlg.ShowModal() != wxID_OK )
755 return;
756
757 wxString newFieldName = dlg.GetValue();
758
759 if( newFieldName == fieldName )
760 return;
761
762 if( m_dataModel->GetFieldNameCol( newFieldName ) != -1 )
763 {
764 DisplayError( this, wxString::Format( _( "Field name '%s' already exists." ), newFieldName ) );
765 return;
766 }
767
768 RenameField( fieldName, newFieldName );
769
770 m_viewControlsDataModel->SetCanonicalFieldName( row, newFieldName );
771 m_viewControlsDataModel->SetValue( row, DISPLAY_NAME_COLUMN, newFieldName );
772 m_viewControlsDataModel->SetValue( row, LABEL_COLUMN, GetGeneratedFieldDisplayName( newFieldName ) );
773
775 OnModify();
776}
777
778
779void DIALOG_LIB_FIELDS_TABLE::OnFilterText( wxCommandEvent& event )
780{
781 m_dataModel->SetFilter( m_filter->GetValue() );
783}
784
785
787{
788 wxPoint pos = aEvent.GetPosition();
789 wxRect ctrlRect = m_filter->GetScreenRect();
790 int buttonWidth = ctrlRect.GetHeight(); // Presume buttons are square
791
792 // TODO: restore cursor when mouse leaves the filter field (or is it a MSW bug?)
793 if( m_filter->IsSearchButtonVisible() && pos.x < buttonWidth )
794 SetCursor( wxCURSOR_ARROW );
795 else if( m_filter->IsCancelButtonVisible() && pos.x > ctrlRect.GetWidth() - buttonWidth )
796 SetCursor( wxCURSOR_ARROW );
797 else
798 SetCursor( wxCURSOR_IBEAM );
799}
800
801
803{
804 LIB_SYMBOL_LIBRARY_MANAGER& libMgr = m_parent->GetLibManager();
805 wxString targetLib = m_parent->GetTargetLibId().GetLibNickname();
806 wxString targetSymbol = m_parent->GetTargetLibId().GetLibItemName();
807 wxArrayString symbolNames;
808
809 SetTitle( wxString::Format( _( "Library Fields Table (%s)" ), targetLib ) );
810
811 m_scope = aScope;
812
813 if( m_scope == SCOPE::SCOPE_RELATED_SYMBOLS )
814 {
815 const LIB_SYMBOL* symbol = libMgr.GetBufferedSymbol( targetSymbol, targetLib );
816 LIB_SYMBOL_SPTR root = symbol ? symbol->GetRootSymbol() : nullptr;
817
818 if( root )
819 {
820 symbolNames.Add( root->GetName() );
821
822 // Now we have the root symbol, collect all its derived symbols
823 libMgr.GetDerivedSymbolNames( root->GetName(), targetLib, symbolNames );
824 }
825 }
826 else
827 {
828 // Get all symbol names from the library manager
829 libMgr.GetSymbolNames( targetLib, symbolNames );
830 }
831
832 // Get all symbols from the library
833 loadSymbols( symbolNames );
834
835 // Update the field list and refresh the grid
839}
840
841
842void DIALOG_LIB_FIELDS_TABLE::OnScope( wxCommandEvent& aEvent )
843{
844 switch( aEvent.GetSelection() )
845 {
846 case 0: setScope( SCOPE::SCOPE_LIBRARY ); break;
847 case 1: setScope( SCOPE::SCOPE_RELATED_SYMBOLS ); break;
848 }
849}
850
851
852void DIALOG_LIB_FIELDS_TABLE::OnRegroupSymbols( wxCommandEvent& event )
853{
855}
856
857
859{
860 m_grid->ForceRefresh();
861 OnModify();
862}
863
864
866{
867 wxString cellValue = m_grid->GetCellValue( event.GetRow(), event.GetCol() );
868
869 if( cellValue.StartsWith( wxS( "> " ) ) || cellValue.StartsWith( wxS( "v " ) ) )
870 {
871 m_grid->ClearSelection();
872 m_dataModel->ExpandCollapseRow( event.GetRow() );
873 m_grid->SetGridCursor( event.GetRow(), event.GetCol() );
874 // Don't call event.Skip() - we've handled this event
875 }
876 else
877 {
878 event.Skip(); // Let normal cell editing proceed
879 }
880}
881
882
884{
885 if( m_grid )
886 {
887 // Get global mouse position and convert to grid client coords
888 wxPoint mousePos = wxGetMousePosition();
889 wxPoint gridPt = m_grid->ScreenToClient( mousePos );
890
891 int row = m_grid->YToRow( gridPt.y );
892 int col = m_grid->XToCol( gridPt.x );
893
894 if ( row != -1 && col != -1 )
895 m_grid->SetGridCursor( row, col );
896 }
897
898 event.Skip();
899}
900
901
902void DIALOG_LIB_FIELDS_TABLE::OnTableColSize(wxGridSizeEvent& aEvent)
903{
904 aEvent.Skip();
905
906 m_grid->ForceRefresh();
907}
908
909
911{
912 const wxString& showColLabel = m_viewControlsGrid->GetColLabelValue( SHOW_FIELD_COLUMN );
913 const wxString& groupByColLabel = m_viewControlsGrid->GetColLabelValue( GROUP_BY_COLUMN );
914 int showColWidth = KIUI::GetTextSize( showColLabel, m_viewControlsGrid ).x + COLUMN_MARGIN;
915 int groupByColWidth = KIUI::GetTextSize( groupByColLabel, m_viewControlsGrid ).x + COLUMN_MARGIN;
916 int remainingWidth = m_viewControlsGrid->GetSize().GetX() - showColWidth - groupByColWidth;
917
918 m_viewControlsGrid->SetColSize( showColWidth, SHOW_FIELD_COLUMN );
919 m_viewControlsGrid->SetColSize( groupByColWidth, GROUP_BY_COLUMN );
920
921 if( m_viewControlsGrid->IsColShown( DISPLAY_NAME_COLUMN ) && m_viewControlsGrid->IsColShown( LABEL_COLUMN ) )
922 {
923 m_viewControlsGrid->SetColSize( DISPLAY_NAME_COLUMN, std::max( remainingWidth / 2, 60 ) );
924 m_viewControlsGrid->SetColSize( LABEL_COLUMN, std::max( remainingWidth - ( remainingWidth / 2 ), 60 ) );
925 }
926 else if( m_viewControlsGrid->IsColShown( DISPLAY_NAME_COLUMN ) )
927 {
928 m_viewControlsGrid->SetColSize( DISPLAY_NAME_COLUMN, std::max( remainingWidth, 60 ) );
929 }
930 else if( m_viewControlsGrid->IsColShown( LABEL_COLUMN ) )
931 {
932 m_viewControlsGrid->SetColSize( LABEL_COLUMN, std::max( remainingWidth, 60 ) );
933 }
934
935 event.Skip();
936}
937
938
939void DIALOG_LIB_FIELDS_TABLE::OnSidebarToggle( wxCommandEvent& event )
940{
941 SYMBOL_EDITOR_SETTINGS::PANEL_LIB_FIELDS_TABLE& cfg = m_parent->libeditconfig()->m_LibFieldEditor;
942
943 if( cfg.sidebar_collapsed )
944 {
945 cfg.sidebar_collapsed = false;
946 m_splitterMainWindow->SplitVertically( m_leftPanel, m_rightPanel, cfg.sash_pos );
948 }
949 else
950 {
951 cfg.sash_pos = m_splitterMainWindow->GetSashPosition();
952
953 cfg.sidebar_collapsed = true;
956 }
957}
958
959
960void DIALOG_LIB_FIELDS_TABLE::OnApply(wxCommandEvent& event)
961{
963}
964
965
966void DIALOG_LIB_FIELDS_TABLE::OnCancel(wxCommandEvent& event)
967{
968 m_grid->CommitPendingChanges( true );
969
970 if( m_dataModel->IsEdited() )
971 {
972 if( !HandleUnsavedChanges( this, _( "Save changes?" ),
973 [&]() -> bool
974 {
975 return TransferDataFromWindow();
976 } ) )
977 return;
978 }
979
980 EndModal( wxID_CANCEL );
981}
982
983
984void DIALOG_LIB_FIELDS_TABLE::OnOk(wxCommandEvent& event)
985{
987 EndModal( wxID_OK );
988}
989
990
991void DIALOG_LIB_FIELDS_TABLE::OnClose( wxCloseEvent& aEvent )
992{
993 m_grid->CommitPendingChanges( true );
994
995 if( m_dataModel->IsEdited() )
996 {
997 if( !HandleUnsavedChanges( this, _( "Save changes?" ),
998 [&]() -> bool
999 {
1000 return TransferDataFromWindow();
1001 } ) )
1002 {
1003 aEvent.Veto();
1004 return;
1005 }
1006 }
1007
1008 aEvent.Skip();
1009}
1010
1011
1013{
1014 auto addMandatoryField =
1015 [&]( FIELD_T fieldId, bool show, bool groupBy )
1016 {
1017 AddField( GetCanonicalFieldName( fieldId ),
1018 GetDefaultFieldName( fieldId, DO_TRANSLATE ), show, groupBy );
1019 };
1020
1021 // Add mandatory fields first show groupBy
1022 addMandatoryField( FIELD_T::REFERENCE, false, false );
1023 addMandatoryField( FIELD_T::VALUE, true, false );
1024 addMandatoryField( FIELD_T::FOOTPRINT, true, false );
1025 addMandatoryField( FIELD_T::DATASHEET, true, false );
1026 addMandatoryField( FIELD_T::DESCRIPTION, false, false );
1027
1028 AddField( wxS( "Keywords" ), _( "Keywords" ), true, false );
1029
1030 // Add attribute fields as checkboxes show groupBy user checkbox
1031 AddField( wxS( "${EXCLUDE_FROM_BOM}" ), _( "Exclude From BOM" ), true, false, false, true );
1032 AddField( wxS( "${EXCLUDE_FROM_SIM}" ), _( "Exclude From Simulation" ), true, false, false, true );
1033 AddField( wxS( "${EXCLUDE_FROM_BOARD}" ), _( "Exclude From Board" ), true, false, false, true );
1034
1035 AddField( wxS( "Power" ), _( "Power Symbol" ), true, false, false, true );
1036 AddField( wxS( "LocalPower" ), _( "Local Power Symbol" ), true, false, false, true );
1037
1038 // User fields next
1039 std::set<wxString> userFieldNames;
1040
1041 for( LIB_SYMBOL* symbol : m_symbolsList )
1042 {
1043 std::vector< SCH_FIELD* > fields;
1044 symbol->GetFields( fields );
1045
1046 for( SCH_FIELD* field : fields )
1047 {
1048 if( !field->IsMandatory() && !field->IsPrivate() )
1049 userFieldNames.insert( field->GetName() );
1050 }
1051 }
1052
1053 for( const wxString& fieldName : userFieldNames )
1054 AddField( fieldName, GetGeneratedFieldDisplayName( fieldName ), true, false );
1055}
1056
1057
1058void DIALOG_LIB_FIELDS_TABLE::AddField( const wxString& aFieldName, const wxString& aLabelValue, bool show,
1059 bool groupBy, bool addedByUser, bool aIsCheckbox )
1060{
1061 // Users can add fields with variable names that match the special names in the grid,
1062 // e.g. ${QUANTITY} so make sure we don't add them twice
1063 for( int row = 0; row < m_viewControlsDataModel->GetNumberRows(); row++ )
1064 {
1065 if( m_viewControlsDataModel->GetCanonicalFieldName( row ) == aFieldName )
1066 return;
1067 }
1068
1069 m_dataModel->AddColumn( aFieldName, aLabelValue, addedByUser, aIsCheckbox );
1070
1071 wxGridTableMessage msg( m_dataModel, wxGRIDTABLE_NOTIFY_COLS_APPENDED, 1 );
1072 m_grid->ProcessTableMessage( msg );
1073
1074 m_viewControlsGrid->OnAddRow(
1075 [&]() -> std::pair<int, int>
1076 {
1077 m_viewControlsDataModel->AppendRow( aFieldName, aLabelValue, show, groupBy );
1078
1079 return { m_viewControlsDataModel->GetNumberRows() - 1, -1 };
1080 } );
1081}
1082
1083
1084void DIALOG_LIB_FIELDS_TABLE::RemoveField(const wxString& fieldName)
1085{
1086 int col = m_dataModel->GetFieldNameCol( fieldName );
1087 wxCHECK_RET( col != -1, wxS( "Field name not found" ) );
1088
1089 m_dataModel->RemoveColumn( col );
1090}
1091
1092
1093void DIALOG_LIB_FIELDS_TABLE::RenameField(const wxString& oldName, const wxString& newName)
1094{
1095 int col = m_dataModel->GetFieldNameCol( oldName );
1096 wxCHECK_RET( col != -1, wxS( "Existing field name missing from data model" ) );
1097
1098 m_dataModel->RenameColumn( col, newName );
1099}
1100
1101
1103{
1104 m_dataModel->RebuildRows();
1105 m_grid->ForceRefresh();
1106}
1107
1108
1109void DIALOG_LIB_FIELDS_TABLE::OnColSort(wxGridEvent& aEvent)
1110{
1111 int sortCol = aEvent.GetCol();
1112 std::string key( m_dataModel->GetColFieldName( sortCol ).ToUTF8() );
1113 bool ascending;
1114
1115 // This is bonkers, but wxWidgets doesn't tell us ascending/descending in the event, and
1116 // if we ask it will give us pre-event info.
1117 if( m_grid->IsSortingBy( sortCol ) )
1118 {
1119 // same column; invert ascending
1120 ascending = !m_grid->IsSortOrderAscending();
1121 }
1122 else
1123 {
1124 // different column; start with ascending
1125 ascending = true;
1126 }
1127
1128 m_dataModel->SetSorting( sortCol, ascending );
1130}
1131
1132
1133void DIALOG_LIB_FIELDS_TABLE::OnColMove(wxGridEvent& aEvent)
1134{
1135 int origPos = aEvent.GetCol();
1136
1137 // Save column widths since the setup function uses the saved config values
1138 SYMBOL_EDITOR_SETTINGS* cfg = m_parent->GetSettings();
1139
1140 for( int i = 0; i < m_grid->GetNumberCols(); i++ )
1141 {
1142 if( m_grid->IsColShown( i ) )
1143 {
1144 std::string fieldName( m_dataModel->GetColFieldName( i ).ToUTF8() );
1145 cfg->m_LibFieldEditor.field_widths[fieldName] = m_grid->GetColSize( i );
1146 }
1147 }
1148
1149 CallAfter(
1150 [origPos, this]()
1151 {
1152 int newPos = m_grid->GetColPos( origPos );
1153
1154#ifdef __WXMAC__
1155 if( newPos < origPos )
1156 newPos += 1;
1157#endif
1158
1159 m_dataModel->MoveColumn( origPos, newPos );
1160
1161 // "Unmove" the column since we've moved the column internally
1162 m_grid->ResetColPos();
1163
1164 // We need to reset all the column attr's to the correct column order
1166
1167 m_grid->ForceRefresh();
1168 } );
1169}
1170
1171
1173{
1174 if( aShow )
1175 m_grid->ShowCol( aCol );
1176 else
1177 m_grid->HideCol( aCol );
1178
1179 m_dataModel->SetShowColumn( aCol, aShow );
1180
1181 m_grid->ForceRefresh();
1182 OnModify();
1183}
1184
1185
1187{
1188 int row = aEvent.GetRow();
1189
1190 wxCHECK( row < m_viewControlsGrid->GetNumberRows(), /* void */ );
1191
1192 switch( aEvent.GetCol() )
1193 {
1195 {
1196 wxString label = m_viewControlsDataModel->GetValue( row, DISPLAY_NAME_COLUMN );
1197 wxString fieldName = m_viewControlsDataModel->GetCanonicalFieldName( row );
1198 int dataCol = m_dataModel->GetFieldNameCol( fieldName );
1199
1200 if( dataCol != -1 )
1201 {
1202 m_dataModel->SetColLabelValue( dataCol, label );
1203 m_grid->SetColLabelValue( dataCol, label );
1204
1205 m_grid->ForceRefresh();
1206 OnModify();
1207 }
1208
1209 break;
1210 }
1211
1212 case SHOW_FIELD_COLUMN:
1213 {
1214 wxString fieldName = m_viewControlsDataModel->GetCanonicalFieldName( row );
1215 bool value = m_viewControlsDataModel->GetValueAsBool( row, SHOW_FIELD_COLUMN );
1216 int dataCol = m_dataModel->GetFieldNameCol( fieldName );
1217
1218 if( dataCol != -1 )
1219 ShowHideColumn( dataCol, value );
1220
1221 break;
1222 }
1223
1224 case GROUP_BY_COLUMN:
1225 {
1226 wxString fieldName = m_viewControlsDataModel->GetCanonicalFieldName( row );
1227 bool value = m_viewControlsDataModel->GetValueAsBool( row, GROUP_BY_COLUMN );
1228 int dataCol = m_dataModel->GetFieldNameCol( fieldName );
1229
1230 m_dataModel->SetGroupColumn( dataCol, value );
1231 m_dataModel->RebuildRows();
1232
1233 m_grid->ForceRefresh();
1234 OnModify();
1235 break;
1236 }
1237
1238 default:
1239 break;
1240 }
1241}
1242
1243
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:110
DIALOG_LIB_FIELDS_TABLE_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Library Fields Table (%s)"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER)
void OnTableColSize(wxGridSizeEvent &event) override
void OnFilterMouseMoved(wxMouseEvent &event) override
void OnScope(wxCommandEvent &event) override
void OnTableItemContextMenu(wxGridEvent &event) override
void OnSidebarToggle(wxCommandEvent &event) override
void OnAddField(wxCommandEvent &event) override
void ShowHideColumn(int aCol, bool aShow)
LIB_FIELDS_EDITOR_GRID_DATA_MODEL * m_dataModel
void OnTableCellClick(wxGridEvent &event) override
void OnViewControlsCellChanged(wxGridEvent &aEvent) override
void RenameField(const wxString &oldName, const wxString &newName)
void OnClose(wxCloseEvent &event) override
void OnOk(wxCommandEvent &event) override
void OnTableValueChanged(wxGridEvent &event) override
void AddField(const wxString &aFieldName, const wxString &aLabelValue, bool show, bool groupBy, bool addedByUser=false, bool aIsCheckbox=false)
void OnApply(wxCommandEvent &event) override
std::vector< LIB_SYMBOL * > m_symbolsList
void OnRegroupSymbols(wxCommandEvent &event) override
void OnSizeViewControlsGrid(wxSizeEvent &event) override
void OnCancel(wxCommandEvent &event) override
void OnRenameField(wxCommandEvent &event) override
void RemoveField(const wxString &fieldName)
DIALOG_LIB_FIELDS_TABLE(SYMBOL_EDIT_FRAME *parent, DIALOG_LIB_FIELDS_TABLE::SCOPE aScope)
void OnColSort(wxGridEvent &aEvent)
VIEW_CONTROLS_GRID_DATA_MODEL * m_viewControlsDataModel
void OnColMove(wxGridEvent &aEvent)
void loadSymbols(const wxArrayString &aSymbolNames)
void OnFilterText(wxCommandEvent &event) override
void OnRemoveField(wxCommandEvent &event) override
wxString GetName() const override
int vertPixelsFromDU(int y) const
Convert an integer number of dialog units to pixels, vertically.
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition dialog_shim.h:82
void SetupStandardButtons(std::map< int, wxString > aLabels={})
int horizPixelsFromDU(int x) const
Convert an integer number of dialog units to pixels, horizontally.
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
int ShowModal() override
The base class for create windows for drawing purpose.
const KIID m_Uuid
Definition eda_item.h:516
GRID_TRICKS(WX_GRID *aGrid)
virtual void doPopupSelection(wxCommandEvent &event)
virtual void showPopupMenu(wxMenu &menu, wxGridEvent &aEvent)
WX_GRID * m_grid
I don't own the grid, but he owns me.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
wxString AsString() const
Definition kiid.cpp:246
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
LIB_FIELDS_EDITOR_GRID_DATA_MODEL * m_dataModel
LIB_FIELDS_EDITOR_GRID_TRICKS(DIALOG_LIB_FIELDS_TABLE *aParent, WX_GRID *aGrid, VIEW_CONTROLS_GRID_DATA_MODEL *aViewFieldsData, LIB_FIELDS_EDITOR_GRID_DATA_MODEL *aDataModel)
VIEW_CONTROLS_GRID_DATA_MODEL * m_viewControlsDataModel
void doPopupSelection(wxCommandEvent &event) override
void showPopupMenu(wxMenu &menu, wxGridEvent &aEvent) override
Symbol library management helper that is specific to the symbol library editor frame.
Define a library symbol object.
Definition lib_symbol.h:85
const wxString GetLibraryName() const
wxString GetName() const override
Definition lib_symbol.h:148
wxArrayString GetFPFilters() const
Definition lib_symbol.h:217
wxString GetLibNickname() const override
Sets the Description field text value.
Definition lib_symbol.h:160
std::vector< SCH_PIN * > GetGraphicalPins(int aUnit=0, int aBodyStyle=0) const
Graphical pins: Return schematic pin objects as drawn (unexpanded), filtered by unit/body.
LIB_SYMBOL_SPTR GetRootSymbol() const
Get the parent symbol that does not have another parent.
static SEARCH_STACK * SchSearchS(PROJECT *aProject)
Accessor for Eeschema search stack.
PANEL_LIB_FIELDS_TABLE m_LibFieldEditor
The symbol library editor main window.
LIB_SYMBOL * GetBufferedSymbol(const wxString &aSymbolName, const wxString &aLibrary)
Return the symbol copy from the buffer.
void GetSymbolNames(const wxString &aLibName, wxArrayString &aSymbolNames, SYMBOL_NAME_FILTER aFilter=SYMBOL_NAME_FILTER::ALL)
size_t GetDerivedSymbolNames(const wxString &aSymbolName, const wxString &aLibraryName, wxArrayString &aList)
Fetch all of the symbols derived from a aSymbolName into aList.
void doPopupSelection(wxCommandEvent &event) override
wxString GetGeneratedFieldDisplayName(const wxString &aSource)
Returns any variables unexpanded, e.g.
Definition common.cpp:123
bool IsGeneratedField(const wxString &aSource)
Returns true if the string is generated, e.g contains a single text var reference.
Definition common.cpp:136
The common library.
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:251
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
Definition confirm.cpp:129
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:169
This file is part of the common library.
DIALOG_LIB_NEW_SYMBOL DIALOG_NEW_SYMBOL
#define COLUMN_MARGIN
@ MYID_CREATE_DERIVED_SYMBOL
@ MYID_SELECT_FOOTPRINT
#define _(s)
bool GetAssociatedDocument(wxWindow *aParent, const wxString &aDocName, PROJECT *aProject, SEARCH_STACK *aPaths, std::vector< EMBEDDED_FILES * > aFilesStack)
Open a document (file) with the suitable browser.
Definition eda_doc.cpp:62
This file is part of the common library.
#define LABEL_COLUMN
#define DISPLAY_NAME_COLUMN
#define GROUP_BY_COLUMN
#define SHOW_FIELD_COLUMN
@ FRAME_FOOTPRINT_CHOOSER
Definition frame_type.h:44
@ GRIDTRICKS_FIRST_SHOWHIDE
Definition grid_tricks.h:51
@ GRIDTRICKS_FIRST_CLIENT_ID
Definition grid_tricks.h:48
const wxChar *const traceLibFieldTable
std::shared_ptr< LIB_SYMBOL > LIB_SYMBOL_SPTR
shared pointer to LIB_SYMBOL
Definition lib_symbol.h:52
KICOMMON_API wxSize GetTextSize(const wxString &aSingleLine, wxWindow *aWindow)
Return the size of aSingleLine of text when it is rendered in aWindow using whatever font is currentl...
Definition ui_common.cpp:78
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_LINE
wxString GetDefaultFieldName(FIELD_T aFieldId, bool aTranslateForHI)
Return a default symbol field name for a mandatory field type.
#define DO_TRANSLATE
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ DESCRIPTION
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ DATASHEET
name of datasheet
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
wxString GetCanonicalFieldName(FIELD_T aFieldType)
wxLogTrace helper definitions.