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
233 {
234 return true;
235 }
236};
237
238
240{
241 auto autoSizeCol =
242 [&]( WX_GRID* aCurrGrid, int aCol )
243 {
244 int prevWidth = aCurrGrid->GetColSize( aCol );
245
246 aCurrGrid->AutoSizeColumn( aCol, false );
247 aCurrGrid->SetColSize( aCol, std::max( prevWidth, aCurrGrid->GetColSize( aCol ) ) );
248 };
249
251
252 // Give a bit more room for combobox editors
253 for( int ii = 0; ii < aGrid->GetNumberRows(); ++ii )
254 aGrid->SetRowSize( ii, aGrid->GetDefaultRowSize() + 4 );
255
256 // add Cut, Copy, and Paste to wxGrids
257 aGrid->PushEventHandler( new SYMBOL_GRID_TRICKS( m_parent, aGrid ) );
258
259 aGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
260
261 // Set special attributes
262 wxGridCellAttr* attr;
263
264 attr = new wxGridCellAttr;
265
266 wxString fileFiltersStr;
267 wxString allWildcardsStr;
268
269 attr->SetEditor( new GRID_CELL_PATH_EDITOR( m_parent, aGrid,
270 &cfg->m_lastSymbolLibDir,
271 true, m_project->GetProjectPath(),
272 []( WX_GRID* grid, int row ) -> wxString
273 {
274 auto* libTable = static_cast<SYMBOL_LIB_TABLE_GRID*>( grid->GetTable() );
275 auto* tableRow = static_cast<SYMBOL_LIB_TABLE_ROW*>( libTable->at( row ) );
276
277 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( tableRow->GetFileType() ) );
278
279 if( pi )
280 {
281 const IO_BASE::IO_FILE_DESC& desc = pi->GetLibraryDesc();
282
283 if( desc.m_IsFile )
284 return desc.FileFilter();
285 }
286
287 return wxEmptyString;
288 } ) );
289 aGrid->SetColAttr( COL_URI, attr );
290
291 attr = new wxGridCellAttr;
292 attr->SetEditor( new wxGridCellChoiceEditor( m_pluginChoices ) );
293 aGrid->SetColAttr( COL_TYPE, 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_ENABLED, attr );
299
300 attr = new wxGridCellAttr;
301 attr->SetRenderer( new wxGridCellBoolRenderer() );
302 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
303 aGrid->SetColAttr( COL_VISIBLE, attr );
304
305 // all but COL_OPTIONS, which is edited with Option Editor anyways.
306 autoSizeCol( aGrid, COL_NICKNAME );
307 autoSizeCol( aGrid, COL_TYPE );
308 autoSizeCol( aGrid, COL_URI );
309 autoSizeCol( aGrid, COL_DESCR );
310 autoSizeCol( aGrid, COL_ENABLED );
311
312 // Gives a selection to each grid, mainly for delete button. wxGrid's wake up with
313 // a currentCell which is sometimes not highlighted.
314 if( aGrid->GetNumberRows() > 0 )
315 aGrid->SelectRow( 0 );
316};
317
318
320 SYMBOL_LIB_TABLE* aGlobalTable,
321 const wxString& aGlobalTablePath,
322 SYMBOL_LIB_TABLE* aProjectTable,
323 const wxString& aProjectTablePath ) :
324 PANEL_SYM_LIB_TABLE_BASE( aParent ),
325 m_globalTable( aGlobalTable ),
326 m_projectTable( aProjectTable ),
327 m_project( aProject ),
328 m_parent( aParent )
329{
330 // wxGrid only supports user owned tables if they exist past end of ~wxGrid(),
331 // so make it a grid owned table.
333
334 for( const SCH_IO_MGR::SCH_FILE_T& type : SCH_IO_MGR::SCH_FILE_T_vector )
335 {
336 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( type ) );
337
338 if( !pi )
339 continue;
340
341 if( const IO_BASE::IO_FILE_DESC& desc = pi->GetLibraryDesc() )
343 }
344
346
347 if( cfg->m_lastSymbolLibDir.IsEmpty() )
349
351
352
354
355 if( m_projectTable )
356 {
359 }
360 else
361 {
362 m_pageNdx = 0;
363 m_notebook->DeletePage( 1 );
364 m_project_grid = nullptr;
365 }
366
367 // add Cut, Copy, and Paste to wxGrids
368 m_path_subs_grid->PushEventHandler( new GRID_TRICKS( m_path_subs_grid ) );
369
371
372 // select the last selected page
373 m_notebook->SetSelection( m_pageNdx );
375
376 m_path_subs_grid->SetColLabelValue( 0, _( "Name" ) );
377 m_path_subs_grid->SetColLabelValue( 1, _( "Value" ) );
378
379 // for ALT+A handling, we want the initial focus to be on the first selected grid.
381
382 // Configure button logos
383 m_append_button->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
384 m_delete_button->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
385 m_move_up_button->SetBitmap( KiBitmapBundle( BITMAPS::small_up ) );
386 m_move_down_button->SetBitmap( KiBitmapBundle( BITMAPS::small_down ) );
387 m_browse_button->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
388}
389
390
392{
393 // Delete the GRID_TRICKS.
394 // Any additional event handlers should be popped before the window is deleted.
395 m_global_grid->PopEventHandler( true );
396
397 if( m_project_grid )
398 m_project_grid->PopEventHandler( true );
399
400 m_path_subs_grid->PopEventHandler( true );
401}
402
403
405{
406 // When the plugin type depends only of the file extension, return true.
407 // if it needs to read the actual file (taht can be not available), return false
408
409 wxFileName fn( aLibraryPath );
410 wxString ext = fn.GetExt().Lower();
411
412 // Currently, only the extension .lib is common to legacy libraries and Cadstar libraries
413 // so return false in this case
415 return false;
416
417 return true;
418}
419
420
422{
423 wxString msg;
424 wxBusyCursor wait;
425
426 for( SYMBOL_LIB_TABLE_GRID* model : { global_model(), project_model() } )
427 {
428 if( !model )
429 continue;
430
431 for( int r = 0; r < model->GetNumberRows(); )
432 {
433 wxString nick = model->GetValue( r, COL_NICKNAME ).Trim( false ).Trim();
434 wxString uri = model->GetValue( r, COL_URI ).Trim( false ).Trim();
435 unsigned illegalCh = 0;
436
437 if( !nick || !uri )
438 {
439 if( !nick && !uri )
440 msg = _( "A library table row nickname and path cells are empty." );
441 else if( !nick )
442 msg = _( "A library table row nickname cell is empty." );
443 else
444 msg = _( "A library table row path cell is empty." );
445
446 wxWindow* topLevelParent = wxGetTopLevelParent( this );
447
448 wxMessageDialog badCellDlg( topLevelParent, msg, _( "Invalid Row Definition" ),
449 wxYES_NO | wxCENTER | wxICON_QUESTION | wxYES_DEFAULT );
450 badCellDlg.SetExtendedMessage( _( "Empty cells will result in all rows that are "
451 "invalid to be removed from the table." ) );
452 badCellDlg.SetYesNoLabels( wxMessageDialog::ButtonLabel( _( "Remove Invalid Cells" ) ),
453 wxMessageDialog::ButtonLabel( _( "Cancel Table Update" ) ) );
454
455 wxEndBusyCursor();
456
457 if( badCellDlg.ShowModal() == wxID_NO )
458 return false;
459
460 wxBeginBusyCursor( wxHOURGLASS_CURSOR );
461
462 // Delete the "empty" row, where empty means missing nick or uri.
463 // This also updates the UI which could be slow, but there should only be a few
464 // rows to delete, unless the user fell asleep on the Add Row
465 // button.
466 model->DeleteRows( r, 1 );
467 }
468 else if( ( illegalCh = LIB_ID::FindIllegalLibraryNameChar( nick ) ) )
469 {
470 msg = wxString::Format( _( "Illegal character '%c' in nickname '%s'" ),
471 illegalCh,
472 nick );
473
474 // show the tabbed panel holding the grid we have flunked:
475 if( model != cur_model() )
476 m_notebook->SetSelection( model == global_model() ? 0 : 1 );
477
478 m_cur_grid->MakeCellVisible( r, 0 );
479 m_cur_grid->SetGridCursor( r, 1 );
480
481 wxWindow* topLevelParent = wxGetTopLevelParent( this );
482
483 wxMessageDialog errdlg( topLevelParent, msg, _( "Library Nickname Error" ) );
484
485 wxEndBusyCursor();
486 errdlg.ShowModal();
487 return false;
488 }
489 else
490 {
491 // set the trimmed values back into the table so they get saved to disk.
492 model->SetValue( r, COL_NICKNAME, nick );
493
495 model->SetValue( r, COL_URI, uri );
496 else
497 {
498 wxString ltype = model->GetValue( r, COL_TYPE );
499 model->LIB_TABLE_GRID::SetValue( r, COL_URI, uri );
500 model->SetValue( r, COL_TYPE, ltype );
501 }
502
503 ++r; // this row was OK.
504 }
505 }
506 }
507
508 // check for duplicate nickNames, separately in each table.
509 for( SYMBOL_LIB_TABLE_GRID* model : { global_model(), project_model() } )
510 {
511 if( !model )
512 continue;
513
514 for( int r1 = 0; r1 < model->GetNumberRows() - 1; ++r1 )
515 {
516 wxString nick1 = model->GetValue( r1, COL_NICKNAME );
517
518 for( int r2=r1+1; r2 < model->GetNumberRows(); ++r2 )
519 {
520 wxString nick2 = model->GetValue( r2, COL_NICKNAME );
521
522 if( nick1 == nick2 )
523 {
524 msg = wxString::Format( _( "Multiple libraries cannot share the same "
525 "nickname ('%s')." ), nick1 );
526
527 // show the tabbed panel holding the grid we have flunked:
528 if( model != cur_model() )
529 m_notebook->SetSelection( model == global_model() ? 0 : 1 );
530
531 // go to the lower of the two rows, it is technically the duplicate:
532 m_cur_grid->MakeCellVisible( r2, 0 );
533 m_cur_grid->SetGridCursor( r2, 1 );
534
535 wxWindow* topLevelParent = wxGetTopLevelParent( this );
536
537 wxEndBusyCursor();
538 wxMessageDialog errdlg( topLevelParent, msg, _( "Library Nickname Error" ) );
539 errdlg.ShowModal();
540
541 return false;
542 }
543 }
544 }
545 }
546
547 for( SYMBOL_LIB_TABLE* table : { global_model(), project_model() } )
548 {
549 if( !table )
550 continue;
551
552 for( unsigned int r = 0; r < table->GetCount(); ++r )
553 {
554 SYMBOL_LIB_TABLE_ROW& row = dynamic_cast<SYMBOL_LIB_TABLE_ROW&>( table->At( r ) );
555
556 // Newly-added rows won't have set this yet
557 row.SetParent( table );
558
559 if( !row.GetIsEnabled() )
560 continue;
561
562 try
563 {
564 if( row.Refresh() )
565 {
566 if( table == global_model() )
568 else
570 }
571 }
572 catch( const IO_ERROR& ioe )
573 {
574 msg.Printf( _( "Symbol library '%s' failed to load." ), row.GetNickName() );
575
576 wxWindow* topLevelParent = wxGetTopLevelParent( this );
577 wxEndBusyCursor();
578 wxMessageDialog errdlg( topLevelParent, msg + wxS( "\n" ) + ioe.What(),
579 _( "Error Loading Library" ) );
580 errdlg.ShowModal();
581
582 return true;
583 }
584 }
585 }
586
587 return true;
588}
589
590
591void PANEL_SYM_LIB_TABLE::OnUpdateUI( wxUpdateUIEvent& event )
592{
593}
594
595
597{
598 wxString fileFiltersStr;
599 wxString allWildcardsStr;
600
601 for( const SCH_IO_MGR::SCH_FILE_T& fileType : SCH_IO_MGR::SCH_FILE_T_vector )
602 {
603 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
604
605 if( !pi )
606 continue;
607
608 const IO_BASE::IO_FILE_DESC& desc = pi->GetLibraryDesc();
609
610 if( desc.m_FileExtensions.empty() )
611 continue;
612
613 if( !fileFiltersStr.IsEmpty() )
614 fileFiltersStr += wxChar( '|' );
615
616 fileFiltersStr += desc.FileFilter();
617
618 for( const std::string& ext : desc.m_FileExtensions )
619 allWildcardsStr << wxT( "*." ) << formatWildcardExt( ext ) << wxT( ";" );
620 }
621
622 fileFiltersStr = _( "All supported formats" ) + wxT( "|" ) + allWildcardsStr + wxT( "|" )
623 + fileFiltersStr;
624
626
627 wxString openDir = cfg->m_lastSymbolLibDir;
628
630 openDir = m_lastProjectLibDir;
631
632 wxWindow* topLevelParent = wxGetTopLevelParent( this );
633
634 wxFileDialog dlg( topLevelParent, _( "Add Library" ), openDir, wxEmptyString, fileFiltersStr,
635 wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE );
636
637 if( dlg.ShowModal() == wxID_CANCEL )
638 return;
639
641 cfg->m_lastSymbolLibDir = dlg.GetDirectory();
642 else
643 m_lastProjectLibDir = dlg.GetDirectory();
644
645 const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
646 bool addDuplicates = false;
647 bool applyToAll = false;
648 wxString warning = _( "Warning: Duplicate Nickname" );
649 wxString msg = _( "A library nicknamed '%s' already exists." );
650 wxString detailedMsg = _( "One of the nicknames will need to be changed after "
651 "adding this library." );
652
653 wxArrayString filePathsList;
654 dlg.GetPaths( filePathsList );
655
656 for( const wxString& filePath : filePathsList )
657 {
658 wxFileName fn( filePath );
659 wxString nickname = LIB_ID::FixIllegalChars( fn.GetName(), true );
660 bool doAdd = true;
661
662 if( cur_model()->ContainsNickname( nickname ) )
663 {
664 if( !applyToAll )
665 {
666 // The cancel button adds the library to the table anyway
667 addDuplicates = OKOrCancelDialog( wxGetTopLevelParent( this ), warning,
668 wxString::Format( msg, nickname ),
669 detailedMsg, _( "Skip" ), _( "Add Anyway" ),
670 &applyToAll ) == wxID_CANCEL;
671 }
672
673 doAdd = addDuplicates;
674 }
675
676 if( doAdd && m_cur_grid->AppendRows( 1 ) )
677 {
678 int last_row = m_cur_grid->GetNumberRows() - 1;
679
680 m_cur_grid->SetCellValue( last_row, COL_NICKNAME, nickname );
681
682 // attempt to auto-detect the plugin type
683 SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromLibPath( filePath );
684
685 if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
686 pluginType = SCH_IO_MGR::SCH_KICAD;
687
688 m_cur_grid->SetCellValue( last_row, COL_TYPE, SCH_IO_MGR::ShowType( pluginType ) );
689
690 // try to use path normalized to an environmental variable or project path
691 wxString path = NormalizePath( filePath, &envVars, m_project->GetProjectPath() );
692
693 // Do not use the project path in the global library table. This will almost
694 // assuredly be wrong for a different project.
695 if( m_pageNdx == 0 && path.Contains( "${KIPRJMOD}" ) )
696 path = fn.GetFullPath();
697
698 m_cur_grid->SetCellValue( last_row, COL_URI, path );
699 }
700 }
701
702 if( !filePathsList.IsEmpty() )
703 {
704 m_cur_grid->MakeCellVisible( m_cur_grid->GetNumberRows() - 1, COL_ENABLED );
705 m_cur_grid->SetGridCursor( m_cur_grid->GetNumberRows() - 1, COL_NICKNAME );
706 }
707}
708
709
710void PANEL_SYM_LIB_TABLE::appendRowHandler( wxCommandEvent& event )
711{
713 return;
714
715 if( m_cur_grid->AppendRows( 1 ) )
716 {
717 int row = m_cur_grid->GetNumberRows() - 1;
718
719 // wx documentation is wrong, SetGridCursor does not make visible.
720 m_cur_grid->MakeCellVisible( row, COL_ENABLED );
721 m_cur_grid->SetGridCursor( row, COL_NICKNAME );
722 m_cur_grid->EnableCellEditControl( true );
723 m_cur_grid->ShowCellEditControl();
724 }
725}
726
727
728void PANEL_SYM_LIB_TABLE::deleteRowHandler( wxCommandEvent& event )
729{
731 return;
732
733 int curRow = m_cur_grid->GetGridCursorRow();
734 int curCol = m_cur_grid->GetGridCursorCol();
735
736 // In a wxGrid, collect rows that have a selected cell, or are selected
737 // It is not so easy: it depends on the way the selection was made.
738 // Here, we collect rows selected by clicking on a row label, and rows that contain
739 // previously-selected cells.
740 // If no candidate, just delete the row with the grid cursor.
741 wxArrayInt selectedRows = m_cur_grid->GetSelectedRows();
742 wxGridCellCoordsArray cells = m_cur_grid->GetSelectedCells();
743 wxGridCellCoordsArray blockTopLeft = m_cur_grid->GetSelectionBlockTopLeft();
744 wxGridCellCoordsArray blockBotRight = m_cur_grid->GetSelectionBlockBottomRight();
745
746 // Add all row having cell selected to list:
747 for( unsigned ii = 0; ii < cells.GetCount(); ii++ )
748 selectedRows.Add( cells[ii].GetRow() );
749
750 // Handle block selection
751 if( !blockTopLeft.IsEmpty() && !blockBotRight.IsEmpty() )
752 {
753 for( int i = blockTopLeft[0].GetRow(); i <= blockBotRight[0].GetRow(); ++i )
754 selectedRows.Add( i );
755 }
756
757 // Use the row having the grid cursor only if we have no candidate:
758 if( selectedRows.size() == 0 && m_cur_grid->GetGridCursorRow() >= 0 )
759 selectedRows.Add( m_cur_grid->GetGridCursorRow() );
760
761 if( selectedRows.size() == 0 )
762 {
763 wxBell();
764 return;
765 }
766
767 std::sort( selectedRows.begin(), selectedRows.end() );
768
769 // Remove selected rows (note: a row can be stored more than once in list)
770 int last_row = -1;
771
772 // Needed to avoid a wxWidgets alert if the row to delete is the last row
773 // at least on wxMSW 3.2
774 m_cur_grid->ClearSelection();
775
776 for( int ii = selectedRows.GetCount()-1; ii >= 0; ii-- )
777 {
778 int row = selectedRows[ii];
779
780 if( row != last_row )
781 {
782 last_row = row;
783 m_cur_grid->DeleteRows( row, 1 );
784 }
785 }
786
787 if( m_cur_grid->GetNumberRows() > 0 && curRow >= 0 )
788 m_cur_grid->SetGridCursor( std::min( curRow, m_cur_grid->GetNumberRows() - 1 ), curCol );
789}
790
791
792void PANEL_SYM_LIB_TABLE::moveUpHandler( wxCommandEvent& event )
793{
795 return;
796
798 int curRow = m_cur_grid->GetGridCursorRow();
799
800 // @todo: add multiple selection moves.
801 if( curRow >= 1 )
802 {
803 tbl->ChangeRowOrder( curRow--, -1 );
804
805 if( tbl->GetView() )
806 {
807 // Update the wxGrid
808 wxGridTableMessage msg( tbl, wxGRIDTABLE_NOTIFY_ROWS_INSERTED, curRow, 0 );
809 tbl->GetView()->ProcessTableMessage( msg );
810 }
811
812 m_cur_grid->MakeCellVisible( curRow, m_cur_grid->GetGridCursorCol() );
813 m_cur_grid->SetGridCursor( curRow, m_cur_grid->GetGridCursorCol() );
814 }
815}
816
817
818void PANEL_SYM_LIB_TABLE::moveDownHandler( wxCommandEvent& event )
819{
821 return;
822
824 int curRow = m_cur_grid->GetGridCursorRow();
825
826 // @todo: add multiple selection moves.
827 if( unsigned( curRow + 1 ) < tbl->m_rows.size() )
828 {
829 tbl->ChangeRowOrder( curRow++, 1 );
830
831 if( tbl->GetView() )
832 {
833 // Update the wxGrid
834 wxGridTableMessage msg( tbl, wxGRIDTABLE_NOTIFY_ROWS_INSERTED, curRow - 1, 0 );
835 tbl->GetView()->ProcessTableMessage( msg );
836 }
837
838 m_cur_grid->MakeCellVisible( curRow, m_cur_grid->GetGridCursorCol() );
839 m_cur_grid->SetGridCursor( curRow, m_cur_grid->GetGridCursorCol() );
840 }
841}
842
843
844void PANEL_SYM_LIB_TABLE::onReset( wxCommandEvent& event )
845{
847 return;
848
849 // No need to prompt to preserve an empty table
850 if( m_global_grid->GetNumberRows() > 0 &&
851 !IsOK( this, wxString::Format( _( "This action will reset your global library table on "
852 "disk and cannot be undone." ) ) ) )
853 {
854 return;
855 }
856
857
859
860 if( dlg.ShowModal() == wxID_OK )
861 {
862 m_global_grid->Freeze();
863
864 wxGridTableBase* table = m_global_grid->GetTable();
865 m_global_grid->DestroyTable( table );
866
868 m_global_grid->PopEventHandler( true );
871
872 m_global_grid->Thaw();
873 }
874}
875
876
877void PANEL_SYM_LIB_TABLE::onPageChange( wxBookCtrlEvent& event )
878{
879 m_pageNdx = (unsigned) std::max( 0, m_notebook->GetSelection() );
880
881 if( m_pageNdx == 0 )
882 {
884 m_resetGlobal->Enable();
885 }
886 else
887 {
889 m_resetGlobal->Disable();
890 }
891}
892
893
895{
897 return;
898
899 wxArrayInt selectedRows = m_cur_grid->GetSelectedRows();
900
901 if( selectedRows.empty() && m_cur_grid->GetGridCursorRow() >= 0 )
902 selectedRows.push_back( m_cur_grid->GetGridCursorRow() );
903
904 wxArrayInt legacyRows;
905 wxString databaseType = SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_DATABASE );
906 wxString kicadType = SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_KICAD );
907 wxString msg;
908
909 for( int row : selectedRows )
910 {
911 if( m_cur_grid->GetCellValue( row, COL_TYPE ) != databaseType &&
912 m_cur_grid->GetCellValue( row, COL_TYPE ) != kicadType )
913 {
914 legacyRows.push_back( row );
915 }
916 }
917
918 if( legacyRows.size() <= 0 )
919 {
920 wxMessageBox( _( "Select one or more rows containing libraries "
921 "to save as current KiCad format (*.kicad_sym)." ) );
922 return;
923 }
924 else
925 {
926 if( legacyRows.size() == 1 )
927 {
928 msg.Printf( _( "Save '%s' as current KiCad format (*.kicad_sym) "
929 "and replace legacy entry in table?" ),
930 m_cur_grid->GetCellValue( legacyRows[0], COL_NICKNAME ) );
931 }
932 else
933 {
934 msg.Printf( _( "Save %d libraries as current KiCad format (*.kicad_sym) "
935 "and replace legacy entries in table?" ),
936 (int) legacyRows.size() );
937 }
938
939 if( !IsOK( m_parent, msg ) )
940 return;
941 }
942
943 for( int row : legacyRows )
944 {
945 wxString libName = m_cur_grid->GetCellValue( row, COL_NICKNAME );
946 wxString relPath = m_cur_grid->GetCellValue( row, COL_URI );
947 wxString resolvedPath = ExpandEnvVarSubstitutions( relPath, m_project );
948 wxFileName legacyLib( resolvedPath );
949
950 if( !legacyLib.Exists() )
951 {
952 msg.Printf( _( "Library '%s' not found." ), relPath );
953
954 wxWindow* topLevelParent = wxGetTopLevelParent( this );
955
956 DisplayErrorMessage( topLevelParent, msg );
957 continue;
958 }
959
960 wxFileName newLib( resolvedPath );
961 newLib.SetExt( "kicad_sym" );
962
963 if( newLib.Exists() )
964 {
965 msg.Printf( _( "File '%s' already exists. Do you want overwrite this file?" ),
966 newLib.GetFullPath() );
967
968 switch( wxMessageBox( msg, _( "Migrate Library" ),
969 wxYES_NO | wxCANCEL | wxICON_QUESTION, m_parent ) )
970 {
971 case wxYES: break;
972 case wxNO: continue;
973 case wxCANCEL: return;
974 }
975 }
976
977 wxString options = m_cur_grid->GetCellValue( row, COL_OPTIONS );
978 std::unique_ptr<STRING_UTF8_MAP> props( LIB_TABLE::ParseOptions( options.ToStdString() ) );
979
980 if( SCH_IO_MGR::ConvertLibrary( props.get(), legacyLib.GetFullPath(), newLib.GetFullPath() ) )
981 {
982 relPath = NormalizePath( newLib.GetFullPath(), &Pgm().GetLocalEnvVariables(),
983 m_project );
984
985 // Do not use the project path in the global library table. This will almost
986 // assuredly be wrong for a different project.
987 if( m_cur_grid == m_global_grid && relPath.Contains( "${KIPRJMOD}" ) )
988 relPath = newLib.GetFullPath();
989
990 m_cur_grid->SetCellValue( row, COL_URI, relPath );
991 m_cur_grid->SetCellValue( row, COL_TYPE, kicadType );
992 m_cur_grid->SetCellValue( row, COL_OPTIONS, wxEmptyString );
993 }
994 else
995 {
996 msg.Printf( _( "Failed to save symbol library file '%s'." ), newLib.GetFullPath() );
997
998 wxWindow* topLevelParent = wxGetTopLevelParent( this );
999
1000 DisplayErrorMessage( topLevelParent, msg );
1001 }
1002 }
1003}
1004
1005
1007{
1009 return false;
1010
1011 if( !verifyTables() )
1012 return false;
1013
1014 if( *global_model() != *m_globalTable )
1015 {
1017
1020 }
1021
1023 {
1025
1028 }
1029
1030 return true;
1031}
1032
1033
1035{
1036 wxRegEx re( ".*?(\\$\\{(.+?)\\})|(\\$\\((.+?)\\)).*?", wxRE_ADVANCED );
1037 wxASSERT( re.IsValid() ); // wxRE_ADVANCED is required.
1038
1039 std::set< wxString > unique;
1040
1041 // clear the table
1043
1044 for( SYMBOL_LIB_TABLE_GRID* tbl : { global_model(), project_model() } )
1045 {
1046 if( !tbl )
1047 continue;
1048
1049 for( int row = 0; row < tbl->GetNumberRows(); ++row )
1050 {
1051 wxString uri = tbl->GetValue( row, COL_URI );
1052
1053 while( re.Matches( uri ) )
1054 {
1055 wxString envvar = re.GetMatch( uri, 2 );
1056
1057 // if not ${...} form then must be $(...)
1058 if( envvar.IsEmpty() )
1059 envvar = re.GetMatch( uri, 4 );
1060
1061 // ignore duplicates
1062 unique.insert( envvar );
1063
1064 // delete the last match and search again
1065 uri.Replace( re.GetMatch( uri, 0 ), wxEmptyString );
1066 }
1067 }
1068 }
1069
1070 // Make sure this special environment variable shows up even if it was
1071 // not used yet. It is automatically set by KiCad to the directory holding
1072 // the current project.
1073 unique.insert( PROJECT_VAR_NAME );
1075
1076 for( const wxString& evName : unique )
1077 {
1078 int row = m_path_subs_grid->GetNumberRows();
1079 m_path_subs_grid->AppendRows( 1 );
1080
1081 m_path_subs_grid->SetCellValue( row, 0, wxT( "${" ) + evName + wxT( "}" ) );
1082 m_path_subs_grid->SetCellEditor( row, 0, new GRID_CELL_READONLY_TEXT_EDITOR() );
1083
1084 wxString evValue;
1085 wxGetEnv( evName, &evValue );
1086 m_path_subs_grid->SetCellValue( row, 1, evValue );
1087 m_path_subs_grid->SetCellEditor( row, 1, new GRID_CELL_READONLY_TEXT_EDITOR() );
1088 }
1089
1090 // No combobox editors here, but it looks better if its consistent with the other
1091 // grids in the dialog.
1092 m_path_subs_grid->SetDefaultRowSize( m_path_subs_grid->GetDefaultRowSize() + 2 );
1093
1094 adjustPathSubsGridColumns( m_path_subs_grid->GetRect().GetWidth() );
1095}
1096
1097
1099{
1100 // Account for scroll bars
1101 aWidth -= ( m_path_subs_grid->GetSize().x - m_path_subs_grid->GetClientSize().x );
1102
1103 m_path_subs_grid->AutoSizeColumn( 0 );
1104 m_path_subs_grid->SetColSize( 0, std::max( 72, m_path_subs_grid->GetColSize( 0 ) ) );
1105 m_path_subs_grid->SetColSize( 1, std::max( 120, aWidth - m_path_subs_grid->GetColSize( 0 ) ) );
1106}
1107
1108
1109void PANEL_SYM_LIB_TABLE::onSizeGrid( wxSizeEvent& event )
1110{
1111 adjustPathSubsGridColumns( event.GetSize().GetX() );
1112
1113 event.Skip();
1114}
1115
1116
1118{
1119 return (SYMBOL_LIB_TABLE_GRID*) m_global_grid->GetTable();
1120}
1121
1122
1124{
1125 return m_project_grid ? (SYMBOL_LIB_TABLE_GRID*) m_project_grid->GetTable() : nullptr;
1126}
1127
1128
1130{
1131 return (SYMBOL_LIB_TABLE_GRID*) m_cur_grid->GetTable();
1132}
1133
1134
1136
1137
1138void InvokeSchEditSymbolLibTable( KIWAY* aKiway, wxWindow *aParent )
1139{
1140 auto* symbolEditor = (SYMBOL_EDIT_FRAME*) aKiway->Player( FRAME_SCH_SYMBOL_EDITOR, false );
1141
1143 wxString globalTablePath = SYMBOL_LIB_TABLE::GetGlobalTableFileName();
1144 SYMBOL_LIB_TABLE* projectTable = nullptr;
1145 wxString projectPath = aKiway->Prj().GetProjectPath();
1146 wxFileName projectTableFn( projectPath, SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() );
1147 wxString msg;
1148 wxString currentLib;
1149
1150 // Don't allow editing project tables if no project is open
1151 if( !aKiway->Prj().IsNullProject() )
1152 projectTable = PROJECT_SCH::SchSymbolLibTable( &aKiway->Prj() );
1153
1154 if( symbolEditor )
1155 {
1156 currentLib = symbolEditor->GetCurLib();
1157
1158 // This prevents an ugly crash on OSX (https://bugs.launchpad.net/kicad/+bug/1765286)
1159 symbolEditor->FreezeLibraryTree();
1160
1161 if( symbolEditor->HasLibModifications() )
1162 {
1163 msg = _( "Modifications have been made to one or more symbol libraries.\n"
1164 "Changes must be saved or discarded before the symbol library "
1165 "table can be modified." );
1166
1167 switch( UnsavedChangesDialog( aParent, msg ) )
1168 {
1169 case wxID_YES: symbolEditor->SaveAll(); break;
1170 case wxID_NO: symbolEditor->RevertAll(); break;
1171 default:
1172 case wxID_CANCEL: symbolEditor->ThawLibraryTree(); return;
1173 }
1174 }
1175 }
1176
1177 DIALOG_EDIT_LIBRARY_TABLES dlg( aParent, _( "Symbol Libraries" ) );
1178 dlg.SetKiway( &dlg, aKiway );
1179
1180 dlg.InstallPanel( new PANEL_SYM_LIB_TABLE( &dlg, &aKiway->Prj(), globalTable, globalTablePath,
1181 projectTable, projectTableFn.GetFullPath() ) );
1182
1183 if( dlg.ShowModal() == wxID_CANCEL )
1184 {
1185 if( symbolEditor )
1186 symbolEditor->ThawLibraryTree();
1187
1188 return;
1189 }
1190
1191 if( dlg.m_GlobalTableChanged )
1192 {
1193 try
1194 {
1195 globalTable->Save( globalTablePath );
1196 }
1197 catch( const IO_ERROR& ioe )
1198 {
1199 msg.Printf( _( "Error saving global library table:\n\n%s" ), ioe.What() );
1200 wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
1201 }
1202 }
1203
1204 if( projectTable && dlg.m_ProjectTableChanged )
1205 {
1206 try
1207 {
1208 projectTable->Save( projectTableFn.GetFullPath() );
1209 }
1210 catch( const IO_ERROR& ioe )
1211 {
1212 msg.Printf( _( "Error saving project-specific library table:\n\n%s" ), ioe.What() );
1213 wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
1214 }
1215 }
1216
1217 if( symbolEditor )
1218 {
1219 symbolEditor->ThawLibraryTree();
1220 }
1221
1222 std::string payload = "";
1223 aKiway->ExpressMail( FRAME_SCH, MAIL_RELOAD_LIB, payload );
1225 aKiway->ExpressMail( FRAME_SCH_VIEWER, MAIL_RELOAD_LIB, payload );
1226}
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.
bool supportsVisibilityColumn() override
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:343
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.