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 <functional>
42#include <eeschema_id.h>
43#include <symbol_edit_frame.h>
44#include <symbol_viewer_frame.h>
45#include <sch_edit_frame.h>
46#include <kiway.h>
47#include <paths.h>
48#include <pgm_base.h>
53#include <sch_file_versions.h>
54#include <wx/filedlg.h>
55#include <wx/msgdlg.h>
56#include <project_sch.h>
57
58
59
60// clang-format off
61
66{
67 wxString m_Description;
68 wxString m_FileFilter;
69
72 bool m_IsFile;
73 SCH_IO_MGR::SCH_FILE_T m_Plugin;
74};
75
76
80enum {
83};
84
85// clang-format on
86
91{
92 friend class PANEL_SYM_LIB_TABLE;
93 friend class SYMBOL_GRID_TRICKS;
94
95protected:
96 LIB_TABLE_ROW* at( size_t aIndex ) override { return &m_rows.at( aIndex ); }
97
98 size_t size() const override { return m_rows.size(); }
99
101 {
102 return dynamic_cast< LIB_TABLE_ROW* >( new SYMBOL_LIB_TABLE_ROW );
103 }
104
105 LIB_TABLE_ROWS_ITER begin() override { return m_rows.begin(); }
106
108 {
109 return m_rows.insert( aIterator, aRow );
110 }
111
112 void push_back( LIB_TABLE_ROW* aRow ) override { m_rows.push_back( aRow ); }
113
115 {
116 return m_rows.erase( aFirst, aLast );
117 }
118
119public:
120 void SetValue( int aRow, int aCol, const wxString &aValue ) override
121 {
122 wxCHECK( aRow < (int) size(), /* void */ );
123
124 LIB_TABLE_GRID::SetValue( aRow, aCol, aValue );
125
126 // If setting a filepath, attempt to auto-detect the format
127 if( aCol == COL_URI )
128 {
129 LIB_TABLE_ROW* row = at( (size_t) aRow );
130 wxString fullURI = row->GetFullURI( true );
131
132 SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromLibPath( fullURI );
133
134 if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
135 pluginType = SCH_IO_MGR::SCH_KICAD;
136
137 SetValue( aRow, COL_TYPE, SCH_IO_MGR::ShowType( pluginType ) );
138 }
139 }
140
141
143 {
144 m_rows = aTableToEdit.m_rows;
145 }
146};
147
149{
150public:
152 LIB_TABLE_GRID_TRICKS( aGrid ),
153 m_dialog( aParent )
154 {
155 }
156
158 std::function<void( wxCommandEvent& )> aAddHandler ) :
159 LIB_TABLE_GRID_TRICKS( aGrid, aAddHandler ),
160 m_dialog( aParent )
161 {
162 }
163
164protected:
166
167 virtual void optionsEditor( int aRow ) override
168 {
170
171 if( tbl->GetNumberRows() > aRow )
172 {
173 LIB_TABLE_ROW* row = tbl->at( (size_t) aRow );
174 const wxString& options = row->GetOptions();
175 wxString result = options;
176 std::map<std::string, UTF8> choices;
177
178 SCH_IO_MGR::SCH_FILE_T pi_type = SCH_IO_MGR::EnumFromStr( row->GetType() );
179 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( pi_type ) );
180 pi->GetLibraryOptions( &choices );
181
182 DIALOG_PLUGIN_OPTIONS dlg( m_dialog, row->GetNickName(), choices, options, &result );
183 dlg.ShowModal();
184
185 if( options != result )
186 {
187 row->SetOptions( result );
188 m_grid->Refresh();
189 }
190 }
191
192 }
193
196 virtual void paste_text( const wxString& cb_text ) override
197 {
199 size_t ndx = cb_text.find( "(sym_lib_table" );
200
201 if( ndx != std::string::npos )
202 {
203 // paste the SYMBOL_LIB_TABLE_ROWs of s-expression (sym_lib_table), starting
204 // at column 0 regardless of current cursor column.
205
206 STRING_LINE_READER slr( TO_UTF8( cb_text ), wxS( "Clipboard" ) );
207 LIB_TABLE_LEXER lexer( &slr );
208 SYMBOL_LIB_TABLE tmp_tbl;
209 bool parsed = true;
210
211 try
212 {
213 tmp_tbl.Parse( &lexer );
214 }
215 catch( PARSE_ERROR& pe )
216 {
217 DisplayError( m_dialog, pe.What() );
218 parsed = false;
219 }
220
221 if( parsed )
222 {
223 // make sure the table is big enough...
224 if( tmp_tbl.GetCount() > (unsigned) tbl->GetNumberRows() )
225 tbl->AppendRows( tmp_tbl.GetCount() - tbl->GetNumberRows() );
226
227 for( unsigned i = 0; i < tmp_tbl.GetCount(); ++i )
228 tbl->ReplaceRow( i, tmp_tbl.At( i ).clone() );
229 }
230
231 m_grid->AutoSizeColumns( false );
232 }
233 else
234 {
235 wxString text = cb_text;
236
237 if( !text.Contains( '\t' ) && text.Contains( ',' ) )
238 text.Replace( ',', '\t' );
239
240 if( text.Contains( '\t' ) )
241 {
242 int row = m_grid->GetGridCursorRow();
243 m_grid->ClearSelection();
244 m_grid->SelectRow( row );
245 m_grid->SetGridCursor( row, 0 );
247 }
248
250
251 m_grid->AutoSizeColumns( false );
252 }
253 }
254
256 {
257 return true;
258 }
259};
260
261
263{
264 auto autoSizeCol =
265 [&]( WX_GRID* aCurrGrid, int aCol )
266 {
267 int prevWidth = aCurrGrid->GetColSize( aCol );
268
269 aCurrGrid->AutoSizeColumn( aCol, false );
270 aCurrGrid->SetColSize( aCol, std::max( prevWidth, aCurrGrid->GetColSize( aCol ) ) );
271 };
272
273 // add Cut, Copy, and Paste to wxGrids
274 aGrid->PushEventHandler( new SYMBOL_GRID_TRICKS( m_parent, aGrid,
275 [this]( wxCommandEvent& event ) { appendRowHandler( event ); } ) );
276
277 aGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
278
279 // Set special attributes
280 wxGridCellAttr* attr = new wxGridCellAttr;
281
282 wxString fileFiltersStr;
283 wxString allWildcardsStr;
284
286 {
287 attr->SetEditor( new GRID_CELL_PATH_EDITOR(
288 m_parent, aGrid, &cfg->m_lastSymbolLibDir, true, m_project->GetProjectPath(),
289 []( WX_GRID* grid, int row ) -> wxString
290 {
291 auto* libTable = static_cast<SYMBOL_LIB_TABLE_GRID*>( grid->GetTable() );
292 auto* tableRow = static_cast<SYMBOL_LIB_TABLE_ROW*>( libTable->at( row ) );
293
294 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( tableRow->GetFileType() ) );
295
296 if( pi )
297 {
298 const IO_BASE::IO_FILE_DESC& desc = pi->GetLibraryDesc();
299
300 if( desc.m_IsFile )
301 return desc.FileFilter();
302 }
303
304 return wxEmptyString;
305 } ) );
306 }
307
308 aGrid->SetColAttr( COL_URI, attr );
309
310 attr = new wxGridCellAttr;
311 attr->SetEditor( new wxGridCellChoiceEditor( m_pluginChoices ) );
312 aGrid->SetColAttr( COL_TYPE, attr );
313
314 attr = new wxGridCellAttr;
315 attr->SetRenderer( new wxGridCellBoolRenderer() );
316 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
317 aGrid->SetColAttr( COL_ENABLED, attr );
318
319 attr = new wxGridCellAttr;
320 attr->SetRenderer( new wxGridCellBoolRenderer() );
321 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
322 aGrid->SetColAttr( COL_VISIBLE, attr );
323
324 // all but COL_OPTIONS, which is edited with Option Editor anyways.
325 autoSizeCol( aGrid, COL_NICKNAME );
326 autoSizeCol( aGrid, COL_TYPE );
327 autoSizeCol( aGrid, COL_URI );
328 autoSizeCol( aGrid, COL_DESCR );
329 autoSizeCol( aGrid, COL_ENABLED );
330
331 // Gives a selection to each grid, mainly for delete button. wxGrid's wake up with
332 // a currentCell which is sometimes not highlighted.
333 if( aGrid->GetNumberRows() > 0 )
334 aGrid->SelectRow( 0 );
335};
336
337
339 SYMBOL_LIB_TABLE* aGlobalTable,
340 const wxString& aGlobalTablePath,
341 SYMBOL_LIB_TABLE* aProjectTable,
342 const wxString& aProjectTablePath ) :
343 PANEL_SYM_LIB_TABLE_BASE( aParent ),
344 m_globalTable( aGlobalTable ),
345 m_projectTable( aProjectTable ),
346 m_project( aProject ),
347 m_parent( aParent )
348{
349 // wxGrid only supports user owned tables if they exist past end of ~wxGrid(),
350 // so make it a grid owned table.
351 m_global_grid->SetTable( new SYMBOL_LIB_TABLE_GRID( *m_globalTable ), true );
352
353 for( const SCH_IO_MGR::SCH_FILE_T& type : SCH_IO_MGR::SCH_FILE_T_vector )
354 {
355 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( type ) );
356
357 if( !pi )
358 continue;
359
360 if( const IO_BASE::IO_FILE_DESC& desc = pi->GetLibraryDesc() )
362 }
363
365 {
366 if( cfg->m_lastSymbolLibDir.IsEmpty() )
367 cfg->m_lastSymbolLibDir = PATHS::GetDefaultUserSymbolsPath();
368 }
369
370 m_lastProjectLibDir = m_project->GetProjectPath();
371
373
374 if( m_projectTable )
375 {
376 m_project_grid->SetTable( new SYMBOL_LIB_TABLE_GRID( *m_projectTable ), true );
378 }
379 else
380 {
381 m_pageNdx = 0;
382 m_notebook->DeletePage( 1 );
383 m_project_grid = nullptr;
384 }
385
386 // add Cut, Copy, and Paste to wxGrids
387 m_path_subs_grid->PushEventHandler( new GRID_TRICKS( m_path_subs_grid ) );
388
390
391 // select the last selected page
392 m_notebook->SetSelection( m_pageNdx );
394
395 m_path_subs_grid->SetColLabelValue( 0, _( "Name" ) );
396 m_path_subs_grid->SetColLabelValue( 1, _( "Value" ) );
397
398 // for ALT+A handling, we want the initial focus to be on the first selected grid.
399 m_parent->SetInitialFocus( m_cur_grid );
400
401 // Configure button logos
407}
408
409
411{
412 // Delete the GRID_TRICKS.
413 // Any additional event handlers should be popped before the window is deleted.
414 m_global_grid->PopEventHandler( true );
415
416 if( m_project_grid )
417 m_project_grid->PopEventHandler( true );
418
419 m_path_subs_grid->PopEventHandler( true );
420}
421
422
424{
425 // When the plugin type depends only of the file extension, return true.
426 // if it needs to read the actual file (that can be not available), return false
427
428 wxFileName fn( aLibraryPath );
429 wxString ext = fn.GetExt().Lower();
430
431 // Currently, only the extension .lib is common to legacy libraries and Cadstar libraries
432 // so return false in this case
434 return false;
435
436 return true;
437}
438
439
441{
442 wxString msg;
443 int cursorCol;
444 std::unique_ptr<wxBusyCursor> wait;
445 wait.reset( new wxBusyCursor );
446
447 for( SYMBOL_LIB_TABLE_GRID* model : { global_model(), project_model() } )
448 {
449 if( !model )
450 continue;
451
452 for( int r = 0; r < model->GetNumberRows(); ++r )
453 {
454 wxString nick = model->GetValue( r, COL_NICKNAME ).Trim( false ).Trim();
455 wxString uri = model->GetValue( r, COL_URI ).Trim( false ).Trim();
456 unsigned illegalCh = 0;
457
458 if( !nick || !uri )
459 {
460 if( !nick && !uri )
461 {
462 msg = _( "Nickname and path cannot be empty." );
463 cursorCol = COL_NICKNAME;
464 }
465 else if( !nick )
466 {
467 msg = _( "Nickname cannot be empty." );
468 cursorCol = COL_NICKNAME;
469 }
470 else
471 {
472 msg = _( "Path cannot be empty." );
473 cursorCol = COL_URI;
474 }
475
476 // show the tabbed panel holding the grid we have flunked:
477 if( model != cur_model() )
478 m_notebook->SetSelection( model == global_model() ? 0 : 1 );
479
480 m_cur_grid->MakeCellVisible( r, 0 );
481 m_cur_grid->SetGridCursor( r, cursorCol );
482
483 wxWindow* topLevelParent = wxGetTopLevelParent( this );
484
485 wxMessageDialog errdlg( topLevelParent, msg, _( "Library Table Error" ) );
486
487 wait.reset();
488 errdlg.ShowModal();
489 return false;
490 }
491 else if( ( illegalCh = LIB_ID::FindIllegalLibraryNameChar( nick ) ) )
492 {
493 msg = wxString::Format( _( "Illegal character '%c' in nickname '%s'" ),
494 illegalCh,
495 nick );
496
497 // show the tabbed panel holding the grid we have flunked:
498 if( model != cur_model() )
499 m_notebook->SetSelection( model == global_model() ? 0 : 1 );
500
501 m_cur_grid->MakeCellVisible( r, 0 );
502 m_cur_grid->SetGridCursor( r, COL_NICKNAME );
503
504 wxWindow* topLevelParent = wxGetTopLevelParent( this );
505
506 wxMessageDialog errdlg( topLevelParent, msg, _( "Library Nickname Error" ) );
507
508 wait.reset();
509 errdlg.ShowModal();
510 return false;
511 }
512 else
513 {
514 // set the trimmed values back into the table so they get saved to disk.
515 model->SetValue( r, COL_NICKNAME, nick );
516
518 {
519 model->SetValue( r, COL_URI, uri );
520 }
521 else
522 {
523 wxString ltype = model->GetValue( r, COL_TYPE );
524 model->LIB_TABLE_GRID::SetValue( r, COL_URI, uri );
525 model->SetValue( r, COL_TYPE, ltype );
526 }
527 }
528 }
529 }
530
531 // check for duplicate nickNames, separately in each table.
532 for( SYMBOL_LIB_TABLE_GRID* model : { global_model(), project_model() } )
533 {
534 if( !model )
535 continue;
536
537 for( int r1 = 0; r1 < model->GetNumberRows() - 1; ++r1 )
538 {
539 wxString nick1 = model->GetValue( r1, COL_NICKNAME );
540
541 for( int r2 = r1 + 1; r2 < model->GetNumberRows(); ++r2 )
542 {
543 wxString nick2 = model->GetValue( r2, COL_NICKNAME );
544
545 if( nick1 == nick2 )
546 {
547 msg = wxString::Format( _( "Multiple libraries cannot share the same nickname ('%s')." ),
548 nick1 );
549
550 // show the tabbed panel holding the grid we have flunked:
551 if( model != cur_model() )
552 m_notebook->SetSelection( model == global_model() ? 0 : 1 );
553
554 // go to the lower of the two rows, it is technically the duplicate:
555 m_cur_grid->MakeCellVisible( r2, 0 );
556 m_cur_grid->SetGridCursor( r2, COL_NICKNAME );
557
558 wxWindow* topLevelParent = wxGetTopLevelParent( this );
559
560 wait.reset();
561 wxMessageDialog errdlg( topLevelParent, msg, _( "Library Nickname Error" ) );
562 errdlg.ShowModal();
563
564 return false;
565 }
566 }
567 }
568 }
569
571 {
572 if( !table )
573 continue;
574
575 for( unsigned int r = 0; r < table->GetCount(); ++r )
576 {
577 SYMBOL_LIB_TABLE_ROW& row = dynamic_cast<SYMBOL_LIB_TABLE_ROW&>( table->At( r ) );
578
579 // Newly-added rows won't have set this yet
580 row.SetParent( table );
581
582 if( !row.GetIsEnabled() )
583 continue;
584
585 try
586 {
587 if( row.Refresh() )
588 {
589 if( table == global_model() )
590 m_parent->m_GlobalTableChanged = true;
591 else
592 m_parent->m_ProjectTableChanged = true;
593 }
594 }
595 catch( const IO_ERROR& ioe )
596 {
597 msg.Printf( _( "Symbol library '%s' failed to load." ), row.GetNickName() );
598
599 wxWindow* topLevelParent = wxGetTopLevelParent( this );
600 wait.reset();
601 wxMessageDialog errdlg( topLevelParent, msg + wxS( "\n" ) + ioe.What(), _( "Error Loading Library" ) );
602 errdlg.ShowModal();
603
604 return true;
605 }
606 }
607 }
608
609 return true;
610}
611
612
613void PANEL_SYM_LIB_TABLE::OnUpdateUI( wxUpdateUIEvent& event )
614{
615}
616
617
619{
620 wxString fileFiltersStr;
621 wxString allWildcardsStr;
622
623 for( const SCH_IO_MGR::SCH_FILE_T& fileType : SCH_IO_MGR::SCH_FILE_T_vector )
624 {
625 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
626
627 if( !pi )
628 continue;
629
630 const IO_BASE::IO_FILE_DESC& desc = pi->GetLibraryDesc();
631
632 if( desc.m_FileExtensions.empty() )
633 continue;
634
635 if( !fileFiltersStr.IsEmpty() )
636 fileFiltersStr += wxChar( '|' );
637
638 fileFiltersStr += desc.FileFilter();
639
640 for( const std::string& ext : desc.m_FileExtensions )
641 allWildcardsStr << wxT( "*." ) << formatWildcardExt( ext ) << wxT( ";" );
642 }
643
644 fileFiltersStr = _( "All supported formats" ) + wxT( "|" ) + allWildcardsStr + wxT( "|" )
645 + fileFiltersStr;
646
648 wxString dummy;
649 wxString* lastDir;
650
652 lastDir = &m_lastProjectLibDir;
653 else
654 lastDir = cfg ? &cfg->m_lastSymbolLibDir : &dummy;
655
656 wxWindow* topLevelParent = wxGetTopLevelParent( this );
657
658 wxFileDialog dlg( topLevelParent, _( "Add Library" ), *lastDir, wxEmptyString, fileFiltersStr,
659 wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE );
660
661 if( dlg.ShowModal() == wxID_CANCEL )
662 return;
663
664 *lastDir = dlg.GetDirectory();
665
666 const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
667 bool addDuplicates = false;
668 bool applyToAll = false;
669
670 wxArrayString filePathsList;
671 dlg.GetPaths( filePathsList );
672
673 for( const wxString& filePath : filePathsList )
674 {
675 wxFileName fn( filePath );
676 wxString nickname = LIB_ID::FixIllegalChars( fn.GetName(), true );
677 bool doAdd = true;
678
679 if( cur_model()->ContainsNickname( nickname ) )
680 {
681 if( !applyToAll )
682 {
683 // The cancel button adds the library to the table anyway
684 addDuplicates = OKOrCancelDialog( wxGetTopLevelParent( this ), _( "Warning: Duplicate Nickname" ),
685 wxString::Format( _( "A library nicknamed '%s' already exists." ),
686 nickname ),
687 _( "One of the nicknames will need to be changed after adding "
688 "this library." ),
689 _( "Skip" ), _( "Add Anyway" ),
690 &applyToAll ) == wxID_CANCEL;
691 }
692
693 doAdd = addDuplicates;
694 }
695
696 if( doAdd && m_cur_grid->AppendRows( 1 ) )
697 {
698 int last_row = m_cur_grid->GetNumberRows() - 1;
699
700 m_cur_grid->SetCellValue( last_row, COL_NICKNAME, nickname );
701
702 // attempt to auto-detect the plugin type
703 SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromLibPath( filePath );
704
705 if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
706 pluginType = SCH_IO_MGR::SCH_KICAD;
707
708 m_cur_grid->SetCellValue( last_row, COL_TYPE, SCH_IO_MGR::ShowType( pluginType ) );
709
710 // try to use path normalized to an environmental variable or project path
711 wxString path = NormalizePath( filePath, &envVars, m_project->GetProjectPath() );
712
713 // Do not use the project path in the global library table. This will almost
714 // assuredly be wrong for a different project.
715 if( m_pageNdx == 0 && path.Contains( "${KIPRJMOD}" ) )
716 path = fn.GetFullPath();
717
718 m_cur_grid->SetCellValue( last_row, COL_URI, path );
719 }
720 }
721
722 if( !filePathsList.IsEmpty() )
723 {
724 m_cur_grid->MakeCellVisible( m_cur_grid->GetNumberRows() - 1, COL_ENABLED );
725 m_cur_grid->SetGridCursor( m_cur_grid->GetNumberRows() - 1, COL_NICKNAME );
726 }
727}
728
729
730void PANEL_SYM_LIB_TABLE::appendRowHandler( wxCommandEvent& event )
731{
732 m_cur_grid->OnAddRow(
733 [&]() -> std::pair<int, int>
734 {
735 m_cur_grid->AppendRows( 1 );
736 return { m_cur_grid->GetNumberRows() - 1, COL_NICKNAME };
737 } );
738}
739
740
741void PANEL_SYM_LIB_TABLE::deleteRowHandler( wxCommandEvent& event )
742{
743 if( !m_cur_grid->CommitPendingChanges() )
744 return;
745
746 wxGridUpdateLocker noUpdates( m_cur_grid );
747
748 int curRow = m_cur_grid->GetGridCursorRow();
749 int curCol = m_cur_grid->GetGridCursorCol();
750
751 // In a wxGrid, collect rows that have a selected cell, or are selected
752 // It is not so easy: it depends on the way the selection was made.
753 // Here, we collect rows selected by clicking on a row label, and rows that contain
754 // previously-selected cells.
755 // If no candidate, just delete the row with the grid cursor.
756 wxArrayInt selectedRows = m_cur_grid->GetSelectedRows();
757 wxGridCellCoordsArray cells = m_cur_grid->GetSelectedCells();
758 wxGridCellCoordsArray blockTopLeft = m_cur_grid->GetSelectionBlockTopLeft();
759 wxGridCellCoordsArray blockBotRight = m_cur_grid->GetSelectionBlockBottomRight();
760
761 // Add all row having cell selected to list:
762 for( unsigned ii = 0; ii < cells.GetCount(); ii++ )
763 selectedRows.Add( cells[ii].GetRow() );
764
765 // Handle block selection
766 if( !blockTopLeft.IsEmpty() && !blockBotRight.IsEmpty() )
767 {
768 for( int i = blockTopLeft[0].GetRow(); i <= blockBotRight[0].GetRow(); ++i )
769 selectedRows.Add( i );
770 }
771
772 // Use the row having the grid cursor only if we have no candidate:
773 if( selectedRows.size() == 0 && m_cur_grid->GetGridCursorRow() >= 0 )
774 selectedRows.Add( m_cur_grid->GetGridCursorRow() );
775
776 if( selectedRows.size() == 0 )
777 {
778 wxBell();
779 return;
780 }
781
782 std::sort( selectedRows.begin(), selectedRows.end() );
783
784 // Remove selected rows (note: a row can be stored more than once in list)
785 int last_row = -1;
786
787 // Needed to avoid a wxWidgets alert if the row to delete is the last row
788 // at least on wxMSW 3.2
789 m_cur_grid->ClearSelection();
790
791 for( int ii = selectedRows.GetCount()-1; ii >= 0; ii-- )
792 {
793 int row = selectedRows[ii];
794
795 if( row != last_row )
796 {
797 last_row = row;
798 m_cur_grid->DeleteRows( row, 1 );
799 }
800 }
801
802 if( m_cur_grid->GetNumberRows() > 0 && curRow >= 0 )
803 m_cur_grid->SetGridCursor( std::min( curRow, m_cur_grid->GetNumberRows() - 1 ), curCol );
804}
805
806
807void PANEL_SYM_LIB_TABLE::moveUpHandler( wxCommandEvent& event )
808{
809 m_cur_grid->OnMoveRowUp(
810 [&]( int row )
811 {
812 cur_model()->ChangeRowOrder( row, -1 );
813
814 // Update the wxGrid
815 wxGridTableMessage msg( cur_model(), wxGRIDTABLE_NOTIFY_ROWS_INSERTED, row - 1, 0 );
816 cur_model()->GetView()->ProcessTableMessage( msg );
817 } );
818}
819
820
821void PANEL_SYM_LIB_TABLE::moveDownHandler( wxCommandEvent& event )
822{
823 m_cur_grid->OnMoveRowDown(
824 [&]( int row )
825 {
826 cur_model()->ChangeRowOrder( row, 1 );
827
828 // Update the wxGrid
829 wxGridTableMessage msg( cur_model(), wxGRIDTABLE_NOTIFY_ROWS_INSERTED, row, 0 );
830 cur_model()->GetView()->ProcessTableMessage( msg );
831 } );
832}
833
834
835void PANEL_SYM_LIB_TABLE::onReset( wxCommandEvent& event )
836{
837 if( !m_cur_grid->CommitPendingChanges() )
838 return;
839
840 // No need to prompt to preserve an empty table
841 if( m_global_grid->GetNumberRows() > 0 &&
842 !IsOK( this, wxString::Format( _( "This action will reset your global library table on "
843 "disk and cannot be undone." ) ) ) )
844 {
845 return;
846 }
847
848
850
851 if( dlg.ShowModal() == wxID_OK )
852 {
853 m_global_grid->Freeze();
854
855 wxGridTableBase* table = m_global_grid->GetTable();
856 m_global_grid->DestroyTable( table );
857
858 m_global_grid->SetTable( new SYMBOL_LIB_TABLE_GRID( *m_globalTable ), true );
859 m_global_grid->PopEventHandler( true );
861 m_parent->m_GlobalTableChanged = true;
862
863 m_global_grid->Thaw();
864 }
865}
866
867
868void PANEL_SYM_LIB_TABLE::onPageChange( wxBookCtrlEvent& event )
869{
870 m_pageNdx = (unsigned) std::max( 0, m_notebook->GetSelection() );
871
872 if( m_pageNdx == 0 )
873 {
875 m_resetGlobal->Enable();
876 }
877 else
878 {
880 m_resetGlobal->Disable();
881 }
882}
883
884
886{
887 if( !m_cur_grid->CommitPendingChanges() )
888 return;
889
890 wxArrayInt selectedRows = m_cur_grid->GetSelectedRows();
891
892 if( selectedRows.empty() && m_cur_grid->GetGridCursorRow() >= 0 )
893 selectedRows.push_back( m_cur_grid->GetGridCursorRow() );
894
895 wxArrayInt legacyRows;
896 wxString databaseType = SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_DATABASE );
897 wxString kicadType = SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_KICAD );
898 wxString msg;
899
900 for( int row : selectedRows )
901 {
902 if( m_cur_grid->GetCellValue( row, COL_TYPE ) != databaseType &&
903 m_cur_grid->GetCellValue( row, COL_TYPE ) != kicadType )
904 {
905 legacyRows.push_back( row );
906 }
907 }
908
909 if( legacyRows.size() <= 0 )
910 {
911 wxMessageBox( _( "Select one or more rows containing libraries "
912 "to save as current KiCad format (*.kicad_sym)." ) );
913 return;
914 }
915 else
916 {
917 if( legacyRows.size() == 1 )
918 {
919 msg.Printf( _( "Save '%s' as current KiCad format (*.kicad_sym) "
920 "and replace legacy entry in table?" ),
921 m_cur_grid->GetCellValue( legacyRows[0], COL_NICKNAME ) );
922 }
923 else
924 {
925 msg.Printf( _( "Save %d libraries as current KiCad format (*.kicad_sym) "
926 "and replace legacy entries in table?" ),
927 (int) legacyRows.size() );
928 }
929
930 if( !IsOK( m_parent, msg ) )
931 return;
932 }
933
934 for( int row : legacyRows )
935 {
936 wxString libName = m_cur_grid->GetCellValue( row, COL_NICKNAME );
937 wxString relPath = m_cur_grid->GetCellValue( row, COL_URI );
938 wxString resolvedPath = ExpandEnvVarSubstitutions( relPath, m_project );
939 wxFileName legacyLib( resolvedPath );
940
941 if( !legacyLib.Exists() )
942 {
943 msg.Printf( _( "Library '%s' not found." ), relPath );
944
945 wxWindow* topLevelParent = wxGetTopLevelParent( this );
946
947 DisplayErrorMessage( topLevelParent, msg );
948 continue;
949 }
950
951 wxFileName newLib( resolvedPath );
952 newLib.SetExt( "kicad_sym" );
953
954 if( newLib.Exists() )
955 {
956 msg.Printf( _( "File '%s' already exists. Do you want overwrite this file?" ),
957 newLib.GetFullPath() );
958
959 switch( wxMessageBox( msg, _( "Migrate Library" ),
960 wxYES_NO | wxCANCEL | wxICON_QUESTION, m_parent ) )
961 {
962 case wxYES: break;
963 case wxNO: continue;
964 case wxCANCEL: return;
965 }
966 }
967
968 wxString options = m_cur_grid->GetCellValue( row, COL_OPTIONS );
969 std::unique_ptr<std::map<std::string, UTF8>> props(
970 LIB_TABLE::ParseOptions( options.ToStdString() ) );
971
972 if( SCH_IO_MGR::ConvertLibrary( props.get(), legacyLib.GetFullPath(), newLib.GetFullPath() ) )
973 {
974 relPath = NormalizePath( newLib.GetFullPath(), &Pgm().GetLocalEnvVariables(), m_project );
975
976 // Do not use the project path in the global library table. This will almost
977 // assuredly be wrong for a different project.
978 if( m_cur_grid == m_global_grid && relPath.Contains( "${KIPRJMOD}" ) )
979 relPath = newLib.GetFullPath();
980
981 m_cur_grid->SetCellValue( row, COL_URI, relPath );
982 m_cur_grid->SetCellValue( row, COL_TYPE, kicadType );
983 m_cur_grid->SetCellValue( row, COL_OPTIONS, wxEmptyString );
984 }
985 else
986 {
987 msg.Printf( _( "Failed to save symbol library file '%s'." ), newLib.GetFullPath() );
988
989 wxWindow* topLevelParent = wxGetTopLevelParent( this );
990
991 DisplayErrorMessage( topLevelParent, msg );
992 }
993 }
994}
995
996
998{
999 if( !m_cur_grid->CommitPendingChanges() )
1000 return false;
1001
1002 if( !verifyTables() )
1003 return false;
1004
1005 if( *global_model() != *m_globalTable )
1006 {
1007 m_parent->m_GlobalTableChanged = true;
1008 m_globalTable->TransferRows( global_model()->m_rows );
1009 }
1010
1012 {
1013 m_parent->m_ProjectTableChanged = true;
1014 m_projectTable->TransferRows( project_model()->m_rows );
1015 }
1016
1017 return true;
1018}
1019
1020
1022{
1023 wxRegEx re( ".*?(\\$\\{(.+?)\\})|(\\$\\((.+?)\\)).*?", wxRE_ADVANCED );
1024 wxASSERT( re.IsValid() ); // wxRE_ADVANCED is required.
1025
1026 std::set< wxString > unique;
1027
1028 // clear the table
1029 m_path_subs_grid->ClearRows();
1030
1031 for( SYMBOL_LIB_TABLE_GRID* tbl : { global_model(), project_model() } )
1032 {
1033 if( !tbl )
1034 continue;
1035
1036 for( int row = 0; row < tbl->GetNumberRows(); ++row )
1037 {
1038 wxString uri = tbl->GetValue( row, COL_URI );
1039
1040 while( re.Matches( uri ) )
1041 {
1042 wxString envvar = re.GetMatch( uri, 2 );
1043
1044 // if not ${...} form then must be $(...)
1045 if( envvar.IsEmpty() )
1046 envvar = re.GetMatch( uri, 4 );
1047
1048 // ignore duplicates
1049 unique.insert( envvar );
1050
1051 // delete the last match and search again
1052 uri.Replace( re.GetMatch( uri, 0 ), wxEmptyString );
1053 }
1054 }
1055 }
1056
1057 // Make sure this special environment variable shows up even if it was
1058 // not used yet. It is automatically set by KiCad to the directory holding
1059 // the current project.
1060 unique.insert( PROJECT_VAR_NAME );
1062
1063 for( const wxString& evName : unique )
1064 {
1065 int row = m_path_subs_grid->GetNumberRows();
1066 m_path_subs_grid->AppendRows( 1 );
1067
1068 m_path_subs_grid->SetCellValue( row, 0, wxT( "${" ) + evName + wxT( "}" ) );
1069 m_path_subs_grid->SetCellEditor( row, 0, new GRID_CELL_READONLY_TEXT_EDITOR() );
1070
1071 wxString evValue;
1072 wxGetEnv( evName, &evValue );
1073 m_path_subs_grid->SetCellValue( row, 1, evValue );
1074 m_path_subs_grid->SetCellEditor( row, 1, new GRID_CELL_READONLY_TEXT_EDITOR() );
1075 }
1076
1077 adjustPathSubsGridColumns( m_path_subs_grid->GetRect().GetWidth() );
1078}
1079
1080
1082{
1083 // Account for scroll bars
1084 aWidth -= ( m_path_subs_grid->GetSize().x - m_path_subs_grid->GetClientSize().x );
1085
1086 m_path_subs_grid->AutoSizeColumn( 0 );
1087 m_path_subs_grid->SetColSize( 0, std::max( 72, m_path_subs_grid->GetColSize( 0 ) ) );
1088 m_path_subs_grid->SetColSize( 1, std::max( 120, aWidth - m_path_subs_grid->GetColSize( 0 ) ) );
1089}
1090
1091
1092void PANEL_SYM_LIB_TABLE::onSizeGrid( wxSizeEvent& event )
1093{
1094 adjustPathSubsGridColumns( event.GetSize().GetX() );
1095
1096 event.Skip();
1097}
1098
1099
1104
1105
1110
1111
1116
1117
1119
1120
1121void InvokeSchEditSymbolLibTable( KIWAY* aKiway, wxWindow *aParent )
1122{
1123 auto* symbolEditor = (SYMBOL_EDIT_FRAME*) aKiway->Player( FRAME_SCH_SYMBOL_EDITOR, false );
1124
1126 wxString globalTablePath = SYMBOL_LIB_TABLE::GetGlobalTableFileName();
1127 SYMBOL_LIB_TABLE* projectTable = nullptr;
1128 wxString projectPath = aKiway->Prj().GetProjectPath();
1129 wxFileName projectTableFn( projectPath, SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() );
1130 wxString msg;
1131 wxString currentLib;
1132
1133 // Don't allow editing project tables if no project is open
1134 if( !aKiway->Prj().IsNullProject() )
1135 projectTable = PROJECT_SCH::SchSymbolLibTable( &aKiway->Prj() );
1136
1137 if( symbolEditor )
1138 {
1139 currentLib = symbolEditor->GetCurLib();
1140
1141 // This prevents an ugly crash on OSX (https://bugs.launchpad.net/kicad/+bug/1765286)
1142 symbolEditor->FreezeLibraryTree();
1143
1144 if( symbolEditor->HasLibModifications() )
1145 {
1146 msg = _( "Modifications have been made to one or more symbol libraries.\n"
1147 "Changes must be saved or discarded before the symbol library table can be modified." );
1148
1149 switch( UnsavedChangesDialog( aParent, msg ) )
1150 {
1151 case wxID_YES: symbolEditor->SaveAll(); break;
1152 case wxID_NO: symbolEditor->RevertAll(); break;
1153 default:
1154 case wxID_CANCEL: symbolEditor->ThawLibraryTree(); return;
1155 }
1156 }
1157 }
1158
1159 DIALOG_EDIT_LIBRARY_TABLES dlg( aParent, _( "Symbol Libraries" ) );
1160 dlg.SetKiway( &dlg, aKiway );
1161
1162 dlg.InstallPanel( new PANEL_SYM_LIB_TABLE( &dlg, &aKiway->Prj(), globalTable, globalTablePath,
1163 projectTable, projectTableFn.GetFullPath() ) );
1164
1165 if( dlg.ShowModal() == wxID_CANCEL )
1166 {
1167 if( symbolEditor )
1168 symbolEditor->ThawLibraryTree();
1169
1170 return;
1171 }
1172
1173 if( dlg.m_GlobalTableChanged )
1174 {
1175 try
1176 {
1177 globalTable->Save( globalTablePath );
1178 }
1179 catch( const IO_ERROR& ioe )
1180 {
1181 msg.Printf( _( "Error saving global library table:\n\n%s" ), ioe.What() );
1182 wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
1183 }
1184 }
1185
1186 if( projectTable && dlg.m_ProjectTableChanged )
1187 {
1188 try
1189 {
1190 projectTable->Save( projectTableFn.GetFullPath() );
1191 }
1192 catch( const IO_ERROR& ioe )
1193 {
1194 msg.Printf( _( "Error saving project-specific library table:\n\n%s" ), ioe.What() );
1195 wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
1196 }
1197 }
1198
1199 if( symbolEditor )
1200 symbolEditor->ThawLibraryTree();
1201
1202 std::string payload = "";
1203 aKiway->ExpressMail( FRAME_SCH, MAIL_RELOAD_LIB, payload );
1205 aKiway->ExpressMail( FRAME_SCH_VIEWER, MAIL_RELOAD_LIB, payload );
1206}
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.
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)
void getSelectedArea()
Puts the selected area into a sensible rectangle of m_sel_{row,col}_{start,count} above.
WX_GRID * m_grid
I don't own the grid, but he owns me.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
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
LIB_TABLE_GRID_TRICKS(WX_GRID *aGrid)
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.
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.
PANEL_SYM_LIB_TABLE_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
STD_BITMAP_BUTTON * m_move_down_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:822
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:162
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Definition project.cpp:180
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.
static SCH_FILE_T EnumFromStr(const wxString &aFileType)
Return the #SCH_FILE_T from the corresponding plugin type name: "kicad", "legacy",...
static const wxString ShowType(SCH_FILE_T aFileType)
Return a brief name for a plugin, given aFileType enum.
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.
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.
SYMBOL_GRID_TRICKS(DIALOG_EDIT_LIBRARY_TABLES *aParent, WX_GRID *aGrid, std::function< void(wxCommandEvent &)> aAddHandler)
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()
SYMBOL_LIB_TABLE(SYMBOL_LIB_TABLE *aFallBackTable=nullptr)
Build a symbol library table by pre-pending this table fragment in front of aFallBackTable.
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...
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:78
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:913
see class PGM_BASE
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
Definition project.h:40
T * GetAppSettings(const char *aFilename)
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.
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,...
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 result
Test unit parsing edge cases and error handling.
wxString formatWildcardExt(const wxString &aWildcard)
Format wildcard extension to support case sensitive file dialogs.
Definition of file extensions used in Kicad.