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