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