KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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-2024 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 <build_version.h>
26#include <common.h> // For ExpandEnvVarSubstitutions
29#include <project.h>
30#include <panel_sym_lib_table.h>
31#include <lib_id.h>
32#include <symbol_lib_table.h>
33#include <lib_table_lexer.h>
35#include <widgets/wx_grid.h>
36#include <confirm.h>
37#include <bitmaps.h>
38#include <lib_table_grid.h>
40#include <env_paths.h>
41#include <eeschema_id.h>
42#include <symbol_edit_frame.h>
43#include <symbol_viewer_frame.h>
44#include <sch_edit_frame.h>
45#include <kiway.h>
46#include <paths.h>
47#include <pgm_base.h>
52#include <sch_file_versions.h>
53#include <wx/filedlg.h>
54#include <wx/msgdlg.h>
55#include <project_sch.h>
56
57
58
59// clang-format off
60
65{
66 wxString m_Description;
67 wxString m_FileFilter;
69 bool m_IsFile;
70 SCH_IO_MGR::SCH_FILE_T m_Plugin;
71};
72
73
77enum {
80};
81
82// clang-format on
83
88{
89 friend class PANEL_SYM_LIB_TABLE;
90 friend class SYMBOL_GRID_TRICKS;
91
92protected:
93 LIB_TABLE_ROW* at( size_t aIndex ) override { return &m_rows.at( aIndex ); }
94
95 size_t size() const override { return m_rows.size(); }
96
98 {
99 return dynamic_cast< LIB_TABLE_ROW* >( new SYMBOL_LIB_TABLE_ROW );
100 }
101
102 LIB_TABLE_ROWS_ITER begin() override { return m_rows.begin(); }
103
105 {
106 return m_rows.insert( aIterator, aRow );
107 }
108
109 void push_back( LIB_TABLE_ROW* aRow ) override { m_rows.push_back( aRow ); }
110
112 {
113 return m_rows.erase( aFirst, aLast );
114 }
115
116public:
117 void SetValue( int aRow, int aCol, const wxString &aValue ) override
118 {
119 wxCHECK( aRow < (int) size(), /* void */ );
120
121 LIB_TABLE_GRID::SetValue( aRow, aCol, aValue );
122
123 // If setting a filepath, attempt to auto-detect the format
124 if( aCol == COL_URI )
125 {
126 LIB_TABLE_ROW* row = at( (size_t) aRow );
127 wxString fullURI = row->GetFullURI( true );
128
129 SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromLibPath( fullURI );
130
131 if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
132 pluginType = SCH_IO_MGR::SCH_KICAD;
133
134 SetValue( aRow, COL_TYPE, SCH_IO_MGR::ShowType( pluginType ) );
135 }
136 }
137
138
140 {
141 m_rows = aTableToEdit.m_rows;
142 }
143};
144
146{
147public:
149 LIB_TABLE_GRID_TRICKS( aGrid ),
150 m_dialog( aParent )
151 {
152 }
153
154protected:
156
157 virtual void optionsEditor( int aRow ) override
158 {
160
161 if( tbl->GetNumberRows() > aRow )
162 {
163 LIB_TABLE_ROW* row = tbl->at( (size_t) aRow );
164 const wxString& options = row->GetOptions();
165 wxString result = options;
166 STRING_UTF8_MAP choices;
167
168 SCH_IO_MGR::SCH_FILE_T pi_type = SCH_IO_MGR::EnumFromStr( row->GetType() );
169 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( pi_type ) );
170 pi->GetLibraryOptions( &choices );
171
172 DIALOG_PLUGIN_OPTIONS dlg( m_dialog, row->GetNickName(), choices, options, &result );
173 dlg.ShowModal();
174
175 if( options != result )
176 {
177 row->SetOptions( result );
178 m_grid->Refresh();
179 }
180 }
181
182 }
183
186 virtual void paste_text( const wxString& cb_text ) override
187 {
189 size_t ndx = cb_text.find( "(sym_lib_table" );
190
191 if( ndx != std::string::npos )
192 {
193 // paste the SYMBOL_LIB_TABLE_ROWs of s-expression (sym_lib_table), starting
194 // at column 0 regardless of current cursor column.
195
196 STRING_LINE_READER slr( TO_UTF8( cb_text ), wxS( "Clipboard" ) );
197 LIB_TABLE_LEXER lexer( &slr );
198 SYMBOL_LIB_TABLE tmp_tbl;
199 bool parsed = true;
200
201 try
202 {
203 tmp_tbl.Parse( &lexer );
204 }
205 catch( PARSE_ERROR& pe )
206 {
207 DisplayError( m_dialog, pe.What() );
208 parsed = false;
209 }
210
211 if( parsed )
212 {
213 // make sure the table is big enough...
214 if( tmp_tbl.GetCount() > (unsigned) tbl->GetNumberRows() )
215 tbl->AppendRows( tmp_tbl.GetCount() - tbl->GetNumberRows() );
216
217 for( unsigned i = 0; i < tmp_tbl.GetCount(); ++i )
218 tbl->ReplaceRow( i, tmp_tbl.At( i ).clone() );
219 }
220
221 m_grid->AutoSizeColumns( false );
222 }
223 else
224 {
225 // paste spreadsheet formatted text.
226 GRID_TRICKS::paste_text( cb_text );
227
228 m_grid->AutoSizeColumns( false );
229 }
230 }
231};
232
233
235{
236 auto autoSizeCol =
237 [&]( WX_GRID* aCurrGrid, int aCol )
238 {
239 int prevWidth = aCurrGrid->GetColSize( aCol );
240
241 aCurrGrid->AutoSizeColumn( aCol, false );
242 aCurrGrid->SetColSize( aCol, std::max( prevWidth, aCurrGrid->GetColSize( aCol ) ) );
243 };
244
246
247 // Give a bit more room for combobox editors
248 for( int ii = 0; ii < aGrid->GetNumberRows(); ++ii )
249 aGrid->SetRowSize( ii, aGrid->GetDefaultRowSize() + 4 );
250
251 // add Cut, Copy, and Paste to wxGrids
252 aGrid->PushEventHandler( new SYMBOL_GRID_TRICKS( m_parent, aGrid ) );
253
254 aGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
255
256 // Set special attributes
257 wxGridCellAttr* attr;
258
259 attr = new wxGridCellAttr;
260
261 wxString fileFiltersStr;
262 wxString allWildcardsStr;
263
264 attr->SetEditor( new GRID_CELL_PATH_EDITOR( m_parent, aGrid,
265 &cfg->m_lastSymbolLibDir,
266 true, m_project->GetProjectPath(),
267 []( WX_GRID* grid, int row ) -> wxString
268 {
269 auto* libTable = static_cast<SYMBOL_LIB_TABLE_GRID*>( grid->GetTable() );
270 auto* tableRow = static_cast<SYMBOL_LIB_TABLE_ROW*>( libTable->at( row ) );
271
272 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( tableRow->GetFileType() ) );
273
274 if( pi )
275 {
276 const IO_BASE::IO_FILE_DESC& desc = pi->GetLibraryDesc();
277
278 if( desc.m_IsFile )
279 return desc.FileFilter();
280 }
281
282 return wxEmptyString;
283 } ) );
284 aGrid->SetColAttr( COL_URI, attr );
285
286 attr = new wxGridCellAttr;
287 attr->SetEditor( new wxGridCellChoiceEditor( m_pluginChoices ) );
288 aGrid->SetColAttr( COL_TYPE, attr );
289
290 attr = new wxGridCellAttr;
291 attr->SetRenderer( new wxGridCellBoolRenderer() );
292 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
293 aGrid->SetColAttr( COL_ENABLED, attr );
294
295 attr = new wxGridCellAttr;
296 attr->SetRenderer( new wxGridCellBoolRenderer() );
297 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
298 aGrid->SetColAttr( COL_VISIBLE, attr );
299
300 // all but COL_OPTIONS, which is edited with Option Editor anyways.
301 autoSizeCol( aGrid, COL_NICKNAME );
302 autoSizeCol( aGrid, COL_TYPE );
303 autoSizeCol( aGrid, COL_URI );
304 autoSizeCol( aGrid, COL_DESCR );
305 autoSizeCol( aGrid, COL_ENABLED );
306
307 // Gives a selection to each grid, mainly for delete button. wxGrid's wake up with
308 // a currentCell which is sometimes not highlighted.
309 if( aGrid->GetNumberRows() > 0 )
310 aGrid->SelectRow( 0 );
311};
312
313
315 SYMBOL_LIB_TABLE* aGlobalTable,
316 const wxString& aGlobalTablePath,
317 SYMBOL_LIB_TABLE* aProjectTable,
318 const wxString& aProjectTablePath ) :
319 PANEL_SYM_LIB_TABLE_BASE( aParent ),
320 m_globalTable( aGlobalTable ),
321 m_projectTable( aProjectTable ),
322 m_project( aProject ),
323 m_parent( aParent )
324{
325 // wxGrid only supports user owned tables if they exist past end of ~wxGrid(),
326 // so make it a grid owned table.
328
329 for( const SCH_IO_MGR::SCH_FILE_T& type : SCH_IO_MGR::SCH_FILE_T_vector )
330 {
331 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( type ) );
332
333 if( !pi )
334 continue;
335
336 if( const IO_BASE::IO_FILE_DESC& desc = pi->GetLibraryDesc() )
338 }
339
341
342 if( cfg->m_lastSymbolLibDir.IsEmpty() )
344
346
347
349
350 if( m_projectTable )
351 {
354 }
355 else
356 {
357 m_pageNdx = 0;
358 m_notebook->DeletePage( 1 );
359 m_project_grid = nullptr;
360 }
361
362 // add Cut, Copy, and Paste to wxGrids
363 m_path_subs_grid->PushEventHandler( new GRID_TRICKS( m_path_subs_grid ) );
364
366
367 // select the last selected page
368 m_notebook->SetSelection( m_pageNdx );
370
371 m_path_subs_grid->SetColLabelValue( 0, _( "Name" ) );
372 m_path_subs_grid->SetColLabelValue( 1, _( "Value" ) );
373
374 // for ALT+A handling, we want the initial focus to be on the first selected grid.
376
377 // Configure button logos
378 m_append_button->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
379 m_delete_button->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
380 m_move_up_button->SetBitmap( KiBitmapBundle( BITMAPS::small_up ) );
381 m_move_down_button->SetBitmap( KiBitmapBundle( BITMAPS::small_down ) );
382 m_browse_button->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
383}
384
385
387{
388 // Delete the GRID_TRICKS.
389 // Any additional event handlers should be popped before the window is deleted.
390 m_global_grid->PopEventHandler( true );
391
392 if( m_project_grid )
393 m_project_grid->PopEventHandler( true );
394
395 m_path_subs_grid->PopEventHandler( true );
396}
397
398
400{
401 // When the plugin type depends only of the file extension, return true.
402 // if it needs to read the actual file (taht can be not available), return false
403
404 wxFileName fn( aLibraryPath );
405 wxString ext = fn.GetExt().Lower();
406
407 // Currently, only the extension .lib is common to legacy libraries and Cadstar libraries
408 // so return false in this case
410 return false;
411
412 return true;
413}
414
415
417{
418 wxString msg;
419 wxBusyCursor wait;
420
421 for( SYMBOL_LIB_TABLE_GRID* model : { global_model(), project_model() } )
422 {
423 if( !model )
424 continue;
425
426 for( int r = 0; r < model->GetNumberRows(); )
427 {
428 wxString nick = model->GetValue( r, COL_NICKNAME ).Trim( false ).Trim();
429 wxString uri = model->GetValue( r, COL_URI ).Trim( false ).Trim();
430 unsigned illegalCh = 0;
431
432 if( !nick || !uri )
433 {
434 if( !nick && !uri )
435 msg = _( "A library table row nickname and path cells are empty." );
436 else if( !nick )
437 msg = _( "A library table row nickname cell is empty." );
438 else
439 msg = _( "A library table row path cell is empty." );
440
441 wxWindow* topLevelParent = wxGetTopLevelParent( this );
442
443 wxMessageDialog badCellDlg( topLevelParent, msg, _( "Invalid Row Definition" ),
444 wxYES_NO | wxCENTER | wxICON_QUESTION | wxYES_DEFAULT );
445 badCellDlg.SetExtendedMessage( _( "Empty cells will result in all rows that are "
446 "invalid to be removed from the table." ) );
447 badCellDlg.SetYesNoLabels( wxMessageDialog::ButtonLabel( _( "Remove Invalid Cells" ) ),
448 wxMessageDialog::ButtonLabel( _( "Cancel Table Update" ) ) );
449
450 wxEndBusyCursor();
451
452 if( badCellDlg.ShowModal() == wxID_NO )
453 return false;
454
455 wxBeginBusyCursor( wxHOURGLASS_CURSOR );
456
457 // Delete the "empty" row, where empty means missing nick or uri.
458 // This also updates the UI which could be slow, but there should only be a few
459 // rows to delete, unless the user fell asleep on the Add Row
460 // button.
461 model->DeleteRows( r, 1 );
462 }
463 else if( ( illegalCh = LIB_ID::FindIllegalLibraryNameChar( nick ) ) )
464 {
465 msg = wxString::Format( _( "Illegal character '%c' in nickname '%s'" ),
466 illegalCh,
467 nick );
468
469 // show the tabbed panel holding the grid we have flunked:
470 if( model != cur_model() )
471 m_notebook->SetSelection( model == global_model() ? 0 : 1 );
472
473 m_cur_grid->MakeCellVisible( r, 0 );
474 m_cur_grid->SetGridCursor( r, 1 );
475
476 wxWindow* topLevelParent = wxGetTopLevelParent( this );
477
478 wxMessageDialog errdlg( topLevelParent, msg, _( "Library Nickname Error" ) );
479
480 wxEndBusyCursor();
481 errdlg.ShowModal();
482 return false;
483 }
484 else
485 {
486 // set the trimmed values back into the table so they get saved to disk.
487 model->SetValue( r, COL_NICKNAME, nick );
488
490 model->SetValue( r, COL_URI, uri );
491 else
492 {
493 wxString ltype = model->GetValue( r, COL_TYPE );
494 model->LIB_TABLE_GRID::SetValue( r, COL_URI, uri );
495 model->SetValue( r, COL_TYPE, ltype );
496 }
497
498 ++r; // this row was OK.
499 }
500 }
501 }
502
503 // check for duplicate nickNames, separately in each table.
504 for( SYMBOL_LIB_TABLE_GRID* model : { global_model(), project_model() } )
505 {
506 if( !model )
507 continue;
508
509 for( int r1 = 0; r1 < model->GetNumberRows() - 1; ++r1 )
510 {
511 wxString nick1 = model->GetValue( r1, COL_NICKNAME );
512
513 for( int r2=r1+1; r2 < model->GetNumberRows(); ++r2 )
514 {
515 wxString nick2 = model->GetValue( r2, COL_NICKNAME );
516
517 if( nick1 == nick2 )
518 {
519 msg = wxString::Format( _( "Multiple libraries cannot share the same "
520 "nickname ('%s')." ), nick1 );
521
522 // show the tabbed panel holding the grid we have flunked:
523 if( model != cur_model() )
524 m_notebook->SetSelection( model == global_model() ? 0 : 1 );
525
526 // go to the lower of the two rows, it is technically the duplicate:
527 m_cur_grid->MakeCellVisible( r2, 0 );
528 m_cur_grid->SetGridCursor( r2, 1 );
529
530 wxWindow* topLevelParent = wxGetTopLevelParent( this );
531
532 wxEndBusyCursor();
533 wxMessageDialog errdlg( topLevelParent, msg, _( "Library Nickname Error" ) );
534 errdlg.ShowModal();
535
536 return false;
537 }
538 }
539 }
540 }
541
542 for( SYMBOL_LIB_TABLE* table : { global_model(), project_model() } )
543 {
544 if( !table )
545 continue;
546
547 for( unsigned int r = 0; r < table->GetCount(); ++r )
548 {
549 SYMBOL_LIB_TABLE_ROW& row = dynamic_cast<SYMBOL_LIB_TABLE_ROW&>( table->At( r ) );
550
551 // Newly-added rows won't have set this yet
552 row.SetParent( table );
553
554 if( !row.GetIsEnabled() )
555 continue;
556
557 try
558 {
559 if( row.Refresh() )
560 {
561 if( table == global_model() )
563 else
565 }
566 }
567 catch( const IO_ERROR& ioe )
568 {
569 msg.Printf( _( "Symbol library '%s' failed to load." ), row.GetNickName() );
570
571 wxWindow* topLevelParent = wxGetTopLevelParent( this );
572 wxEndBusyCursor();
573 wxMessageDialog errdlg( topLevelParent, msg + wxS( "\n" ) + ioe.What(),
574 _( "Error Loading Library" ) );
575 errdlg.ShowModal();
576
577 return true;
578 }
579 }
580 }
581
582 return true;
583}
584
585
586void PANEL_SYM_LIB_TABLE::OnUpdateUI( wxUpdateUIEvent& event )
587{
588}
589
590
592{
593 wxString fileFiltersStr;
594 wxString allWildcardsStr;
595
596 for( const SCH_IO_MGR::SCH_FILE_T& fileType : SCH_IO_MGR::SCH_FILE_T_vector )
597 {
598 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
599
600 if( !pi )
601 continue;
602
603 const IO_BASE::IO_FILE_DESC& desc = pi->GetLibraryDesc();
604
605 if( desc.m_FileExtensions.empty() )
606 continue;
607
608 if( !fileFiltersStr.IsEmpty() )
609 fileFiltersStr += wxChar( '|' );
610
611 fileFiltersStr += desc.FileFilter();
612
613 for( const std::string& ext : desc.m_FileExtensions )
614 allWildcardsStr << wxT( "*." ) << formatWildcardExt( ext ) << wxT( ";" );
615 }
616
617 fileFiltersStr = _( "All supported formats" ) + wxT( "|" ) + allWildcardsStr + wxT( "|" )
618 + fileFiltersStr;
619
621
622 wxString openDir = cfg->m_lastSymbolLibDir;
623
625 openDir = m_lastProjectLibDir;
626
627 wxWindow* topLevelParent = wxGetTopLevelParent( this );
628
629 wxFileDialog dlg( topLevelParent, _( "Add Library" ), openDir, wxEmptyString, fileFiltersStr,
630 wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE );
631
632 if( dlg.ShowModal() == wxID_CANCEL )
633 return;
634
636 cfg->m_lastSymbolLibDir = dlg.GetDirectory();
637 else
638 m_lastProjectLibDir = dlg.GetDirectory();
639
640 const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
641 bool addDuplicates = false;
642 bool applyToAll = false;
643 wxString warning = _( "Warning: Duplicate Nickname" );
644 wxString msg = _( "A library nicknamed '%s' already exists." );
645 wxString detailedMsg = _( "One of the nicknames will need to be changed after "
646 "adding this library." );
647
648 wxArrayString filePathsList;
649 dlg.GetPaths( filePathsList );
650
651 for( const wxString& filePath : filePathsList )
652 {
653 wxFileName fn( filePath );
654 wxString nickname = LIB_ID::FixIllegalChars( fn.GetName(), true );
655 bool doAdd = true;
656
657 if( cur_model()->ContainsNickname( nickname ) )
658 {
659 if( !applyToAll )
660 {
661 // The cancel button adds the library to the table anyway
662 addDuplicates = OKOrCancelDialog( wxGetTopLevelParent( this ), warning,
663 wxString::Format( msg, nickname ),
664 detailedMsg, _( "Skip" ), _( "Add Anyway" ),
665 &applyToAll ) == wxID_CANCEL;
666 }
667
668 doAdd = addDuplicates;
669 }
670
671 if( doAdd && m_cur_grid->AppendRows( 1 ) )
672 {
673 int last_row = m_cur_grid->GetNumberRows() - 1;
674
675 m_cur_grid->SetCellValue( last_row, COL_NICKNAME, nickname );
676
677 // attempt to auto-detect the plugin type
678 SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromLibPath( filePath );
679
680 if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
681 pluginType = SCH_IO_MGR::SCH_KICAD;
682
683 m_cur_grid->SetCellValue( last_row, COL_TYPE, SCH_IO_MGR::ShowType( pluginType ) );
684
685 // try to use path normalized to an environmental variable or project path
686 wxString path = NormalizePath( filePath, &envVars, m_project->GetProjectPath() );
687
688 // Do not use the project path in the global library table. This will almost
689 // assuredly be wrong for a different project.
690 if( m_pageNdx == 0 && path.Contains( "${KIPRJMOD}" ) )
691 path = fn.GetFullPath();
692
693 m_cur_grid->SetCellValue( last_row, COL_URI, path );
694 }
695 }
696
697 if( !filePathsList.IsEmpty() )
698 {
699 m_cur_grid->MakeCellVisible( m_cur_grid->GetNumberRows() - 1, COL_ENABLED );
700 m_cur_grid->SetGridCursor( m_cur_grid->GetNumberRows() - 1, COL_NICKNAME );
701 }
702}
703
704
705void PANEL_SYM_LIB_TABLE::appendRowHandler( wxCommandEvent& event )
706{
708 return;
709
710 if( m_cur_grid->AppendRows( 1 ) )
711 {
712 int row = m_cur_grid->GetNumberRows() - 1;
713
714 // wx documentation is wrong, SetGridCursor does not make visible.
715 m_cur_grid->MakeCellVisible( row, COL_ENABLED );
716 m_cur_grid->SetGridCursor( row, COL_NICKNAME );
717 m_cur_grid->EnableCellEditControl( true );
718 m_cur_grid->ShowCellEditControl();
719 }
720}
721
722
723void PANEL_SYM_LIB_TABLE::deleteRowHandler( wxCommandEvent& event )
724{
726 return;
727
728 int curRow = m_cur_grid->GetGridCursorRow();
729 int curCol = m_cur_grid->GetGridCursorCol();
730
731 // In a wxGrid, collect rows that have a selected cell, or are selected
732 // It is not so easy: it depends on the way the selection was made.
733 // Here, we collect rows selected by clicking on a row label, and rows that contain
734 // previously-selected cells.
735 // If no candidate, just delete the row with the grid cursor.
736 wxArrayInt selectedRows = m_cur_grid->GetSelectedRows();
737 wxGridCellCoordsArray cells = m_cur_grid->GetSelectedCells();
738 wxGridCellCoordsArray blockTopLeft = m_cur_grid->GetSelectionBlockTopLeft();
739 wxGridCellCoordsArray blockBotRight = m_cur_grid->GetSelectionBlockBottomRight();
740
741 // Add all row having cell selected to list:
742 for( unsigned ii = 0; ii < cells.GetCount(); ii++ )
743 selectedRows.Add( cells[ii].GetRow() );
744
745 // Handle block selection
746 if( !blockTopLeft.IsEmpty() && !blockBotRight.IsEmpty() )
747 {
748 for( int i = blockTopLeft[0].GetRow(); i <= blockBotRight[0].GetRow(); ++i )
749 selectedRows.Add( i );
750 }
751
752 // Use the row having the grid cursor only if we have no candidate:
753 if( selectedRows.size() == 0 && m_cur_grid->GetGridCursorRow() >= 0 )
754 selectedRows.Add( m_cur_grid->GetGridCursorRow() );
755
756 if( selectedRows.size() == 0 )
757 {
758 wxBell();
759 return;
760 }
761
762 std::sort( selectedRows.begin(), selectedRows.end() );
763
764 // Remove selected rows (note: a row can be stored more than once in list)
765 int last_row = -1;
766
767 // Needed to avoid a wxWidgets alert if the row to delete is the last row
768 // at least on wxMSW 3.2
769 m_cur_grid->ClearSelection();
770
771 for( int ii = selectedRows.GetCount()-1; ii >= 0; ii-- )
772 {
773 int row = selectedRows[ii];
774
775 if( row != last_row )
776 {
777 last_row = row;
778 m_cur_grid->DeleteRows( row, 1 );
779 }
780 }
781
782 if( m_cur_grid->GetNumberRows() > 0 && curRow >= 0 )
783 m_cur_grid->SetGridCursor( std::min( curRow, m_cur_grid->GetNumberRows() - 1 ), curCol );
784}
785
786
787void PANEL_SYM_LIB_TABLE::moveUpHandler( wxCommandEvent& event )
788{
790 return;
791
793 int curRow = m_cur_grid->GetGridCursorRow();
794
795 // @todo: add multiple selection moves.
796 if( curRow >= 1 )
797 {
798 tbl->ChangeRowOrder( curRow--, -1 );
799
800 if( tbl->GetView() )
801 {
802 // Update the wxGrid
803 wxGridTableMessage msg( tbl, wxGRIDTABLE_NOTIFY_ROWS_INSERTED, curRow, 0 );
804 tbl->GetView()->ProcessTableMessage( msg );
805 }
806
807 m_cur_grid->MakeCellVisible( curRow, m_cur_grid->GetGridCursorCol() );
808 m_cur_grid->SetGridCursor( curRow, m_cur_grid->GetGridCursorCol() );
809 }
810}
811
812
813void PANEL_SYM_LIB_TABLE::moveDownHandler( wxCommandEvent& event )
814{
816 return;
817
819 int curRow = m_cur_grid->GetGridCursorRow();
820
821 // @todo: add multiple selection moves.
822 if( unsigned( curRow + 1 ) < tbl->m_rows.size() )
823 {
824 tbl->ChangeRowOrder( curRow++, 1 );
825
826 if( tbl->GetView() )
827 {
828 // Update the wxGrid
829 wxGridTableMessage msg( tbl, wxGRIDTABLE_NOTIFY_ROWS_INSERTED, curRow - 1, 0 );
830 tbl->GetView()->ProcessTableMessage( msg );
831 }
832
833 m_cur_grid->MakeCellVisible( curRow, m_cur_grid->GetGridCursorCol() );
834 m_cur_grid->SetGridCursor( curRow, m_cur_grid->GetGridCursorCol() );
835 }
836}
837
838
839void PANEL_SYM_LIB_TABLE::onReset( wxCommandEvent& event )
840{
842 return;
843
844 // No need to prompt to preserve an empty table
845 if( m_global_grid->GetNumberRows() > 0 &&
846 !IsOK( this, wxString::Format( _( "This action will reset your global library table on "
847 "disk and cannot be undone." ) ) ) )
848 {
849 return;
850 }
851
852
854
855 if( dlg.ShowModal() == wxID_OK )
856 {
857 m_global_grid->Freeze();
858
859 wxGridTableBase* table = m_global_grid->GetTable();
860 m_global_grid->DestroyTable( table );
861
863 m_global_grid->PopEventHandler( true );
866
867 m_global_grid->Thaw();
868 }
869}
870
871
872void PANEL_SYM_LIB_TABLE::onPageChange( wxBookCtrlEvent& event )
873{
874 m_pageNdx = (unsigned) std::max( 0, m_notebook->GetSelection() );
875
876 if( m_pageNdx == 0 )
877 {
879 m_resetGlobal->Enable();
880 }
881 else
882 {
884 m_resetGlobal->Disable();
885 }
886}
887
888
890{
892 return;
893
894 wxArrayInt selectedRows = m_cur_grid->GetSelectedRows();
895
896 if( selectedRows.empty() && m_cur_grid->GetGridCursorRow() >= 0 )
897 selectedRows.push_back( m_cur_grid->GetGridCursorRow() );
898
899 wxArrayInt legacyRows;
900 wxString databaseType = SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_DATABASE );
901 wxString kicadType = SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_KICAD );
902 wxString msg;
903
904 for( int row : selectedRows )
905 {
906 if( m_cur_grid->GetCellValue( row, COL_TYPE ) != databaseType &&
907 m_cur_grid->GetCellValue( row, COL_TYPE ) != kicadType )
908 {
909 legacyRows.push_back( row );
910 }
911 }
912
913 if( legacyRows.size() <= 0 )
914 {
915 wxMessageBox( _( "Select one or more rows containing libraries "
916 "to save as current KiCad format (*.kicad_sym)." ) );
917 return;
918 }
919 else
920 {
921 if( legacyRows.size() == 1 )
922 {
923 msg.Printf( _( "Save '%s' as current KiCad format (*.kicad_sym) "
924 "and replace legacy entry in table?" ),
925 m_cur_grid->GetCellValue( legacyRows[0], COL_NICKNAME ) );
926 }
927 else
928 {
929 msg.Printf( _( "Save %d libraries as current KiCad format (*.kicad_sym) "
930 "and replace legacy entries in table?" ),
931 (int) legacyRows.size() );
932 }
933
934 if( !IsOK( m_parent, msg ) )
935 return;
936 }
937
938 for( int row : legacyRows )
939 {
940 wxString libName = m_cur_grid->GetCellValue( row, COL_NICKNAME );
941 wxString relPath = m_cur_grid->GetCellValue( row, COL_URI );
942 wxString resolvedPath = ExpandEnvVarSubstitutions( relPath, m_project );
943 wxFileName legacyLib( resolvedPath );
944
945 if( !legacyLib.Exists() )
946 {
947 msg.Printf( _( "Library '%s' not found." ), relPath );
948
949 wxWindow* topLevelParent = wxGetTopLevelParent( this );
950
951 DisplayErrorMessage( topLevelParent, msg );
952 continue;
953 }
954
955 wxFileName newLib( resolvedPath );
956 newLib.SetExt( "kicad_sym" );
957
958 if( newLib.Exists() )
959 {
960 msg.Printf( _( "File '%s' already exists. Do you want overwrite this file?" ),
961 newLib.GetFullPath() );
962
963 switch( wxMessageBox( msg, _( "Migrate Library" ),
964 wxYES_NO | wxCANCEL | wxICON_QUESTION, m_parent ) )
965 {
966 case wxYES: break;
967 case wxNO: continue;
968 case wxCANCEL: return;
969 }
970 }
971
972 wxString options = m_cur_grid->GetCellValue( row, COL_OPTIONS );
973 std::unique_ptr<STRING_UTF8_MAP> props( LIB_TABLE::ParseOptions( options.ToStdString() ) );
974
975 if( SCH_IO_MGR::ConvertLibrary( props.get(), legacyLib.GetFullPath(), newLib.GetFullPath() ) )
976 {
977 relPath = NormalizePath( newLib.GetFullPath(), &Pgm().GetLocalEnvVariables(),
978 m_project );
979
980 // Do not use the project path in the global library table. This will almost
981 // assuredly be wrong for a different project.
982 if( m_cur_grid == m_global_grid && relPath.Contains( "${KIPRJMOD}" ) )
983 relPath = newLib.GetFullPath();
984
985 m_cur_grid->SetCellValue( row, COL_URI, relPath );
986 m_cur_grid->SetCellValue( row, COL_TYPE, kicadType );
987 m_cur_grid->SetCellValue( row, COL_OPTIONS, wxEmptyString );
988 }
989 else
990 {
991 msg.Printf( _( "Failed to save symbol library file '%s'." ), newLib.GetFullPath() );
992
993 wxWindow* topLevelParent = wxGetTopLevelParent( this );
994
995 DisplayErrorMessage( topLevelParent, msg );
996 }
997 }
998}
999
1000
1002{
1004 return false;
1005
1006 if( !verifyTables() )
1007 return false;
1008
1009 if( *global_model() != *m_globalTable )
1010 {
1012
1015 }
1016
1018 {
1020
1023 }
1024
1025 return true;
1026}
1027
1028
1030{
1031 wxRegEx re( ".*?(\\$\\{(.+?)\\})|(\\$\\((.+?)\\)).*?", wxRE_ADVANCED );
1032 wxASSERT( re.IsValid() ); // wxRE_ADVANCED is required.
1033
1034 std::set< wxString > unique;
1035
1036 // clear the table
1038
1039 for( SYMBOL_LIB_TABLE_GRID* tbl : { global_model(), project_model() } )
1040 {
1041 if( !tbl )
1042 continue;
1043
1044 for( int row = 0; row < tbl->GetNumberRows(); ++row )
1045 {
1046 wxString uri = tbl->GetValue( row, COL_URI );
1047
1048 while( re.Matches( uri ) )
1049 {
1050 wxString envvar = re.GetMatch( uri, 2 );
1051
1052 // if not ${...} form then must be $(...)
1053 if( envvar.IsEmpty() )
1054 envvar = re.GetMatch( uri, 4 );
1055
1056 // ignore duplicates
1057 unique.insert( envvar );
1058
1059 // delete the last match and search again
1060 uri.Replace( re.GetMatch( uri, 0 ), wxEmptyString );
1061 }
1062 }
1063 }
1064
1065 // Make sure this special environment variable shows up even if it was
1066 // not used yet. It is automatically set by KiCad to the directory holding
1067 // the current project.
1068 unique.insert( PROJECT_VAR_NAME );
1070
1071 for( const wxString& evName : unique )
1072 {
1073 int row = m_path_subs_grid->GetNumberRows();
1074 m_path_subs_grid->AppendRows( 1 );
1075
1076 m_path_subs_grid->SetCellValue( row, 0, wxT( "${" ) + evName + wxT( "}" ) );
1077 m_path_subs_grid->SetCellEditor( row, 0, new GRID_CELL_READONLY_TEXT_EDITOR() );
1078
1079 wxString evValue;
1080 wxGetEnv( evName, &evValue );
1081 m_path_subs_grid->SetCellValue( row, 1, evValue );
1082 m_path_subs_grid->SetCellEditor( row, 1, new GRID_CELL_READONLY_TEXT_EDITOR() );
1083 }
1084
1085 // No combobox editors here, but it looks better if its consistent with the other
1086 // grids in the dialog.
1087 m_path_subs_grid->SetDefaultRowSize( m_path_subs_grid->GetDefaultRowSize() + 2 );
1088
1089 adjustPathSubsGridColumns( m_path_subs_grid->GetRect().GetWidth() );
1090}
1091
1092
1094{
1095 // Account for scroll bars
1096 aWidth -= ( m_path_subs_grid->GetSize().x - m_path_subs_grid->GetClientSize().x );
1097
1098 m_path_subs_grid->AutoSizeColumn( 0 );
1099 m_path_subs_grid->SetColSize( 0, std::max( 72, m_path_subs_grid->GetColSize( 0 ) ) );
1100 m_path_subs_grid->SetColSize( 1, std::max( 120, aWidth - m_path_subs_grid->GetColSize( 0 ) ) );
1101}
1102
1103
1104void PANEL_SYM_LIB_TABLE::onSizeGrid( wxSizeEvent& event )
1105{
1106 adjustPathSubsGridColumns( event.GetSize().GetX() );
1107
1108 event.Skip();
1109}
1110
1111
1113{
1114 return (SYMBOL_LIB_TABLE_GRID*) m_global_grid->GetTable();
1115}
1116
1117
1119{
1120 return m_project_grid ? (SYMBOL_LIB_TABLE_GRID*) m_project_grid->GetTable() : nullptr;
1121}
1122
1123
1125{
1126 return (SYMBOL_LIB_TABLE_GRID*) m_cur_grid->GetTable();
1127}
1128
1129
1131
1132
1133void InvokeSchEditSymbolLibTable( KIWAY* aKiway, wxWindow *aParent )
1134{
1135 auto* symbolEditor = (SYMBOL_EDIT_FRAME*) aKiway->Player( FRAME_SCH_SYMBOL_EDITOR, false );
1136
1138 wxString globalTablePath = SYMBOL_LIB_TABLE::GetGlobalTableFileName();
1139 SYMBOL_LIB_TABLE* projectTable = nullptr;
1140 wxString projectPath = aKiway->Prj().GetProjectPath();
1141 wxFileName projectTableFn( projectPath, SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() );
1142 wxString msg;
1143 wxString currentLib;
1144
1145 // Don't allow editing project tables if no project is open
1146 if( !aKiway->Prj().IsNullProject() )
1147 projectTable = PROJECT_SCH::SchSymbolLibTable( &aKiway->Prj() );
1148
1149 if( symbolEditor )
1150 {
1151 currentLib = symbolEditor->GetCurLib();
1152
1153 // This prevents an ugly crash on OSX (https://bugs.launchpad.net/kicad/+bug/1765286)
1154 symbolEditor->FreezeLibraryTree();
1155
1156 if( symbolEditor->HasLibModifications() )
1157 {
1158 msg = _( "Modifications have been made to one or more symbol libraries.\n"
1159 "Changes must be saved or discarded before the symbol library "
1160 "table can be modified." );
1161
1162 switch( UnsavedChangesDialog( aParent, msg ) )
1163 {
1164 case wxID_YES: symbolEditor->SaveAll(); break;
1165 case wxID_NO: symbolEditor->RevertAll(); break;
1166 default:
1167 case wxID_CANCEL: symbolEditor->ThawLibraryTree(); return;
1168 }
1169 }
1170 }
1171
1172 DIALOG_EDIT_LIBRARY_TABLES dlg( aParent, _( "Symbol Libraries" ) );
1173 dlg.SetKiway( &dlg, aKiway );
1174
1175 dlg.InstallPanel( new PANEL_SYM_LIB_TABLE( &dlg, &aKiway->Prj(), globalTable, globalTablePath,
1176 projectTable, projectTableFn.GetFullPath() ) );
1177
1178 if( dlg.ShowModal() == wxID_CANCEL )
1179 {
1180 if( symbolEditor )
1181 symbolEditor->ThawLibraryTree();
1182
1183 return;
1184 }
1185
1186 if( dlg.m_GlobalTableChanged )
1187 {
1188 try
1189 {
1190 globalTable->Save( globalTablePath );
1191 }
1192 catch( const IO_ERROR& ioe )
1193 {
1194 msg.Printf( _( "Error saving global library table:\n\n%s" ), ioe.What() );
1195 wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
1196 }
1197 }
1198
1199 if( projectTable && dlg.m_ProjectTableChanged )
1200 {
1201 try
1202 {
1203 projectTable->Save( projectTableFn.GetFullPath() );
1204 }
1205 catch( const IO_ERROR& ioe )
1206 {
1207 msg.Printf( _( "Error saving project-specific library table:\n\n%s" ), ioe.What() );
1208 wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
1209 }
1210 }
1211
1212 if( symbolEditor )
1213 {
1214 symbolEditor->ThawLibraryTree();
1215 }
1216
1217 std::string payload = "";
1218 aKiway->ExpressMail( FRAME_SCH, MAIL_RELOAD_LIB, payload );
1220 aKiway->ExpressMail( FRAME_SCH_VIEWER, MAIL_RELOAD_LIB, payload );
1221}
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
Definition: bitmap.cpp:110
DIALOG_PLUGIN_OPTIONS is an options editor in the form of a two column name/value spreadsheet like (t...
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:102
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:125
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
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:279
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:406
virtual void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string &aPayload, wxWindow *aSource=nullptr)
Send aPayload to aDestination from aSource.
Definition: kiway.cpp:527
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
Definition: kiway.cpp:196
static unsigned FindIllegalLibraryNameChar(const UTF8 &aLibraryName)
Looks for characters that are illegal in library nicknames.
Definition: lib_id.cpp:243
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, bool aLib)
Replace illegal LIB_ID item name characters with underscores '_'.
Definition: lib_id.cpp:191
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.
const wxString & GetOptions() const
Return the options string, which may hold a password or anything else needed to instantiate the under...
virtual const wxString GetType() const =0
Return the type of library represented by this row.
void SetParent(LIB_TABLE *aParent)
const wxString & GetNickName() const
const wxString GetFullURI(bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
LIB_TABLE_ROW * clone() const
bool GetIsEnabled() const
void SetOptions(const wxString &aOptions)
Change the library options strings.
bool ReplaceRow(size_t aIndex, LIB_TABLE_ROW *aRow)
Replaces the Nth row with the given new row.
LIB_TABLE_ROW & At(unsigned aIndex)
Get the 'n'th LIB_TABLE_ROW object.
void TransferRows(LIB_TABLE_ROWS &aRowsList)
Takes ownership of another list of rows; the original list will be freed.
LIB_TABLE_ROWS m_rows
Owning set of rows.
void Clear()
Delete all rows.
unsigned GetCount() const
Get the number of rows contained in the table.
bool ChangeRowOrder(size_t aIndex, int aOffset)
Moves a row within the table.
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
static STRING_UTF8_MAP * ParseOptions(const std::string &aOptionsList)
Parses aOptionsList and places the result into a #PROPERTIES object which is returned.
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
void onPageChange(wxBookCtrlEvent &event) override
bool allowAutomaticPluginTypeSelection(wxString &aLibraryPath)
SYMBOL_LIB_TABLE * m_projectTable
static size_t m_pageNdx
Remember the last notebook page selected.
void setupGrid(WX_GRID *aGrid)
void onReset(wxCommandEvent &event) override
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)
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
wxArrayString m_pluginChoices
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:87
virtual ENV_VAR_MAP & GetLocalEnvVariables() const
Definition: pgm_base.cpp:923
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:142
static SYMBOL_LIB_TABLE * SchSymbolLibTable(PROJECT *aProject)
Accessor for project symbol library table.
Container for project specific data.
Definition: project.h:62
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:135
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Definition: project.cpp:153
static SCH_FILE_T EnumFromStr(const wxString &aFileType)
Return the #SCH_FILE_T from the corresponding plugin type name: "kicad", "legacy",...
Definition: sch_io_mgr.cpp:107
static const wxString ShowType(SCH_FILE_T aFileType)
Return a brief name for a plugin, given aFileType enum.
Definition: sch_io_mgr.cpp:83
static bool ConvertLibrary(STRING_UTF8_MAP *aOldFileProps, const wxString &aOldFilePath, const wxString &aNewFilepath)
Convert a schematic symbol library to the latest KiCad format.
Definition: sch_io_mgr.cpp:191
static SCH_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath, int aCtl=0)
Return a plugin type given a symbol library using the file extension of aLibPath.
Definition: sch_io_mgr.cpp:140
T * GetAppSettings()
Returns a handle to the a given settings by type If the settings have already been loaded,...
void SetBitmap(const wxBitmapBundle &aBmp)
Is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition: richio.h:253
A name/value tuple with unique names and optional values.
The symbol library editor main window.
DIALOG_EDIT_LIBRARY_TABLES * m_dialog
virtual void optionsEditor(int aRow) override
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_IO object i...
bool Refresh() override
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...
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:267
void DestroyTable(wxGridTableBase *aTable)
Work-around for a bug in wxGrid which crashes when deleting the table if the cell edit control was no...
Definition: wx_grid.cpp:400
void ClearRows()
wxWidgets recently added an ASSERT which fires if the position is greater than or equal to the number...
Definition: wx_grid.h:165
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:594
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:334
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:143
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:250
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:195
int UnsavedChangesDialog(wxWindow *parent, const wxString &aMessage, bool *aApplyToAll)
A specialized version of HandleUnsavedChanges which handles an apply-to-all checkbox.
Definition: confirm.cpp:66
This file is part of the common library.
#define _(s)
@ ID_END_EESCHEMA_ID_LIST
Definition: eeschema_id.h:71
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
static const std::string LegacySymbolLibFileExtension
std::map< wxString, ENV_VAR_ITEM > ENV_VAR_MAP
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition: io_mgr.h:33
LIB_TABLE_ROWS::iterator LIB_TABLE_ROWS_ITER
@ COL_DESCR
@ COL_NICKNAME
@ COL_OPTIONS
@ COL_ENABLED
@ COL_URI
@ MAIL_RELOAD_LIB
Definition: mail_type.h:56
void InvokeSchEditSymbolLibTable(KIWAY *aKiway, wxWindow *aParent)
@ ID_PANEL_SYM_LIB_LEGACY
@ ID_PANEL_SYM_LIB_KICAD
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1059
see class PGM_BASE
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
Definition: project.h:39
MODEL3D_FORMAT_TYPE fileType(const char *aFileName)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: string_utils.h:391
Container that describes file type info.
Definition: io_base.h:40
std::vector< std::string > m_FileExtensions
Filter used for file pickers if m_IsFile is true.
Definition: io_base.h:42
wxString FileFilter() const
Definition: io_base.cpp:40
A filename or source description, a problem input line, a line number, a byte offset,...
Definition: ki_exception.h:120
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.
wxString formatWildcardExt(const wxString &aWildcard)
Format wildcard extension to support case sensitive file dialogs.
Definition of file extensions used in Kicad.