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
253 EESCHEMA_SETTINGS* cfg = mgr.GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" );
254
255 // Give a bit more room for combobox editors
256 for( int ii = 0; ii < aGrid->GetNumberRows(); ++ii )
257 aGrid->SetRowSize( ii, aGrid->GetDefaultRowSize() + 4 );
258
259 // add Cut, Copy, and Paste to wxGrids
260 aGrid->PushEventHandler( new SYMBOL_GRID_TRICKS( m_parent, aGrid ) );
261
262 aGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
263
264 // Set special attributes
265 wxGridCellAttr* attr;
266
267 attr = new wxGridCellAttr;
268
269 wxString fileFiltersStr;
270 wxString allWildcardsStr;
271
272 attr->SetEditor( new GRID_CELL_PATH_EDITOR( m_parent, aGrid,
273 &cfg->m_lastSymbolLibDir,
274 true, m_project->GetProjectPath(),
275 []( WX_GRID* grid, int row ) -> wxString
276 {
277 auto* libTable = static_cast<SYMBOL_LIB_TABLE_GRID*>( grid->GetTable() );
278 auto* tableRow = static_cast<SYMBOL_LIB_TABLE_ROW*>( libTable->at( row ) );
279
280 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( tableRow->GetFileType() ) );
281
282 if( pi )
283 {
284 const IO_BASE::IO_FILE_DESC& desc = pi->GetLibraryDesc();
285
286 if( desc.m_IsFile )
287 return desc.FileFilter();
288 }
289
290 return wxEmptyString;
291 } ) );
292 aGrid->SetColAttr( COL_URI, attr );
293
294 attr = new wxGridCellAttr;
295 attr->SetEditor( new wxGridCellChoiceEditor( m_pluginChoices ) );
296 aGrid->SetColAttr( COL_TYPE, attr );
297
298 attr = new wxGridCellAttr;
299 attr->SetRenderer( new wxGridCellBoolRenderer() );
300 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
301 aGrid->SetColAttr( COL_ENABLED, attr );
302
303 attr = new wxGridCellAttr;
304 attr->SetRenderer( new wxGridCellBoolRenderer() );
305 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
306 aGrid->SetColAttr( COL_VISIBLE, attr );
307
308 // all but COL_OPTIONS, which is edited with Option Editor anyways.
309 autoSizeCol( aGrid, COL_NICKNAME );
310 autoSizeCol( aGrid, COL_TYPE );
311 autoSizeCol( aGrid, COL_URI );
312 autoSizeCol( aGrid, COL_DESCR );
313 autoSizeCol( aGrid, COL_ENABLED );
314
315 // Gives a selection to each grid, mainly for delete button. wxGrid's wake up with
316 // a currentCell which is sometimes not highlighted.
317 if( aGrid->GetNumberRows() > 0 )
318 aGrid->SelectRow( 0 );
319};
320
321
323 SYMBOL_LIB_TABLE* aGlobalTable,
324 const wxString& aGlobalTablePath,
325 SYMBOL_LIB_TABLE* aProjectTable,
326 const wxString& aProjectTablePath ) :
327 PANEL_SYM_LIB_TABLE_BASE( aParent ),
328 m_globalTable( aGlobalTable ),
329 m_projectTable( aProjectTable ),
330 m_project( aProject ),
331 m_parent( aParent )
332{
333 // wxGrid only supports user owned tables if they exist past end of ~wxGrid(),
334 // so make it a grid owned table.
336
337 for( const SCH_IO_MGR::SCH_FILE_T& type : SCH_IO_MGR::SCH_FILE_T_vector )
338 {
339 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( type ) );
340
341 if( !pi )
342 continue;
343
344 if( const IO_BASE::IO_FILE_DESC& desc = pi->GetLibraryDesc() )
346 }
347
349 EESCHEMA_SETTINGS* cfg = mgr.GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" );
350
351 if( cfg->m_lastSymbolLibDir.IsEmpty() )
353
355
356
358 m_global_grid->Bind( wxEVT_GRID_CELL_LEFT_CLICK,
360
361 if( m_projectTable )
362 {
365 m_project_grid->Bind( wxEVT_GRID_CELL_LEFT_CLICK,
367 }
368 else
369 {
370 m_pageNdx = 0;
371 m_notebook->DeletePage( 1 );
372 m_project_grid = nullptr;
373 }
374
375 // add Cut, Copy, and Paste to wxGrids
376 m_path_subs_grid->PushEventHandler( new GRID_TRICKS( m_path_subs_grid ) );
377
379
380 // select the last selected page
381 m_notebook->SetSelection( m_pageNdx );
383
384 m_path_subs_grid->SetColLabelValue( 0, _( "Name" ) );
385 m_path_subs_grid->SetColLabelValue( 1, _( "Value" ) );
386
387 // for ALT+A handling, we want the initial focus to be on the first selected grid.
389
390 // Configure button logos
391 m_append_button->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
392 m_delete_button->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
393 m_move_up_button->SetBitmap( KiBitmapBundle( BITMAPS::small_up ) );
394 m_move_down_button->SetBitmap( KiBitmapBundle( BITMAPS::small_down ) );
395 m_browse_button->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
396}
397
398
400{
401 // Delete the GRID_TRICKS.
402 // Any additional event handlers should be popped before the window is deleted.
403 m_global_grid->PopEventHandler( true );
404 m_global_grid->Unbind( wxEVT_GRID_CELL_LEFT_CLICK,
406
407 if( m_project_grid )
408 {
409 m_project_grid->PopEventHandler( true );
410 m_project_grid->Unbind( wxEVT_GRID_CELL_LEFT_CLICK,
412 }
413
414 m_path_subs_grid->PopEventHandler( true );
415}
416
417
419{
420 // When the plugin type depends only of the file extension, return true.
421 // if it needs to read the actual file (that can be not available), return false
422
423 wxFileName fn( aLibraryPath );
424 wxString ext = fn.GetExt().Lower();
425
426 // Currently, only the extension .lib is common to legacy libraries and Cadstar libraries
427 // so return false in this case
429 return false;
430
431 return true;
432}
433
434
436{
437 wxString msg;
438 std::unique_ptr<wxBusyCursor> wait;
439 wait.reset( new wxBusyCursor );
440
441 for( SYMBOL_LIB_TABLE_GRID* model : { global_model(), project_model() } )
442 {
443 if( !model )
444 continue;
445
446 for( int r = 0; r < model->GetNumberRows(); )
447 {
448 wxString nick = model->GetValue( r, COL_NICKNAME ).Trim( false ).Trim();
449 wxString uri = model->GetValue( r, COL_URI ).Trim( false ).Trim();
450 unsigned illegalCh = 0;
451
452 if( !nick || !uri )
453 {
454 if( !nick && !uri )
455 msg = _( "A library table row nickname and path cells are empty." );
456 else if( !nick )
457 msg = _( "A library table row nickname cell is empty." );
458 else
459 msg = _( "A library table row path cell is empty." );
460
461 wxWindow* topLevelParent = wxGetTopLevelParent( this );
462
463 wxMessageDialog badCellDlg( topLevelParent, msg, _( "Invalid Row Definition" ),
464 wxYES_NO | wxCENTER | wxICON_QUESTION | wxYES_DEFAULT );
465 badCellDlg.SetExtendedMessage( _( "Empty cells will result in all rows that are "
466 "invalid to be removed from the table." ) );
467 badCellDlg.SetYesNoLabels(
468 wxMessageDialog::ButtonLabel( _( "Remove Invalid Cells" ) ),
469 wxMessageDialog::ButtonLabel( _( "Cancel Table Update" ) ) );
470
471 wait.reset();
472
473 if( badCellDlg.ShowModal() == wxID_NO )
474 return false;
475
476 wait.reset( new wxBusyCursor );
477
478 // Delete the "empty" row, where empty means missing nick or uri.
479 // This also updates the UI which could be slow, but there should only be a few
480 // rows to delete, unless the user fell asleep on the Add Row
481 // button.
482 model->DeleteRows( r, 1 );
483 }
484 else if( ( illegalCh = LIB_ID::FindIllegalLibraryNameChar( nick ) ) )
485 {
486 msg = wxString::Format( _( "Illegal character '%c' in nickname '%s'" ),
487 illegalCh,
488 nick );
489
490 // show the tabbed panel holding the grid we have flunked:
491 if( model != cur_model() )
492 m_notebook->SetSelection( model == global_model() ? 0 : 1 );
493
494 m_cur_grid->MakeCellVisible( r, 0 );
495 m_cur_grid->SetGridCursor( r, 1 );
496
497 wxWindow* topLevelParent = wxGetTopLevelParent( this );
498
499 wxMessageDialog errdlg( topLevelParent, msg, _( "Library Nickname Error" ) );
500
501 wait.reset();
502 errdlg.ShowModal();
503 return false;
504 }
505 else
506 {
507 // set the trimmed values back into the table so they get saved to disk.
508 model->SetValue( r, COL_NICKNAME, nick );
509
511 {
512 model->SetValue( r, COL_URI, uri );
513 }
514 else
515 {
516 wxString ltype = model->GetValue( r, COL_TYPE );
517 model->LIB_TABLE_GRID::SetValue( r, COL_URI, uri );
518 model->SetValue( r, COL_TYPE, ltype );
519 }
520
521 ++r; // this row was OK.
522 }
523 }
524 }
525
526 // check for duplicate nickNames, separately in each table.
527 for( SYMBOL_LIB_TABLE_GRID* model : { global_model(), project_model() } )
528 {
529 if( !model )
530 continue;
531
532 for( int r1 = 0; r1 < model->GetNumberRows() - 1; ++r1 )
533 {
534 wxString nick1 = model->GetValue( r1, COL_NICKNAME );
535
536 for( int r2 = r1 + 1; r2 < model->GetNumberRows(); ++r2 )
537 {
538 wxString nick2 = model->GetValue( r2, COL_NICKNAME );
539
540 if( nick1 == nick2 )
541 {
542 msg = wxString::Format( _( "Multiple libraries cannot share the same "
543 "nickname ('%s')." ), nick1 );
544
545 // show the tabbed panel holding the grid we have flunked:
546 if( model != cur_model() )
547 m_notebook->SetSelection( model == global_model() ? 0 : 1 );
548
549 // go to the lower of the two rows, it is technically the duplicate:
550 m_cur_grid->MakeCellVisible( r2, 0 );
551 m_cur_grid->SetGridCursor( r2, 1 );
552
553 wxWindow* topLevelParent = wxGetTopLevelParent( this );
554
555 wait.reset();
556 wxMessageDialog errdlg( topLevelParent, msg, _( "Library Nickname Error" ) );
557 errdlg.ShowModal();
558
559 return false;
560 }
561 }
562 }
563 }
564
565 for( SYMBOL_LIB_TABLE* table : { global_model(), project_model() } )
566 {
567 if( !table )
568 continue;
569
570 for( unsigned int r = 0; r < table->GetCount(); ++r )
571 {
572 SYMBOL_LIB_TABLE_ROW& row = dynamic_cast<SYMBOL_LIB_TABLE_ROW&>( table->At( r ) );
573
574 // Newly-added rows won't have set this yet
575 row.SetParent( table );
576
577 if( !row.GetIsEnabled() )
578 continue;
579
580 try
581 {
582 if( row.Refresh() )
583 {
584 if( table == global_model() )
586 else
588 }
589 }
590 catch( const IO_ERROR& ioe )
591 {
592 msg.Printf( _( "Symbol library '%s' failed to load." ), row.GetNickName() );
593
594 wxWindow* topLevelParent = wxGetTopLevelParent( this );
595 wait.reset();
596 wxMessageDialog errdlg( topLevelParent, msg + wxS( "\n" ) + ioe.What(),
597 _( "Error Loading Library" ) );
598 errdlg.ShowModal();
599
600 return true;
601 }
602 }
603 }
604
605 return true;
606}
607
608
609void PANEL_SYM_LIB_TABLE::OnUpdateUI( wxUpdateUIEvent& event )
610{
611}
612
613
615{
616 wxString fileFiltersStr;
617 wxString allWildcardsStr;
618
619 for( const SCH_IO_MGR::SCH_FILE_T& fileType : SCH_IO_MGR::SCH_FILE_T_vector )
620 {
621 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
622
623 if( !pi )
624 continue;
625
626 const IO_BASE::IO_FILE_DESC& desc = pi->GetLibraryDesc();
627
628 if( desc.m_FileExtensions.empty() )
629 continue;
630
631 if( !fileFiltersStr.IsEmpty() )
632 fileFiltersStr += wxChar( '|' );
633
634 fileFiltersStr += desc.FileFilter();
635
636 for( const std::string& ext : desc.m_FileExtensions )
637 allWildcardsStr << wxT( "*." ) << formatWildcardExt( ext ) << wxT( ";" );
638 }
639
640 fileFiltersStr = _( "All supported formats" ) + wxT( "|" ) + allWildcardsStr + wxT( "|" )
641 + fileFiltersStr;
642
644 EESCHEMA_SETTINGS* cfg = mgr.GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" );
645
646 wxString openDir = cfg->m_lastSymbolLibDir;
647
649 openDir = m_lastProjectLibDir;
650
651 wxWindow* topLevelParent = wxGetTopLevelParent( this );
652
653 wxFileDialog dlg( topLevelParent, _( "Add Library" ), openDir, wxEmptyString, fileFiltersStr,
654 wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE );
655
656 if( dlg.ShowModal() == wxID_CANCEL )
657 return;
658
660 cfg->m_lastSymbolLibDir = dlg.GetDirectory();
661 else
662 m_lastProjectLibDir = dlg.GetDirectory();
663
664 const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
665 bool addDuplicates = false;
666 bool applyToAll = false;
667 wxString warning = _( "Warning: Duplicate Nickname" );
668 wxString msg = _( "A library nicknamed '%s' already exists." );
669 wxString detailedMsg = _( "One of the nicknames will need to be changed after "
670 "adding this library." );
671
672 wxArrayString filePathsList;
673 dlg.GetPaths( filePathsList );
674
675 for( const wxString& filePath : filePathsList )
676 {
677 wxFileName fn( filePath );
678 wxString nickname = LIB_ID::FixIllegalChars( fn.GetName(), true );
679 bool doAdd = true;
680
681 if( cur_model()->ContainsNickname( nickname ) )
682 {
683 if( !applyToAll )
684 {
685 // The cancel button adds the library to the table anyway
686 addDuplicates = OKOrCancelDialog( wxGetTopLevelParent( this ), warning,
687 wxString::Format( msg, nickname ),
688 detailedMsg, _( "Skip" ), _( "Add Anyway" ),
689 &applyToAll ) == wxID_CANCEL;
690 }
691
692 doAdd = addDuplicates;
693 }
694
695 if( doAdd && m_cur_grid->AppendRows( 1 ) )
696 {
697 int last_row = m_cur_grid->GetNumberRows() - 1;
698
699 m_cur_grid->SetCellValue( last_row, COL_NICKNAME, nickname );
700
701 // attempt to auto-detect the plugin type
702 SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromLibPath( filePath );
703
704 if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
705 pluginType = SCH_IO_MGR::SCH_KICAD;
706
707 m_cur_grid->SetCellValue( last_row, COL_TYPE, SCH_IO_MGR::ShowType( pluginType ) );
708
709 // try to use path normalized to an environmental variable or project path
710 wxString path = NormalizePath( filePath, &envVars, m_project->GetProjectPath() );
711
712 // Do not use the project path in the global library table. This will almost
713 // assuredly be wrong for a different project.
714 if( m_pageNdx == 0 && path.Contains( "${KIPRJMOD}" ) )
715 path = fn.GetFullPath();
716
717 m_cur_grid->SetCellValue( last_row, COL_URI, path );
718 }
719 }
720
721 if( !filePathsList.IsEmpty() )
722 {
723 m_cur_grid->MakeCellVisible( m_cur_grid->GetNumberRows() - 1, COL_ENABLED );
724 m_cur_grid->SetGridCursor( m_cur_grid->GetNumberRows() - 1, COL_NICKNAME );
725 }
726}
727
728
729void PANEL_SYM_LIB_TABLE::appendRowHandler( wxCommandEvent& event )
730{
732 return;
733
734 if( m_cur_grid->AppendRows( 1 ) )
735 {
736 int row = m_cur_grid->GetNumberRows() - 1;
737
738 // wx documentation is wrong, SetGridCursor does not make visible.
739 m_cur_grid->MakeCellVisible( row, COL_ENABLED );
740 m_cur_grid->SetGridCursor( row, COL_NICKNAME );
741 m_cur_grid->EnableCellEditControl( true );
742 m_cur_grid->ShowCellEditControl();
743 }
744}
745
746
747void PANEL_SYM_LIB_TABLE::deleteRowHandler( wxCommandEvent& event )
748{
750 return;
751
752 wxGridUpdateLocker noUpdates( m_cur_grid );
753
754 int curRow = m_cur_grid->GetGridCursorRow();
755 int curCol = m_cur_grid->GetGridCursorCol();
756
757 // In a wxGrid, collect rows that have a selected cell, or are selected
758 // It is not so easy: it depends on the way the selection was made.
759 // Here, we collect rows selected by clicking on a row label, and rows that contain
760 // previously-selected cells.
761 // If no candidate, just delete the row with the grid cursor.
762 wxArrayInt selectedRows = m_cur_grid->GetSelectedRows();
763 wxGridCellCoordsArray cells = m_cur_grid->GetSelectedCells();
764 wxGridCellCoordsArray blockTopLeft = m_cur_grid->GetSelectionBlockTopLeft();
765 wxGridCellCoordsArray blockBotRight = m_cur_grid->GetSelectionBlockBottomRight();
766
767 // Add all row having cell selected to list:
768 for( unsigned ii = 0; ii < cells.GetCount(); ii++ )
769 selectedRows.Add( cells[ii].GetRow() );
770
771 // Handle block selection
772 if( !blockTopLeft.IsEmpty() && !blockBotRight.IsEmpty() )
773 {
774 for( int i = blockTopLeft[0].GetRow(); i <= blockBotRight[0].GetRow(); ++i )
775 selectedRows.Add( i );
776 }
777
778 // Use the row having the grid cursor only if we have no candidate:
779 if( selectedRows.size() == 0 && m_cur_grid->GetGridCursorRow() >= 0 )
780 selectedRows.Add( m_cur_grid->GetGridCursorRow() );
781
782 if( selectedRows.size() == 0 )
783 {
784 wxBell();
785 return;
786 }
787
788 std::sort( selectedRows.begin(), selectedRows.end() );
789
790 // Remove selected rows (note: a row can be stored more than once in list)
791 int last_row = -1;
792
793 // Needed to avoid a wxWidgets alert if the row to delete is the last row
794 // at least on wxMSW 3.2
795 m_cur_grid->ClearSelection();
796
797 for( int ii = selectedRows.GetCount()-1; ii >= 0; ii-- )
798 {
799 int row = selectedRows[ii];
800
801 if( row != last_row )
802 {
803 last_row = row;
804 m_cur_grid->DeleteRows( row, 1 );
805 }
806 }
807
808 if( m_cur_grid->GetNumberRows() > 0 && curRow >= 0 )
809 m_cur_grid->SetGridCursor( std::min( curRow, m_cur_grid->GetNumberRows() - 1 ), curCol );
810}
811
812
813void PANEL_SYM_LIB_TABLE::moveUpHandler( wxCommandEvent& event )
814{
816 return;
817
819 int curRow = m_cur_grid->GetGridCursorRow();
820
821 // @todo: add multiple selection moves.
822 if( curRow >= 1 )
823 {
824 tbl->ChangeRowOrder( curRow--, -1 );
825
826 if( tbl->GetView() )
827 {
828 // Update the wxGrid
829 wxGridTableMessage msg( tbl, wxGRIDTABLE_NOTIFY_ROWS_INSERTED, curRow, 0 );
830 tbl->GetView()->ProcessTableMessage( msg );
831 }
832
833 m_cur_grid->MakeCellVisible( curRow, m_cur_grid->GetGridCursorCol() );
834 m_cur_grid->SetGridCursor( curRow, m_cur_grid->GetGridCursorCol() );
835 }
836}
837
838
839void PANEL_SYM_LIB_TABLE::moveDownHandler( wxCommandEvent& event )
840{
842 return;
843
845 int curRow = m_cur_grid->GetGridCursorRow();
846
847 // @todo: add multiple selection moves.
848 if( unsigned( curRow + 1 ) < tbl->m_rows.size() )
849 {
850 tbl->ChangeRowOrder( curRow++, 1 );
851
852 if( tbl->GetView() )
853 {
854 // Update the wxGrid
855 wxGridTableMessage msg( tbl, wxGRIDTABLE_NOTIFY_ROWS_INSERTED, curRow - 1, 0 );
856 tbl->GetView()->ProcessTableMessage( msg );
857 }
858
859 m_cur_grid->MakeCellVisible( curRow, m_cur_grid->GetGridCursorCol() );
860 m_cur_grid->SetGridCursor( curRow, m_cur_grid->GetGridCursorCol() );
861 }
862}
863
864
865void PANEL_SYM_LIB_TABLE::onReset( wxCommandEvent& event )
866{
868 return;
869
870 // No need to prompt to preserve an empty table
871 if( m_global_grid->GetNumberRows() > 0 &&
872 !IsOK( this, wxString::Format( _( "This action will reset your global library table on "
873 "disk and cannot be undone." ) ) ) )
874 {
875 return;
876 }
877
878
880
881 if( dlg.ShowModal() == wxID_OK )
882 {
883 m_global_grid->Freeze();
884
885 wxGridTableBase* table = m_global_grid->GetTable();
886 m_global_grid->DestroyTable( table );
887
889 m_global_grid->PopEventHandler( true );
892
893 m_global_grid->Thaw();
894 }
895}
896
897
898void PANEL_SYM_LIB_TABLE::onPageChange( wxBookCtrlEvent& event )
899{
900 m_pageNdx = (unsigned) std::max( 0, m_notebook->GetSelection() );
901
902 if( m_pageNdx == 0 )
903 {
905 m_resetGlobal->Enable();
906 }
907 else
908 {
910 m_resetGlobal->Disable();
911 }
912}
913
914
916{
918 return;
919
920 wxArrayInt selectedRows = m_cur_grid->GetSelectedRows();
921
922 if( selectedRows.empty() && m_cur_grid->GetGridCursorRow() >= 0 )
923 selectedRows.push_back( m_cur_grid->GetGridCursorRow() );
924
925 wxArrayInt legacyRows;
926 wxString databaseType = SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_DATABASE );
927 wxString kicadType = SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_KICAD );
928 wxString msg;
929
930 for( int row : selectedRows )
931 {
932 if( m_cur_grid->GetCellValue( row, COL_TYPE ) != databaseType &&
933 m_cur_grid->GetCellValue( row, COL_TYPE ) != kicadType )
934 {
935 legacyRows.push_back( row );
936 }
937 }
938
939 if( legacyRows.size() <= 0 )
940 {
941 wxMessageBox( _( "Select one or more rows containing libraries "
942 "to save as current KiCad format (*.kicad_sym)." ) );
943 return;
944 }
945 else
946 {
947 if( legacyRows.size() == 1 )
948 {
949 msg.Printf( _( "Save '%s' as current KiCad format (*.kicad_sym) "
950 "and replace legacy entry in table?" ),
951 m_cur_grid->GetCellValue( legacyRows[0], COL_NICKNAME ) );
952 }
953 else
954 {
955 msg.Printf( _( "Save %d libraries as current KiCad format (*.kicad_sym) "
956 "and replace legacy entries in table?" ),
957 (int) legacyRows.size() );
958 }
959
960 if( !IsOK( m_parent, msg ) )
961 return;
962 }
963
964 for( int row : legacyRows )
965 {
966 wxString libName = m_cur_grid->GetCellValue( row, COL_NICKNAME );
967 wxString relPath = m_cur_grid->GetCellValue( row, COL_URI );
968 wxString resolvedPath = ExpandEnvVarSubstitutions( relPath, m_project );
969 wxFileName legacyLib( resolvedPath );
970
971 if( !legacyLib.Exists() )
972 {
973 msg.Printf( _( "Library '%s' not found." ), relPath );
974
975 wxWindow* topLevelParent = wxGetTopLevelParent( this );
976
977 DisplayErrorMessage( topLevelParent, msg );
978 continue;
979 }
980
981 wxFileName newLib( resolvedPath );
982 newLib.SetExt( "kicad_sym" );
983
984 if( newLib.Exists() )
985 {
986 msg.Printf( _( "File '%s' already exists. Do you want overwrite this file?" ),
987 newLib.GetFullPath() );
988
989 switch( wxMessageBox( msg, _( "Migrate Library" ),
990 wxYES_NO | wxCANCEL | wxICON_QUESTION, m_parent ) )
991 {
992 case wxYES: break;
993 case wxNO: continue;
994 case wxCANCEL: return;
995 }
996 }
997
998 wxString options = m_cur_grid->GetCellValue( row, COL_OPTIONS );
999 std::unique_ptr<std::map<std::string, UTF8>> props(
1000 LIB_TABLE::ParseOptions( options.ToStdString() ) );
1001
1002 if( SCH_IO_MGR::ConvertLibrary( props.get(),
1003 legacyLib.GetFullPath(), newLib.GetFullPath() ) )
1004 {
1005 relPath = NormalizePath( newLib.GetFullPath(), &Pgm().GetLocalEnvVariables(),
1006 m_project );
1007
1008 // Do not use the project path in the global library table. This will almost
1009 // assuredly be wrong for a different project.
1010 if( m_cur_grid == m_global_grid && relPath.Contains( "${KIPRJMOD}" ) )
1011 relPath = newLib.GetFullPath();
1012
1013 m_cur_grid->SetCellValue( row, COL_URI, relPath );
1014 m_cur_grid->SetCellValue( row, COL_TYPE, kicadType );
1015 m_cur_grid->SetCellValue( row, COL_OPTIONS, wxEmptyString );
1016 }
1017 else
1018 {
1019 msg.Printf( _( "Failed to save symbol library file '%s'." ), newLib.GetFullPath() );
1020
1021 wxWindow* topLevelParent = wxGetTopLevelParent( this );
1022
1023 DisplayErrorMessage( topLevelParent, msg );
1024 }
1025 }
1026}
1027
1028
1030{
1032 return false;
1033
1034 if( !verifyTables() )
1035 return false;
1036
1037 if( *global_model() != *m_globalTable )
1038 {
1041 }
1042
1044 {
1047 }
1048
1049 return true;
1050}
1051
1052
1054{
1055 wxRegEx re( ".*?(\\$\\{(.+?)\\})|(\\$\\((.+?)\\)).*?", wxRE_ADVANCED );
1056 wxASSERT( re.IsValid() ); // wxRE_ADVANCED is required.
1057
1058 std::set< wxString > unique;
1059
1060 // clear the table
1062
1063 for( SYMBOL_LIB_TABLE_GRID* tbl : { global_model(), project_model() } )
1064 {
1065 if( !tbl )
1066 continue;
1067
1068 for( int row = 0; row < tbl->GetNumberRows(); ++row )
1069 {
1070 wxString uri = tbl->GetValue( row, COL_URI );
1071
1072 while( re.Matches( uri ) )
1073 {
1074 wxString envvar = re.GetMatch( uri, 2 );
1075
1076 // if not ${...} form then must be $(...)
1077 if( envvar.IsEmpty() )
1078 envvar = re.GetMatch( uri, 4 );
1079
1080 // ignore duplicates
1081 unique.insert( envvar );
1082
1083 // delete the last match and search again
1084 uri.Replace( re.GetMatch( uri, 0 ), wxEmptyString );
1085 }
1086 }
1087 }
1088
1089 // Make sure this special environment variable shows up even if it was
1090 // not used yet. It is automatically set by KiCad to the directory holding
1091 // the current project.
1092 unique.insert( PROJECT_VAR_NAME );
1094
1095 for( const wxString& evName : unique )
1096 {
1097 int row = m_path_subs_grid->GetNumberRows();
1098 m_path_subs_grid->AppendRows( 1 );
1099
1100 m_path_subs_grid->SetCellValue( row, 0, wxT( "${" ) + evName + wxT( "}" ) );
1101 m_path_subs_grid->SetCellEditor( row, 0, new GRID_CELL_READONLY_TEXT_EDITOR() );
1102
1103 wxString evValue;
1104 wxGetEnv( evName, &evValue );
1105 m_path_subs_grid->SetCellValue( row, 1, evValue );
1106 m_path_subs_grid->SetCellEditor( row, 1, new GRID_CELL_READONLY_TEXT_EDITOR() );
1107 }
1108
1109 // No combobox editors here, but it looks better if its consistent with the other
1110 // grids in the dialog.
1111 m_path_subs_grid->SetDefaultRowSize( m_path_subs_grid->GetDefaultRowSize() + 2 );
1112
1113 adjustPathSubsGridColumns( m_path_subs_grid->GetRect().GetWidth() );
1114}
1115
1116
1118{
1119 // Account for scroll bars
1120 aWidth -= ( m_path_subs_grid->GetSize().x - m_path_subs_grid->GetClientSize().x );
1121
1122 m_path_subs_grid->AutoSizeColumn( 0 );
1123 m_path_subs_grid->SetColSize( 0, std::max( 72, m_path_subs_grid->GetColSize( 0 ) ) );
1124 m_path_subs_grid->SetColSize( 1, std::max( 120, aWidth - m_path_subs_grid->GetColSize( 0 ) ) );
1125}
1126
1127
1128void PANEL_SYM_LIB_TABLE::onSizeGrid( wxSizeEvent& event )
1129{
1130 adjustPathSubsGridColumns( event.GetSize().GetX() );
1131
1132 event.Skip();
1133}
1134
1135
1137{
1138 return (SYMBOL_LIB_TABLE_GRID*) m_global_grid->GetTable();
1139}
1140
1141
1143{
1144 return m_project_grid ? (SYMBOL_LIB_TABLE_GRID*) m_project_grid->GetTable() : nullptr;
1145}
1146
1147
1149{
1150 return (SYMBOL_LIB_TABLE_GRID*) m_cur_grid->GetTable();
1151}
1152
1153
1155{
1156 // Get the grid object that triggered the event
1157 wxGrid* grid = dynamic_cast<wxGrid*>( event.GetEventObject() );
1158
1159 // If the event object is a wxGrid, proceed with the handling
1160 if( grid )
1161 {
1162 int row = event.GetRow();
1163 int col = event.GetCol();
1164
1165 // Get the cell renderer for the clicked cell
1166 wxGridCellRenderer* renderer = grid->GetCellRenderer( row, col );
1167
1168 // Check if the renderer is a wxGridCellBoolRenderer using dynamic_cast
1169 if( dynamic_cast<wxGridCellBoolRenderer*>( renderer ) )
1170 {
1171 // Set the grid cursor to the clicked boolean cell
1172 grid->SetGridCursor( row, col );
1173 }
1174 }
1175
1176 // Allow the default behavior to continue (toggle the bool)
1177 event.Skip();
1178}
1179
1180
1182
1183
1184void InvokeSchEditSymbolLibTable( KIWAY* aKiway, wxWindow *aParent )
1185{
1186 auto* symbolEditor = (SYMBOL_EDIT_FRAME*) aKiway->Player( FRAME_SCH_SYMBOL_EDITOR, false );
1187
1189 wxString globalTablePath = SYMBOL_LIB_TABLE::GetGlobalTableFileName();
1190 SYMBOL_LIB_TABLE* projectTable = nullptr;
1191 wxString projectPath = aKiway->Prj().GetProjectPath();
1192 wxFileName projectTableFn( projectPath, SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() );
1193 wxString msg;
1194 wxString currentLib;
1195
1196 // Don't allow editing project tables if no project is open
1197 if( !aKiway->Prj().IsNullProject() )
1198 projectTable = PROJECT_SCH::SchSymbolLibTable( &aKiway->Prj() );
1199
1200 if( symbolEditor )
1201 {
1202 currentLib = symbolEditor->GetCurLib();
1203
1204 // This prevents an ugly crash on OSX (https://bugs.launchpad.net/kicad/+bug/1765286)
1205 symbolEditor->FreezeLibraryTree();
1206
1207 if( symbolEditor->HasLibModifications() )
1208 {
1209 msg = _( "Modifications have been made to one or more symbol libraries.\n"
1210 "Changes must be saved or discarded before the symbol library "
1211 "table can be modified." );
1212
1213 switch( UnsavedChangesDialog( aParent, msg ) )
1214 {
1215 case wxID_YES: symbolEditor->SaveAll(); break;
1216 case wxID_NO: symbolEditor->RevertAll(); break;
1217 default:
1218 case wxID_CANCEL: symbolEditor->ThawLibraryTree(); return;
1219 }
1220 }
1221 }
1222
1223 DIALOG_EDIT_LIBRARY_TABLES dlg( aParent, _( "Symbol Libraries" ) );
1224 dlg.SetKiway( &dlg, aKiway );
1225
1226 dlg.InstallPanel( new PANEL_SYM_LIB_TABLE( &dlg, &aKiway->Prj(), globalTable, globalTablePath,
1227 projectTable, projectTableFn.GetFullPath() ) );
1228
1229 if( dlg.ShowModal() == wxID_CANCEL )
1230 {
1231 if( symbolEditor )
1232 symbolEditor->ThawLibraryTree();
1233
1234 return;
1235 }
1236
1237 if( dlg.m_GlobalTableChanged )
1238 {
1239 try
1240 {
1241 globalTable->Save( globalTablePath );
1242 }
1243 catch( const IO_ERROR& ioe )
1244 {
1245 msg.Printf( _( "Error saving global library table:\n\n%s" ), ioe.What() );
1246 wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
1247 }
1248 }
1249
1250 if( projectTable && dlg.m_ProjectTableChanged )
1251 {
1252 try
1253 {
1254 projectTable->Save( projectTableFn.GetFullPath() );
1255 }
1256 catch( const IO_ERROR& ioe )
1257 {
1258 msg.Printf( _( "Error saving project-specific library table:\n\n%s" ), ioe.What() );
1259 wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
1260 }
1261 }
1262
1263 if( symbolEditor )
1264 {
1265 symbolEditor->ThawLibraryTree();
1266 }
1267
1268 std::string payload = "";
1269 aKiway->ExpressMail( FRAME_SCH, MAIL_RELOAD_LIB, payload );
1271 aKiway->ExpressMail( FRAME_SCH_VIEWER, MAIL_RELOAD_LIB, payload );
1272}
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
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:102
int ShowModal() override
Editor for wxGrid cells that adds a file/folder browser to the grid input field.
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition: grid_tricks.h:61
virtual void paste_text(const wxString &cb_text)
WX_GRID * m_grid
I don't own the grid, but he owns me.
Definition: grid_tricks.h:125
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
void SetKiway(wxWindow *aDest, KIWAY *aKiway)
It is only used for debugging, since "this" is not a wxWindow*.
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:285
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:406
virtual void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string &aPayload, wxWindow *aSource=nullptr)
Send aPayload to aDestination from aSource.
Definition: kiway.cpp:527
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
Definition: kiway.cpp:195
static unsigned FindIllegalLibraryNameChar(const UTF8 &aLibraryName)
Looks for characters that are illegal in library nicknames.
Definition: lib_id.cpp:243
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, bool aLib)
Replace illegal LIB_ID item name characters with underscores '_'.
Definition: lib_id.cpp:191
This abstract base class mixes any object derived from LIB_TABLE into wxGridTableBase so the result c...
void SetValue(int aRow, int aCol, const wxString &aValue) override
bool AppendRows(size_t aNumRows=1) override
int GetNumberRows() override
Hold a record identifying a library accessed by the appropriate plug in object in the LIB_TABLE.
const wxString & GetOptions() const
Return the options string, which may hold a password or anything else needed to instantiate the under...
virtual const wxString GetType() const =0
Return the type of library represented by this row.
void SetParent(LIB_TABLE *aParent)
const wxString & GetNickName() const
const wxString GetFullURI(bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
LIB_TABLE_ROW * clone() const
bool GetIsEnabled() const
void SetOptions(const wxString &aOptions)
Change the library options strings.
bool ReplaceRow(size_t aIndex, LIB_TABLE_ROW *aRow)
Replaces the Nth row with the given new row.
static std::map< std::string, UTF8 > * ParseOptions(const std::string &aOptionsList)
Parses aOptionsList and places the result into a #PROPERTIES object which is returned.
LIB_TABLE_ROW & At(unsigned aIndex)
Get the 'n'th LIB_TABLE_ROW object.
void TransferRows(LIB_TABLE_ROWS &aRowsList)
Takes ownership of another list of rows; the original list will be freed.
LIB_TABLE_ROWS m_rows
Owning set of rows.
unsigned GetCount() const
Get the number of rows contained in the table.
bool ChangeRowOrder(size_t aIndex, int aOffset)
Moves a row within the table.
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
Class PANEL_SYM_LIB_TABLE_BASE.
STD_BITMAP_BUTTON * m_browse_button
STD_BITMAP_BUTTON * m_move_up_button
STD_BITMAP_BUTTON * m_delete_button
STD_BITMAP_BUTTON * m_move_down_button
STD_BITMAP_BUTTON * m_append_button
Dialog to show and edit symbol library tables.
void OnUpdateUI(wxUpdateUIEvent &event) override
void moveUpHandler(wxCommandEvent &event) override
void onPageChange(wxBookCtrlEvent &event) override
bool allowAutomaticPluginTypeSelection(wxString &aLibraryPath)
SYMBOL_LIB_TABLE * m_projectTable
static size_t m_pageNdx
Remember the last notebook page selected.
void setupGrid(WX_GRID *aGrid)
void onReset(wxCommandEvent &event) override
void deleteRowHandler(wxCommandEvent &event) override
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
void onGridCellLeftClickHandler(wxGridEvent &event)
bool TransferDataFromWindow() override
void appendRowHandler(wxCommandEvent &event) override
static wxString GetDefaultUserSymbolsPath()
Gets the default path we point users to create projects.
Definition: paths.cpp:88
virtual ENV_VAR_MAP & GetLocalEnvVariables() const
Definition: pgm_base.cpp:935
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:125
static SYMBOL_LIB_TABLE * SchSymbolLibTable(PROJECT *aProject)
Accessor for project symbol library table.
Container for project specific data.
Definition: project.h:64
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:146
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Definition: project.cpp:164
static bool ConvertLibrary(std::map< std::string, UTF8 > *aOldFileProps, const wxString &aOldFilePath, const wxString &aNewFilepath)
Convert a schematic symbol library to the latest KiCad format.
Definition: sch_io_mgr.cpp:191
static SCH_FILE_T EnumFromStr(const wxString &aFileType)
Return the #SCH_FILE_T from the corresponding plugin type name: "kicad", "legacy",...
Definition: sch_io_mgr.cpp:107
static const wxString ShowType(SCH_FILE_T aFileType)
Return a brief name for a plugin, given aFileType enum.
Definition: sch_io_mgr.cpp:83
static SCH_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath, int aCtl=0)
Return a plugin type given a symbol library using the file extension of aLibPath.
Definition: sch_io_mgr.cpp:140
T * GetAppSettings(const wxString &aFilename)
Return a handle to the a given settings by type.
void SetBitmap(const wxBitmapBundle &aBmp)
Is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition: richio.h:253
The symbol library editor main window.
bool supportsVisibilityColumn() override
DIALOG_EDIT_LIBRARY_TABLES * m_dialog
virtual void optionsEditor(int aRow) override
SYMBOL_GRID_TRICKS(DIALOG_EDIT_LIBRARY_TABLES *aParent, WX_GRID *aGrid)
virtual void paste_text(const wxString &cb_text) override
handle specialized clipboard text, with leading "(sym_lib_table" or spreadsheet formatted text.
Build a wxGridTableBase by wrapping an SYMBOL_LIB_TABLE object.
void SetValue(int aRow, int aCol, const wxString &aValue) override
LIB_TABLE_ROW * at(size_t aIndex) override
LIB_TABLE_ROWS_ITER erase(LIB_TABLE_ROWS_ITER aFirst, LIB_TABLE_ROWS_ITER aLast) override
LIB_TABLE_ROWS_ITER begin() override
LIB_TABLE_ROWS_ITER insert(LIB_TABLE_ROWS_ITER aIterator, LIB_TABLE_ROW *aRow) override
LIB_TABLE_ROW * makeNewRow() override
void push_back(LIB_TABLE_ROW *aRow) override
size_t size() const override
SYMBOL_LIB_TABLE_GRID(const SYMBOL_LIB_TABLE &aTableToEdit)
Hold a record identifying a symbol library accessed by the appropriate symbol library SCH_IO object i...
bool Refresh() override
Attempt to reload the library.
static SYMBOL_LIB_TABLE & GetGlobalLibTable()
virtual void Parse(LIB_TABLE_LEXER *aLexer) override
Parse the #LIB_TABLE_LEXER s-expression library table format into the appropriate LIB_TABLE_ROW objec...
static const wxString GetSymbolLibTableFileName()
static wxString GetGlobalTableFileName()
Fetch the global symbol library table file name.
static const wxString GlobalPathEnvVariableName()
Return the name of the environment variable used to hold the directory of locally installed "KiCad sp...
void SetTable(wxGridTableBase *table, bool aTakeOwnership=false)
Hide wxGrid's SetTable() method with one which doesn't mess up the grid column widths when setting th...
Definition: wx_grid.cpp:277
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:451
void ClearRows()
wxWidgets recently added an ASSERT which fires if the position is greater than or equal to the number...
Definition: wx_grid.h:193
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:646
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:351
The common library.
int OKOrCancelDialog(wxWindow *aParent, const wxString &aWarning, const wxString &aMessage, const wxString &aDetailedMessage, const wxString &aOKLabel, const wxString &aCancelLabel, bool *aApplyToAll)
Display a warning dialog with aMessage and returns the user response.
Definition: confirm.cpp:143
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:250
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:195
int UnsavedChangesDialog(wxWindow *parent, const wxString &aMessage, bool *aApplyToAll)
A specialized version of HandleUnsavedChanges which handles an apply-to-all checkbox.
Definition: confirm.cpp:66
This file is part of the common library.
#define _(s)
@ ID_END_EESCHEMA_ID_LIST
Definition: eeschema_id.h:71
wxString NormalizePath(const wxFileName &aFilePath, const ENV_VAR_MAP *aEnvVars, const wxString &aProjectPath)
Normalize a file path to an environmental variable, if possible.
Definition: env_paths.cpp: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:56
@ ID_PANEL_SYM_LIB_LEGACY
@ ID_PANEL_SYM_LIB_KICAD
void InvokeSchEditSymbolLibTable(KIWAY *aKiway, wxWindow *aParent)
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:1073
see class PGM_BASE
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
Definition: project.h:40
MODEL3D_FORMAT_TYPE fileType(const char *aFileName)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: string_utils.h:398
Container that describes file type info.
Definition: io_base.h:43
std::vector< std::string > m_FileExtensions
Filter used for file pickers if m_IsFile is true.
Definition: io_base.h: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.