KiCad PCB EDA Suite
dialog_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 <dick@softplc.com>
5  * Copyright (C) 2013 CERN
6  * Copyright (C) 2012-2018 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/regex.h>
36 
37 #include <fctsys.h>
38 #include <project.h>
39 #include <3d_viewer.h> // for KISYS3DMOD
41 #include <lib_id.h>
42 #include <fp_lib_table.h>
43 #include <lib_table_lexer.h>
44 #include <invoke_pcb_dialog.h>
45 #include <grid_tricks.h>
46 #include <confirm.h>
47 #include <wizard_add_fplib.h>
48 #include <lib_table_grid.h>
49 
50 
55 {
56  friend class FP_GRID_TRICKS;
57 
58 protected:
59  LIB_TABLE_ROW* at( size_t aIndex ) override { return &rows.at( aIndex ); }
60 
61  size_t size() const override { return rows.size(); }
62 
64  {
65  return dynamic_cast< LIB_TABLE_ROW* >( new FP_LIB_TABLE_ROW );
66  }
67 
68  LIB_TABLE_ROWS_ITER begin() override { return rows.begin(); }
69 
71  {
72  return rows.insert( aIterator, aRow );
73  }
74 
75  void push_back( LIB_TABLE_ROW* aRow ) override { rows.push_back( aRow ); }
76 
78  {
79  return rows.erase( aFirst, aLast );
80  }
81 
82 public:
83 
84  FP_LIB_TABLE_GRID( const FP_LIB_TABLE& aTableToEdit )
85  {
86  rows = aTableToEdit.rows;
87  }
88 };
89 
90 
92 {
93 public:
94  FP_GRID_TRICKS( wxGrid* aGrid ) :
95  GRID_TRICKS( aGrid )
96  {
97  }
98 
99 protected:
100 
103  virtual void paste_text( const wxString& cb_text ) override
104  {
105  FP_LIB_TABLE_GRID* tbl = (FP_LIB_TABLE_GRID*) m_grid->GetTable();
106 
107  size_t ndx = cb_text.find( "(fp_lib_table" );
108 
109  if( ndx != std::string::npos )
110  {
111  // paste the FP_LIB_TABLE_ROWs of s-expression (fp_lib_table), starting
112  // at column 0 regardless of current cursor column.
113 
114  STRING_LINE_READER slr( TO_UTF8( cb_text ), "Clipboard" );
115  LIB_TABLE_LEXER lexer( &slr );
116  FP_LIB_TABLE tmp_tbl;
117  bool parsed = true;
118 
119  try
120  {
121  tmp_tbl.Parse( &lexer );
122  }
123  catch( PARSE_ERROR& pe )
124  {
125  DisplayError( NULL, pe.What() );
126  parsed = false;
127  }
128 
129  if( parsed )
130  {
131  const int cur_row = std::max( getCursorRow(), 0 );
132 
133  // if clipboard rows would extend past end of current table size...
134  if( tmp_tbl.GetCount() > tbl->GetNumberRows() - cur_row )
135  {
136  int newRowsNeeded = tmp_tbl.GetCount() - ( tbl->GetNumberRows() - cur_row );
137  tbl->AppendRows( newRowsNeeded );
138  }
139 
140  for( int i = 0; i < tmp_tbl.GetCount(); ++i )
141  {
142  tbl->rows.replace( cur_row+i, tmp_tbl.At( i ) );
143  }
144  }
145 
146  m_grid->AutoSizeColumns( false );
147  }
148  else
149  {
150  // paste spreadsheet formatted text.
151  GRID_TRICKS::paste_text( cb_text );
152  }
153  }
154 };
155 
156 
163 {
164 
165 public:
166  DIALOG_FP_LIB_TABLE( wxTopLevelWindow* aParent, FP_LIB_TABLE* aGlobal, FP_LIB_TABLE* aProject ) :
167  DIALOG_FP_LIB_TABLE_BASE( aParent ),
168  m_global( aGlobal ),
169  m_project( aProject )
170  {
171  // For user info, shows the table filenames:
172  m_PrjTableFilename->SetLabel( Prj().FootprintLibTblName() );
173  m_GblTableFilename->SetLabel( FP_LIB_TABLE::GetGlobalTableFileName() );
174 
175  // wxGrid only supports user owned tables if they exist past end of ~wxGrid(),
176  // so make it a grid owned table.
177  m_global_grid->SetTable( new FP_LIB_TABLE_GRID( *aGlobal ), true );
178  m_project_grid->SetTable( new FP_LIB_TABLE_GRID( *aProject ), true );
179 
180  // add Cut, Copy, and Paste to wxGrids
181  m_global_grid->PushEventHandler( new FP_GRID_TRICKS( m_global_grid ) );
182  m_project_grid->PushEventHandler( new FP_GRID_TRICKS( m_project_grid ) );
183 
184  m_global_grid->AutoSizeColumns( false );
185  m_project_grid->AutoSizeColumns( false );
186 
187  wxArrayString choices;
188 
189  choices.Add( IO_MGR::ShowType( IO_MGR::KICAD_SEXP ) );
190  choices.Add( IO_MGR::ShowType( IO_MGR::GITHUB ) );
191  choices.Add( IO_MGR::ShowType( IO_MGR::LEGACY ) );
192  choices.Add( IO_MGR::ShowType( IO_MGR::EAGLE ) );
193  choices.Add( IO_MGR::ShowType( IO_MGR::GEDA_PCB ) );
194 
195  /* PCAD_PLUGIN does not support Footprint*() functions
196  choices.Add( IO_MGR::ShowType( IO_MGR::GITHUB ) );
197  */
198 
199  populateEnvironReadOnlyTable();
200 
201  for( int i=0; i<2; ++i )
202  {
203  wxGrid* g = i==0 ? m_global_grid : m_project_grid;
204 
205  wxGridCellAttr* attr;
206 
207  attr = new wxGridCellAttr;
208  attr->SetEditor( new wxGridCellChoiceEditor( choices ) );
209  g->SetColAttr( COL_TYPE, attr );
210 
211  attr = new wxGridCellAttr;
212  attr->SetRenderer( new wxGridCellBoolRenderer() );
213  attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
214  g->SetColAttr( COL_ENABLED, attr );
215 
216  // all but COL_OPTIONS, which is edited with Option Editor anyways.
217  g->AutoSizeColumn( COL_NICKNAME, false );
218  g->AutoSizeColumn( COL_TYPE, false );
219  g->AutoSizeColumn( COL_URI, false );
220  g->AutoSizeColumn( COL_DESCR, false );
221 
222  // would set this to width of title, if it was easily known.
223  g->SetColSize( COL_OPTIONS, 80 );
224  }
225 
226  // This scrunches the dialog hideously, probably due to wxAUI container.
227  // Fit();
228  // We derive from DIALOG_SHIM so prior size will be used anyways.
229 
230  // select the last selected page
231  m_auinotebook->SetSelection( m_pageNdx );
232 
233  // fire pageChangedHandler() so m_cur_grid gets set
234  // m_auinotebook->SetSelection will generate a pageChangedHandler()
235  // event call later, but too late.
236  wxAuiNotebookEvent uneventful;
237  pageChangedHandler( uneventful );
238 
239  // Gives a selection for each grid, mainly for delete lib button.
240  // Without that, we do not see what lib will be deleted
241  m_global_grid->SelectRow( 0 );
242  m_project_grid->SelectRow( 0 );
243 
244  // for ALT+A handling, we want the initial focus to be on the first selected grid.
245  m_cur_grid->SetFocus();
246 
247  SetSizeInDU( 450, 380 );
248 
249  // On some windows manager (Unity, XFCE), this dialog is
250  // not always raised, depending on this dialog is run.
251  // Force it to be raised
252  Raise();
253  }
254 
256  {
257  // Delete the GRID_TRICKS.
258  // Any additional event handlers should be popped before the window is deleted.
259  m_global_grid->PopEventHandler( true );
260  m_project_grid->PopEventHandler( true );
261  }
262 
263 
264 private:
267  int getCursorCol() const
268  {
269  return m_cur_grid->GetGridCursorCol();
270  }
271 
274  int getCursorRow() const
275  {
276  return m_cur_grid->GetGridCursorRow();
277  }
278 
285  {
286  for( int t=0; t<2; ++t )
287  {
288  FP_LIB_TABLE_GRID& model = t==0 ? *global_model() : *project_model();
289 
290  for( int r = 0; r < model.GetNumberRows(); )
291  {
292  wxString nick = model.GetValue( r, COL_NICKNAME ).Trim( false ).Trim();
293  wxString uri = model.GetValue( r, COL_URI ).Trim( false ).Trim();
294  unsigned illegalCh = 0;
295 
296  if( !nick || !uri )
297  {
298  // Delete the "empty" row, where empty means missing nick or uri.
299  // This also updates the UI which could be slow, but there should only be a few
300  // rows to delete, unless the user fell asleep on the Add Row
301  // button.
302  model.DeleteRows( r, 1 );
303  }
304  else if( ( illegalCh = LIB_ID::FindIllegalChar( nick, LIB_ID::ID_PCB ) ) )
305  {
306  wxString msg = wxString::Format(
307  _( "Illegal character \"%c\" found in Nickname: \"%s\" in row %d" ),
308  illegalCh, GetChars( nick ), r );
309 
310  // show the tabbed panel holding the grid we have flunked:
311  if( &model != cur_model() )
312  {
313  m_auinotebook->SetSelection( &model == global_model() ? 0 : 1 );
314  }
315 
316  // go to the problematic row
317  m_cur_grid->SetGridCursor( r, 0 );
318  m_cur_grid->SelectBlock( r, 0, r, 0 );
319  m_cur_grid->MakeCellVisible( r, 0 );
320 
321  wxMessageDialog errdlg( this, msg, _( "No Colon in Nicknames" ) );
322  errdlg.ShowModal();
323  return false;
324  }
325  else
326  {
327  // set the trimmed values back into the table so they get saved to disk.
328  model.SetValue( r, COL_NICKNAME, nick );
329  model.SetValue( r, COL_URI, uri );
330  ++r; // this row was OK.
331  }
332  }
333  }
334 
335  // check for duplicate nickNames, separately in each table.
336  for( int t=0; t<2; ++t )
337  {
338  FP_LIB_TABLE_GRID& model = t==0 ? *global_model() : *project_model();
339 
340  for( int r1 = 0; r1 < model.GetNumberRows() - 1; ++r1 )
341  {
342  wxString nick1 = model.GetValue( r1, COL_NICKNAME );
343 
344  for( int r2=r1+1; r2 < model.GetNumberRows(); ++r2 )
345  {
346  wxString nick2 = model.GetValue( r2, COL_NICKNAME );
347 
348  if( nick1 == nick2 )
349  {
350  wxString msg = wxString::Format(
351  _( "Duplicate Nickname: \"%s\" in rows %d and %d" ),
352  GetChars( nick1 ), r1+1, r2+1
353  );
354 
355  // show the tabbed panel holding the grid we have flunked:
356  if( &model != cur_model() )
357  {
358  m_auinotebook->SetSelection( &model == global_model() ? 0 : 1 );
359  }
360 
361  // go to the lower of the two rows, it is technically the duplicate:
362  m_cur_grid->SetGridCursor( r2, 0 );
363  m_cur_grid->SelectBlock( r2, 0, r2, 0 );
364  m_cur_grid->MakeCellVisible( r2, 0 );
365 
366  wxMessageDialog errdlg( this, msg, _( "Please Delete or Modify One" ) );
367  errdlg.ShowModal();
368  return false;
369  }
370  }
371  }
372  }
373 
374  return true;
375  }
376 
377  //-----<event handlers>----------------------------------
378 
379  void onKeyDown( wxKeyEvent& ev ) override
380  {
381 #if 0
382  // send the key to the current grid
383  ((wxEvtHandler*)m_cur_grid)->ProcessEvent( ev );
384 #else
385  // or no:
386  // m_cur_grid has the focus most of the time anyways, so above not needed.
387  ev.Skip();
388 #endif
389  }
390 
391  void pageChangedHandler( wxAuiNotebookEvent& event ) override
392  {
393  m_pageNdx = m_auinotebook->GetSelection();
394  m_cur_grid = ( m_pageNdx == 0 ) ? m_global_grid : m_project_grid;
395  }
396 
397  void appendRowHandler( wxCommandEvent& event ) override
398  {
399  if( m_cur_grid->AppendRows( 1 ) )
400  {
401  int last_row = m_cur_grid->GetNumberRows() - 1;
402 
403  // wx documentation is wrong, SetGridCursor does not make visible.
404  m_cur_grid->MakeCellVisible( last_row, 0 );
405  m_cur_grid->SetGridCursor( last_row, 0 );
406  m_cur_grid->SelectRow( m_cur_grid->GetGridCursorRow() );
407  }
408  }
409 
410  void deleteRowHandler( wxCommandEvent& event ) override
411  {
412  int currRow = getCursorRow();
413 
414  // In a wxGrid, collect rows that have a selected cell, or are selected
415  // is not so easy: it depend on the way the selection was made.
416  // Here, we collect row selected by clicking on a row label, and
417  // row that contain a cell previously selected.
418  // If no candidate, just delete the row with the grid cursor.
419  wxArrayInt selectedRows = m_cur_grid->GetSelectedRows();
420  wxGridCellCoordsArray cells = m_cur_grid->GetSelectedCells();
421  wxGridCellCoordsArray blockTopLeft = m_cur_grid->GetSelectionBlockTopLeft();
422  wxGridCellCoordsArray blockBotRight = m_cur_grid->GetSelectionBlockBottomRight();
423 
424  // Add all row having cell selected to list:
425  for( unsigned ii = 0; ii < cells.GetCount(); ii++ )
426  selectedRows.Add( cells[ii].GetRow() );
427 
428  // Handle block selection
429  if( !blockTopLeft.IsEmpty() && !blockBotRight.IsEmpty() )
430  {
431  for( int i = blockTopLeft[0].GetRow(); i <= blockBotRight[0].GetRow(); ++i )
432  selectedRows.Add( i );
433  }
434 
435  // Use the row having the grid cursor only if we have no candidate:
436  if( selectedRows.size() == 0 && getCursorRow() >= 0 )
437  selectedRows.Add( getCursorRow() );
438 
439  std::sort( selectedRows.begin(), selectedRows.end() );
440 
441  // Remove selected rows (note: a row can be stored more than once in list)
442  int last_row = -1;
443  for( int ii = selectedRows.GetCount()-1; ii >= 0; ii-- )
444  {
445  int row = selectedRows[ii];
446 
447  if( row != last_row )
448  {
449  last_row = row;
450  m_cur_grid->DeleteRows( row, 1 );
451  }
452  }
453 
454  if( currRow >= m_cur_grid->GetNumberRows() )
455  m_cur_grid->SetGridCursor(m_cur_grid->GetNumberRows()-1, getCursorCol() );
456 
457  m_cur_grid->SelectRow( m_cur_grid->GetGridCursorRow() );
458  }
459 
460  void moveUpHandler( wxCommandEvent& event ) override
461  {
462  wxArrayInt rowsSelected = m_cur_grid->GetSelectedRows();
463 
464  if( rowsSelected.GetCount() == 0 )
465  return;
466 
467  // @todo: add multiple selection moves.
468  int curRow = rowsSelected[0];
469 
470  if( curRow >= 1 )
471  {
472  int curCol = getCursorCol();
473 
474  FP_LIB_TABLE_GRID* tbl = cur_model();
475 
476  boost::ptr_vector< LIB_TABLE_ROW >::auto_type move_me =
477  tbl->rows.release( tbl->rows.begin() + curRow );
478 
479  --curRow;
480  tbl->rows.insert( tbl->rows.begin() + curRow, move_me.release() );
481 
482  if( tbl->GetView() )
483  {
484  // fire a msg to cause redrawing
485  wxGridTableMessage msg( tbl,
486  wxGRIDTABLE_NOTIFY_ROWS_INSERTED,
487  curRow,
488  0 );
489 
490  tbl->GetView()->ProcessTableMessage( msg );
491  }
492 
493  m_cur_grid->MakeCellVisible( curRow, curCol );
494  m_cur_grid->SetGridCursor( curRow, curCol );
495  m_cur_grid->SelectRow( getCursorRow() );
496  }
497  }
498 
499  void moveDownHandler( wxCommandEvent& event ) override
500  {
501  wxArrayInt rowsSelected = m_cur_grid->GetSelectedRows();
502 
503  if( rowsSelected.GetCount() == 0 )
504  return;
505 
506  FP_LIB_TABLE_GRID* tbl = cur_model();
507 
508  // @todo: add multiple selection moves.
509  int curRow = rowsSelected[0];
510 
511  if( unsigned( curRow + 1 ) < tbl->rows.size() )
512  {
513  int curCol = getCursorCol();
514 
515  boost::ptr_vector< LIB_TABLE_ROW >::auto_type move_me =
516  tbl->rows.release( tbl->rows.begin() + curRow );
517 
518  ++curRow;
519  tbl->rows.insert( tbl->rows.begin() + curRow, move_me.release() );
520 
521  if( tbl->GetView() )
522  {
523  // fire a msg to cause redrawing
524  wxGridTableMessage msg( tbl,
525  wxGRIDTABLE_NOTIFY_ROWS_INSERTED,
526  curRow - 1,
527  0 );
528 
529  tbl->GetView()->ProcessTableMessage( msg );
530  }
531 
532  m_cur_grid->MakeCellVisible( curRow, curCol );
533  m_cur_grid->SetGridCursor( curRow, curCol );
534  m_cur_grid->SelectRow( getCursorRow() );
535  }
536  }
537 
538  void optionsEditor( wxCommandEvent& event ) override
539  {
540  FP_LIB_TABLE_GRID* tbl = cur_model();
541 
542  if( tbl->GetNumberRows() )
543  {
544  int curRow = getCursorRow();
545  LIB_TABLE_ROW* row = &tbl->rows[curRow];
546 
547  wxString result;
548  const wxString& options = row->GetOptions();
549 
550  InvokePluginOptionsEditor( this, row->GetNickName(), row->GetType(), options, &result );
551 
552  if( options != result )
553  {
554  row->SetOptions( result );
555 
556  // all but options:
557  m_cur_grid->AutoSizeColumn( COL_NICKNAME, false );
558  m_cur_grid->AutoSizeColumn( COL_URI, false );
559  m_cur_grid->AutoSizeColumn( COL_TYPE, false );
560 
561  // On Windows, the grid is not refresh,
562  // so force resfresh after a change
563 #ifdef __WINDOWS__
564  Refresh();
565 #endif
566  }
567  }
568  }
569 
570  void OnClickLibraryWizard( wxCommandEvent& event ) override;
571 
572  void onCancelButtonClick( wxCommandEvent& event ) override
573  {
574  EndModal( 0 );
575  }
576 
577  void onCancelCaptionButtonClick( wxCloseEvent& event ) override
578  {
579  EndModal( 0 );
580  }
581 
582  void onOKButtonClick( wxCommandEvent& event ) override
583  {
584  int dialogRet = 0;
585 
586  // stuff any pending cell editor text into the table.
587  m_cur_grid->DisableCellEditControl();
588 
589  if( verifyTables() )
590  {
591  if( *global_model() != *m_global )
592  {
593  dialogRet |= 1;
594 
595  m_global->Clear();
596  m_global->rows.transfer( m_global->rows.end(), global_model()->rows.begin(),
597  global_model()->rows.end(), global_model()->rows );
598  m_global->reindex();
599  }
600 
601  if( *project_model() != *m_project )
602  {
603  dialogRet |= 2;
604 
605  m_project->Clear();
606  m_project->rows.transfer( m_project->rows.end(), project_model()->rows.begin(),
607  project_model()->rows.end(), project_model()->rows );
608  m_project->reindex();
609  }
610 
611  EndModal( dialogRet );
612  }
613  }
614 
618  {
619  wxRegEx re( ".*?\\$\\{(.+?)\\}.*?", wxRE_ADVANCED );
620  wxASSERT( re.IsValid() ); // wxRE_ADVANCED is required.
621 
622  std::set< wxString > unique;
623  typedef std::set<wxString>::const_iterator SET_CITER;
624 
625  // clear the table
626  m_path_subs_grid->DeleteRows( 0, m_path_subs_grid->GetNumberRows() );
627 
628  FP_LIB_TABLE_GRID* gbl = global_model();
629  FP_LIB_TABLE_GRID* prj = project_model();
630 
631  int gblRowCount = gbl->GetNumberRows();
632  int prjRowCount = prj->GetNumberRows();
633  int row;
634 
635  for( row = 0; row < gblRowCount; ++row )
636  {
637  wxString uri = gbl->GetValue( row, COL_URI );
638 
639  while( re.Matches( uri ) )
640  {
641  wxString envvar = re.GetMatch( uri, 1 );
642 
643  // ignore duplicates
644  unique.insert( envvar );
645 
646  // delete the last match and search again
647  uri.Replace( re.GetMatch( uri, 0 ), wxEmptyString );
648  }
649  }
650 
651  for( row = 0; row < prjRowCount; ++row )
652  {
653  wxString uri = prj->GetValue( row, COL_URI );
654 
655  while( re.Matches( uri ) )
656  {
657  wxString envvar = re.GetMatch( uri, 1 );
658 
659  // ignore duplicates
660  unique.insert( envvar );
661 
662  // delete the last match and search again
663  uri.Replace( re.GetMatch( uri, 0 ), wxEmptyString );
664  }
665  }
666 
667  // Make sure this special environment variable shows up even if it was
668  // not used yet. It is automatically set by KiCad to the directory holding
669  // the current project.
670  unique.insert( PROJECT_VAR_NAME );
671  unique.insert( FP_LIB_TABLE::GlobalPathEnvVariableName() );
672  // This special environment variable is used to locate 3d shapes
673  unique.insert( KISYS3DMOD );
674 
675  m_path_subs_grid->AppendRows( unique.size() );
676 
677  row = 0;
678 
679  for( SET_CITER it = unique.begin(); it != unique.end(); ++it, ++row )
680  {
681  wxString evName = *it;
682  wxString evValue;
683 
684  m_path_subs_grid->SetCellValue( row, 0, evName );
685 
686  if( wxGetEnv( evName, &evValue ) )
687  m_path_subs_grid->SetCellValue( row, 1, evValue );
688  }
689 
690  m_path_subs_grid->AutoSizeColumns();
691  }
692 
693  //-----</event handlers>---------------------------------
694 
695  // caller's tables are modified only on OK button and successful verification.
698 
700  {
701  return (FP_LIB_TABLE_GRID*) m_global_grid->GetTable();
702  }
703 
705  {
706  return (FP_LIB_TABLE_GRID*) m_project_grid->GetTable();
707  }
708 
710  {
711  return (FP_LIB_TABLE_GRID*) m_cur_grid->GetTable();
712  }
713 
714  wxGrid* m_cur_grid;
715  static int m_pageNdx;
716 };
717 
718 
720 
721 
722 void DIALOG_FP_LIB_TABLE::OnClickLibraryWizard( wxCommandEvent& event )
723 {
724  WIZARD_FPLIB_TABLE dlg( this );
725 
726  if( !dlg.RunWizard( dlg.GetFirstPage() ) )
727  return; // Aborted by user
728 
729  const std::vector<WIZARD_FPLIB_TABLE::LIBRARY>& libs = dlg.GetLibraries();
730  bool global_scope = dlg.GetLibScope() == WIZARD_FPLIB_TABLE::GLOBAL;
731  wxGrid* libgrid = global_scope ? m_global_grid : m_project_grid;
732  FP_LIB_TABLE_GRID* tbl = (FP_LIB_TABLE_GRID*) libgrid->GetTable();
733 
734  for( std::vector<WIZARD_FPLIB_TABLE::LIBRARY>::const_iterator it = libs.begin();
735  it != libs.end(); ++it )
736  {
737  if( it->GetStatus() == WIZARD_FPLIB_TABLE::LIBRARY::INVALID )
738  continue;
739 
740  if( libgrid->AppendRows( 1 ) )
741  {
742  int last_row = libgrid->GetNumberRows() - 1;
743 
744  // Add the nickname: currently make it from filename
745  tbl->SetValue( last_row, COL_NICKNAME,
746  LIB_ID::FixIllegalChars( it->GetDescription(), LIB_ID::ID_PCB ) );
747 
748  // Add the path:
749  tbl->SetValue( last_row, COL_URI, it->GetAutoPath( dlg.GetLibScope() ) );
750 
751  // Add the plugin name:
752  tbl->SetValue( last_row, COL_TYPE, it->GetPluginName() );
753 
754  libgrid->MakeCellVisible( last_row, 0 );
755  libgrid->SetGridCursor( last_row, 0 );
756  }
757  }
758 
759  // Switch to the current scope tab
760  if( global_scope )
761  m_auinotebook->SetSelection( 0 );
762  else
763  m_auinotebook->SetSelection( 1 );
764 
765  libgrid->SelectRow( libgrid->GetGridCursorRow() );
766 }
767 
768 
769 int InvokePcbLibTableEditor( wxTopLevelWindow* aCaller, FP_LIB_TABLE* aGlobal,
770  FP_LIB_TABLE* aProject )
771 {
772  DIALOG_FP_LIB_TABLE dlg( aCaller, aGlobal, aProject );
773 
774  int dialogRet = dlg.ShowModal(); // returns value passed to EndModal() above
775 
776  return dialogRet;
777 }
778 
779 
780 int InvokeFootprintWizard( wxTopLevelWindow* aParent, FP_LIB_TABLE* aGlobal,
781  FP_LIB_TABLE* aProject )
782 {
783  WIZARD_FPLIB_TABLE dlg( aParent );
784 
785  if( !dlg.RunWizard( dlg.GetFirstPage() ) )
786  return 0; // Aborted by user
787 
788  const std::vector<WIZARD_FPLIB_TABLE::LIBRARY>& libs = dlg.GetLibraries();
790  FP_LIB_TABLE* fp_tbl = ( scope == WIZARD_FPLIB_TABLE::GLOBAL ? aGlobal : aProject );
791 
792  if( fp_tbl )
793  {
794  for( std::vector<WIZARD_FPLIB_TABLE::LIBRARY>::const_iterator it = libs.begin();
795  it != libs.end(); ++it )
796  {
797  if( it->GetStatus() == WIZARD_FPLIB_TABLE::LIBRARY::INVALID )
798  continue;
799 
800  FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( it->GetDescription(),
801  it->GetAutoPath( scope ),
802  it->GetPluginName(),
803  wxEmptyString ); // options
804  fp_tbl->InsertRow( row );
805  }
806  }
807 
808  return scope;
809 }
int GetCount()
FP_LIB_TABLE_GRID * project_model() const
int getCursorCol() const
If the cursor is not on a valid cell, because there are no rows at all, return -1, else return a 0 based column index.
void push_back(LIB_TABLE_ROW *aRow) override
int getCursorRow() const
If the cursor is not on a valid cell, because there are no rows at all, return -1, else return a 0 based row index.
Hold a record identifying a library accessed by the appropriate plug in object in the LIB_TABLE...
LIB_SCOPE GetLibScope() const
Function GetLibScope Returns the scope for the added libraries (global / project specific).
void OnClickLibraryWizard(wxCommandEvent &event) override
void appendRowHandler(wxCommandEvent &event) override
Class FP_LIB_TABLE_ROW.
Definition: fp_lib_table.h:42
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Adds aRow if it does not already exist or if doReplace is true.
This file is part of the common library.
PROJECT & Prj()
Definition: kicad.cpp:270
void onCancelCaptionButtonClick(wxCloseEvent &event) override
void InvokePluginOptionsEditor(wxTopLevelWindow *aCaller, const wxString &aNickname, const wxString &aPluginType, const wxString &aOptions, wxString *aResult)
Function InvokePluginOptionsEditor calls DIALOG_FP_PLUGIN_OPTIONS dialog so that plugin options set c...
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
Definition: project.h:36
Class GRID_TRICKS is used to add cut, copy, and paste to an otherwise unmodied wxGrid instance...
Definition: grid_tricks.h:34
void deleteRowHandler(wxCommandEvent &event) override
bool DeleteRows(size_t aPos, size_t aNumRows) override
Class DIALOG_FP_LIB_TABLE shows and edits the PCB library tables.
const wxString & GetOptions() const
Return the options string, which may hold a password or anything else needed to instantiate the under...
LIB_TABLE_ROW * At(int aIndex)
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, LIB_ID_TYPE aType)
Replace illegal LIB_ID item name characters with underscores &#39;_&#39;.
Definition: lib_id.cpp:374
LIB_TABLE_ROWS rows
void moveUpHandler(wxCommandEvent &event) override
static const wxString ShowType(PCB_FILE_T aFileType)
Function ShowType returns a brief name for a plugin, given aFileType enum.
Definition: io_mgr.cpp:77
virtual const wxString GetType() const =0
Return the type of library represented by this row.
int InvokeFootprintWizard(wxTopLevelWindow *aParent, FP_LIB_TABLE *aGlobal, FP_LIB_TABLE *aProject)
Function InvokeFootprintWizard Runs the footprint library wizard for easy library addition...
int GetNumberRows() override
void moveDownHandler(wxCommandEvent &event) override
Geda PCB file formats.
Definition: io_mgr.h:58
size_t size() const override
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 ...
This abstract base class mixes any object derived from LIB_TABLE into wxGridTableBase so the result c...
static unsigned FindIllegalChar(const UTF8 &aNickname, LIB_ID_TYPE aType)
Looks for characters that are illegal in library and item names.
Definition: lib_id.cpp:388
LIB_TABLE_ROWS_ITER insert(LIB_TABLE_ROWS_ITER aIterator, LIB_TABLE_ROW *aRow) override
virtual void paste_text(const wxString &cb_text)
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
static const wxString GlobalPathEnvVariableName()
Function GlobalPathEnvVarVariableName.
virtual void paste_text(const wxString &cb_text) override
handle specialized clipboard text, with leading "(fp_lib_table", OR spreadsheet formatted text...
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...
void Refresh()
Update the board display after modifying it bu a python script (note: it is automatically called by a...
LIB_SCOPE
Scope (global/project)
#define KISYS3DMOD
A variable name whose value holds the path of 3D shape files.
Definition: 3d_viewer.h:38
int InvokePcbLibTableEditor(wxTopLevelWindow *aCaller, FP_LIB_TABLE *aGlobal, FP_LIB_TABLE *aProject)
Function InvokePcbLibTableEditor shows the modal DIALOG_FP_LIB_TABLE for purposes of editing two lib ...
void pageChangedHandler(wxAuiNotebookEvent &event) override
const std::vector< LIBRARY > & GetLibraries() const
Function GetLibraries Returns libraries selected by the user.
bool AppendRows(size_t aNumRows=1) override
FP_LIB_TABLE_GRID * cur_model() const
DIALOG_FP_LIB_TABLE(wxTopLevelWindow *aParent, FP_LIB_TABLE *aGlobal, FP_LIB_TABLE *aProject)
void onKeyDown(wxKeyEvent &ev) override
LIB_TABLE_ROWS_ITER begin() override
Class DIALOG_FP_LIB_TABLE_BASE.
void SetValue(int aRow, int aCol, const wxString &aValue) override
wxString GetValue(int aRow, int aCol) override
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
const wxString & GetNickName() const
Struct PARSE_ERROR contains a filename or source description, a problem input line, a line number, a byte offset, and an error message which contains the the caller&#39;s report and his call site information: CPP source file, function, and line number.
Definition: ki_exception.h:94
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
Legacy Pcbnew file formats prior to s-expression.
Definition: io_mgr.h:54
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
LIB_TABLE_ROW * makeNewRow() override
#define max(a, b)
Definition: auxiliary.h:86
FP_LIB_TABLE_GRID(const FP_LIB_TABLE &aTableToEdit)
size_t i
Definition: json11.cpp:597
wxWizardPage * GetFirstPage() const
Function GetFirstPage Returns the welcoming page for the wizard.
static int m_pageNdx
Remember the last notebook page selected during a session.
LIB_TABLE_ROWS::iterator LIB_TABLE_ROWS_ITER
LIB_TABLE_ROWS_ITER erase(LIB_TABLE_ROWS_ITER aFirst, LIB_TABLE_ROWS_ITER aLast) override
FP_GRID_TRICKS(wxGrid *aGrid)
wxGrid * m_cur_grid
changed based on tab choice
This class builds a wxGridTableBase by wrapping an FP_LIB_TABLE object.
void SetOptions(const wxString &aOptions)
Change the library options strings.
void onOKButtonClick(wxCommandEvent &event) override
void onCancelButtonClick(wxCommandEvent &event) override
bool verifyTables()
Function verifyTables trims important fields, removes blank row entries, and checks for duplicates...
Class STRING_LINE_READER is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition: richio.h:254
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:185
Read only http://github.com repo holding pretty footprints.
Definition: io_mgr.h:59
LIB_TABLE_ROW * at(size_t aIndex) override
Declaration of the eda_3d_viewer class.
static wxString GetGlobalTableFileName()
Function GetGlobalTableFileName.
void optionsEditor(wxCommandEvent &event) override
S-expression Pcbnew file format.
Definition: io_mgr.h:55