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