KiCad PCB EDA Suite
panel_sym_lib_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) 2017 Wayne Stambaugh <[email protected]>
5 * Copyright (C) 2021 CERN
6 * Copyright (C) 2017-2022 KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <set>
23#include <wx/regex.h>
24
25#include <common.h> // For ExpandEnvVarSubstitutions
26#include <project.h>
27#include <panel_sym_lib_table.h>
28#include <lib_id.h>
29#include <symbol_lib_table.h>
30#include <lib_table_lexer.h>
32#include <widgets/wx_grid.h>
33#include <confirm.h>
34#include <bitmaps.h>
35#include <lib_table_grid.h>
37#include <env_paths.h>
38#include <eeschema_id.h>
39#include <symbol_edit_frame.h>
40#include <symbol_viewer_frame.h>
41#include <sch_edit_frame.h>
42#include <kiway.h>
43#include <paths.h>
44#include <pgm_base.h>
49#include <sch_file_versions.h>
50#include <wx/filedlg.h>
51
52
53
54// clang-format off
55
60{
61 wxString m_Description;
62 wxString m_FileFilter;
64 bool m_IsFile;
65 SCH_IO_MGR::SCH_FILE_T m_Plugin;
66};
67
68
72enum {
75};
76
77
82{
83 friend class SYMBOL_GRID_TRICKS;
84
85protected:
86 LIB_TABLE_ROW* at( size_t aIndex ) override { return &m_rows.at( aIndex ); }
87
88 size_t size() const override { return m_rows.size(); }
89
91 {
92 return dynamic_cast< LIB_TABLE_ROW* >( new SYMBOL_LIB_TABLE_ROW );
93 }
94
95 LIB_TABLE_ROWS_ITER begin() override { return m_rows.begin(); }
96
98 {
99 return m_rows.insert( aIterator, aRow );
100 }
101
102 void push_back( LIB_TABLE_ROW* aRow ) override { m_rows.push_back( aRow ); }
103
105 {
106 return m_rows.erase( aFirst, aLast );
107 }
108
109public:
110 void SetValue( int aRow, int aCol, const wxString &aValue ) override
111 {
112 LIB_TABLE_GRID::SetValue( aRow, aCol, aValue );
113
114 // If setting a filepath, attempt to auto-detect the format
115 if( aCol == COL_URI )
116 {
117 wxFileName fn( aValue );
118
119 for( SCH_IO_MGR::SCH_FILE_T piType : SCH_IO_MGR::SCH_FILE_T_vector )
120 {
121 if( SCH_IO_MGR::GetLibraryFileExtension( piType ).Lower() == fn.GetExt().Lower() )
122 {
123 SetValue( aRow, COL_TYPE, SCH_IO_MGR::ShowType( piType ) );
124 break;
125 }
126 }
127 }
128 }
129
130
132 {
133 m_rows = aTableToEdit.m_rows;
134 }
135};
136
138{
139public:
141 LIB_TABLE_GRID_TRICKS( aGrid ),
142 m_dialog( aParent )
143 {
144 }
145
146protected:
148
151 virtual void paste_text( const wxString& cb_text ) override
152 {
154 size_t ndx = cb_text.find( "(sym_lib_table" );
155
156 if( ndx != std::string::npos )
157 {
158 // paste the SYMBOL_LIB_TABLE_ROWs of s-expression (sym_lib_table), starting
159 // at column 0 regardless of current cursor column.
160
161 STRING_LINE_READER slr( TO_UTF8( cb_text ), wxS( "Clipboard" ) );
162 LIB_TABLE_LEXER lexer( &slr );
163 SYMBOL_LIB_TABLE tmp_tbl;
164 bool parsed = true;
165
166 try
167 {
168 tmp_tbl.Parse( &lexer );
169 }
170 catch( PARSE_ERROR& pe )
171 {
172 DisplayError( m_dialog, pe.What() );
173 parsed = false;
174 }
175
176 if( parsed )
177 {
178 // make sure the table is big enough...
179 if( tmp_tbl.GetCount() > (unsigned) tbl->GetNumberRows() )
180 tbl->AppendRows( tmp_tbl.GetCount() - tbl->GetNumberRows() );
181
182 for( unsigned i = 0; i < tmp_tbl.GetCount(); ++i )
183 tbl->m_rows.replace( i, tmp_tbl.At( i ).clone() );
184 }
185
186 m_grid->AutoSizeColumns( false );
187 }
188 else
189 {
190 // paste spreadsheet formatted text.
191 GRID_TRICKS::paste_text( cb_text );
192
193 m_grid->AutoSizeColumns( false );
194 }
195 }
196};
197
198
200 SYMBOL_LIB_TABLE* aGlobalTable,
201 const wxString& aGlobalTablePath,
202 SYMBOL_LIB_TABLE* aProjectTable,
203 const wxString& aProjectTablePath ) :
204 PANEL_SYM_LIB_TABLE_BASE( aParent ),
205 m_globalTable( aGlobalTable ),
206 m_projectTable( aProjectTable ),
207 m_project( aProject ),
208 m_parent( aParent )
209{
210 // wxGrid only supports user owned tables if they exist past end of ~wxGrid(),
211 // so make it a grid owned table.
213
214 wxArrayString pluginChoices;
215
216 pluginChoices.Add( SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_KICAD ) );
217 pluginChoices.Add( SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_LEGACY ) );
218 pluginChoices.Add( SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_DATABASE ) );
219
220 EESCHEMA_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
221
222 if( cfg->m_lastSymbolLibDir.IsEmpty() )
224
226
227 auto autoSizeCol =
228 [&]( WX_GRID* aGrid, int aCol )
229 {
230 int prevWidth = aGrid->GetColSize( aCol );
231
232 aGrid->AutoSizeColumn( aCol, false );
233 aGrid->SetColSize( aCol, std::max( prevWidth, aGrid->GetColSize( aCol ) ) );
234 };
235
236 auto setupGrid =
237 [&]( WX_GRID* aGrid )
238 {
239 // Give a bit more room for combobox editors
240 aGrid->SetDefaultRowSize( aGrid->GetDefaultRowSize() + 4 );
241
242 // add Cut, Copy, and Paste to wxGrids
243 aGrid->PushEventHandler( new SYMBOL_GRID_TRICKS( m_parent, aGrid ) );
244
245 aGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
246
247 // Set special attributes
248 wxGridCellAttr* attr;
249
250 attr = new wxGridCellAttr;
251
252 wxString wildcards = AllSymbolLibFilesWildcard()
255 attr->SetEditor( new GRID_CELL_PATH_EDITOR( m_parent, aGrid,
256 &cfg->m_lastSymbolLibDir, wildcards,
257 true, m_project->GetProjectPath() ) );
258 aGrid->SetColAttr( COL_URI, attr );
259
260 attr = new wxGridCellAttr;
261 attr->SetEditor( new wxGridCellChoiceEditor( pluginChoices ) );
262 aGrid->SetColAttr( COL_TYPE, attr );
263
264 attr = new wxGridCellAttr;
265 attr->SetRenderer( new wxGridCellBoolRenderer() );
266 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
267 aGrid->SetColAttr( COL_ENABLED, attr );
268
269 attr = new wxGridCellAttr;
270 attr->SetRenderer( new wxGridCellBoolRenderer() );
271 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
272 aGrid->SetColAttr( COL_VISIBLE, attr );
273
274 // all but COL_OPTIONS, which is edited with Option Editor anyways.
275 autoSizeCol( aGrid, COL_NICKNAME );
276 autoSizeCol( aGrid, COL_TYPE );
277 autoSizeCol( aGrid, COL_URI );
278 autoSizeCol( aGrid, COL_DESCR );
279 autoSizeCol( aGrid, COL_ENABLED );
280
281 // Gives a selection to each grid, mainly for delete button. wxGrid's wake up with
282 // a currentCell which is sometimes not highlighted.
283 if( aGrid->GetNumberRows() > 0 )
284 aGrid->SelectRow( 0 );
285 };
286
287 setupGrid( m_global_grid );
288
289 if( m_projectTable )
290 {
292 setupGrid( m_project_grid );
293 }
294 else
295 {
296 m_pageNdx = 0;
297 m_notebook->DeletePage( 1 );
298 m_project_grid = nullptr;
299 }
300
301 // add Cut, Copy, and Paste to wxGrids
302 m_path_subs_grid->PushEventHandler( new GRID_TRICKS( m_path_subs_grid ) );
303
305
306 // select the last selected page
307 m_notebook->SetSelection( m_pageNdx );
309
310 m_path_subs_grid->SetColLabelValue( 0, _( "Name" ) );
311 m_path_subs_grid->SetColLabelValue( 1, _( "Value" ) );
312
313 // for ALT+A handling, we want the initial focus to be on the first selected grid.
315
316 // Configure button logos
322}
323
324
326{
327 // Delete the GRID_TRICKS.
328 // Any additional event handlers should be popped before the window is deleted.
329 m_global_grid->PopEventHandler( true );
330
331 if( m_project_grid )
332 m_project_grid->PopEventHandler( true );
333
334 m_path_subs_grid->PopEventHandler( true );
335}
336
337
339{
340 wxString msg;
341
342 for( SYMBOL_LIB_TABLE_GRID* model : { global_model(), project_model() } )
343 {
344 if( !model )
345 continue;
346
347 for( int r = 0; r < model->GetNumberRows(); )
348 {
349 wxString nick = model->GetValue( r, COL_NICKNAME ).Trim( false ).Trim();
350 wxString uri = model->GetValue( r, COL_URI ).Trim( false ).Trim();
351 unsigned illegalCh = 0;
352
353 if( !nick || !uri )
354 {
355 if( !nick && !uri )
356 msg = _( "A library table row nickname and path cells are empty." );
357 else if( !nick )
358 msg = _( "A library table row nickname cell is empty." );
359 else
360 msg = _( "A library table row path cell is empty." );
361
362 wxMessageDialog badCellDlg( this, msg, _( "Invalid Row Definition" ),
363 wxYES_NO | wxCENTER | wxICON_QUESTION | wxYES_DEFAULT );
364 badCellDlg.SetExtendedMessage( _( "Empty cells will result in all rows that are "
365 "invalid to be removed from the table." ) );
366 badCellDlg.SetYesNoLabels( wxMessageDialog::ButtonLabel( _( "Remove Invalid Cells" ) ),
367 wxMessageDialog::ButtonLabel( _( "Cancel Table Update" ) ) );
368
369 if( badCellDlg.ShowModal() == wxID_NO )
370 return false;
371
372 // Delete the "empty" row, where empty means missing nick or uri.
373 // This also updates the UI which could be slow, but there should only be a few
374 // rows to delete, unless the user fell asleep on the Add Row
375 // button.
376 model->DeleteRows( r, 1 );
377 }
378 else if( ( illegalCh = LIB_ID::FindIllegalLibraryNameChar( nick ) ) )
379 {
380 msg = wxString::Format( _( "Illegal character '%c' in nickname '%s'" ),
381 illegalCh,
382 nick );
383
384 // show the tabbed panel holding the grid we have flunked:
385 if( model != cur_model() )
386 m_notebook->SetSelection( model == global_model() ? 0 : 1 );
387
388 m_cur_grid->MakeCellVisible( r, 0 );
389 m_cur_grid->SetGridCursor( r, 1 );
390
391 wxMessageDialog errdlg( this, msg, _( "Library Nickname Error" ) );
392 errdlg.ShowModal();
393 return false;
394 }
395 else
396 {
397 // set the trimmed values back into the table so they get saved to disk.
398 model->SetValue( r, COL_NICKNAME, nick );
399 model->SetValue( r, COL_URI, uri );
400 ++r; // this row was OK.
401 }
402 }
403 }
404
405 // check for duplicate nickNames, separately in each table.
406 for( SYMBOL_LIB_TABLE_GRID* model : { global_model(), project_model() } )
407 {
408 if( !model )
409 continue;
410
411 for( int r1 = 0; r1 < model->GetNumberRows() - 1; ++r1 )
412 {
413 wxString nick1 = model->GetValue( r1, COL_NICKNAME );
414
415 for( int r2=r1+1; r2 < model->GetNumberRows(); ++r2 )
416 {
417 wxString nick2 = model->GetValue( r2, COL_NICKNAME );
418
419 if( nick1 == nick2 )
420 {
421 msg = wxString::Format( _( "Multiple libraries cannot share the same "
422 "nickname ('%s')." ), nick1 );
423
424 // show the tabbed panel holding the grid we have flunked:
425 if( model != cur_model() )
426 m_notebook->SetSelection( model == global_model() ? 0 : 1 );
427
428 // go to the lower of the two rows, it is technically the duplicate:
429 m_cur_grid->MakeCellVisible( r2, 0 );
430 m_cur_grid->SetGridCursor( r2, 1 );
431
432 wxMessageDialog errdlg( this, msg, _( "Library Nickname Error" ) );
433 errdlg.ShowModal();
434
435 return false;
436 }
437 }
438 }
439 }
440
441 for( SYMBOL_LIB_TABLE* table : { global_model(), project_model() } )
442 {
443 if( !table )
444 continue;
445
446 for( unsigned int r = 0; r < table->GetCount(); ++r )
447 {
448 SYMBOL_LIB_TABLE_ROW& row = dynamic_cast<SYMBOL_LIB_TABLE_ROW&>( table->At( r ) );
449
450 if( !row.GetParent() )
451 row.SetParent( table );
452
453 if( !row.GetIsEnabled() )
454 continue;
455
456 try
457 {
458 if( row.Refresh() )
459 {
460 if( table == global_model() )
462 else
464 }
465 }
466 catch( const IO_ERROR& ioe )
467 {
468 msg.Printf( _( "Symbol library '%s' failed to load." ), row.GetNickName() );
469
470 wxMessageDialog errdlg( this, msg + wxS( "\n" ) + ioe.What(),
471 _( "Error Loading Library" ) );
472 errdlg.ShowModal();
473
474 return true;
475 }
476 }
477 }
478
479 return true;
480}
481
482
483void PANEL_SYM_LIB_TABLE::OnUpdateUI( wxUpdateUIEvent& event )
484{
485 m_pageNdx = (unsigned) std::max( 0, m_notebook->GetSelection() );
487}
488
489
491{
492 wxString wildcards = AllSymbolLibFilesWildcard()
495 + "|" + DatabaseLibFileWildcard();
496
497 EESCHEMA_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
498
499 wxString openDir = cfg->m_lastSymbolLibDir;
500
502 openDir = m_lastProjectLibDir;
503
504 wxFileDialog dlg( this, _( "Select Library" ), openDir, wxEmptyString, wildcards,
505 wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE );
506
507 if( dlg.ShowModal() == wxID_CANCEL )
508 return;
509
511 cfg->m_lastSymbolLibDir = dlg.GetDirectory();
512 else
513 m_lastProjectLibDir = dlg.GetDirectory();
514
515 const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
516 bool addDuplicates = false;
517 bool applyToAll = false;
518 wxString warning = _( "Warning: Duplicate Nickname" );
519 wxString msg = _( "A library nicknamed '%s' already exists." );
520 wxString detailedMsg = _( "One of the nicknames will need to be changed after "
521 "adding this library." );
522
523 wxArrayString filePathsList;
524 dlg.GetPaths( filePathsList );
525
526 for( const wxString& filePath : filePathsList )
527 {
528 wxFileName fn( filePath );
529 wxString nickname = LIB_ID::FixIllegalChars( fn.GetName(), true );
530 bool doAdd = true;
531
532 if( cur_model()->ContainsNickname( nickname ) )
533 {
534 if( !applyToAll )
535 {
536 // The cancel button adds the library to the table anyway
537 addDuplicates = OKOrCancelDialog( this, warning, wxString::Format( msg, nickname ),
538 detailedMsg, _( "Skip" ), _( "Add Anyway" ),
539 &applyToAll ) == wxID_CANCEL;
540 }
541
542 doAdd = addDuplicates;
543 }
544
545 if( doAdd && m_cur_grid->AppendRows( 1 ) )
546 {
547 int last_row = m_cur_grid->GetNumberRows() - 1;
548
549 m_cur_grid->SetCellValue( last_row, COL_NICKNAME, nickname );
550
551 // attempt to auto-detect the plugin type
552 for( SCH_IO_MGR::SCH_FILE_T piType : SCH_IO_MGR::SCH_FILE_T_vector )
553 {
554 if( SCH_IO_MGR::GetLibraryFileExtension( piType ).Lower() == fn.GetExt().Lower() )
555 {
556 m_cur_grid->SetCellValue( last_row, COL_TYPE, SCH_IO_MGR::ShowType( piType ) );
557 break;
558 }
559 }
560
561 // try to use path normalized to an environmental variable or project path
562 wxString path = NormalizePath( filePath, &envVars, m_project->GetProjectPath() );
563
564 // Do not use the project path in the global library table. This will almost
565 // assuredly be wrong for a different project.
566 if( m_pageNdx == 0 && path.Contains( "${KIPRJMOD}" ) )
567 path = fn.GetFullPath();
568
569 m_cur_grid->SetCellValue( last_row, COL_URI, path );
570 }
571 }
572
573 if( !filePathsList.IsEmpty() )
574 {
575 m_cur_grid->MakeCellVisible( m_cur_grid->GetNumberRows() - 1, 0 );
576 m_cur_grid->SetGridCursor( m_cur_grid->GetNumberRows() - 1, 1 );
577 }
578}
579
580
581void PANEL_SYM_LIB_TABLE::appendRowHandler( wxCommandEvent& event )
582{
584 return;
585
586 if( m_cur_grid->AppendRows( 1 ) )
587 {
588 int row = m_cur_grid->GetNumberRows() - 1;
589
590 // wx documentation is wrong, SetGridCursor does not make visible.
591 m_cur_grid->MakeCellVisible( row, 0 );
592 m_cur_grid->SetGridCursor( row, 1 );
593 m_cur_grid->EnableCellEditControl( true );
594 m_cur_grid->ShowCellEditControl();
595 }
596}
597
598
599void PANEL_SYM_LIB_TABLE::deleteRowHandler( wxCommandEvent& event )
600{
602 return;
603
604 int curRow = m_cur_grid->GetGridCursorRow();
605 int curCol = m_cur_grid->GetGridCursorCol();
606
607 // In a wxGrid, collect rows that have a selected cell, or are selected
608 // It is not so easy: it depends on the way the selection was made.
609 // Here, we collect rows selected by clicking on a row label, and rows that contain
610 // previously-selected cells.
611 // If no candidate, just delete the row with the grid cursor.
612 wxArrayInt selectedRows = m_cur_grid->GetSelectedRows();
613 wxGridCellCoordsArray cells = m_cur_grid->GetSelectedCells();
614 wxGridCellCoordsArray blockTopLeft = m_cur_grid->GetSelectionBlockTopLeft();
615 wxGridCellCoordsArray blockBotRight = m_cur_grid->GetSelectionBlockBottomRight();
616
617 // Add all row having cell selected to list:
618 for( unsigned ii = 0; ii < cells.GetCount(); ii++ )
619 selectedRows.Add( cells[ii].GetRow() );
620
621 // Handle block selection
622 if( !blockTopLeft.IsEmpty() && !blockBotRight.IsEmpty() )
623 {
624 for( int i = blockTopLeft[0].GetRow(); i <= blockBotRight[0].GetRow(); ++i )
625 selectedRows.Add( i );
626 }
627
628 // Use the row having the grid cursor only if we have no candidate:
629 if( selectedRows.size() == 0 && m_cur_grid->GetGridCursorRow() >= 0 )
630 selectedRows.Add( m_cur_grid->GetGridCursorRow() );
631
632 if( selectedRows.size() == 0 )
633 {
634 wxBell();
635 return;
636 }
637
638 std::sort( selectedRows.begin(), selectedRows.end() );
639
640 // Remove selected rows (note: a row can be stored more than once in list)
641 int last_row = -1;
642
643 for( int ii = selectedRows.GetCount()-1; ii >= 0; ii-- )
644 {
645 int row = selectedRows[ii];
646
647 if( row != last_row )
648 {
649 last_row = row;
650 m_cur_grid->DeleteRows( row, 1 );
651 }
652 }
653
654 if( m_cur_grid->GetNumberRows() > 0 && curRow >= 0 )
655 m_cur_grid->SetGridCursor( std::min( curRow, m_cur_grid->GetNumberRows() - 1 ), curCol );
656}
657
658
659void PANEL_SYM_LIB_TABLE::moveUpHandler( wxCommandEvent& event )
660{
662 return;
663
665 int curRow = m_cur_grid->GetGridCursorRow();
666
667 // @todo: add multiple selection moves.
668 if( curRow >= 1 )
669 {
670 boost::ptr_vector< LIB_TABLE_ROW >::auto_type move_me =
671 tbl->m_rows.release( tbl->m_rows.begin() + curRow );
672
673 --curRow;
674 tbl->m_rows.insert( tbl->m_rows.begin() + curRow, move_me.release() );
675
676 if( tbl->GetView() )
677 {
678 // Update the wxGrid
679 wxGridTableMessage msg( tbl, wxGRIDTABLE_NOTIFY_ROWS_INSERTED, curRow, 0 );
680 tbl->GetView()->ProcessTableMessage( msg );
681 }
682
683 m_cur_grid->MakeCellVisible( curRow, m_cur_grid->GetGridCursorCol() );
684 m_cur_grid->SetGridCursor( curRow, m_cur_grid->GetGridCursorCol() );
685 }
686}
687
688
689void PANEL_SYM_LIB_TABLE::moveDownHandler( wxCommandEvent& event )
690{
692 return;
693
695 int curRow = m_cur_grid->GetGridCursorRow();
696
697 // @todo: add multiple selection moves.
698 if( unsigned( curRow + 1 ) < tbl->m_rows.size() )
699 {
700 boost::ptr_vector< LIB_TABLE_ROW >::auto_type move_me =
701 tbl->m_rows.release( tbl->m_rows.begin() + curRow );
702
703 ++curRow;
704 tbl->m_rows.insert( tbl->m_rows.begin() + curRow, move_me.release() );
705
706 if( tbl->GetView() )
707 {
708 // Update the wxGrid
709 wxGridTableMessage msg( tbl, wxGRIDTABLE_NOTIFY_ROWS_INSERTED, curRow - 1, 0 );
710 tbl->GetView()->ProcessTableMessage( msg );
711 }
712
713 m_cur_grid->MakeCellVisible( curRow, m_cur_grid->GetGridCursorCol() );
714 m_cur_grid->SetGridCursor( curRow, m_cur_grid->GetGridCursorCol() );
715 }
716}
717
718
720{
722 return;
723
724 wxArrayInt selectedRows = m_cur_grid->GetSelectedRows();
725
726 if( selectedRows.empty() && m_cur_grid->GetGridCursorRow() >= 0 )
727 selectedRows.push_back( m_cur_grid->GetGridCursorRow() );
728
729 wxArrayInt legacyRows;
730 wxString legacyType = SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_LEGACY );
731 wxString kicadType = SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_KICAD );
732 wxString msg;
733
734 for( int row : selectedRows )
735 {
736 if( m_cur_grid->GetCellValue( row, COL_TYPE ) == legacyType )
737 legacyRows.push_back( row );
738 }
739
740 if( legacyRows.size() <= 0 )
741 {
742 wxMessageBox( _( "Select one or more rows containing libraries in Legacy format (*.lib) "
743 "to save as current KiCad format (*.kicad_sym)." ) );
744 return;
745 }
746 else
747 {
748 if( legacyRows.size() == 1 )
749 {
750 msg.Printf( _( "Save '%s' as current KiCad format (*.kicad_sym) "
751 "and replace legacy entry in table?" ),
752 m_cur_grid->GetCellValue( legacyRows[0], COL_NICKNAME ) );
753 }
754 else
755 {
756 msg.Printf( _( "Save %d Legacy format libraries as current KiCad format (*.kicad_sym) "
757 "and replace legacy entries in table?" ),
758 (int) legacyRows.size() );
759 }
760
761 if( !IsOK( m_parent, msg ) )
762 return;
763 }
764
765 for( int row : legacyRows )
766 {
767 wxString libName = m_cur_grid->GetCellValue( row, COL_NICKNAME );
768 wxString relPath = m_cur_grid->GetCellValue( row, COL_URI );
769 wxString resolvedPath = ExpandEnvVarSubstitutions( relPath, m_project );
770 wxFileName legacyLib( resolvedPath );
771
772 if( !legacyLib.Exists() )
773 {
774 msg.Printf( _( "Library '%s' not found." ), relPath );
775 DisplayErrorMessage( this, msg );
776 continue;
777 }
778
779 wxFileName newLib( resolvedPath );
780 newLib.SetExt( "kicad_sym" );
781
782 if( newLib.Exists() )
783 {
784 msg.Printf( _( "File '%s' already exists. Do you want overwrite this file?" ),
785 newLib.GetFullPath() );
786
787 switch( wxMessageBox( msg, _( "Migrate Library" ),
788 wxYES_NO | wxCANCEL | wxICON_QUESTION, m_parent ) )
789 {
790 case wxYES: break;
791 case wxNO: continue;
792 case wxCANCEL: return;
793 }
794 }
795
796 if( convertLibrary( libName, legacyLib.GetFullPath(), newLib.GetFullPath() ) )
797 {
798 relPath = NormalizePath( newLib.GetFullPath(), &Pgm().GetLocalEnvVariables(),
799 m_project );
800
801 // Do not use the project path in the global library table. This will almost
802 // assuredly be wrong for a different project.
803 if( m_cur_grid == m_global_grid && relPath.Contains( "${KIPRJMOD}" ) )
804 relPath = newLib.GetFullPath();
805
806 m_cur_grid->SetCellValue( row, COL_URI, relPath );
807 m_cur_grid->SetCellValue( row, COL_TYPE, kicadType );
808 }
809 else
810 {
811 msg.Printf( _( "Failed to save symbol library file '%s'." ), newLib.GetFullPath() );
812 DisplayErrorMessage( this, msg );
813 }
814 }
815}
816
817
818bool PANEL_SYM_LIB_TABLE::convertLibrary( const wxString& aLibrary, const wxString& legacyFilepath,
819 const wxString& newFilepath )
820{
821 SCH_PLUGIN::SCH_PLUGIN_RELEASER legacyPI( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) );
822 SCH_PLUGIN::SCH_PLUGIN_RELEASER kicadPI( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
823 std::vector<LIB_SYMBOL*> symbols;
824 std::vector<LIB_SYMBOL*> newSymbols;
825 std::map<LIB_SYMBOL*, LIB_SYMBOL*> symbolMap;
826
827 try
828 {
829 // Write a stub file; SaveSymbol() expects something to be there already.
830 FILE_OUTPUTFORMATTER* formatter = new FILE_OUTPUTFORMATTER( newFilepath );
831
832 formatter->Print( 0, "(kicad_symbol_lib (version %d) (generator kicad_converter))",
834
835 // This will write the file
836 delete formatter;
837
838 legacyPI->EnumerateSymbolLib( symbols, legacyFilepath );
839
840 // Copy non-aliases first so we can build a map from symbols to newSymbols
841 for( LIB_SYMBOL* symbol : symbols )
842 {
843 if( symbol->IsAlias() )
844 continue;
845
846 symbol->SetName( EscapeString( symbol->GetName(), CTX_LIBID ) );
847
848 newSymbols.push_back( new LIB_SYMBOL( *symbol ) );
849 symbolMap[symbol] = newSymbols.back();
850 }
851
852 // Now do the aliases using the map to hook them up to their newSymbol parents
853 for( LIB_SYMBOL* symbol : symbols )
854 {
855 if( !symbol->IsAlias() )
856 continue;
857
858 symbol->SetName( EscapeString( symbol->GetName(), CTX_LIBID ) );
859
860 newSymbols.push_back( new LIB_SYMBOL( *symbol ) );
861 newSymbols.back()->SetParent( symbolMap[ symbol->GetParent().lock().get() ] );
862 }
863
864 // Finally write out newSymbols
865 for( LIB_SYMBOL* symbol : newSymbols )
866 {
867 kicadPI->SaveSymbol( newFilepath, symbol );
868 }
869 }
870 catch( ... )
871 {
872 return false;
873 }
874
875 return true;
876}
877
878
880{
882 return false;
883
884 if( !verifyTables() )
885 return false;
886
887 if( *global_model() != *m_globalTable )
888 {
890
892 m_globalTable->m_rows.transfer( m_globalTable->m_rows.end(), global_model()->m_rows.begin(),
893 global_model()->m_rows.end(), global_model()->m_rows );
895 }
896
898 {
900
902 m_projectTable->m_rows.transfer( m_projectTable->m_rows.end(), project_model()->m_rows.begin(),
903 project_model()->m_rows.end(), project_model()->m_rows );
905 }
906
907 return true;
908}
909
910
912{
913 wxRegEx re( ".*?(\\$\\{(.+?)\\})|(\\$\\((.+?)\\)).*?", wxRE_ADVANCED );
914 wxASSERT( re.IsValid() ); // wxRE_ADVANCED is required.
915
916 std::set< wxString > unique;
917
918 // clear the table
920
922 {
923 if( !tbl )
924 continue;
925
926 for( int row = 0; row < tbl->GetNumberRows(); ++row )
927 {
928 wxString uri = tbl->GetValue( row, COL_URI );
929
930 while( re.Matches( uri ) )
931 {
932 wxString envvar = re.GetMatch( uri, 2 );
933
934 // if not ${...} form then must be $(...)
935 if( envvar.IsEmpty() )
936 envvar = re.GetMatch( uri, 4 );
937
938 // ignore duplicates
939 unique.insert( envvar );
940
941 // delete the last match and search again
942 uri.Replace( re.GetMatch( uri, 0 ), wxEmptyString );
943 }
944 }
945 }
946
947 // Make sure this special environment variable shows up even if it was
948 // not used yet. It is automatically set by KiCad to the directory holding
949 // the current project.
950 unique.insert( PROJECT_VAR_NAME );
952
953 for( const wxString& evName : unique )
954 {
955 int row = m_path_subs_grid->GetNumberRows();
956 m_path_subs_grid->AppendRows( 1 );
957
958 m_path_subs_grid->SetCellValue( row, 0, wxT( "${" ) + evName + wxT( "}" ) );
959 m_path_subs_grid->SetCellEditor( row, 0, new GRID_CELL_READONLY_TEXT_EDITOR() );
960
961 wxString evValue;
962 wxGetEnv( evName, &evValue );
963 m_path_subs_grid->SetCellValue( row, 1, evValue );
964 m_path_subs_grid->SetCellEditor( row, 1, new GRID_CELL_READONLY_TEXT_EDITOR() );
965 }
966
967 // No combobox editors here, but it looks better if its consistent with the other
968 // grids in the dialog.
969 m_path_subs_grid->SetDefaultRowSize( m_path_subs_grid->GetDefaultRowSize() + 2 );
970
971 adjustPathSubsGridColumns( m_path_subs_grid->GetRect().GetWidth() );
972}
973
974
976{
977 // Account for scroll bars
978 aWidth -= ( m_path_subs_grid->GetSize().x - m_path_subs_grid->GetClientSize().x );
979
980 m_path_subs_grid->AutoSizeColumn( 0 );
981 m_path_subs_grid->SetColSize( 0, std::max( 72, m_path_subs_grid->GetColSize( 0 ) ) );
982 m_path_subs_grid->SetColSize( 1, std::max( 120, aWidth - m_path_subs_grid->GetColSize( 0 ) ) );
983}
984
985
986void PANEL_SYM_LIB_TABLE::onSizeGrid( wxSizeEvent& event )
987{
988 adjustPathSubsGridColumns( event.GetSize().GetX() );
989
990 event.Skip();
991}
992
993
995{
996 return (SYMBOL_LIB_TABLE_GRID*) m_global_grid->GetTable();
997}
998
999
1001{
1002 return m_project_grid ? (SYMBOL_LIB_TABLE_GRID*) m_project_grid->GetTable() : nullptr;
1003}
1004
1005
1007{
1008 return (SYMBOL_LIB_TABLE_GRID*) m_cur_grid->GetTable();
1009}
1010
1011
1013
1014
1015void InvokeSchEditSymbolLibTable( KIWAY* aKiway, wxWindow *aParent )
1016{
1017 auto* schEditor = (SCH_EDIT_FRAME*) aKiway->Player( FRAME_SCH, false );
1018 auto* symbolEditor = (SYMBOL_EDIT_FRAME*) aKiway->Player( FRAME_SCH_SYMBOL_EDITOR, false );
1019 auto* symbolViewer = (SYMBOL_VIEWER_FRAME*) aKiway->Player( FRAME_SCH_VIEWER, false );
1020
1022 wxString globalTablePath = SYMBOL_LIB_TABLE::GetGlobalTableFileName();
1023 SYMBOL_LIB_TABLE* projectTable = nullptr;
1024 wxString projectPath = aKiway->Prj().GetProjectPath();
1025 wxFileName projectTableFn( projectPath, SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() );
1026 wxString msg;
1027 wxString currentLib;
1028
1029 // Don't allow editing project tables if no project is open
1030 if( !aKiway->Prj().IsNullProject() )
1031 projectTable = aKiway->Prj().SchSymbolLibTable();
1032
1033 if( symbolEditor )
1034 {
1035 currentLib = symbolEditor->GetCurLib();
1036
1037 // This prevents an ugly crash on OSX (https://bugs.launchpad.net/kicad/+bug/1765286)
1038 symbolEditor->FreezeLibraryTree();
1039
1040 if( symbolEditor->HasLibModifications() )
1041 {
1042 msg = _( "Modifications have been made to one or more symbol libraries.\n"
1043 "Changes must be saved or discarded before the symbol library "
1044 "table can be modified." );
1045
1046 switch( UnsavedChangesDialog( aParent, msg ) )
1047 {
1048 case wxID_YES: symbolEditor->SaveAll(); break;
1049 case wxID_NO: symbolEditor->RevertAll(); break;
1050 default:
1051 case wxID_CANCEL: symbolEditor->ThawLibraryTree(); return;
1052 }
1053 }
1054 }
1055
1056 DIALOG_EDIT_LIBRARY_TABLES dlg( aParent, _( "Symbol Libraries" ) );
1057 dlg.SetKiway( &dlg, aKiway );
1058
1059 dlg.InstallPanel( new PANEL_SYM_LIB_TABLE( &dlg, &aKiway->Prj(), globalTable, globalTablePath,
1060 projectTable, projectTableFn.GetFullPath() ) );
1061
1062 if( dlg.ShowModal() == wxID_CANCEL )
1063 {
1064 if( symbolEditor )
1065 symbolEditor->ThawLibraryTree();
1066
1067 return;
1068 }
1069
1070 if( dlg.m_GlobalTableChanged )
1071 {
1072 try
1073 {
1074 globalTable->Save( globalTablePath );
1075 }
1076 catch( const IO_ERROR& ioe )
1077 {
1078 msg.Printf( _( "Error saving global library table:\n\n%s" ), ioe.What() );
1079 wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
1080 }
1081 }
1082
1083 if( projectTable && dlg.m_ProjectTableChanged )
1084 {
1085 try
1086 {
1087 projectTable->Save( projectTableFn.GetFullPath() );
1088 }
1089 catch( const IO_ERROR& ioe )
1090 {
1091 msg.Printf( _( "Error saving project-specific library table:\n\n%s" ), ioe.What() );
1092 wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
1093 }
1094 }
1095
1096 if( schEditor )
1097 schEditor->SyncView();
1098
1099 if( symbolEditor )
1100 {
1101 // Check if the currently selected symbol library been removed or disabled.
1102 if( !currentLib.empty() && projectTable && !projectTable->HasLibrary( currentLib, true ) )
1103 {
1104 symbolEditor->SetCurLib( wxEmptyString );
1105 symbolEditor->emptyScreen();
1106 }
1107
1108 symbolEditor->SyncLibraries( true );
1109 symbolEditor->ThawLibraryTree();
1110 symbolEditor->RefreshLibraryTree();
1111 }
1112
1113 if( symbolViewer )
1114 symbolViewer->ReCreateLibList();
1115}
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
@ small_folder
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:97
Used for text file output.
Definition: richio.h:457
Editor for wxGrid cells that adds a file/folder browser to the grid input field.
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition: grid_tricks.h:61
virtual void paste_text(const wxString &cb_text)
WX_GRID * m_grid
I don't own the grid, but he owns me.
Definition: grid_tricks.h:121
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:76
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
void SetKiway(wxWindow *aDest, KIWAY *aKiway)
It is only used for debugging, since "this" is not a wxWindow*.
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:274
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:394
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
Definition: kiway.cpp:192
static unsigned FindIllegalLibraryNameChar(const UTF8 &aLibraryName)
Looks for characters that are illegal in library nicknames.
Definition: lib_id.cpp:242
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, bool aLib)
Replace illegal LIB_ID item name characters with underscores '_'.
Definition: lib_id.cpp:190
Define a library symbol object.
Definition: lib_symbol.h:99
This abstract base class mixes any object derived from LIB_TABLE into wxGridTableBase so the result c...
void SetValue(int aRow, int aCol, const wxString &aValue) override
bool AppendRows(size_t aNumRows=1) override
int GetNumberRows() override
Hold a record identifying a library accessed by the appropriate plug in object in the LIB_TABLE.
LIB_TABLE * GetParent() const
void SetParent(LIB_TABLE *aParent)
const wxString & GetNickName() const
LIB_TABLE_ROW * clone() const
bool GetIsEnabled() const
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
LIB_TABLE_ROW & At(unsigned aIndex)
Get the 'n'th LIB_TABLE_ROW object.
LIB_TABLE_ROWS m_rows
void Clear()
Delete all rows.
unsigned GetCount() const
Get the number of rows contained in the table.
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
void reindex()
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Format and write text to the output stream.
Definition: richio.cpp:433
Class PANEL_SYM_LIB_TABLE_BASE.
STD_BITMAP_BUTTON * m_browse_button
STD_BITMAP_BUTTON * m_move_up_button
STD_BITMAP_BUTTON * m_delete_button
STD_BITMAP_BUTTON * m_move_down_button
STD_BITMAP_BUTTON * m_append_button
Dialog to show and edit symbol library tables.
void OnUpdateUI(wxUpdateUIEvent &event) override
void moveUpHandler(wxCommandEvent &event) override
SYMBOL_LIB_TABLE * m_projectTable
static size_t m_pageNdx
Remember the last notebook page selected.
void deleteRowHandler(wxCommandEvent &event) override
void browseLibrariesHandler(wxCommandEvent &event) override
SYMBOL_LIB_TABLE_GRID * cur_model() const
PANEL_SYM_LIB_TABLE(DIALOG_EDIT_LIBRARY_TABLES *aParent, PROJECT *m_project, SYMBOL_LIB_TABLE *aGlobal, const wxString &aGlobalTablePath, SYMBOL_LIB_TABLE *aProject, const wxString &aProjectTablePath)
bool verifyTables()
Trim important fields, removes blank row entries, and checks for duplicates.
void adjustPathSubsGridColumns(int aWidth)
bool convertLibrary(const wxString &aLibrary, const wxString &legacyFilepath, const wxString &newFilepath)
SYMBOL_LIB_TABLE_GRID * global_model() const
SYMBOL_LIB_TABLE * m_globalTable
void onSizeGrid(wxSizeEvent &event) override
void onConvertLegacyLibraries(wxCommandEvent &event) override
SYMBOL_LIB_TABLE_GRID * project_model() const
void moveDownHandler(wxCommandEvent &event) override
void populateEnvironReadOnlyTable()
Populate the readonly environment variable table with names and values by examining all the full_uri ...
WX_GRID * m_cur_grid
changed based on tab choice
DIALOG_EDIT_LIBRARY_TABLES * m_parent
bool TransferDataFromWindow() override
void appendRowHandler(wxCommandEvent &event) override
static wxString GetDefaultUserSymbolsPath()
Gets the default path we point users to create projects.
Definition: paths.cpp:97
Container for project specific data.
Definition: project.h:64
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:126
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Definition: project.cpp:138
Schematic editor (Eeschema) main window.
static const wxString ShowType(SCH_FILE_T aFileType)
Return a brief name for a plugin, given aFileType enum.
Definition: sch_io_mgr.cpp:81
static const wxString GetLibraryFileExtension(SCH_FILE_T aFileType)
Return the symbol library file extension (if any) for aFileType.
Definition: sch_io_mgr.cpp:141
Helper object to release a SCH_PLUGIN in the context of a potential thrown exception through its dest...
Definition: sch_io_mgr.h:535
virtual void EnumerateSymbolLib(wxArrayString &aSymbolNameList, const wxString &aLibraryPath, const STRING_UTF8_MAP *aProperties=nullptr)
Populate a list of LIB_SYMBOL alias names contained within the library aLibraryPath.
Definition: sch_plugin.cpp:67
virtual void SaveSymbol(const wxString &aLibraryPath, const LIB_SYMBOL *aSymbol, const STRING_UTF8_MAP *aProperties=nullptr)
Write aSymbol to an existing library located at aLibraryPath.
Definition: sch_plugin.cpp:94
void SetBitmap(const wxBitmap &aBmp)
Is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition: richio.h:241
The symbol library editor main window.
DIALOG_EDIT_LIBRARY_TABLES * m_dialog
SYMBOL_GRID_TRICKS(DIALOG_EDIT_LIBRARY_TABLES *aParent, WX_GRID *aGrid)
virtual void paste_text(const wxString &cb_text) override
handle specialized clipboard text, with leading "(sym_lib_table" or spreadsheet formatted text.
Build a wxGridTableBase by wrapping an SYMBOL_LIB_TABLE object.
void SetValue(int aRow, int aCol, const wxString &aValue) override
LIB_TABLE_ROW * at(size_t aIndex) override
LIB_TABLE_ROWS_ITER erase(LIB_TABLE_ROWS_ITER aFirst, LIB_TABLE_ROWS_ITER aLast) override
LIB_TABLE_ROWS_ITER begin() override
LIB_TABLE_ROWS_ITER insert(LIB_TABLE_ROWS_ITER aIterator, LIB_TABLE_ROW *aRow) override
LIB_TABLE_ROW * makeNewRow() override
void push_back(LIB_TABLE_ROW *aRow) override
size_t size() const override
SYMBOL_LIB_TABLE_GRID(const SYMBOL_LIB_TABLE &aTableToEdit)
Hold a record identifying a symbol library accessed by the appropriate symbol library SCH_PLUGIN obje...
bool Refresh()
Attempt to reload the library.
static SYMBOL_LIB_TABLE & GetGlobalLibTable()
virtual void Parse(LIB_TABLE_LEXER *aLexer) override
Parse the #LIB_TABLE_LEXER s-expression library table format into the appropriate LIB_TABLE_ROW objec...
static const wxString & GetSymbolLibTableFileName()
static wxString GetGlobalTableFileName()
Fetch the global symbol library table file name.
static const wxString GlobalPathEnvVariableName()
Return the name of the environment variable used to hold the directory of locally installed "KiCad sp...
Symbol library viewer main window.
void SetTable(wxGridTableBase *table, bool aTakeOwnership=false)
Hide wxGrid's SetTable() method with one which doesn't mess up the grid column widths when setting th...
Definition: wx_grid.cpp:164
void ClearRows()
wxWidgets recently added an ASSERT which fires if the position is greater than or equal to the number...
Definition: wx_grid.h:139
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:423
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:299
The common library.
int OKOrCancelDialog(wxWindow *aParent, const wxString &aWarning, const wxString &aMessage, const wxString &aDetailedMessage, const wxString &aOKLabel, const wxString &aCancelLabel, bool *aApplyToAll)
Display a warning dialog with aMessage and returns the user response.
Definition: confirm.cpp:273
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:380
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:300
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:325
int UnsavedChangesDialog(wxWindow *parent, const wxString &aMessage, bool *aApplyToAll)
A specialized version of HandleUnsavedChanges which handles an apply-to-all checkbox.
Definition: confirm.cpp:197
This file is part of the common library.
#define _(s)
@ ID_END_EESCHEMA_ID_LIST
Definition: eeschema_id.h:83
wxString NormalizePath(const wxFileName &aFilePath, const ENV_VAR_MAP *aEnvVars, const wxString &aProjectPath)
Normalize a file path to an environmental variable, if possible.
Definition: env_paths.cpp:71
@ FRAME_SCH_SYMBOL_EDITOR
Definition: frame_type.h:35
@ FRAME_SCH_VIEWER
Definition: frame_type.h:36
@ FRAME_SCH
Definition: frame_type.h:34
wxString DatabaseLibFileWildcard()
wxString LegacySymbolLibFileWildcard()
wxString KiCadSymbolLibFileWildcard()
wxString AllSymbolLibFilesWildcard()
std::map< wxString, ENV_VAR_ITEM > ENV_VAR_MAP
LIB_TABLE_ROWS::iterator LIB_TABLE_ROWS_ITER
@ COL_DESCR
@ COL_NICKNAME
@ COL_ENABLED
@ COL_URI
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
void InvokeSchEditSymbolLibTable(KIWAY *aKiway, wxWindow *aParent)
@ ID_PANEL_SYM_LIB_LEGACY
@ ID_PANEL_SYM_LIB_KICAD
see class PGM_BASE
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
Definition: project.h:39
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
#define SEXPR_SYMBOL_LIB_FILE_VERSION
This file contains the file format version information for the s-expression schematic and symbol libr...
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_LIBID
Definition: string_utils.h:55
A filename or source description, a problem input line, a line number, a byte offset,...
Definition: ki_exception.h:119
Container that describes file type info for the add a library options.
bool m_IsFile
Whether the library is a folder or a file.
wxString m_Description
Description shown in the file picker dialog.
wxString m_FileFilter
Filter used for file pickers if m_IsFile is true.
SCH_IO_MGR::SCH_FILE_T m_Plugin
wxString m_FolderSearchExtension
In case of folders it stands for extensions of files stored inside.
Definition of file extensions used in Kicad.