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