KiCad PCB EDA Suite
Loading...
Searching...
No Matches
panel_fp_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) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
5 * Copyright (C) 2013-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
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26
27/* TODO:
28
29*) After any change to uri, reparse the environment variables.
30
31*/
32
33
34#include <set>
35#include <wx/dir.h>
36#include <wx/regex.h>
37#include <wx/grid.h>
38#include <wx/dirdlg.h>
39#include <wx/filedlg.h>
40#include <wx/msgdlg.h>
41#include <functional>
42
43#include <project.h>
44#include <env_vars.h>
46#include <panel_fp_lib_table.h>
47#include <lib_id.h>
48#include <fp_lib_table.h>
49#include <lib_table_lexer.h>
50#include <invoke_pcb_dialog.h>
51#include <bitmaps.h>
53#include <widgets/wx_grid.h>
55#include <confirm.h>
56#include <lib_table_grid.h>
58#include <pgm_base.h>
59#include <pcb_edit_frame.h>
60#include <env_paths.h>
66#include <kiway.h>
67#include <kiway_express.h>
70#include <pcbnew_id.h> // For ID_PCBNEW_END_LIST
72#include <paths.h>
73#include <macros.h>
74#include <project_pcb.h>
75#include <common.h>
78
79
84{
85 friend class PANEL_FP_LIB_TABLE;
86 friend class FP_GRID_TRICKS;
87
88protected:
89 LIB_TABLE_ROW* at( size_t aIndex ) override { return &m_rows.at( aIndex ); }
90
91 size_t size() const override { return m_rows.size(); }
92
94 {
95 return dynamic_cast< LIB_TABLE_ROW* >( new FP_LIB_TABLE_ROW );
96 }
97
98 LIB_TABLE_ROWS_ITER begin() override { return m_rows.begin(); }
99
101 {
102 return m_rows.insert( aIterator, aRow );
103 }
104
105 void push_back( LIB_TABLE_ROW* aRow ) override { m_rows.push_back( aRow ); }
106
108 {
109 return m_rows.erase( aFirst, aLast );
110 }
111
112public:
113
114 FP_LIB_TABLE_GRID( const FP_LIB_TABLE& aTableToEdit )
115 {
116 m_rows = aTableToEdit.m_rows;
117 }
118
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
132
133 if( pluginType == PCB_IO_MGR::FILE_TYPE_NONE )
134 pluginType = PCB_IO_MGR::KICAD_SEXP;
135
136 SetValue( aRow, COL_TYPE, PCB_IO_MGR::ShowType( pluginType ) );
137 }
138 }
139};
140
141
142
144{
145public:
147 LIB_TABLE_GRID_TRICKS( aGrid ),
148 m_dialog( aParent )
149 { }
150
152 std::function<void( wxCommandEvent& )> aAddHandler ) :
153 LIB_TABLE_GRID_TRICKS( aGrid, aAddHandler ),
154 m_dialog( aParent )
155 { }
156
157protected:
159
160 void optionsEditor( int aRow ) override
161 {
162 FP_LIB_TABLE_GRID* tbl = (FP_LIB_TABLE_GRID*) m_grid->GetTable();
163
164 if( tbl->GetNumberRows() > aRow )
165 {
166 LIB_TABLE_ROW* row = tbl->at( (size_t) aRow );
167 const wxString& options = row->GetOptions();
168 wxString result = options;
169 std::map<std::string, UTF8> choices;
170
173 pi->GetLibraryOptions( &choices );
174
175 DIALOG_PLUGIN_OPTIONS dlg( m_dialog, row->GetNickName(), choices, options, &result );
176 dlg.ShowModal();
177
178 if( options != result )
179 {
180 row->SetOptions( result );
181 m_grid->Refresh();
182 }
183 }
184 }
185
188 void paste_text( const wxString& cb_text ) override
189 {
190 FP_LIB_TABLE_GRID* tbl = (FP_LIB_TABLE_GRID*) m_grid->GetTable();
191 size_t ndx = cb_text.find( "(fp_lib_table" );
192
193 if( ndx != std::string::npos )
194 {
195 // paste the FP_LIB_TABLE_ROWs of s-expression (fp_lib_table), starting
196 // at column 0 regardless of current cursor column.
197
198 STRING_LINE_READER slr( TO_UTF8( cb_text ), wxT( "Clipboard" ) );
199 LIB_TABLE_LEXER lexer( &slr );
200 FP_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->m_rows.replace( i, tmp_tbl.At( i ).clone() );
221 }
222
223 m_grid->AutoSizeColumns( false );
224 }
225 else
226 {
227 wxString text = cb_text;
228
229 if( !text.Contains( '\t' ) && text.Contains( ',' ) )
230 text.Replace( ',', '\t' );
231
232 if( text.Contains( '\t' ) )
233 {
234 int row = m_grid->GetGridCursorRow();
235 m_grid->ClearSelection();
236 m_grid->SelectRow( row );
237 m_grid->SetGridCursor( row, 0 );
239 }
240
242
243 m_grid->AutoSizeColumns( false );
244 }
245 }
246
247
248 bool toggleCell( int aRow, int aCol, bool aPreserveSelection ) override
249 {
250 if( aCol == COL_VISIBLE )
251 {
252 m_dialog->ShowInfoBarError( _( "Hidden footprint libraries are not yet supported." ) );
253 return true;
254 }
255
256 return LIB_TABLE_GRID_TRICKS::toggleCell( aRow, aCol, aPreserveSelection );
257 }
258};
259
260
262{
263 auto autoSizeCol =
264 [&]( WX_GRID* aLocGrid, int aCol )
265 {
266 int prevWidth = aLocGrid->GetColSize( aCol );
267
268 aLocGrid->AutoSizeColumn( aCol, false );
269 aLocGrid->SetColSize( aCol, std::max( prevWidth, aLocGrid->GetColSize( aCol ) ) );
270 };
271
272 // Give a bit more room for wxChoice editors
273 for( int ii = 0; ii < aGrid->GetNumberRows(); ++ii )
274 aGrid->SetRowSize( ii, aGrid->GetDefaultRowSize() + 4 );
275
276 // add Cut, Copy, and Paste to wxGrids
277 aGrid->PushEventHandler( new FP_GRID_TRICKS( m_parent, aGrid,
278 [this]( wxCommandEvent& event ) { appendRowHandler( event ); } ) );
279
280 aGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
281
282 wxGridCellAttr* attr;
283
284 attr = new wxGridCellAttr;
285
286 if( PCBNEW_SETTINGS* cfg = GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" ) )
287 {
288 attr->SetEditor( new GRID_CELL_PATH_EDITOR(
289 m_parent, aGrid, &cfg->m_LastFootprintLibDir, true, m_projectBasePath,
290 [this]( WX_GRID* grid, int row ) -> wxString
291 {
292 auto* libTable = static_cast<FP_LIB_TABLE_GRID*>( grid->GetTable() );
293 auto* tableRow = static_cast<FP_LIB_TABLE_ROW*>( libTable->at( row ) );
294 PCB_IO_MGR::PCB_FILE_T fileType = tableRow->GetFileType();
295 const IO_BASE::IO_FILE_DESC& pluginDesc = m_supportedFpFiles.at( fileType );
296
297 if( pluginDesc.m_IsFile )
298 return pluginDesc.FileFilter();
299 else
300 return wxEmptyString;
301 } ) );
302 }
303
304 aGrid->SetColAttr( COL_URI, attr );
305
306 attr = new wxGridCellAttr;
307 attr->SetEditor( new wxGridCellChoiceEditor( m_pluginChoices ) );
308 aGrid->SetColAttr( COL_TYPE, attr );
309
310 attr = new wxGridCellAttr;
311 attr->SetRenderer( new wxGridCellBoolRenderer() );
312 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
313 aGrid->SetColAttr( COL_ENABLED, attr );
314
315 attr = new wxGridCellAttr;
316 attr->SetRenderer( new wxGridCellBoolRenderer() );
317 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
318 aGrid->SetColAttr( COL_VISIBLE, attr );
319 // No visibility control for footprint libraries yet; this feature is primarily
320 // useful for database libraries and it's only implemented for schematic symbols
321 // at the moment.
322 aGrid->HideCol( COL_VISIBLE );
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
330 // Gives a selection to each grid, mainly for delete button. wxGrid's wake up with
331 // a currentCell which is sometimes not highlighted.
332 if( aGrid->GetNumberRows() > 0 )
333 aGrid->SelectRow( 0 );
334};
335
336
338 FP_LIB_TABLE* aGlobalTable, const wxString& aGlobalTblPath,
339 FP_LIB_TABLE* aProjectTable, const wxString& aProjectTblPath,
340 const wxString& aProjectBasePath ) :
341 PANEL_FP_LIB_TABLE_BASE( aParent ),
342 m_globalTable( aGlobalTable ),
343 m_projectTable( aProjectTable ),
344 m_project( aProject ),
345 m_projectBasePath( aProjectBasePath ),
346 m_parent( aParent )
347{
348 m_global_grid->SetTable( new FP_LIB_TABLE_GRID( *aGlobalTable ), true );
349
350 // add Cut, Copy, and Paste to wxGrids
351 m_path_subs_grid->PushEventHandler( new GRID_TRICKS( m_path_subs_grid ) );
352
354
355 for( auto& [fileType, desc] : m_supportedFpFiles )
357
358 if( PCBNEW_SETTINGS* cfg = GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" ) )
359 {
360 if( cfg->m_LastFootprintLibDir.IsEmpty() )
361 cfg->m_LastFootprintLibDir = PATHS::GetDefaultUserFootprintsPath();
362 }
363
365
367
369
370 if( aProjectTable )
371 {
372 m_project_grid->SetTable( new FP_LIB_TABLE_GRID( *aProjectTable ), true );
374 }
375 else
376 {
377 m_pageNdx = 0;
378 m_notebook->DeletePage( 1 );
379 m_project_grid = nullptr;
380 }
381
382 m_path_subs_grid->SetColLabelValue( 0, _( "Name" ) );
383 m_path_subs_grid->SetColLabelValue( 1, _( "Value" ) );
384
385 // select the last selected page
386 m_notebook->SetSelection( m_pageNdx );
388
389 // for ALT+A handling, we want the initial focus to be on the first selected grid.
390 m_parent->SetInitialFocus( m_cur_grid );
391
392 // Configure button logos
398
399 // For aesthetic reasons, we must set the size of m_browseButton to match the other bitmaps
400 // manually (for instance m_append_button)
401 Layout(); // Needed at least on MSW to compute the actual buttons sizes, after initializing
402 // their bitmaps
403 wxSize buttonSize = m_append_button->GetSize();
404
405 m_browseButton->SetWidthPadding( 4 );
406 m_browseButton->SetMinSize( buttonSize );
407
408 // Populate the browse library options
409 wxMenu* browseMenu = m_browseButton->GetSplitButtonMenu();
410
411 auto joinExts = []( const std::vector<std::string>& aExts )
412 {
413 wxString joined;
414 for( const std::string& ext : aExts )
415 {
416 if( !joined.empty() )
417 joined << wxS( ", " );
418
419 joined << wxS( "*." ) << ext;
420 }
421
422 return joined;
423 };
424
425 for( auto& [type, desc] : m_supportedFpFiles )
426 {
427 wxString entryStr = PCB_IO_MGR::ShowType( type );
428
429 if( desc.m_IsFile && !desc.m_FileExtensions.empty() )
430 {
431 entryStr << wxString::Format( wxS( " (%s)" ), joinExts( desc.m_FileExtensions ) );
432 }
433 else if( !desc.m_IsFile && !desc.m_ExtensionsInDir.empty() )
434 {
435 wxString midPart = wxString::Format( _( "folder with %s files" ),
436 joinExts( desc.m_ExtensionsInDir ) );
437
438 entryStr << wxString::Format( wxS( " (%s)" ), midPart );
439 }
440
441 browseMenu->Append( type, entryStr );
442
443 browseMenu->Bind( wxEVT_COMMAND_MENU_SELECTED, &PANEL_FP_LIB_TABLE::browseLibrariesHandler, this, type );
444 }
445
446 Layout();
447
448 // This is the button only press for the browse button instead of the menu
450}
451
452
454{
455 wxMenu* browseMenu = m_browseButton->GetSplitButtonMenu();
456
457 for( auto& [type, desc] : m_supportedFpFiles )
458 browseMenu->Unbind( wxEVT_COMMAND_MENU_SELECTED, &PANEL_FP_LIB_TABLE::browseLibrariesHandler, this, type );
459
460 m_browseButton->Unbind( wxEVT_BUTTON, &PANEL_FP_LIB_TABLE::browseLibrariesHandler, this );
461
462 // Delete the GRID_TRICKS.
463 // Any additional event handlers should be popped before the window is deleted.
464 m_global_grid->PopEventHandler( true );
465
466 if( m_project_grid )
467 m_project_grid->PopEventHandler( true );
468
469 m_path_subs_grid->PopEventHandler( true );
470}
471
472
474{
475 for( const auto& plugin : PCB_IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
476 {
477 IO_RELEASER<PCB_IO> pi( plugin.m_createFunc() );
478
479 if( !pi )
480 continue;
481
482 if( const IO_BASE::IO_FILE_DESC& desc = pi->GetLibraryDesc() )
483 m_supportedFpFiles.emplace( plugin.m_type, desc );
484 }
485}
486
487
489{
490 wxString msg;
491
492 for( FP_LIB_TABLE_GRID* model : { global_model(), project_model() } )
493 {
494 if( !model )
495 continue;
496
497 for( int r = 0; r < model->GetNumberRows(); )
498 {
499 wxString nick = model->GetValue( r, COL_NICKNAME ).Trim( false ).Trim();
500 wxString uri = model->GetValue( r, COL_URI ).Trim( false ).Trim();
501 unsigned illegalCh = 0;
502
503 if( !nick || !uri )
504 {
505 if( !nick && !uri )
506 msg = _( "A library table row nickname and path cells are empty." );
507 else if( !nick )
508 msg = _( "A library table row nickname cell is empty." );
509 else
510 msg = _( "A library table row path cell is empty." );
511
512 wxWindow* topLevelParent = wxGetTopLevelParent( this );
513
514 wxMessageDialog badCellDlg( topLevelParent, msg, _( "Invalid Row Definition" ),
515 wxYES_NO | wxCENTER | wxICON_QUESTION | wxYES_DEFAULT );
516 badCellDlg.SetExtendedMessage( _( "Empty cells will result in all rows that are "
517 "invalid to be removed from the table." ) );
518 badCellDlg.SetYesNoLabels( wxMessageDialog::ButtonLabel( _( "Remove Invalid Cells" ) ),
519 wxMessageDialog::ButtonLabel( _( "Cancel Table Update" ) ) );
520
521 if( badCellDlg.ShowModal() == wxID_NO )
522 return false;
523
524 // Delete the "empty" row, where empty means missing nick or uri.
525 // This also updates the UI which could be slow, but there should only be a few
526 // rows to delete, unless the user fell asleep on the Add Row
527 // button.
528 model->DeleteRows( r, 1 );
529 }
530 else if( ( illegalCh = LIB_ID::FindIllegalLibraryNameChar( nick ) ) )
531 {
532 msg = wxString::Format( _( "Illegal character '%c' in nickname '%s'." ),
533 illegalCh,
534 nick );
535
536 // show the tabbed panel holding the grid we have flunked:
537 if( model != cur_model() )
538 m_notebook->SetSelection( model == global_model() ? 0 : 1 );
539
540 m_cur_grid->MakeCellVisible( r, 0 );
541 m_cur_grid->SetGridCursor( r, 1 );
542
543 wxWindow* topLevelParent = wxGetTopLevelParent( this );
544
545 wxMessageDialog errdlg( topLevelParent, msg, _( "Library Nickname Error" ) );
546 errdlg.ShowModal();
547 return false;
548 }
549 else
550 {
551 // set the trimmed values back into the table so they get saved to disk.
552 model->SetValue( r, COL_NICKNAME, nick );
553 model->SetValue( r, COL_URI, uri );
554
555 // Make sure to not save a hidden flag
556 model->SetValue( r, COL_VISIBLE, wxS( "1" ) );
557
558 ++r; // this row was OK.
559 }
560 }
561 }
562
563 // check for duplicate nickNames, separately in each table.
564 for( FP_LIB_TABLE_GRID* model : { global_model(), project_model() } )
565 {
566 if( !model )
567 continue;
568
569 for( int r1 = 0; r1 < model->GetNumberRows() - 1; ++r1 )
570 {
571 wxString nick1 = model->GetValue( r1, COL_NICKNAME );
572
573 for( int r2 = r1 + 1; r2 < model->GetNumberRows(); ++r2 )
574 {
575 wxString nick2 = model->GetValue( r2, COL_NICKNAME );
576
577 if( nick1 == nick2 )
578 {
579 msg = wxString::Format( _( "Multiple libraries cannot share the same nickname ('%s')." ),
580 nick1 );
581
582 // show the tabbed panel holding the grid we have flunked:
583 if( model != cur_model() )
584 m_notebook->SetSelection( model == global_model() ? 0 : 1 );
585
586 // go to the lower of the two rows, it is technically the duplicate:
587 m_cur_grid->MakeCellVisible( r2, 0 );
588 m_cur_grid->SetGridCursor( r2, 1 );
589
590 wxWindow* topLevelParent = wxGetTopLevelParent( this );
591
592 wxMessageDialog errdlg( topLevelParent, msg, _( "Library Nickname Error" ) );
593 errdlg.ShowModal();
594 return false;
595 }
596 }
597 }
598 }
599
600 return true;
601}
602
603
604void PANEL_FP_LIB_TABLE::OnUpdateUI( wxUpdateUIEvent& event )
605{
606}
607
608
609void PANEL_FP_LIB_TABLE::appendRowHandler( wxCommandEvent& event )
610{
611 m_cur_grid->OnAddRow(
612 [&]() -> std::pair<int, int>
613 {
614 m_cur_grid->AppendRows( 1 );
615 return { m_cur_grid->GetNumberRows() - 1, COL_NICKNAME };
616 } );
617}
618
619
620void PANEL_FP_LIB_TABLE::deleteRowHandler( wxCommandEvent& event )
621{
622 if( !m_cur_grid->CommitPendingChanges() )
623 return;
624
625 wxGridUpdateLocker noUpdates( m_cur_grid );
626
627 int curRow = m_cur_grid->GetGridCursorRow();
628 int curCol = m_cur_grid->GetGridCursorCol();
629
630 // In a wxGrid, collect rows that have a selected cell, or are selected
631 // It is not so easy: it depends on the way the selection was made.
632 // Here, we collect rows selected by clicking on a row label, and rows that contain any
633 // previously-selected cells.
634 // If no candidate, just delete the row with the grid cursor.
635 wxArrayInt selectedRows = m_cur_grid->GetSelectedRows();
636 wxGridCellCoordsArray cells = m_cur_grid->GetSelectedCells();
637 wxGridCellCoordsArray blockTopLeft = m_cur_grid->GetSelectionBlockTopLeft();
638 wxGridCellCoordsArray blockBotRight = m_cur_grid->GetSelectionBlockBottomRight();
639
640 // Add all row having cell selected to list:
641 for( unsigned ii = 0; ii < cells.GetCount(); ii++ )
642 selectedRows.Add( cells[ii].GetRow() );
643
644 // Handle block selection
645 if( !blockTopLeft.IsEmpty() && !blockBotRight.IsEmpty() )
646 {
647 for( int i = blockTopLeft[0].GetRow(); i <= blockBotRight[0].GetRow(); ++i )
648 selectedRows.Add( i );
649 }
650
651 // Use the row having the grid cursor only if we have no candidate:
652 if( selectedRows.size() == 0 && m_cur_grid->GetGridCursorRow() >= 0 )
653 selectedRows.Add( m_cur_grid->GetGridCursorRow() );
654
655 if( selectedRows.size() == 0 )
656 {
657 wxBell();
658 return;
659 }
660
661 std::sort( selectedRows.begin(), selectedRows.end() );
662
663 // Remove selected rows (note: a row can be stored more than once in list)
664 int last_row = -1;
665
666 // Needed to avoid a wxWidgets alert if the row to delete is the last row
667 // at least on wxMSW 3.2
668 m_cur_grid->ClearSelection();
669
670 for( int ii = selectedRows.GetCount()-1; ii >= 0; ii-- )
671 {
672 int row = selectedRows[ii];
673
674 if( row != last_row )
675 {
676 last_row = row;
677 m_cur_grid->DeleteRows( row, 1 );
678 }
679 }
680
681 if( m_cur_grid->GetNumberRows() > 0 && curRow >= 0 )
682 m_cur_grid->SetGridCursor( std::min( curRow, m_cur_grid->GetNumberRows() - 1 ), curCol );
683}
684
685
686void PANEL_FP_LIB_TABLE::moveUpHandler( wxCommandEvent& event )
687{
688 m_cur_grid->OnMoveRowUp(
689 [&]( int row )
690 {
692 boost::ptr_vector<LIB_TABLE_ROW>::auto_type move_me = tbl->m_rows.release( tbl->m_rows.begin() + row );
693
694 tbl->m_rows.insert( tbl->m_rows.begin() + row - 1, move_me.release() );
695
696 // Update the wxGrid
697 wxGridTableMessage msg( tbl, wxGRIDTABLE_NOTIFY_ROWS_INSERTED, row - 1, 0 );
698 tbl->GetView()->ProcessTableMessage( msg );
699 } );
700}
701
702
703void PANEL_FP_LIB_TABLE::moveDownHandler( wxCommandEvent& event )
704{
705 m_cur_grid->OnMoveRowDown(
706 [&]( int row )
707 {
709 boost::ptr_vector<LIB_TABLE_ROW>::auto_type move_me = tbl->m_rows.release( tbl->m_rows.begin() + row );
710
711 tbl->m_rows.insert( tbl->m_rows.begin() + row + 1, move_me.release() );
712
713 // Update the wxGrid
714 wxGridTableMessage msg( tbl, wxGRIDTABLE_NOTIFY_ROWS_INSERTED, row, 0 );
715 tbl->GetView()->ProcessTableMessage( msg );
716 } );
717}
718
719
720// @todo refactor this function into single location shared with PANEL_SYM_LIB_TABLE
721void PANEL_FP_LIB_TABLE::onMigrateLibraries( wxCommandEvent& event )
722{
723 if( !m_cur_grid->CommitPendingChanges() )
724 return;
725
726 wxArrayInt selectedRows = m_cur_grid->GetSelectedRows();
727
728 if( selectedRows.empty() && m_cur_grid->GetGridCursorRow() >= 0 )
729 selectedRows.push_back( m_cur_grid->GetGridCursorRow() );
730
731 wxArrayInt rowsToMigrate;
732 wxString kicadType = PCB_IO_MGR::ShowType( PCB_IO_MGR::KICAD_SEXP );
733 wxString msg;
734 DIALOG_HTML_REPORTER errorReporter( this );
735
736 for( int row : selectedRows )
737 {
738 if( m_cur_grid->GetCellValue( row, COL_TYPE ) != kicadType )
739 rowsToMigrate.push_back( row );
740 }
741
742 if( rowsToMigrate.size() <= 0 )
743 {
744 wxMessageBox( wxString::Format( _( "Select one or more rows containing libraries "
745 "to save as current KiCad format." ) ) );
746 return;
747 }
748 else
749 {
750 if( rowsToMigrate.size() == 1 )
751 {
752 msg.Printf( _( "Save '%s' as current KiCad format and replace entry in table?" ),
753 m_cur_grid->GetCellValue( rowsToMigrate[0], COL_NICKNAME ) );
754 }
755 else
756 {
757 msg.Printf( _( "Save %d libraries as current KiCad format and replace entries in table?" ),
758 (int) rowsToMigrate.size() );
759 }
760
761 if( !IsOK( m_parent, msg ) )
762 return;
763 }
764
765 for( int row : rowsToMigrate )
766 {
767 wxString relPath = m_cur_grid->GetCellValue( row, COL_URI );
768 wxString resolvedPath = ExpandEnvVarSubstitutions( relPath, m_project );
769 wxFileName legacyLib( resolvedPath );
770
771 if( !legacyLib.Exists() )
772 {
773 msg.Printf( _( "Library '%s' not found." ), relPath );
774 DisplayErrorMessage( wxGetTopLevelParent( this ), msg );
775 continue;
776 }
777
778 wxFileName newLib( resolvedPath );
779 newLib.AppendDir( newLib.GetName() + "." + FILEEXT::KiCadFootprintLibPathExtension );
780 newLib.SetName( "" );
781 newLib.ClearExt();
782
783 if( newLib.DirExists() )
784 {
785 msg.Printf( _( "Folder '%s' already exists. Do you want overwrite any existing footprints?" ),
786 newLib.GetFullPath() );
787
788 switch( wxMessageBox( msg, _( "Migrate Library" ), wxYES_NO|wxCANCEL|wxICON_QUESTION, m_parent ) )
789 {
790 case wxYES: break;
791 case wxNO: continue;
792 case wxCANCEL: return;
793 }
794 }
795
796 wxString options = m_cur_grid->GetCellValue( row, COL_OPTIONS );
797 std::unique_ptr<std::map<std::string, UTF8>> props( LIB_TABLE::ParseOptions( options.ToStdString() ) );
798
799 if( PCB_IO_MGR::ConvertLibrary( props.get(), legacyLib.GetFullPath(), newLib.GetFullPath(),
800 errorReporter.m_Reporter ) )
801 {
802 relPath = NormalizePath( newLib.GetFullPath(), &Pgm().GetLocalEnvVariables(), m_project );
803
804 // Do not use the project path in the global library table. This will almost
805 // assuredly be wrong for a different project.
806 if( m_cur_grid == m_global_grid && relPath.Contains( "${KIPRJMOD}" ) )
807 relPath = newLib.GetFullPath();
808
809 m_cur_grid->SetCellValue( row, COL_URI, relPath );
810 m_cur_grid->SetCellValue( row, COL_TYPE, kicadType );
811 }
812 else
813 {
814 msg.Printf( _( "Failed to save footprint library file '%s'." ), newLib.GetFullPath() );
815 DisplayErrorMessage( wxGetTopLevelParent( this ), msg );
816 }
817 }
818
819 if( errorReporter.m_Reporter->HasMessage() )
820 {
821 errorReporter.m_Reporter->Flush(); // Build HTML messages
822 errorReporter.ShowModal();
823 }
824}
825
826
828{
829 if( !m_cur_grid->CommitPendingChanges() )
830 return;
831
833
834 // We are bound both to the menu and button with this one handler
835 // So we must set the file type based on it
836 if( event.GetEventType() == wxEVT_BUTTON )
837 {
838 // Let's default to adding a kicad footprint file for just the footprint
840 }
841 else
842 {
843 fileType = static_cast<PCB_IO_MGR::PCB_FILE_T>( event.GetId() );
844 }
845
847 {
848 wxLogWarning( wxT( "File type selection event received but could not find the file type in the table" ) );
849 return;
850 }
851
852 const IO_BASE::IO_FILE_DESC& fileDesc = m_supportedFpFiles.at( fileType );
854
855 wxString title = wxString::Format( _( "Select %s Library" ), PCB_IO_MGR::ShowType( fileType ) );
856 wxString dummy;
857 wxString* lastDir;
858
860 lastDir = &m_lastProjectLibDir;
861 else
862 lastDir = cfg ? &cfg->m_LastFootprintLibDir : &dummy;
863
864 wxArrayString files;
865
866 wxWindow* topLevelParent = wxGetTopLevelParent( this );
867
868 if( fileDesc.m_IsFile )
869 {
870 wxFileDialog dlg( topLevelParent, title, *lastDir, wxEmptyString, fileDesc.FileFilter(),
871 wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE );
872
873 if( dlg.ShowModal() == wxID_CANCEL )
874 return;
875
876 dlg.GetPaths( files );
877 *lastDir = dlg.GetDirectory();
878 }
879 else
880 {
881 wxDirDialog dlg( topLevelParent, title, *lastDir,
882 wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST | wxDD_MULTIPLE );
883
884 if( dlg.ShowModal() == wxID_CANCEL )
885 return;
886
887 dlg.GetPaths( files );
888
889 if( !files.IsEmpty() )
890 {
891 wxFileName first( files.front() );
892 *lastDir = first.GetPath();
893 }
894 }
895
896 // Drop the last directory if the path is a .pretty folder
898 cfg->m_LastFootprintLibDir = cfg->m_LastFootprintLibDir.BeforeLast( wxFileName::GetPathSeparator() );
899
900 const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
901 bool addDuplicates = false;
902 bool applyToAll = false;
903 wxString warning = _( "Warning: Duplicate Nicknames" );
904 wxString msg = _( "A library nicknamed '%s' already exists." );
905 wxString detailedMsg = _( "One of the nicknames will need to be changed after "
906 "adding this library." );
907
908 for( const wxString& filePath : files )
909 {
910 wxFileName fn( filePath );
911 wxString nickname = LIB_ID::FixIllegalChars( fn.GetName(), true );
912 bool doAdd = true;
913
916 {
917 nickname = LIB_ID::FixIllegalChars( fn.GetFullName(), true ).wx_str();
918 }
919
920 if( cur_model()->ContainsNickname( nickname ) )
921 {
922 if( !applyToAll )
923 {
924 // The cancel button adds the library to the table anyway
925 addDuplicates = OKOrCancelDialog( wxGetTopLevelParent( this ), warning,
926 wxString::Format( msg, nickname ),
927 detailedMsg, _( "Skip" ), _( "Add Anyway" ),
928 &applyToAll ) == wxID_CANCEL;
929 }
930
931 doAdd = addDuplicates;
932 }
933
934 if( doAdd && m_cur_grid->AppendRows( 1 ) )
935 {
936 int last_row = m_cur_grid->GetNumberRows() - 1;
937
938 m_cur_grid->SetCellValue( last_row, COL_NICKNAME, nickname );
939
940 m_cur_grid->SetCellValue( last_row, COL_TYPE, PCB_IO_MGR::ShowType( fileType ) );
941
942 // try to use path normalized to an environmental variable or project path
943 wxString path = NormalizePath( filePath, &envVars, m_projectBasePath );
944
945 // Do not use the project path in the global library table. This will almost
946 // assuredly be wrong for a different project.
947 if( m_pageNdx == 0 && path.Contains( wxT( "${KIPRJMOD}" ) ) )
948 path = fn.GetFullPath();
949
950 m_cur_grid->SetCellValue( last_row, COL_URI, path );
951 }
952 }
953
954 if( !files.IsEmpty() )
955 {
956 int new_row = m_cur_grid->GetNumberRows() - 1;
957 m_cur_grid->MakeCellVisible( new_row, m_cur_grid->GetGridCursorCol() );
958 m_cur_grid->SetGridCursor( new_row, m_cur_grid->GetGridCursorCol() );
959 }
960}
961
962
964{
965 // Account for scroll bars
966 aWidth -= ( m_path_subs_grid->GetSize().x - m_path_subs_grid->GetClientSize().x );
967
968 m_path_subs_grid->AutoSizeColumn( 0 );
969 m_path_subs_grid->SetColSize( 0, std::max( 72, m_path_subs_grid->GetColSize( 0 ) ) );
970 m_path_subs_grid->SetColSize( 1, std::max( 120, aWidth - m_path_subs_grid->GetColSize( 0 ) ) );
971}
972
973
974void PANEL_FP_LIB_TABLE::onSizeGrid( wxSizeEvent& event )
975{
976 adjustPathSubsGridColumns( event.GetSize().GetX() );
977
978 event.Skip();
979}
980
981
982void PANEL_FP_LIB_TABLE::onReset( wxCommandEvent& event )
983{
984 if( !m_cur_grid->CommitPendingChanges() )
985 return;
986
987 // No need to prompt to preserve an empty table
988 if( m_global_grid->GetNumberRows() > 0 &&
989 !IsOK( this, wxString::Format( _( "This action will reset your global library table on "
990 "disk and cannot be undone." ) ) ) )
991 {
992 return;
993 }
994
996
997 if( dlg.ShowModal() == wxID_OK )
998 {
999 m_global_grid->Freeze();
1000
1001 wxGridTableBase* table = m_global_grid->GetTable();
1002 m_global_grid->DestroyTable( table );
1003
1004 m_global_grid->SetTable( new FP_LIB_TABLE_GRID( *m_globalTable ), true );
1005 m_global_grid->PopEventHandler( true );
1007 m_parent->m_GlobalTableChanged = true;
1008
1009 m_global_grid->Thaw();
1010 }
1011}
1012
1013
1014void PANEL_FP_LIB_TABLE::onPageChange( wxBookCtrlEvent& event )
1015{
1016 m_pageNdx = (unsigned) std::max( 0, m_notebook->GetSelection() );
1017
1018 if( m_pageNdx == 0 )
1019 {
1021 m_resetGlobal->Enable();
1022 }
1023 else
1024 {
1026 m_resetGlobal->Disable();
1027 }
1028}
1029
1030
1032{
1033 if( !m_cur_grid->CommitPendingChanges() )
1034 return false;
1035
1036 if( verifyTables() )
1037 {
1038 if( *global_model() != *m_globalTable )
1039 {
1040 m_parent->m_GlobalTableChanged = true;
1041 m_globalTable->TransferRows( global_model()->m_rows );
1042 }
1043
1045 {
1046 m_parent->m_ProjectTableChanged = true;
1047 m_projectTable->TransferRows( project_model()->m_rows );
1048 }
1049
1050 return true;
1051 }
1052
1053 return false;
1054}
1055
1056
1060{
1061 wxRegEx re( ".*?(\\$\\{(.+?)\\})|(\\$\\((.+?)\\)).*?", wxRE_ADVANCED );
1062 wxASSERT( re.IsValid() ); // wxRE_ADVANCED is required.
1063
1064 std::set< wxString > unique;
1065
1066 // clear the table
1067 m_path_subs_grid->ClearRows();
1068
1069 for( FP_LIB_TABLE_GRID* tbl : { global_model(), project_model() } )
1070 {
1071 if( !tbl )
1072 continue;
1073
1074 for( int row = 0; row < tbl->GetNumberRows(); ++row )
1075 {
1076 wxString uri = tbl->GetValue( row, COL_URI );
1077
1078 while( re.Matches( uri ) )
1079 {
1080 wxString envvar = re.GetMatch( uri, 2 );
1081
1082 // if not ${...} form then must be $(...)
1083 if( envvar.IsEmpty() )
1084 envvar = re.GetMatch( uri, 4 );
1085
1086 // ignore duplicates
1087 unique.insert( envvar );
1088
1089 // delete the last match and search again
1090 uri.Replace( re.GetMatch( uri, 0 ), wxEmptyString );
1091 }
1092 }
1093 }
1094
1095 // Make sure this special environment variable shows up even if it was
1096 // not used yet. It is automatically set by KiCad to the directory holding
1097 // the current project.
1098 unique.insert( PROJECT_VAR_NAME );
1099 unique.insert( FP_LIB_TABLE::GlobalPathEnvVariableName() );
1100
1101 // This special environment variable is used to locate 3d shapes
1102 unique.insert( ENV_VAR::GetVersionedEnvVarName( wxS( "3DMODEL_DIR" ) ) );
1103
1104 for( const wxString& evName : unique )
1105 {
1106 int row = m_path_subs_grid->GetNumberRows();
1107 m_path_subs_grid->AppendRows( 1 );
1108
1109 m_path_subs_grid->SetCellValue( row, 0, wxT( "${" ) + evName + wxT( "}" ) );
1110 m_path_subs_grid->SetCellEditor( row, 0, new GRID_CELL_READONLY_TEXT_EDITOR() );
1111
1112 wxString evValue;
1113 wxGetEnv( evName, &evValue );
1114 m_path_subs_grid->SetCellValue( row, 1, evValue );
1115 m_path_subs_grid->SetCellEditor( row, 1, new GRID_CELL_READONLY_TEXT_EDITOR() );
1116 }
1117
1118 adjustPathSubsGridColumns( m_path_subs_grid->GetRect().GetWidth() );
1119}
1120
1121
1122//-----</event handlers>---------------------------------
1123
1124
1125
1127
1128
1129void InvokePcbLibTableEditor( KIWAY* aKiway, wxWindow* aCaller )
1130{
1131 FP_LIB_TABLE* globalTable = &GFootprintTable;
1132 wxString globalTablePath = FP_LIB_TABLE::GetGlobalTableFileName();
1133 FP_LIB_TABLE* projectTable = PROJECT_PCB::PcbFootprintLibs( &aKiway->Prj() );
1134 wxString projectTablePath = aKiway->Prj().FootprintLibTblName();
1135 wxString msg;
1136
1137 DIALOG_EDIT_LIBRARY_TABLES dlg( aCaller, _( "Footprint Libraries" ) );
1138 dlg.SetKiway( &dlg, aKiway );
1139
1140 if( aKiway->Prj().IsNullProject() )
1141 projectTable = nullptr;
1142
1143 dlg.InstallPanel( new PANEL_FP_LIB_TABLE( &dlg, &aKiway->Prj(), globalTable, globalTablePath,
1144 projectTable, projectTablePath,
1145 aKiway->Prj().GetProjectPath() ) );
1146
1147 if( dlg.ShowModal() == wxID_CANCEL )
1148 return;
1149
1150 if( dlg.m_GlobalTableChanged )
1151 {
1152 try
1153 {
1154 globalTable->Save( globalTablePath );
1155 }
1156 catch( const IO_ERROR& ioe )
1157 {
1158 msg.Printf( _( "Error saving global library table:\n\n%s" ), ioe.What() );
1159 wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
1160 }
1161 }
1162
1163 if( projectTable && dlg.m_ProjectTableChanged )
1164 {
1165 try
1166 {
1167 projectTable->Save( projectTablePath );
1168 }
1169 catch( const IO_ERROR& ioe )
1170 {
1171 msg.Printf( _( "Error saving project-specific library table:\n\n%s" ), ioe.What() );
1172 wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
1173 }
1174 }
1175
1176 std::string payload = "";
1179 aKiway->ExpressMail( FRAME_CVPCB, MAIL_RELOAD_LIB, payload );
1180}
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:110
Class DIALOG_HTML_REPORTER.
WX_HTML_REPORT_BOX * m_Reporter
An options editor in the form of a two column name/value spreadsheet like (table) UI.
int ShowModal() override
void paste_text(const wxString &cb_text) override
handle specialized clipboard text, with leading "(fp_lib_table", OR spreadsheet formatted text.
DIALOG_EDIT_LIBRARY_TABLES * m_dialog
FP_GRID_TRICKS(DIALOG_EDIT_LIBRARY_TABLES *aParent, WX_GRID *aGrid)
void optionsEditor(int aRow) override
FP_GRID_TRICKS(DIALOG_EDIT_LIBRARY_TABLES *aParent, WX_GRID *aGrid, std::function< void(wxCommandEvent &)> aAddHandler)
bool toggleCell(int aRow, int aCol, bool aPreserveSelection) override
This class builds a wxGridTableBase by wrapping an FP_LIB_TABLE object.
size_t size() const override
FP_LIB_TABLE_GRID(const FP_LIB_TABLE &aTableToEdit)
void SetValue(int aRow, int aCol, const wxString &aValue) override
LIB_TABLE_ROWS_ITER begin() override
LIB_TABLE_ROWS_ITER erase(LIB_TABLE_ROWS_ITER aFirst, LIB_TABLE_ROWS_ITER aLast) override
LIB_TABLE_ROW * makeNewRow() override
LIB_TABLE_ROW * at(size_t aIndex) override
void push_back(LIB_TABLE_ROW *aRow) override
LIB_TABLE_ROWS_ITER insert(LIB_TABLE_ROWS_ITER aIterator, LIB_TABLE_ROW *aRow) override
friend class PANEL_FP_LIB_TABLE
Hold a record identifying a library accessed by the appropriate footprint library #PLUGIN object in t...
FP_LIB_TABLE(FP_LIB_TABLE *aFallBackTable=nullptr)
Build a footprint library table by pre-pending this table fragment in front of aFallBackTable.
static const wxString GlobalPathEnvVariableName()
Return the name of the environment variable used to hold the directory of locally installed "KiCad sp...
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 wxString GetGlobalTableFileName()
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.
virtual bool toggleCell(int aRow, int aCol, bool aPreserveSelection=false)
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 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.
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
void SetOptions(const wxString &aOptions)
Change the library options strings.
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.
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
STD_BITMAP_BUTTON * m_move_up_button
STD_BITMAP_BUTTON * m_append_button
STD_BITMAP_BUTTON * m_move_down_button
STD_BITMAP_BUTTON * m_delete_button
PANEL_FP_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)
Dialog to show and edit symbol library tables.
FP_LIB_TABLE * m_globalTable
bool verifyTables()
Trim important fields, removes blank row entries, and checks for duplicates.
std::map< PCB_IO_MGR::PCB_FILE_T, IO_BASE::IO_FILE_DESC > m_supportedFpFiles
void onSizeGrid(wxSizeEvent &event) override
void moveUpHandler(wxCommandEvent &event) override
void adjustPathSubsGridColumns(int aWidth)
FP_LIB_TABLE_GRID * cur_model() const
FP_LIB_TABLE_GRID * project_model() const
void moveDownHandler(wxCommandEvent &event) override
wxArrayString m_pluginChoices
void setupGrid(WX_GRID *aGrid)
FP_LIB_TABLE_GRID * global_model() const
void populateEnvironReadOnlyTable()
Populate the readonly environment variable table with names and values by examining all the full_uri ...
FP_LIB_TABLE * m_projectTable
void deleteRowHandler(wxCommandEvent &event) override
void onReset(wxCommandEvent &event) override
void onMigrateLibraries(wxCommandEvent &event) override
void browseLibrariesHandler(wxCommandEvent &event)
bool TransferDataFromWindow() override
PANEL_FP_LIB_TABLE(DIALOG_EDIT_LIBRARY_TABLES *aParent, PROJECT *aProject, FP_LIB_TABLE *aGlobalTable, const wxString &aGlobalTblPath, FP_LIB_TABLE *aProjectTable, const wxString &aProjectTblPath, const wxString &aProjectBasePath)
DIALOG_EDIT_LIBRARY_TABLES * m_parent
void OnUpdateUI(wxUpdateUIEvent &event) override
void onPageChange(wxBookCtrlEvent &event) override
void appendRowHandler(wxCommandEvent &event) override
static wxString GetDefaultUserFootprintsPath()
Gets the default path we point users to create projects.
Definition paths.cpp:92
wxString m_LastFootprintLibDir
static PLUGIN_REGISTRY * Instance()
Definition pcb_io_mgr.h:94
static PCB_IO * PluginFind(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
static PCB_FILE_T EnumFromStr(const wxString &aFileType)
Return the PCB_FILE_T from the corresponding plugin type name: "kicad", "legacy", etc.
PCB_FILE_T
The set of file types that the PCB_IO_MGR knows about, and for which there has been a plugin written,...
Definition pcb_io_mgr.h:56
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition pcb_io_mgr.h:58
static bool ConvertLibrary(std::map< std::string, UTF8 > *aOldFileProps, const wxString &aOldFilePath, const wxString &aNewFilePath, REPORTER *aReporter)
Convert a schematic symbol library to the latest KiCad format.
static PCB_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath, int aCtl=0)
Return a plugin type given a footprint library's libPath.
static const wxString ShowType(PCB_FILE_T aFileType)
Return a brief name for a plugin given aFileType enum.
virtual ENV_VAR_MAP & GetLocalEnvVariables() const
Definition pgm_base.cpp:822
static FP_LIB_TABLE * PcbFootprintLibs(PROJECT *aProject)
Return the table of footprint libraries without Kiway.
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 const wxString FootprintLibTblName() const
Returns the path and filename of this project's footprint library table.
Definition project.cpp:192
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Definition project.cpp:180
Is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition richio.h:253
wxString wx_str() const
Definition utf8.cpp:45
void Flush()
Build the HTML messages page.
bool HasMessage() const override
Returns true if any messages were reported.
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
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.
FP_LIB_TABLE GFootprintTable
The global footprint library table.
Definition cvpcb.cpp:150
#define _(s)
Declaration of the eda_3d_viewer class.
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.
Functions related to environment variables, including help functions.
@ FRAME_FOOTPRINT_VIEWER
Definition frame_type.h:45
@ FRAME_FOOTPRINT_EDITOR
Definition frame_type.h:43
@ FRAME_CVPCB
Definition frame_type.h:52
static const std::string KiCadFootprintLibPathExtension
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
This file contains miscellaneous commonly used macros and functions.
@ MAIL_RELOAD_LIB
Definition mail_type.h:57
KICOMMON_API wxString GetVersionedEnvVarName(const wxString &aBaseName)
Construct a versioned environment variable based on this KiCad major version.
Definition env_vars.cpp:77
void InvokePcbLibTableEditor(KIWAY *aKiway, wxWindow *aCaller)
Function InvokePcbLibTableEditor shows the modal DIALOG_FP_LIB_TABLE for purposes of editing the glob...
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
bool m_IsFile
Whether the library is a folder or a file.
Definition io_base.h:51
wxString FileFilter() const
Definition io_base.cpp:40
A filename or source description, a problem input line, a line number, a byte offset,...
wxString result
Test unit parsing edge cases and error handling.
Definition of file extensions used in Kicad.