KiCad PCB EDA Suite
dialog_fields_editor_global.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 Oliver Walters
5  * Copyright (C) 2017-2019 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 
26 #include <wx/msgdlg.h>
27 #include <wx/grid.h>
28 #include <widgets/wx_grid.h>
29 #include <base_units.h>
30 #include <confirm.h>
31 #include <bitmaps.h>
32 #include <grid_tricks.h>
33 #include <kicad_string.h>
34 #include <refdes_utils.h>
35 #include <general.h>
36 #include <class_library.h>
37 #include <sch_edit_frame.h>
38 #include <sch_reference_list.h>
40 #include <kiface_i.h>
41 #include <eda_doc.h>
43 
45 
46 
47 enum
48 {
49  MYID_SELECT_FOOTPRINT = 991, // must be within GRID_TRICKS' enum range
51 };
52 
53 
55 {
56 public:
58  wxDataViewListCtrl* aFieldsCtrl ) :
59  GRID_TRICKS( aGrid ),
60  m_dlg( aParent ),
61  m_fieldsCtrl( aFieldsCtrl )
62  {}
63 
64 protected:
65  void showPopupMenu( wxMenu& menu ) override
66  {
67  if( m_grid->GetGridCursorCol() == FOOTPRINT )
68  {
69  menu.Append( MYID_SELECT_FOOTPRINT, _( "Select Footprint..." ),
70  _( "Browse for footprint" ) );
71  menu.AppendSeparator();
72  }
73  else if( m_grid->GetGridCursorCol() == DATASHEET )
74  {
75  menu.Append( MYID_SHOW_DATASHEET, _( "Show Datasheet" ),
76  _( "Show datasheet in browser" ) );
77  menu.AppendSeparator();
78  }
79 
81  }
82 
83  void doPopupSelection( wxCommandEvent& event ) override
84  {
85  if( event.GetId() == MYID_SELECT_FOOTPRINT )
86  {
87  // pick a footprint using the footprint picker.
88  wxString fpid = m_grid->GetCellValue( m_grid->GetGridCursorRow(), FOOTPRINT );
90 
91  if( frame->ShowModal( &fpid, m_dlg ) )
92  m_grid->SetCellValue( m_grid->GetGridCursorRow(), FOOTPRINT, fpid );
93 
94  frame->Destroy();
95  }
96  else if (event.GetId() == MYID_SHOW_DATASHEET )
97  {
98  wxString datasheet_uri = m_grid->GetCellValue( m_grid->GetGridCursorRow(), DATASHEET );
99  GetAssociatedDocument( m_dlg, datasheet_uri );
100  }
101  else
102  {
104  }
105 
106  if( event.GetId() >= GRIDTRICKS_FIRST_SHOWHIDE && event.GetId() < GRIDTRICKS_LAST_ID )
107  {
108  if( !m_grid->IsColShown( REFERENCE ) )
109  {
110  DisplayError( m_dlg, _( "The Reference column cannot be hidden." ) );
111 
112  m_grid->ShowCol( REFERENCE );
113  }
114 
115  // Refresh Show checkboxes from grid columns
116  for( int i = 0; i < m_fieldsCtrl->GetItemCount(); ++i )
117  m_fieldsCtrl->SetToggleValue( m_grid->IsColShown( i ), i, 1 );
118  }
119  }
120 
122  wxDataViewListCtrl* m_fieldsCtrl;
123 };
124 
125 
127 {
133 };
134 
135 
137 {
138  DATA_MODEL_ROW( const SCH_REFERENCE& aFirstReference, GROUP_TYPE aType )
139  {
140  m_Refs.push_back( aFirstReference );
141  m_Flag = aType;
142  }
143 
145  std::vector<SCH_REFERENCE> m_Refs;
146 };
147 
148 
149 #define FIELD_NAME_COLUMN 0
150 #define SHOW_FIELD_COLUMN 1
151 #define GROUP_BY_COLUMN 2
152 
153 #define QUANTITY_COLUMN ( GetNumberCols() - 1 )
154 
155 #ifdef __WXMAC__
156 #define COLUMN_MARGIN 5
157 #else
158 #define COLUMN_MARGIN 15
159 #endif
160 
161 
162 class FIELDS_EDITOR_GRID_DATA_MODEL : public wxGridTableBase
163 {
164 protected:
165  // The data model is fundamentally m_componentRefs X m_fieldNames.
166 
169  bool m_edited;
170  std::vector<wxString> m_fieldNames;
173 
174  // However, the grid view can vary in two ways:
175  // 1) the componentRefs can be grouped into fewer rows
176  // 2) some columns can be hidden
177  //
178  // We handle (1) here (ie: a table row maps to a group, and the table is rebuilt
179  // when the groupings change), and we let the wxGrid handle (2) (ie: the number
180  // of columns is constant but are hidden/shown by the wxGrid control).
181 
182  std::vector< DATA_MODEL_ROW > m_rows;
183 
184  // Data store
185  // A map of compID : fieldSet, where fieldSet is a map of fieldName : fieldValue
186  std::map< timestamp_t, std::map<wxString, wxString> > m_dataStore;
187 
188 
189 public:
191  m_frame( aFrame ),
192  m_componentRefs( aComponentList ),
193  m_edited( false ),
194  m_sortColumn( 0 ),
195  m_sortAscending( false )
196  {
198  }
199 
200 
201  void AddColumn( const wxString& aFieldName )
202  {
203  m_fieldNames.push_back( aFieldName );
204 
205  for( unsigned i = 0; i < m_componentRefs.GetCount(); ++i )
206  {
207  SCH_COMPONENT* comp = m_componentRefs[ i ].GetComp();
208  timestamp_t compID = comp->GetTimeStamp();
209 
210  m_dataStore[ compID ][ aFieldName ] = comp->GetFieldText( aFieldName, m_frame );
211  }
212  }
213 
214 
215  int GetNumberRows() override { return m_rows.size(); }
216 
217  // Columns are fieldNames + quantity column
218  int GetNumberCols() override { return (int) m_fieldNames.size() + 1; }
219 
220 
221  wxString GetColLabelValue( int aCol ) override
222  {
223  if( aCol == QUANTITY_COLUMN )
224  return _( "Qty" );
225  else
226  return m_fieldNames[ aCol ];
227  }
228 
229 
230  bool IsEmptyCell( int aRow, int aCol ) override
231  {
232  return false; // don't allow adjacent cell overflow, even if we are actually empty
233  }
234 
235 
236  wxString GetValue( int aRow, int aCol ) override
237  {
238  if( aCol == REFERENCE )
239  {
240  // Poor-man's tree controls
241  if( m_rows[ aRow ].m_Flag == GROUP_COLLAPSED )
242  return wxT( "> " ) + GetValue( m_rows[ aRow ], aCol );
243  else if (m_rows[ aRow ].m_Flag == GROUP_EXPANDED )
244  return wxT( "v " ) + GetValue( m_rows[ aRow ], aCol );
245  else if( m_rows[ aRow ].m_Flag == CHILD_ITEM )
246  return wxT( " " ) + GetValue( m_rows[ aRow ], aCol );
247  else
248  return wxT( " " ) + GetValue( m_rows[ aRow ], aCol );
249  }
250  else
251  return GetValue( m_rows[ aRow ], aCol );
252  }
253 
254  std::vector<SCH_REFERENCE> GetRowReferences( int aRow )
255  {
256  wxCHECK( aRow < (int)m_rows.size(), std::vector<SCH_REFERENCE>() );
257  return m_rows[ aRow ].m_Refs;
258  }
259 
260  wxString GetValue( DATA_MODEL_ROW& group, int aCol )
261  {
262  std::vector<SCH_REFERENCE> references;
263  wxString fieldValue;
264 
265  for( const auto& ref : group.m_Refs )
266  {
267  if( aCol == REFERENCE || aCol == QUANTITY_COLUMN )
268  {
269  references.push_back( ref );
270  }
271  else // Other columns are either a single value or ROW_MULTI_ITEMS
272  {
273  timestamp_t compID = ref.GetComp()->GetTimeStamp();
274 
275  if( !m_dataStore.count( compID ) ||
276  !m_dataStore[ compID ].count( m_fieldNames[ aCol ] ) )
277  return INDETERMINATE;
278 
279  if( &ref == &group.m_Refs.front() )
280  fieldValue = m_dataStore[ compID ][ m_fieldNames[ aCol ] ];
281  else if ( fieldValue != m_dataStore[ compID ][ m_fieldNames[ aCol ] ] )
282  return INDETERMINATE;
283  }
284  }
285 
286  if( aCol == REFERENCE || aCol == QUANTITY_COLUMN )
287  {
288  // Remove duplicates (other units of multi-unit parts)
289  std::sort( references.begin(), references.end(),
290  []( const SCH_REFERENCE& l, const SCH_REFERENCE& r ) -> bool
291  {
292  wxString l_ref( l.GetRef() << l.GetRefNumber() );
293  wxString r_ref( r.GetRef() << r.GetRefNumber() );
294  return UTIL::RefDesStringCompare( l_ref, r_ref ) < 0;
295  } );
296 
297  auto logicalEnd = std::unique( references.begin(), references.end(),
298  []( const SCH_REFERENCE& l, const SCH_REFERENCE& r ) -> bool
299  {
300  // If unannotated then we can't tell what units belong together
301  // so we have to leave them all
302  if( l.GetRefNumber() == wxT( "?" ) )
303  return false;
304 
305  wxString l_ref( l.GetRef() << l.GetRefNumber() );
306  wxString r_ref( r.GetRef() << r.GetRefNumber() );
307  return l_ref == r_ref;
308  } );
309  references.erase( logicalEnd, references.end() );
310  }
311 
312  if( aCol == REFERENCE )
313  {
314  fieldValue = SCH_REFERENCE_LIST::Shorthand( references );
315  }
316  else if( aCol == QUANTITY_COLUMN )
317  {
318  fieldValue = wxString::Format( wxT( "%d" ), ( int )references.size() );
319  }
320 
321  return fieldValue;
322  }
323 
324 
325  void SetValue( int aRow, int aCol, const wxString &aValue ) override
326  {
327  if( aCol == REFERENCE || aCol == QUANTITY_COLUMN )
328  return; // Can't modify references or quantity
329 
330  DATA_MODEL_ROW& rowGroup = m_rows[ aRow ];
331  wxString fieldName = m_fieldNames[ aCol ];
332 
333  for( const auto& ref : rowGroup.m_Refs )
334  m_dataStore[ ref.GetComp()->GetTimeStamp() ][ fieldName ] = aValue;
335 
336  m_edited = true;
337  }
338 
339 
340  static bool cmp( const DATA_MODEL_ROW& lhGroup, const DATA_MODEL_ROW& rhGroup,
341  FIELDS_EDITOR_GRID_DATA_MODEL* dataModel, int sortCol, bool ascending )
342  {
343  // Empty rows always go to the bottom, whether ascending or descending
344  if( lhGroup.m_Refs.size() == 0 )
345  return true;
346  else if( rhGroup.m_Refs.size() == 0 )
347  return false;
348 
349  // N.B. To meet the iterator sort conditions, we cannot simply invert the truth
350  // to get the opposite sort. i.e. ~(a<b) != (a>b)
351  auto local_cmp = [ ascending ]( const auto a, const auto b )
352  {
353  if( ascending )
354  return a < b;
355  else
356  return a > b;
357  };
358 
359  // Primary sort key is sortCol; secondary is always REFERENCE (column 0)
360 
361  wxString lhs = dataModel->GetValue( (DATA_MODEL_ROW&) lhGroup, sortCol );
362  wxString rhs = dataModel->GetValue( (DATA_MODEL_ROW&) rhGroup, sortCol );
363 
364  if( lhs == rhs || sortCol == REFERENCE )
365  {
366  wxString lhRef = lhGroup.m_Refs[ 0 ].GetRef() + lhGroup.m_Refs[ 0 ].GetRefNumber();
367  wxString rhRef = rhGroup.m_Refs[ 0 ].GetRef() + rhGroup.m_Refs[ 0 ].GetRefNumber();
368  return local_cmp( UTIL::RefDesStringCompare( lhRef, rhRef ), 0 );
369  }
370  else
371  return local_cmp( ValueStringCompare( lhs, rhs ), 0 );
372  }
373 
374 
375  void Sort( int aColumn, bool ascending )
376  {
377  if( aColumn < 0 )
378  aColumn = 0;
379 
380  m_sortColumn = aColumn;
381  m_sortAscending = ascending;
382 
383  CollapseForSort();
384 
385  std::sort( m_rows.begin(), m_rows.end(),
386  [ this ]( const DATA_MODEL_ROW& lhs, const DATA_MODEL_ROW& rhs ) -> bool
387  {
388  return cmp( lhs, rhs, this, m_sortColumn, m_sortAscending );
389  } );
390 
391  ExpandAfterSort();
392  }
393 
394 
395  bool unitMatch( const SCH_REFERENCE& lhRef, const SCH_REFERENCE& rhRef )
396  {
397  // If items are unannotated then we can't tell if they're units of the same
398  // component or not
399  if( lhRef.GetRefNumber() == wxT( "?" ) )
400  return false;
401 
402  return ( lhRef.GetRef() == rhRef.GetRef() && lhRef.GetRefNumber() == rhRef.GetRefNumber() );
403  }
404 
405 
406  bool groupMatch( const SCH_REFERENCE& lhRef, const SCH_REFERENCE& rhRef,
407  wxDataViewListCtrl* fieldsCtrl )
408  {
409  bool matchFound = false;
410 
411  // First check the reference column. This can be done directly out of the
412  // SCH_REFERENCEs as the references can't be edited in the grid.
413  if( fieldsCtrl->GetToggleValue( REFERENCE, GROUP_BY_COLUMN ) )
414  {
415  // if we're grouping by reference, then only the prefix must match
416  if( lhRef.GetRef() != rhRef.GetRef() )
417  return false;
418 
419  matchFound = true;
420  }
421 
422  timestamp_t lhRefID = lhRef.GetComp()->GetTimeStamp();
423  timestamp_t rhRefID = rhRef.GetComp()->GetTimeStamp();
424 
425  // Now check all the other columns. This must be done out of the dataStore
426  // for the refresh button to work after editing.
427  for( int i = REFERENCE + 1; i < fieldsCtrl->GetItemCount(); ++i )
428  {
429  if( !fieldsCtrl->GetToggleValue( i, GROUP_BY_COLUMN ) )
430  continue;
431 
432  wxString fieldName = fieldsCtrl->GetTextValue( i, FIELD_NAME_COLUMN );
433 
434  if( m_dataStore[ lhRefID ][ fieldName ] != m_dataStore[ rhRefID ][ fieldName ] )
435  return false;
436 
437  matchFound = true;
438  }
439 
440  return matchFound;
441  }
442 
443 
444  void RebuildRows( wxCheckBox* groupComponentsBox, wxDataViewListCtrl* fieldsCtrl )
445  {
446  if ( GetView() )
447  {
448  // Commit any pending in-place edits before the row gets moved out from under
449  // the editor.
450  static_cast<WX_GRID*>( GetView() )->CommitPendingChanges( true );
451 
452  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, 0, m_rows.size() );
453  GetView()->ProcessTableMessage( msg );
454  }
455 
456  m_rows.clear();
457 
458  for( unsigned i = 0; i < m_componentRefs.GetCount(); ++i )
459  {
460  SCH_REFERENCE ref = m_componentRefs[ i ];
461  bool matchFound = false;
462 
463  // See if we already have a row which this component fits into
464  for( auto& row : m_rows )
465  {
466  // all group members must have identical refs so just use the first one
467  SCH_REFERENCE rowRef = row.m_Refs[ 0 ];
468 
469  if( unitMatch( ref, rowRef ) )
470  {
471  matchFound = true;
472  row.m_Refs.push_back( ref );
473  break;
474  }
475  else if (groupComponentsBox->GetValue() && groupMatch( ref, rowRef, fieldsCtrl ) )
476  {
477  matchFound = true;
478  row.m_Refs.push_back( ref );
479  row.m_Flag = GROUP_COLLAPSED;
480  break;
481  }
482  }
483 
484  if( !matchFound )
485  m_rows.emplace_back( DATA_MODEL_ROW( ref, GROUP_SINGLETON ) );
486  }
487 
488  if ( GetView() )
489  {
490  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_rows.size() );
491  GetView()->ProcessTableMessage( msg );
492  }
493  }
494 
495 
496  void ExpandRow( int aRow )
497  {
498  std::vector<DATA_MODEL_ROW> children;
499 
500  for( auto& ref : m_rows[ aRow ].m_Refs )
501  {
502  bool matchFound = false;
503 
504  // See if we already have a child group which this component fits into
505  for( auto& child : children )
506  {
507  // group members are by definition all matching, so just check
508  // against the first member
509  if( unitMatch( ref, child.m_Refs[ 0 ] ) )
510  {
511  matchFound = true;
512  child.m_Refs.push_back( ref );
513  break;
514  }
515  }
516 
517  if( !matchFound )
518  children.emplace_back( DATA_MODEL_ROW( ref, CHILD_ITEM ) );
519  }
520 
521  if( children.size() < 2 )
522  return;
523 
524  std::sort( children.begin(), children.end(),
525  [ this ] ( const DATA_MODEL_ROW& lhs, const DATA_MODEL_ROW& rhs ) -> bool
526  {
527  return cmp( lhs, rhs, this, m_sortColumn, m_sortAscending );
528  } );
529 
530  m_rows[ aRow ].m_Flag = GROUP_EXPANDED;
531  m_rows.insert( m_rows.begin() + aRow + 1, children.begin(), children.end() );
532 
533  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_INSERTED, aRow, children.size() );
534  GetView()->ProcessTableMessage( msg );
535  }
536 
537 
538  void CollapseRow( int aRow )
539  {
540  auto firstChild = m_rows.begin() + aRow + 1;
541  auto afterLastChild = firstChild;
542  int deleted = 0;
543 
544  while( afterLastChild != m_rows.end() && afterLastChild->m_Flag == CHILD_ITEM )
545  {
546  deleted++;
547  afterLastChild++;
548  }
549 
550  m_rows[ aRow ].m_Flag = GROUP_COLLAPSED;
551  m_rows.erase( firstChild, afterLastChild );
552 
553  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, aRow + 1, deleted );
554  GetView()->ProcessTableMessage( msg );
555  }
556 
557 
558  void ExpandCollapseRow( int aRow )
559  {
560  DATA_MODEL_ROW& group = m_rows[ aRow ];
561 
562  if( group.m_Flag == GROUP_COLLAPSED )
563  ExpandRow( aRow );
564  else if( group.m_Flag == GROUP_EXPANDED )
565  CollapseRow( aRow );
566  }
567 
568 
570  {
571  for( size_t i = 0; i < m_rows.size(); ++i )
572  {
573  if( m_rows[ i ].m_Flag == GROUP_EXPANDED )
574  {
575  CollapseRow( i );
576  m_rows[ i ].m_Flag = GROUP_COLLAPSED_DURING_SORT;
577  }
578  }
579  }
580 
581 
583  {
584  for( size_t i = 0; i < m_rows.size(); ++i )
585  {
586  if( m_rows[ i ].m_Flag == GROUP_COLLAPSED_DURING_SORT )
587  ExpandRow( i );
588  }
589  }
590 
591 
592  void ApplyData()
593  {
594  for( unsigned i = 0; i < m_componentRefs.GetCount(); ++i )
595  {
596  SCH_COMPONENT& comp = *m_componentRefs[i].GetComp();
597 
598  m_frame->SetCurrentSheet( m_componentRefs[i].GetSheetPath() );
599  m_frame->SaveCopyInUndoList( &comp, UR_CHANGED, true );
600 
601  const std::map<wxString, wxString>& fieldStore = m_dataStore[comp.GetTimeStamp()];
602 
603  for( const std::pair<wxString, wxString> srcData : fieldStore )
604  {
605  const wxString& srcName = srcData.first;
606  const wxString& srcValue = srcData.second;
607  SCH_FIELD* destField = comp.FindField( srcName );
608 
609  if( !destField && !srcValue.IsEmpty() )
610  {
611  const auto compOrigin = comp.GetPosition();
612  destField = comp.AddField( SCH_FIELD( compOrigin, -1, &comp, srcName ) );
613  }
614 
615  if( !destField )
616  {
617  comp.RemoveField( srcName );
618  continue;
619  }
620 
621  // Reference and value fields cannot be empty. All other fields can.
622  if( srcValue.IsEmpty()
623  && (destField->GetId() == REFERENCE || destField->GetId() == VALUE))
624  continue;
625 
626  destField->SetText( srcValue );
627  }
628  }
629 
630  m_edited = false;
631  }
632 
633 
634  int GetDataWidth( int aCol )
635  {
636  int width = 0;
637 
638  if( aCol == REFERENCE )
639  {
640  for( int row = 0; row < GetNumberRows(); ++row )
641  {
642  width = std::max( width, GetTextSize( GetValue( row, aCol ), GetView() ).x );
643  }
644  }
645  else
646  {
647  wxString column_label = GetColLabelValue( aCol ); // component fieldName or Qty string
648 
649  for( unsigned compRef = 0; compRef < m_componentRefs.GetCount(); ++ compRef )
650  {
651  timestamp_t compId = m_componentRefs[ compRef ].GetComp()->GetTimeStamp();
652  wxString text = m_dataStore[ compId ][ column_label ];
653  width = std::max( width, GetTextSize( text, GetView() ).x );
654  }
655  }
656 
657  return width;
658  }
659 
660 
661  bool IsEdited()
662  {
663  return m_edited;
664  }
665 };
666 
667 
670  m_config( Kiface().KifaceSettings() ),
671  m_parent( parent )
672 {
673  wxSize defaultDlgSize = ConvertDialogToPixels( wxSize( 600, 300 ) );
674 
675  // Get all components from the list of schematic sheets
676  SCH_SHEET_LIST sheets( g_RootSheet );
677  sheets.GetComponents( m_componentRefs, false );
678 
679  m_bRefresh->SetBitmap( KiBitmap( refresh_xpm ) );
680 
681  m_fieldsCtrl->AppendTextColumn( _( "Field" ), wxDATAVIEW_CELL_INERT, 0, wxALIGN_LEFT, 0 );
682  m_fieldsCtrl->AppendToggleColumn( _( "Show" ), wxDATAVIEW_CELL_ACTIVATABLE, 0, wxALIGN_CENTER,
683  0 );
684  m_fieldsCtrl->AppendToggleColumn( _( "Group By" ), wxDATAVIEW_CELL_ACTIVATABLE, 0,
685  wxALIGN_CENTER, 0 );
686 
687  // SetWidth( wxCOL_WIDTH_AUTOSIZE ) fails here on GTK, so we calculate the title sizes and
688  // set the column widths ourselves.
689  auto column = m_fieldsCtrl->GetColumn( SHOW_FIELD_COLUMN );
690  m_showColWidth = GetTextSize( column->GetTitle(), m_fieldsCtrl ).x + COLUMN_MARGIN;
691  column->SetWidth( m_showColWidth );
692 
693  column = m_fieldsCtrl->GetColumn( GROUP_BY_COLUMN );
694  m_groupByColWidth = GetTextSize( column->GetTitle(), m_fieldsCtrl ).x + COLUMN_MARGIN;
695  column->SetWidth( m_groupByColWidth );
696 
697  // The fact that we're a list should keep the control from reserving space for the
698  // expander buttons... but it doesn't. Fix by forcing the indent to 0.
699  m_fieldsCtrl->SetIndent( 0 );
700 
702 
703  LoadFieldNames(); // loads rows into m_fieldsCtrl and columns into m_dataModel
704 
705  // Now that the fields are loaded we can set the initial location of the splitter
706  // based on the list width. Again, SetWidth( wxCOL_WIDTH_AUTOSIZE ) fails us on GTK.
707  int nameColWidth = 0;
708 
709  for( int row = 0; row < m_fieldsCtrl->GetItemCount(); ++row )
710  {
711  const wxString& fieldName = m_fieldsCtrl->GetTextValue( row, FIELD_NAME_COLUMN );
712  nameColWidth = std::max( nameColWidth, GetTextSize( fieldName, m_fieldsCtrl ).x );
713  }
714 
715  m_fieldsCtrl->GetColumn( FIELD_NAME_COLUMN )->SetWidth( nameColWidth );
716  m_splitter1->SetSashPosition( nameColWidth + m_showColWidth + m_groupByColWidth + 40 );
717 
719  m_dataModel->Sort( 0, true );
720 
721  // wxGrid's column moving is buggy with native headers and this is one dialog where you'd
722  // really like to be able to rearrange columns.
723  m_grid->UseNativeColHeader( false );
724  m_grid->SetTable( m_dataModel, true );
725 
726  // sync m_grid's column visibilities to Show checkboxes in m_fieldsCtrl
727  for( int i = 0; i < m_fieldsCtrl->GetItemCount(); ++i )
728  {
729  if( m_fieldsCtrl->GetToggleValue( i, 1 ) )
730  m_grid->ShowCol( i );
731  else
732  m_grid->HideCol( i );
733  }
734 
735  // add Cut, Copy, and Paste to wxGrid
736  m_grid->PushEventHandler( new FIELDS_EDITOR_GRID_TRICKS( this, m_grid, m_fieldsCtrl ) );
737 
738  // give a bit more room for comboboxes
739  m_grid->SetDefaultRowSize( m_grid->GetDefaultRowSize() + 4 );
740 
741  // set reference column attributes
742  wxGridCellAttr* attr = new wxGridCellAttr;
743  attr->SetReadOnly();
744  m_grid->SetColAttr( REFERENCE, attr );
745 
746  // set footprint column browse button
747  attr = new wxGridCellAttr;
748  attr->SetEditor( new GRID_CELL_FOOTPRINT_ID_EDITOR( this ) );
749  m_grid->SetColAttr( FOOTPRINT, attr );
750 
751  // set datasheet column viewer button
752  attr = new wxGridCellAttr;
753  attr->SetEditor( new GRID_CELL_URL_EDITOR( this ) );
754  m_grid->SetColAttr( DATASHEET, attr );
755 
756  // set quantities column attributes
757  attr = new wxGridCellAttr;
758  attr->SetReadOnly();
759  m_grid->SetColAttr( m_dataModel->GetColsCount() - 1, attr );
760  m_grid->SetColFormatNumber( m_dataModel->GetColsCount() - 1 );
761  m_grid->AutoSizeColumns( false );
762 
763  for( int col = 0; col < m_grid->GetNumberCols(); ++ col )
764  {
765  // Columns are hidden by setting their width to 0 so if we resize them they will
766  // become unhidden.
767  if( m_grid->IsColShown( col ) )
768  {
769  int textWidth = m_dataModel->GetDataWidth( col ) + COLUMN_MARGIN;
770  int maxWidth = defaultDlgSize.x / 3;
771 
772  if( col == m_grid->GetNumberCols() - 1 )
773  m_grid->SetColSize( col, std::min( std::max( 50, textWidth ), maxWidth ) );
774  else
775  m_grid->SetColSize( col, std::min( std::max( 100, textWidth ), maxWidth ) );
776  }
777  }
778 
779  m_grid->SetGridCursor( 0, 1 );
781 
782  m_sdbSizer1OK->SetDefault();
783 
785  SetSize( defaultDlgSize );
786  Center();
787 
788  // Connect Events
789  m_grid->Connect( wxEVT_GRID_COL_SORT,
790  wxGridEventHandler( DIALOG_FIELDS_EDITOR_GLOBAL::OnColSort ), NULL, this );
791 }
792 
793 
795 {
796  // Disconnect Events
797  m_grid->Disconnect( wxEVT_GRID_COL_SORT,
798  wxGridEventHandler( DIALOG_FIELDS_EDITOR_GLOBAL::OnColSort ), NULL, this );
799 
800  // Delete the GRID_TRICKS.
801  m_grid->PopEventHandler( true );
802 
803  // we gave ownership of m_dataModel to the wxGrid...
804 
805  // Clear highlighted symbols, if any
806  m_parent->GetCanvas()->GetView()->HighlightItem( nullptr, nullptr );
807  m_parent->GetCanvas()->Refresh();
808 }
809 
810 
812 {
813  if( !wxDialog::TransferDataFromWindow() )
814  return false;
815 
816  TOOL_MANAGER* toolMgr = m_parent->GetToolManager();
817  EE_SELECTION_TOOL* selectionTool = toolMgr->GetTool<EE_SELECTION_TOOL>();
818  EE_SELECTION& selection = selectionTool->GetSelection();
819  SCH_COMPONENT* component = nullptr;
820 
821  if( selection.GetSize() == 1 )
822  {
823  EDA_ITEM* item = selection.Front();
824 
825  if( item->Type() == SCH_COMPONENT_T )
826  component = (SCH_COMPONENT*) item;
827  else if( item->GetParent() && item->GetParent()->Type() == SCH_COMPONENT_T )
828  component = (SCH_COMPONENT*) item->GetParent();
829  }
830 
831  if( component )
832  {
833  for( int row = 0; row < m_dataModel->GetNumberRows(); ++row )
834  {
835  std::vector<SCH_REFERENCE> references = m_dataModel->GetRowReferences( row );
836  bool found = false;
837 
838  for( const SCH_REFERENCE& ref : references )
839  {
840  if( ref.GetComp() == component )
841  {
842  found = true;
843  break;
844  }
845  }
846 
847  if( found )
848  {
849  m_grid->GoToCell( row, 1 );
850  break;
851  }
852  }
853  }
854 
855  return true;
856 }
857 
858 
860 {
861  if( !m_grid->CommitPendingChanges() )
862  return false;
863 
864  if( !wxDialog::TransferDataFromWindow() )
865  return false;
866 
867  SCH_SHEET_PATH currentSheet = m_parent->GetCurrentSheet();
868 
870  m_parent->SyncView();
871  m_parent->OnModify();
872 
873  // Reset the view to where we left the user
874  m_parent->SetCurrentSheet( currentSheet );
875  m_parent->Refresh();
876 
877  return true;
878 }
879 
880 
881 void DIALOG_FIELDS_EDITOR_GLOBAL::AddField( const wxString& aName,
882  bool defaultShow, bool defaultSortBy )
883 {
884  m_dataModel->AddColumn( aName );
885 
886  wxVector<wxVariant> fieldsCtrlRow;
887 
888  m_config->Read( "SymbolFieldEditor/Show/" + aName, &defaultShow );
889  m_config->Read( "SymbolFieldEditor/GroupBy/" + aName, &defaultSortBy );
890 
891  fieldsCtrlRow.push_back( wxVariant( aName ) );
892  fieldsCtrlRow.push_back( wxVariant( defaultShow ) );
893  fieldsCtrlRow.push_back( wxVariant( defaultSortBy ) );
894 
895  m_fieldsCtrl->AppendItem( fieldsCtrlRow );
896 }
897 
898 
904 {
905  std::set<wxString> userFieldNames;
906 
907  for( unsigned i = 0; i < m_componentRefs.GetCount(); ++i )
908  {
909  SCH_COMPONENT* comp = m_componentRefs[ i ].GetComp();
910 
911  for( int j = MANDATORY_FIELDS; j < comp->GetFieldCount(); ++j )
912  userFieldNames.insert( comp->GetField( j )->GetName() );
913  }
914 
915  // Force References to always be shown
916  m_config->Write( "SymbolFieldEditor/Show/Reference", true );
917 
918  AddField( _( "Reference" ), true, true );
919  AddField( _( "Value" ), true, true );
920  AddField( _( "Footprint" ), true, true );
921  AddField( _( "Datasheet" ), true, false );
922 
923  for( const wxString& fieldName : userFieldNames )
924  AddField( fieldName, true, false );
925 
926  // Add any templateFieldNames which aren't already present in the userFieldNames
927  for( const TEMPLATE_FIELDNAME& templateFieldName : m_parent->GetTemplateFieldNames() )
928  if( userFieldNames.count( templateFieldName.m_Name ) == 0 )
929  AddField( templateFieldName.m_Name, false, false );
930 }
931 
932 
933 void DIALOG_FIELDS_EDITOR_GLOBAL::OnAddField( wxCommandEvent& event )
934 {
935  // quantities column will become new field column, so it needs to be reset
936  auto attr = new wxGridCellAttr;
937  m_grid->SetColAttr( m_dataModel->GetColsCount() - 1, attr );
938  m_grid->SetColFormatCustom( m_dataModel->GetColsCount() - 1, wxGRID_VALUE_STRING );
939 
940  wxTextEntryDialog dlg( this, _( "New field name:" ), _( "Add Field" ) );
941 
942  if( dlg.ShowModal() != wxID_OK )
943  return;
944 
945  wxString fieldName = dlg.GetValue();
946 
947  if( fieldName.IsEmpty() )
948  {
949  DisplayError( this, _( "Field must have a name." ) );
950  return;
951  }
952 
953  for( int i = 0; i < m_dataModel->GetNumberCols(); ++i )
954  {
955  if( fieldName == m_dataModel->GetColLabelValue( i ) )
956  {
957  DisplayError( this, wxString::Format( _( "Field name \"%s\" already in use." ),
958  fieldName ) );
959  return;
960  }
961  }
962 
963  m_config->Write( "SymbolFieldEditor/Show/" + fieldName, true );
964 
965  AddField( fieldName, true, false );
966 
967  wxGridTableMessage msg( m_dataModel, wxGRIDTABLE_NOTIFY_COLS_INSERTED,
968  m_fieldsCtrl->GetItemCount(), 1 );
969  m_grid->ProcessTableMessage( msg );
970 
971  // set up attributes on the new quantities column
972  attr = new wxGridCellAttr;
973  attr->SetReadOnly();
974  m_grid->SetColAttr( m_dataModel->GetColsCount() - 1, attr );
975  m_grid->SetColFormatNumber( m_dataModel->GetColsCount() - 1 );
976  m_grid->SetColSize( m_dataModel->GetColsCount() - 1, 50 );
977 }
978 
979 
981 {
982  wxDataViewItem item = event.GetItem();
983 
984  int row = m_fieldsCtrl->ItemToRow( item );
985  int col = event.GetColumn();
986 
987  switch ( col )
988  {
989  default:
990  break;
991 
992  case SHOW_FIELD_COLUMN:
993  {
994  bool value = m_fieldsCtrl->GetToggleValue( row, col );
995 
996  if( row == REFERENCE && !value )
997  {
998  DisplayError( this, _( "The Reference column cannot be hidden." ) );
999 
1000  value = true;
1001  m_fieldsCtrl->SetToggleValue( value, row, col );
1002  }
1003 
1004  wxString fieldName = m_fieldsCtrl->GetTextValue( row, FIELD_NAME_COLUMN );
1005  m_config->Write( "SymbolFieldEditor/Show/" + fieldName, value );
1006 
1007  if( value )
1008  m_grid->ShowCol( row );
1009  else
1010  m_grid->HideCol( row ); // grid's columns map to fieldsCtrl's rows
1011  break;
1012  }
1013 
1014  case GROUP_BY_COLUMN:
1015  {
1016  bool value = m_fieldsCtrl->GetToggleValue( row, col );
1017  wxString fieldName = m_fieldsCtrl->GetTextValue( row, FIELD_NAME_COLUMN );
1018  m_config->Write( "SymbolFieldEditor/GroupBy/" + fieldName, value );
1020  m_dataModel->Sort( m_grid->GetSortingColumn(), m_grid->IsSortOrderAscending() );
1021  m_grid->ForceRefresh();
1022  break;
1023  }
1024  }
1025 }
1026 
1027 
1029 {
1031  m_dataModel->Sort( m_grid->GetSortingColumn(), m_grid->IsSortOrderAscending() );
1032  m_grid->ForceRefresh();
1033 }
1034 
1035 
1036 void DIALOG_FIELDS_EDITOR_GLOBAL::OnColSort( wxGridEvent& aEvent )
1037 {
1038  int sortCol = aEvent.GetCol();
1039  bool ascending;
1040 
1041  // This is bonkers, but wxWidgets doesn't tell us ascending/descending in the
1042  // event, and if we ask it will give us pre-event info.
1043  if( m_grid->IsSortingBy( sortCol ) )
1044  // same column; invert ascending
1045  ascending = !m_grid->IsSortOrderAscending();
1046  else
1047  // different column; start with ascending
1048  ascending = true;
1049 
1050  m_dataModel->Sort( sortCol, ascending );
1051  m_grid->ForceRefresh();
1052 }
1053 
1054 
1056 {
1057  m_grid->ForceRefresh();
1058 }
1059 
1060 
1062 {
1064  m_dataModel->Sort( m_grid->GetSortingColumn(), m_grid->IsSortOrderAscending() );
1065  m_grid->ForceRefresh();
1066 }
1067 
1068 
1070 {
1071  if( event.GetCol() == REFERENCE )
1072  {
1073  m_grid->ClearSelection();
1074  m_grid->SetGridCursor( event.GetRow(), event.GetCol() );
1075 
1076  // Clear highlighted symbols, if any
1077  m_parent->GetCanvas()->GetView()->HighlightItem( nullptr, nullptr );
1078  m_parent->GetCanvas()->Refresh();
1079 
1080  m_dataModel->ExpandCollapseRow( event.GetRow() );
1081  std::vector<SCH_REFERENCE> refs = m_dataModel->GetRowReferences( event.GetRow() );
1082 
1083  // Focus Eeschema view on the component selected in the dialog
1084  if( refs.size() == 1 )
1085  {
1087 
1088  editor->FindComponentAndItem( refs[0].GetRef() + refs[0].GetRefNumber(), true,
1089  HIGHLIGHT_COMPONENT, wxEmptyString );
1090  }
1091  }
1092  else
1093  {
1094  event.Skip();
1095  }
1096 }
1097 
1098 
1100 {
1101  // TODO: Option to select footprint if FOOTPRINT column selected
1102 
1103  event.Skip();
1104 }
1105 
1106 
1108 {
1109  int nameColWidth = event.GetSize().GetX() - m_showColWidth - m_groupByColWidth - 8;
1110 
1111  // GTK loses its head and messes these up when resizing the splitter bar:
1112  m_fieldsCtrl->GetColumn( 1 )->SetWidth( m_showColWidth );
1113  m_fieldsCtrl->GetColumn( 2 )->SetWidth( m_groupByColWidth );
1114 
1115  m_fieldsCtrl->GetColumn( 0 )->SetWidth( nameColWidth );
1116 
1117  event.Skip();
1118 }
1119 
1120 
1122 {
1123  if( TransferDataFromWindow() )
1124  m_parent->SaveProject();
1125 }
1126 
1127 
1128 void DIALOG_FIELDS_EDITOR_GLOBAL::OnCancel( wxCommandEvent& event )
1129 {
1130  Close();
1131 }
1132 
1133 
1134 void DIALOG_FIELDS_EDITOR_GLOBAL::OnClose( wxCloseEvent& event )
1135 {
1136  // This is a cancel, so commit quietly as we're going to throw the results away anyway.
1137  m_grid->CommitPendingChanges( true );
1138 
1139  if( m_dataModel->IsEdited() )
1140  {
1141  if( !HandleUnsavedChanges( this, wxEmptyString,
1142  [&]()->bool { return TransferDataFromWindow(); } ) )
1143  {
1144  event.Veto();
1145  return;
1146  }
1147  }
1148 
1149  event.Skip();
1150 }
void SetCurrentSheet(const SCH_SHEET_PATH &aSheet)
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:236
void doPopupSelection(wxCommandEvent &event) override
SCH_SHEET_LIST.
KIGFX::SCH_VIEW * GetView() const override
Function GetView() Returns a pointer to the VIEW instance used in the panel.
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:52
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
Definition: confirm.cpp:201
KIWAY_PLAYER is a wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of ...
Definition: kiway_player.h:59
SCH_FIELD * FindField(const wxString &aFieldName, bool aIncludeDefaultFields=true)
Search for a SCH_FIELD with aFieldName.
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_holder.h:56
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
void OnColumnItemToggled(wxDataViewEvent &event) override
void AddColumn(const wxString &aFieldName)
name of datasheet
void LoadFieldNames()
Constructs the rows of m_fieldsCtrl and the columns of m_dataModel from a union of all field names in...
DATA_MODEL_ROW(const SCH_REFERENCE &aFirstReference, GROUP_TYPE aType)
std::vector< SCH_REFERENCE > m_Refs
Implementation of conversion functions that require both schematic and board internal units.
This file is part of the common library.
This file is part of the common library.
FIELDS_EDITOR_GRID_TRICKS(DIALOG_SHIM *aParent, WX_GRID *aGrid, wxDataViewListCtrl *aFieldsCtrl)
SCH_COMPONENT * GetComp() const
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
void FinishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
void OnAddField(wxCommandEvent &event) override
Collection of utility functions for component reference designators (refdes)
GRID_TRICKS is used to add mouse and command handling (such as cut, copy, and paste) to a WX_GRID ins...
Definition: grid_tricks.h:51
int GetId() const
Definition: sch_field.h:108
bool GetAssociatedDocument(wxWindow *aParent, const wxString &aDocName, const wxPathList *aPaths)
Function GetAssociatedDocument open a document (file) with the suitable browser.
Definition: eda_doc.cpp:87
std::map< timestamp_t, std::map< wxString, wxString > > m_dataStore
Schematic editor (Eeschema) main window.
static wxString Shorthand(std::vector< SCH_REFERENCE > aList)
Function Shorthand Returns a shorthand string representing all the references in the list.
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition: dialog_shim.h:84
wxString GetRefNumber() const
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:57
bool IsEmptyCell(int aRow, int aCol) override
wxString GetColLabelValue(int aCol) override
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:115
Field Name Module PCB, i.e. "16DIP300".
void HighlightItem(EDA_ITEM *aItem, LIB_PIN *aPin=nullptr)
Definition: sch_view.cpp:225
Field Reference of part, i.e. "IC21".
SCH_REFERENCE_LIST is used to create a flattened list of components because in a complex hierarchy,...
wxSize GetTextSize(const wxString &aSingleLine, wxWindow *aWindow)
Return the size of aSingleLine of text when it is rendered in aWindow using whatever font is currentl...
Definition: common.cpp:113
DIALOG_FIELDS_EDITOR_GLOBAL(SCH_EDIT_FRAME *parent)
SCH_FIELD * GetField(int aFieldNdx) const
Returns a field in this symbol.
void OnCancel(wxCommandEvent &event) override
WX_GRID * m_grid
I don't own the grid, but he owns me.
Definition: grid_tricks.h:58
EE_SELECTION & GetSelection()
Function GetSelection()
int RefDesStringCompare(const wxString &aFirst, const wxString &aSecond)
Acts just like the strcmp function but treats numbers within the string text correctly for sorting.
SCH_EDITOR_CONTROL.
wxString GetRef() const
void RebuildRows(wxCheckBox *groupComponentsBox, wxDataViewListCtrl *fieldsCtrl)
TOOL_MANAGER.
Definition: tool_manager.h:50
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Construct a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:79
FIELDS_EDITOR_GRID_DATA_MODEL(SCH_EDIT_FRAME *aFrame, SCH_REFERENCE_LIST &aComponentList)
SCH_ITEM * FindComponentAndItem(const wxString &aReference, bool aSearchHierarchy, SCH_SEARCH_T aSearchType, const wxString &aSearchText)
Finds a component in the schematic and an item in this component.
#define VALUE
void OnSizeFieldList(wxSizeEvent &event) override
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:111
#define NULL
VTBL_ENTRY KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=NULL)
Function Player returns the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:341
int ValueStringCompare(wxString strFWord, wxString strSWord)
Compare strings like the strcmp function but handle numbers and modifiers within the string text corr...
Definition: string.cpp:541
void SyncView()
Mark all items for refresh.
#define INDETERMINATE
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
SCH_SHEET_PATH & GetCurrentSheet()
void SaveCopyInUndoList(SCH_ITEM *aItemToCopy, UNDO_REDO_T aTypeCommand, bool aAppend=false, const wxPoint &aTransformPoint=wxPoint(0, 0))
Create a copy of the current schematic item, and put it in the undo list.
timestamp_t GetTimeStamp() const
Definition: base_struct.h:213
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a field to the symbol.
void OnClose(wxCloseEvent &event) override
void OnTableCellClick(wxGridEvent &event) override
EDA_ITEM * GetParent() const
Definition: base_struct.h:215
void showPopupMenu(wxMenu &menu) override
bool unitMatch(const SCH_REFERENCE &lhRef, const SCH_REFERENCE &rhRef)
SCH_SHEET_PATH.
bool groupMatch(const SCH_REFERENCE &lhRef, const SCH_REFERENCE &rhRef, wxDataViewListCtrl *fieldsCtrl)
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:172
void Sort(int aColumn, bool ascending)
int GetFieldCount() const
Return the number of fields in this symbol.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
const BITMAP_OPAQUE refresh_xpm[1]
Definition: refresh.cpp:32
#define SHOW_FIELD_COLUMN
YYCODETYPE lhs
void OnSaveAndContinue(wxCommandEvent &aEvent) override
void OnRegroupComponents(wxCommandEvent &event) override
wxString GetFieldText(const wxString &aFieldName, SCH_EDIT_FRAME *aFrame) const
Search for a field named aFieldName and returns text associated with this field.
FIELDS_EDITOR_GRID_DATA_MODEL * m_dataModel
virtual void doPopupSelection(wxCommandEvent &event)
#define QUANTITY_COLUMN
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
virtual void showPopupMenu(wxMenu &menu)
void SplitReferences()
Function SplitReferences attempts to split all reference designators into a name (U) and number (1).
#define _(s)
Definition: 3d_actions.cpp:31
#define FIELD_NAME_COLUMN
static bool cmp(const DATA_MODEL_ROW &lhGroup, const DATA_MODEL_ROW &rhGroup, FIELDS_EDITOR_GRID_DATA_MODEL *dataModel, int sortCol, bool ascending)
wxString GetName(bool aUseDefaultName=true) const
Function GetName returns the field name.
Definition: sch_field.cpp:371
SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:89
wxPoint GetPosition() const override
Function GetPosition.
void RemoveField(const wxString &aFieldName)
Removes a user field from the symbol.
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:163
#define COLUMN_MARGIN
Struct TEMPLATE_FIELDNAME holds a name of a component's field, field value, and default visibility.
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
void SetValue(int aRow, int aCol, const wxString &aValue) override
#define GROUP_BY_COLUMN
uint32_t timestamp_t
timestamp_t is our type to represent unique IDs for all kinds of elements; historically simply the ti...
Definition: common.h:52
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current screen and u...
SCH_SHEET * g_RootSheet
const TEMPLATE_FIELDNAMES & GetTemplateFieldNames() const
Return a template field names list for read only access.
Definition for part library class.
void GetComponents(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanComponents=false)
Function GetComponents adds a SCH_REFERENCE() object to aReferences for each component in the list of...
Class DIALOG_FIELDS_EDITOR_GLOBAL_BASE.
wxString GetValue(int aRow, int aCol) override
unsigned GetCount()
Function GetCount.
void OnTableItemContextMenu(wxGridEvent &event) override
void OnTableValueChanged(wxGridEvent &event) override
virtual bool ShowModal(wxString *aResult=NULL, wxWindow *aResultantFocusWindow=NULL)
Function ShowModal puts up this wxFrame as if it were a modal dialog, with all other instantiated wxF...
std::vector< DATA_MODEL_ROW > m_rows
SCH_REFERENCE is used as a helper to define a component's reference designator in a schematic.
wxString GetValue(DATA_MODEL_ROW &group, int aCol)
void OnGroupComponentsToggled(wxCommandEvent &event) override
KICAD_T Type() const
Function Type()
Definition: base_struct.h:207
std::vector< SCH_REFERENCE > GetRowReferences(int aRow)
void AddField(const wxString &aName, bool defaultShow, bool defaultSortBy)