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-2021 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 <base_units.h>
27 #include <bitmaps.h>
28 #include <symbol_library.h>
29 #include <confirm.h>
30 #include <eda_doc.h>
31 #include <eeschema_settings.h>
32 #include <general.h>
33 #include <grid_tricks.h>
34 #include <kicad_string.h>
35 #include <kiface_i.h>
36 #include <refdes_utils.h>
37 #include <sch_edit_frame.h>
38 #include <sch_reference_list.h>
39 #include <schematic.h>
42 #include <widgets/wx_grid.h>
43 #include <wx/grid.h>
44 #include <wx/msgdlg.h>
45 #include <wx/textdlg.h>
46 
48 
49 
50 #define DISPLAY_NAME_COLUMN 0
51 #define SHOW_FIELD_COLUMN 1
52 #define GROUP_BY_COLUMN 2
53 #define CANONICAL_NAME_COLUMN 3
54 
55 #define QUANTITY_COLUMN ( GetNumberCols() - 1 )
56 
57 #ifdef __WXMAC__
58 #define COLUMN_MARGIN 5
59 #else
60 #define COLUMN_MARGIN 15
61 #endif
62 
63 enum
64 {
65  MYID_SELECT_FOOTPRINT = 991, // must be within GRID_TRICKS' enum range
67 };
68 
69 
71 {
72 public:
74  wxDataViewListCtrl* aFieldsCtrl ) :
75  GRID_TRICKS( aGrid ),
76  m_dlg( aParent ),
77  m_fieldsCtrl( aFieldsCtrl )
78  {}
79 
80 protected:
81  void showPopupMenu( wxMenu& menu ) override
82  {
83  if( m_grid->GetGridCursorCol() == FOOTPRINT_FIELD )
84  {
85  menu.Append( MYID_SELECT_FOOTPRINT, _( "Select Footprint..." ),
86  _( "Browse for footprint" ) );
87  menu.AppendSeparator();
88  }
89  else if( m_grid->GetGridCursorCol() == DATASHEET_FIELD )
90  {
91  menu.Append( MYID_SHOW_DATASHEET, _( "Show Datasheet" ),
92  _( "Show datasheet in browser" ) );
93  menu.AppendSeparator();
94  }
95 
97  }
98 
99  void doPopupSelection( wxCommandEvent& event ) override
100  {
101  if( event.GetId() == MYID_SELECT_FOOTPRINT )
102  {
103  // pick a footprint using the footprint picker.
104  wxString fpid = m_grid->GetCellValue( m_grid->GetGridCursorRow(), FOOTPRINT_FIELD );
106 
107  if( frame->ShowModal( &fpid, m_dlg ) )
108  m_grid->SetCellValue( m_grid->GetGridCursorRow(), FOOTPRINT_FIELD, fpid );
109 
110  frame->Destroy();
111  }
112  else if (event.GetId() == MYID_SHOW_DATASHEET )
113  {
114  wxString datasheet_uri = m_grid->GetCellValue( m_grid->GetGridCursorRow(), DATASHEET_FIELD );
115  GetAssociatedDocument( m_dlg, datasheet_uri, &m_dlg->Prj() );
116  }
117  else
118  {
120  }
121 
122  if( event.GetId() >= GRIDTRICKS_FIRST_SHOWHIDE && event.GetId() < GRIDTRICKS_LAST_ID )
123  {
124  if( !m_grid->IsColShown( REFERENCE_FIELD ) )
125  {
126  DisplayError( m_dlg, _( "The Reference column cannot be hidden." ) );
127 
128  m_grid->ShowCol( REFERENCE_FIELD );
129  }
130 
131  // Refresh Show checkboxes from grid columns
132  for( int i = 0; i < m_fieldsCtrl->GetItemCount(); ++i )
133  m_fieldsCtrl->SetToggleValue( m_grid->IsColShown( i ), i, 1 );
134  }
135  }
136 
138  wxDataViewListCtrl* m_fieldsCtrl;
139 };
140 
141 
143 {
149 };
150 
151 
153 {
154  DATA_MODEL_ROW( const SCH_REFERENCE& aFirstReference, GROUP_TYPE aType )
155  {
156  m_Refs.push_back( aFirstReference );
157  m_Flag = aType;
158  }
159 
161  std::vector<SCH_REFERENCE> m_Refs;
162 };
163 
164 
165 class FIELDS_EDITOR_GRID_DATA_MODEL : public wxGridTableBase
166 {
167 protected:
168  // The data model is fundamentally m_componentRefs X m_fieldNames.
169 
172  bool m_edited;
173  std::vector<wxString> m_fieldNames;
176 
177  // However, the grid view can vary in two ways:
178  // 1) the componentRefs can be grouped into fewer rows
179  // 2) some columns can be hidden
180  //
181  // We handle (1) here (ie: a table row maps to a group, and the table is rebuilt
182  // when the groupings change), and we let the wxGrid handle (2) (ie: the number
183  // of columns is constant but are hidden/shown by the wxGrid control).
184 
185  std::vector< DATA_MODEL_ROW > m_rows;
186 
187  // Data store
188  // A map of compID : fieldSet, where fieldSet is a map of fieldName : fieldValue
189  std::map< KIID, std::map<wxString, wxString> > m_dataStore;
190 
191 public:
193  m_frame( aFrame ),
194  m_symbolsList( aSymbolsList ),
195  m_edited( false ),
196  m_sortColumn( 0 ),
197  m_sortAscending( false )
198  {
200  }
201 
202  void AddColumn( const wxString& aFieldName )
203  {
204  m_fieldNames.push_back( aFieldName );
205 
206  for( unsigned i = 0; i < m_symbolsList.GetCount(); ++i )
207  {
208  SCH_SYMBOL* symbol = m_symbolsList[ i ].GetSymbol();
209  m_dataStore[ symbol->m_Uuid ][ aFieldName ] = symbol->GetFieldText( aFieldName,
210  m_frame );
211  }
212  }
213 
214  int GetNumberRows() override { return m_rows.size(); }
215 
216  // Columns are fieldNames + quantity column
217  int GetNumberCols() override { return (int) m_fieldNames.size() + 1; }
218 
219  wxString GetColLabelValue( int aCol ) override
220  {
221  if( aCol == QUANTITY_COLUMN )
222  return _( "Qty" );
223  else if( aCol < MANDATORY_FIELDS )
225  else
226  return m_fieldNames[ aCol ];
227  }
228 
229  wxString GetCanonicalColLabel( int aCol )
230  {
231  if( aCol == QUANTITY_COLUMN )
232  return _( "Qty" );
233  else
234  return m_fieldNames[ aCol ];
235  }
236 
237  bool IsEmptyCell( int aRow, int aCol ) override
238  {
239  return false; // don't allow adjacent cell overflow, even if we are actually empty
240  }
241 
242  wxString GetValue( int aRow, int aCol ) override
243  {
244  if( aCol == REFERENCE_FIELD )
245  {
246  // Poor-man's tree controls
247  if( m_rows[ aRow ].m_Flag == GROUP_COLLAPSED )
248  return wxT( "> " ) + GetValue( m_rows[ aRow ], aCol );
249  else if (m_rows[ aRow ].m_Flag == GROUP_EXPANDED )
250  return wxT( "v " ) + GetValue( m_rows[ aRow ], aCol );
251  else if( m_rows[ aRow ].m_Flag == CHILD_ITEM )
252  return wxT( " " ) + GetValue( m_rows[ aRow ], aCol );
253  else
254  return wxT( " " ) + GetValue( m_rows[ aRow ], aCol );
255  }
256  else
257  {
258  return GetValue( m_rows[ aRow ], aCol );
259  }
260  }
261 
262  std::vector<SCH_REFERENCE> GetRowReferences( int aRow ) const
263  {
264  wxCHECK( aRow < (int)m_rows.size(), std::vector<SCH_REFERENCE>() );
265  return m_rows[ aRow ].m_Refs;
266  }
267 
268  wxString GetValue( const DATA_MODEL_ROW& group, int aCol )
269  {
270  std::vector<SCH_REFERENCE> references;
271  wxString fieldValue;
272 
273  for( const auto& ref : group.m_Refs )
274  {
275  if( aCol == REFERENCE_FIELD || aCol == QUANTITY_COLUMN )
276  {
277  references.push_back( ref );
278  }
279  else // Other columns are either a single value or ROW_MULTI_ITEMS
280  {
281  const KIID& symbolID = ref.GetSymbol()->m_Uuid;
282 
283  if( !m_dataStore.count( symbolID )
284  || !m_dataStore[ symbolID ].count( m_fieldNames[ aCol ] ) )
285  {
286  return INDETERMINATE_STATE;
287  }
288 
289  if( &ref == &group.m_Refs.front() )
290  fieldValue = m_dataStore[ symbolID ][ m_fieldNames[ aCol ] ];
291  else if ( fieldValue != m_dataStore[ symbolID ][ m_fieldNames[ aCol ] ] )
292  return INDETERMINATE_STATE;
293  }
294  }
295 
296  if( aCol == REFERENCE_FIELD || aCol == QUANTITY_COLUMN )
297  {
298  // Remove duplicates (other units of multi-unit parts)
299  std::sort( references.begin(), references.end(),
300  []( const SCH_REFERENCE& l, const SCH_REFERENCE& r ) -> bool
301  {
302  wxString l_ref( l.GetRef() << l.GetRefNumber() );
303  wxString r_ref( r.GetRef() << r.GetRefNumber() );
304  return UTIL::RefDesStringCompare( l_ref, r_ref ) < 0;
305  } );
306 
307  auto logicalEnd = std::unique( references.begin(), references.end(),
308  []( const SCH_REFERENCE& l, const SCH_REFERENCE& r ) -> bool
309  {
310  // If unannotated then we can't tell what units belong together
311  // so we have to leave them all
312  if( l.GetRefNumber() == wxT( "?" ) )
313  return false;
314 
315  wxString l_ref( l.GetRef() << l.GetRefNumber() );
316  wxString r_ref( r.GetRef() << r.GetRefNumber() );
317  return l_ref == r_ref;
318  } );
319 
320  references.erase( logicalEnd, references.end() );
321  }
322 
323  if( aCol == REFERENCE_FIELD )
324  fieldValue = SCH_REFERENCE_LIST::Shorthand( references );
325  else if( aCol == QUANTITY_COLUMN )
326  fieldValue = wxString::Format( wxT( "%d" ), ( int )references.size() );
327 
328  return fieldValue;
329  }
330 
331  void SetValue( int aRow, int aCol, const wxString &aValue ) override
332  {
333  if( aCol == REFERENCE_FIELD || aCol == QUANTITY_COLUMN )
334  return; // Can't modify references or quantity
335 
336  DATA_MODEL_ROW& rowGroup = m_rows[ aRow ];
337  wxString fieldName = m_fieldNames[ aCol ];
338 
339  for( const auto& ref : rowGroup.m_Refs )
340  m_dataStore[ ref.GetSymbol()->m_Uuid ][ fieldName ] = aValue;
341 
342  m_edited = true;
343  }
344 
345  static bool cmp( const DATA_MODEL_ROW& lhGroup, const DATA_MODEL_ROW& rhGroup,
346  FIELDS_EDITOR_GRID_DATA_MODEL* dataModel, int sortCol, bool ascending )
347  {
348  // Empty rows always go to the bottom, whether ascending or descending
349  if( lhGroup.m_Refs.size() == 0 )
350  return true;
351  else if( rhGroup.m_Refs.size() == 0 )
352  return false;
353 
354  // N.B. To meet the iterator sort conditions, we cannot simply invert the truth
355  // to get the opposite sort. i.e. ~(a<b) != (a>b)
356  auto local_cmp =
357  [ ascending ]( const auto a, const auto b )
358  {
359  if( ascending )
360  return a < b;
361  else
362  return a > b;
363  };
364 
365  // Primary sort key is sortCol; secondary is always REFERENCE (column 0)
366 
367  wxString lhs = dataModel->GetValue( (DATA_MODEL_ROW&) lhGroup, sortCol );
368  wxString rhs = dataModel->GetValue( (DATA_MODEL_ROW&) rhGroup, sortCol );
369 
370  if( lhs == rhs || sortCol == REFERENCE_FIELD )
371  {
372  wxString lhRef = lhGroup.m_Refs[ 0 ].GetRef() + lhGroup.m_Refs[ 0 ].GetRefNumber();
373  wxString rhRef = rhGroup.m_Refs[ 0 ].GetRef() + rhGroup.m_Refs[ 0 ].GetRefNumber();
374  return local_cmp( UTIL::RefDesStringCompare( lhRef, rhRef ), 0 );
375  }
376  else
377  {
378  return local_cmp( ValueStringCompare( lhs, rhs ), 0 );
379  }
380  }
381 
382  void Sort( int aColumn, bool ascending )
383  {
384  if( aColumn < 0 )
385  aColumn = 0;
386 
387  m_sortColumn = aColumn;
388  m_sortAscending = ascending;
389 
390  CollapseForSort();
391 
392  std::sort( m_rows.begin(), m_rows.end(),
393  [ this ]( const DATA_MODEL_ROW& lhs, const DATA_MODEL_ROW& rhs ) -> bool
394  {
395  return cmp( lhs, rhs, this, m_sortColumn, m_sortAscending );
396  } );
397 
398  ExpandAfterSort();
399  }
400 
401  bool unitMatch( const SCH_REFERENCE& lhRef, const SCH_REFERENCE& rhRef )
402  {
403  // If items are unannotated then we can't tell if they're units of the same symbol or not
404  if( lhRef.GetRefNumber() == wxT( "?" ) )
405  return false;
406 
407  return ( lhRef.GetRef() == rhRef.GetRef() && lhRef.GetRefNumber() == rhRef.GetRefNumber() );
408  }
409 
410  bool groupMatch( const SCH_REFERENCE& lhRef, const SCH_REFERENCE& rhRef,
411  wxDataViewListCtrl* fieldsCtrl )
412  {
413  bool matchFound = false;
414 
415  // First check the reference column. This can be done directly out of the
416  // SCH_REFERENCEs as the references can't be edited in the grid.
417  if( fieldsCtrl->GetToggleValue( REFERENCE_FIELD, GROUP_BY_COLUMN ) )
418  {
419  // if we're grouping by reference, then only the prefix must match
420  if( lhRef.GetRef() != rhRef.GetRef() )
421  return false;
422 
423  matchFound = true;
424  }
425 
426  const KIID& lhRefID = lhRef.GetSymbol()->m_Uuid;
427  const KIID& rhRefID = rhRef.GetSymbol()->m_Uuid;
428 
429  // Now check all the other columns. This must be done out of the dataStore
430  // for the refresh button to work after editing.
431  for( int i = REFERENCE_FIELD + 1; i < fieldsCtrl->GetItemCount(); ++i )
432  {
433  if( !fieldsCtrl->GetToggleValue( i, GROUP_BY_COLUMN ) )
434  continue;
435 
436  wxString fieldName = fieldsCtrl->GetTextValue( i, CANONICAL_NAME_COLUMN );
437 
438  if( m_dataStore[ lhRefID ][ fieldName ] != m_dataStore[ rhRefID ][ fieldName ] )
439  return false;
440 
441  matchFound = true;
442  }
443 
444  return matchFound;
445  }
446 
447  void RebuildRows( wxCheckBox* aGroupSymbolsBox, wxDataViewListCtrl* aFieldsCtrl )
448  {
449  if ( GetView() )
450  {
451  // Commit any pending in-place edits before the row gets moved out from under
452  // the editor.
453  static_cast<WX_GRID*>( GetView() )->CommitPendingChanges( true );
454 
455  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, 0, m_rows.size() );
456  GetView()->ProcessTableMessage( msg );
457  }
458 
459  m_rows.clear();
460 
461  for( unsigned i = 0; i < m_symbolsList.GetCount(); ++i )
462  {
463  SCH_REFERENCE ref = m_symbolsList[ i ];
464  bool matchFound = false;
465 
466  // See if we already have a row which this symbol fits into
467  for( DATA_MODEL_ROW& row : m_rows )
468  {
469  // all group members must have identical refs so just use the first one
470  SCH_REFERENCE rowRef = row.m_Refs[ 0 ];
471 
472  if( unitMatch( ref, rowRef ) )
473  {
474  matchFound = true;
475  row.m_Refs.push_back( ref );
476  break;
477  }
478  else if ( aGroupSymbolsBox->GetValue() && groupMatch( ref, rowRef, aFieldsCtrl ) )
479  {
480  matchFound = true;
481  row.m_Refs.push_back( ref );
482  row.m_Flag = GROUP_COLLAPSED;
483  break;
484  }
485  }
486 
487  if( !matchFound )
488  m_rows.emplace_back( DATA_MODEL_ROW( ref, GROUP_SINGLETON ) );
489  }
490 
491  if ( GetView() )
492  {
493  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_rows.size() );
494  GetView()->ProcessTableMessage( msg );
495  }
496  }
497 
498  void ExpandRow( int aRow )
499  {
500  std::vector<DATA_MODEL_ROW> children;
501 
502  for( SCH_REFERENCE& ref : m_rows[ aRow ].m_Refs )
503  {
504  bool matchFound = false;
505 
506  // See if we already have a child group which this symbol fits into
507  for( DATA_MODEL_ROW& child : children )
508  {
509  // group members are by definition all matching, so just check
510  // against the first member
511  if( unitMatch( ref, child.m_Refs[ 0 ] ) )
512  {
513  matchFound = true;
514  child.m_Refs.push_back( ref );
515  break;
516  }
517  }
518 
519  if( !matchFound )
520  children.emplace_back( DATA_MODEL_ROW( ref, CHILD_ITEM ) );
521  }
522 
523  if( children.size() < 2 )
524  return;
525 
526  std::sort( children.begin(), children.end(),
527  [ this ] ( const DATA_MODEL_ROW& lhs, const DATA_MODEL_ROW& rhs ) -> bool
528  {
529  return cmp( lhs, rhs, this, m_sortColumn, m_sortAscending );
530  } );
531 
532  m_rows[ aRow ].m_Flag = GROUP_EXPANDED;
533  m_rows.insert( m_rows.begin() + aRow + 1, children.begin(), children.end() );
534 
535  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_INSERTED, aRow, children.size() );
536  GetView()->ProcessTableMessage( msg );
537  }
538 
539  void CollapseRow( int aRow )
540  {
541  auto firstChild = m_rows.begin() + aRow + 1;
542  auto afterLastChild = firstChild;
543  int deleted = 0;
544 
545  while( afterLastChild != m_rows.end() && afterLastChild->m_Flag == CHILD_ITEM )
546  {
547  deleted++;
548  afterLastChild++;
549  }
550 
551  m_rows[ aRow ].m_Flag = GROUP_COLLAPSED;
552  m_rows.erase( firstChild, afterLastChild );
553 
554  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, aRow + 1, deleted );
555  GetView()->ProcessTableMessage( msg );
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 
569  {
570  for( size_t i = 0; i < m_rows.size(); ++i )
571  {
572  if( m_rows[ i ].m_Flag == GROUP_EXPANDED )
573  {
574  CollapseRow( i );
575  m_rows[ i ].m_Flag = GROUP_COLLAPSED_DURING_SORT;
576  }
577  }
578  }
579 
581  {
582  for( size_t i = 0; i < m_rows.size(); ++i )
583  {
584  if( m_rows[ i ].m_Flag == GROUP_COLLAPSED_DURING_SORT )
585  ExpandRow( i );
586  }
587  }
588 
589  void ApplyData()
590  {
591  for( unsigned i = 0; i < m_symbolsList.GetCount(); ++i )
592  {
593  SCH_SYMBOL& symbol = *m_symbolsList[ i ].GetSymbol();
594  SCH_SCREEN* screen = m_symbolsList[i].GetSheetPath().LastScreen();
595 
596  m_frame->SaveCopyInUndoList( screen, &symbol, UNDO_REDO::CHANGED, true );
597 
598  const std::map<wxString, wxString>& fieldStore = m_dataStore[symbol.m_Uuid];
599 
600  for( const std::pair<wxString, wxString> srcData : fieldStore )
601  {
602  const wxString& srcName = srcData.first;
603  const wxString& srcValue = srcData.second;
604  SCH_FIELD* destField = symbol.FindField( srcName );
605 
606  if( !destField && !srcValue.IsEmpty() )
607  {
608  const wxPoint symbolPos = symbol.GetPosition();
609  destField = symbol.AddField( SCH_FIELD( symbolPos, -1, &symbol, srcName ) );
610  }
611 
612  if( !destField )
613  {
614  symbol.RemoveField( srcName );
615  }
616  else if( destField->GetId() == REFERENCE_FIELD )
617  {
618  // Reference is not editable
619  }
620  else if( destField->GetId() == VALUE_FIELD )
621  {
622  // Value field cannot be empty
623  if( !srcValue.IsEmpty() )
624  symbol.SetValue( srcValue );
625  }
626  else if( destField->GetId() == FOOTPRINT_FIELD )
627  {
628  symbol.SetFootprint( srcValue );
629  }
630  else
631  {
632  destField->SetText( srcValue );
633  }
634  }
635  }
636 
637  m_edited = false;
638  }
639 
640  int GetDataWidth( int aCol )
641  {
642  int width = 0;
643 
644  if( aCol == REFERENCE_FIELD )
645  {
646  for( int row = 0; row < GetNumberRows(); ++row )
647  width = std::max( width, KIUI::GetTextSize( GetValue( row, aCol ), GetView() ).x );
648  }
649  else
650  {
651  wxString column_label = GetColLabelValue( aCol ); // symbol fieldName or Qty string
652 
653  for( unsigned symbolRef = 0; symbolRef < m_symbolsList.GetCount(); ++ symbolRef )
654  {
655  const KIID& symbolID = m_symbolsList[ symbolRef ].GetSymbol()->m_Uuid;
656  wxString text = m_dataStore[ symbolID ][ column_label ];
657 
658  width = std::max( width, KIUI::GetTextSize( text, GetView() ).x );
659  }
660  }
661 
662  return width;
663  }
664 
665 
666  bool IsEdited()
667  {
668  return m_edited;
669  }
670 };
671 
672 
675  m_parent( parent )
676 {
677  wxSize defaultDlgSize = ConvertDialogToPixels( wxSize( 600, 300 ) );
678 
679  // Get all symbols from the list of schematic sheets
681 
682  m_bRefresh->SetBitmap( KiBitmap( BITMAPS::small_refresh ) );
683 
684  m_fieldsCtrl->AppendTextColumn( _( "Field" ), wxDATAVIEW_CELL_INERT, 0, wxALIGN_LEFT, 0 );
685  m_fieldsCtrl->AppendToggleColumn( _( "Show" ), wxDATAVIEW_CELL_ACTIVATABLE, 0,
686  wxALIGN_CENTER, 0 );
687  m_fieldsCtrl->AppendToggleColumn( _( "Group By" ), wxDATAVIEW_CELL_ACTIVATABLE, 0,
688  wxALIGN_CENTER, 0 );
689 
690  // GTK asserts if the number of columns doesn't match the data, but we still don't want
691  // to display the canonical names. So we'll insert a column for them, but keep it 0 width.
692  m_fieldsCtrl->AppendTextColumn( _( "Name" ), wxDATAVIEW_CELL_INERT, 0, wxALIGN_LEFT, 0 );
693 
694  // SetWidth( wxCOL_WIDTH_AUTOSIZE ) fails here on GTK, so we calculate the title sizes and
695  // set the column widths ourselves.
696  wxDataViewColumn* column = m_fieldsCtrl->GetColumn( SHOW_FIELD_COLUMN );
697  m_showColWidth = KIUI::GetTextSize( column->GetTitle(), m_fieldsCtrl ).x + COLUMN_MARGIN;
698  column->SetMinWidth( m_showColWidth );
699 
700  column = m_fieldsCtrl->GetColumn( GROUP_BY_COLUMN );
701  m_groupByColWidth = KIUI::GetTextSize( column->GetTitle(), m_fieldsCtrl ).x + COLUMN_MARGIN;
702  column->SetMinWidth( m_groupByColWidth );
703 
704  // The fact that we're a list should keep the control from reserving space for the
705  // expander buttons... but it doesn't. Fix by forcing the indent to 0.
706  m_fieldsCtrl->SetIndent( 0 );
707 
709 
710  LoadFieldNames(); // loads rows into m_fieldsCtrl and columns into m_dataModel
711 
712  // Now that the fields are loaded we can set the initial location of the splitter
713  // based on the list width. Again, SetWidth( wxCOL_WIDTH_AUTOSIZE ) fails us on GTK.
714  int nameColWidth = 0;
715 
716  for( int row = 0; row < m_fieldsCtrl->GetItemCount(); ++row )
717  {
718  const wxString& fieldName = m_fieldsCtrl->GetTextValue( row, DISPLAY_NAME_COLUMN );
719  nameColWidth = std::max( nameColWidth, KIUI::GetTextSize( fieldName, m_fieldsCtrl ).x );
720  }
721 
722  int fieldsMinWidth = nameColWidth + m_groupByColWidth + m_showColWidth;
723 
724  m_fieldsCtrl->GetColumn( DISPLAY_NAME_COLUMN )->SetWidth( nameColWidth );
725 
726  // This is used for data only. Don't show it to the user.
727  m_fieldsCtrl->GetColumn( CANONICAL_NAME_COLUMN )->SetWidth( 0 );
728 
729  m_splitterMainWindow->SetMinimumPaneSize( fieldsMinWidth );
730  m_splitterMainWindow->SetSashPosition( fieldsMinWidth + 40 );
731 
733  m_dataModel->Sort( 0, true );
734 
735  // wxGrid's column moving is buggy with native headers and this is one dialog where you'd
736  // really like to be able to rearrange columns.
737  m_grid->UseNativeColHeader( false );
738  m_grid->SetTable( m_dataModel, true );
739 
740  // must be done after SetTable(), which appears to re-set it
741  m_grid->SetSelectionMode( wxGrid::wxGridSelectCells );
742 
743  // sync m_grid's column visibilities to Show checkboxes in m_fieldsCtrl
744  for( int i = 0; i < m_fieldsCtrl->GetItemCount(); ++i )
745  {
746  if( m_fieldsCtrl->GetToggleValue( i, 1 ) )
747  m_grid->ShowCol( i );
748  else
749  m_grid->HideCol( i );
750  }
751 
752  // add Cut, Copy, and Paste to wxGrid
753  m_grid->PushEventHandler( new FIELDS_EDITOR_GRID_TRICKS( this, m_grid, m_fieldsCtrl ) );
754 
755  // give a bit more room for comboboxes
756  m_grid->SetDefaultRowSize( m_grid->GetDefaultRowSize() + 4 );
757 
758  // set reference column attributes
759  wxGridCellAttr* attr = new wxGridCellAttr;
760  attr->SetReadOnly();
761  m_grid->SetColAttr( REFERENCE_FIELD, attr );
762 
763  // set footprint column browse button
764  attr = new wxGridCellAttr;
765  attr->SetEditor( new GRID_CELL_FOOTPRINT_ID_EDITOR( this ) );
766  m_grid->SetColAttr( FOOTPRINT_FIELD, attr );
767 
768  // set datasheet column viewer button
769  attr = new wxGridCellAttr;
770  attr->SetEditor( new GRID_CELL_URL_EDITOR( this ) );
771  m_grid->SetColAttr( DATASHEET_FIELD, attr );
772 
773  // set quantities column attributes
774  attr = new wxGridCellAttr;
775  attr->SetReadOnly();
776  m_grid->SetColAttr( m_dataModel->GetColsCount() - 1, attr );
777  m_grid->SetColFormatNumber( m_dataModel->GetColsCount() - 1 );
778  m_grid->AutoSizeColumns( false );
779 
780  for( int col = 0; col < m_grid->GetNumberCols(); ++col )
781  {
782  // Columns are hidden by setting their width to 0 so if we resize them they will
783  // become unhidden.
784  if( m_grid->IsColShown( col ) )
785  {
786  EESCHEMA_SETTINGS* cfg = static_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
787  std::string key( m_dataModel->GetCanonicalColLabel( col ).ToUTF8() );
788 
789  if( cfg->m_FieldEditorPanel.column_widths.count( key ) )
790  {
791  int width = cfg->m_FieldEditorPanel.column_widths.at( key );
792  m_grid->SetColSize( col, width );
793  }
794  else
795  {
796  int textWidth = m_dataModel->GetDataWidth( col ) + COLUMN_MARGIN;
797  int maxWidth = defaultDlgSize.x / 3;
798 
799  if( col == m_grid->GetNumberCols() - 1 )
800  m_grid->SetColSize( col, std::min( std::max( 50, textWidth ), maxWidth ) );
801  else
802  m_grid->SetColSize( col, std::min( std::max( 100, textWidth ), maxWidth ) );
803  }
804  }
805  }
806 
807  m_grid->SelectRow( 0 );
808  m_grid->SetGridCursor( 0, 1 );
810 
811  m_sdbSizerOK->SetDefault();
812 
814  SetSize( defaultDlgSize );
815  Center();
816 
817  // Connect Events
818  m_grid->Connect( wxEVT_GRID_COL_SORT,
819  wxGridEventHandler( DIALOG_FIELDS_EDITOR_GLOBAL::OnColSort ), NULL, this );
820 }
821 
822 
824 {
825  // Disconnect Events
826  m_grid->Disconnect( wxEVT_GRID_COL_SORT,
827  wxGridEventHandler( DIALOG_FIELDS_EDITOR_GLOBAL::OnColSort ), NULL, this );
828 
829  // Delete the GRID_TRICKS.
830  m_grid->PopEventHandler( true );
831 
832  // we gave ownership of m_dataModel to the wxGrid...
833 }
834 
835 
837 {
838  if( !wxDialog::TransferDataFromWindow() )
839  return false;
840 
841  TOOL_MANAGER* toolMgr = m_parent->GetToolManager();
842  EE_SELECTION_TOOL* selectionTool = toolMgr->GetTool<EE_SELECTION_TOOL>();
843  EE_SELECTION& selection = selectionTool->GetSelection();
844  SCH_SYMBOL* symbol = nullptr;
845 
846  if( selection.GetSize() == 1 )
847  {
848  EDA_ITEM* item = selection.Front();
849 
850  if( item->Type() == SCH_SYMBOL_T )
851  symbol = (SCH_SYMBOL*) item;
852  else if( item->GetParent() && item->GetParent()->Type() == SCH_SYMBOL_T )
853  symbol = (SCH_SYMBOL*) item->GetParent();
854  }
855 
856  if( symbol )
857  {
858  for( int row = 0; row < m_dataModel->GetNumberRows(); ++row )
859  {
860  std::vector<SCH_REFERENCE> references = m_dataModel->GetRowReferences( row );
861  bool found = false;
862 
863  for( const SCH_REFERENCE& ref : references )
864  {
865  if( ref.GetSymbol() == symbol )
866  {
867  found = true;
868  break;
869  }
870  }
871 
872  if( found )
873  {
874  m_grid->GoToCell( row, 1 );
875  break;
876  }
877  }
878  }
879 
880  return true;
881 }
882 
883 
885 {
886  if( !m_grid->CommitPendingChanges() )
887  return false;
888 
889  if( !wxDialog::TransferDataFromWindow() )
890  return false;
891 
892  SCH_SHEET_PATH currentSheet = m_parent->GetCurrentSheet();
893 
895 
896  // Reset the view to where we left the user
897  m_parent->SetCurrentSheet( currentSheet );
898  m_parent->SyncView();
899  m_parent->Refresh();
900 
901  m_parent->OnModify();
902 
903  return true;
904 }
905 
906 
907 void DIALOG_FIELDS_EDITOR_GLOBAL::AddField( const wxString& aDisplayName,
908  const wxString& aCanonicalName,
909  bool defaultShow, bool defaultSortBy )
910 {
911  m_dataModel->AddColumn( aCanonicalName );
912 
913  wxVector<wxVariant> fieldsCtrlRow;
914 
915  EESCHEMA_SETTINGS* cfg = static_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
916  bool show = defaultShow;
917  bool sort_by = defaultSortBy;
918 
919  std::string key( aCanonicalName.ToUTF8() );
920 
921  if( cfg->m_FieldEditorPanel.fields_show.count( key ) )
922  show = cfg->m_FieldEditorPanel.fields_show.at( key );
923 
924  if( cfg->m_FieldEditorPanel.fields_group_by.count( key ) )
925  sort_by = cfg->m_FieldEditorPanel.fields_group_by.at( key );
926 
927  // Don't change these to emplace_back: some versions of wxWidgets don't support it
928  fieldsCtrlRow.push_back( wxVariant( aDisplayName ) );
929  fieldsCtrlRow.push_back( wxVariant( show ) );
930  fieldsCtrlRow.push_back( wxVariant( sort_by ) );
931  fieldsCtrlRow.push_back( wxVariant( aCanonicalName ) );
932 
933  m_fieldsCtrl->AppendItem( fieldsCtrlRow );
934 }
935 
936 
942 {
943  std::set<wxString> userFieldNames;
944 
945  for( unsigned i = 0; i < m_symbolsList.GetCount(); ++i )
946  {
947  SCH_SYMBOL* symbol = m_symbolsList[ i ].GetSymbol();
948 
949  for( int j = MANDATORY_FIELDS; j < symbol->GetFieldCount(); ++j )
950  userFieldNames.insert( symbol->GetFields()[j].GetName() );
951  }
952 
953  // Force References to always be shown
954  auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
955  wxCHECK( cfg, /*void*/ );
956 
957  cfg->m_FieldEditorPanel.fields_show["Reference"] = true;
958 
959  AddField( _( "Reference" ), wxT( "Reference" ), true, true );
960  AddField( _( "Value" ), wxT( "Value" ), true, true );
961  AddField( _( "Footprint" ), wxT( "Footprint" ), true, true );
962  AddField( _( "Datasheet" ), wxT( "Datasheet" ), true, false );
963 
964  for( const wxString& fieldName : userFieldNames )
965  AddField( fieldName, fieldName, true, false );
966 
967  // Add any templateFieldNames which aren't already present in the userFieldNames
968  for( const TEMPLATE_FIELDNAME& templateFieldname :
970  {
971  if( userFieldNames.count( templateFieldname.m_Name ) == 0 )
972  AddField( templateFieldname.m_Name, templateFieldname.m_Name, false, false );
973  }
974 }
975 
976 
977 void DIALOG_FIELDS_EDITOR_GLOBAL::OnAddField( wxCommandEvent& event )
978 {
979  // quantities column will become new field column, so it needs to be reset
980  auto attr = new wxGridCellAttr;
981  m_grid->SetColAttr( m_dataModel->GetColsCount() - 1, attr );
982  m_grid->SetColFormatCustom( m_dataModel->GetColsCount() - 1, wxGRID_VALUE_STRING );
983 
984  wxTextEntryDialog dlg( this, _( "New field name:" ), _( "Add Field" ) );
985 
986  if( dlg.ShowModal() != wxID_OK )
987  return;
988 
989  wxString fieldName = dlg.GetValue();
990 
991  if( fieldName.IsEmpty() )
992  {
993  DisplayError( this, _( "Field must have a name." ) );
994  return;
995  }
996 
997  for( int i = 0; i < m_dataModel->GetNumberCols(); ++i )
998  {
999  if( fieldName == m_dataModel->GetColLabelValue( i ) )
1000  {
1001  DisplayError( this, wxString::Format( _( "Field name \"%s\" already in use." ),
1002  fieldName ) );
1003  return;
1004  }
1005  }
1006 
1007  std::string key( fieldName.ToUTF8() );
1008 
1009  auto cfg = static_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
1010  cfg->m_FieldEditorPanel.fields_show[key] = true;
1011 
1012  AddField( fieldName, fieldName, true, false );
1013 
1014  wxGridTableMessage msg( m_dataModel, wxGRIDTABLE_NOTIFY_COLS_INSERTED,
1015  m_fieldsCtrl->GetItemCount(), 1 );
1016  m_grid->ProcessTableMessage( msg );
1017 
1018  // set up attributes on the new quantities column
1019  attr = new wxGridCellAttr;
1020  attr->SetReadOnly();
1021  m_grid->SetColAttr( m_dataModel->GetColsCount() - 1, attr );
1022  m_grid->SetColFormatNumber( m_dataModel->GetColsCount() - 1 );
1023  m_grid->SetColSize( m_dataModel->GetColsCount() - 1, 50 );
1024 }
1025 
1026 
1028 {
1029  EESCHEMA_SETTINGS* cfg = static_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
1030  wxDataViewItem item = event.GetItem();
1031 
1032  int row = m_fieldsCtrl->ItemToRow( item );
1033  int col = event.GetColumn();
1034 
1035  switch ( col )
1036  {
1037  case SHOW_FIELD_COLUMN:
1038  {
1039  bool value = m_fieldsCtrl->GetToggleValue( row, col );
1040 
1041  if( row == REFERENCE_FIELD && !value )
1042  {
1043  DisplayError( this, _( "The Reference column cannot be hidden." ) );
1044 
1045  value = true;
1046  m_fieldsCtrl->SetToggleValue( value, row, col );
1047  }
1048 
1049  std::string fieldName( m_fieldsCtrl->GetTextValue( row, CANONICAL_NAME_COLUMN ).ToUTF8() );
1050  cfg->m_FieldEditorPanel.fields_show[fieldName] = value;
1051 
1052  if( value )
1053  m_grid->ShowCol( row );
1054  else
1055  m_grid->HideCol( row ); // grid's columns map to fieldsCtrl's rows
1056 
1057  break;
1058  }
1059 
1060  case GROUP_BY_COLUMN:
1061  {
1062  bool value = m_fieldsCtrl->GetToggleValue( row, col );
1063  std::string fieldName( m_fieldsCtrl->GetTextValue( row, CANONICAL_NAME_COLUMN ).ToUTF8() );
1064  cfg->m_FieldEditorPanel.fields_group_by[fieldName] = value;
1065 
1067  m_dataModel->Sort( m_grid->GetSortingColumn(), m_grid->IsSortOrderAscending() );
1068  m_grid->ForceRefresh();
1069  break;
1070  }
1071 
1072  default:
1073  break;
1074  }
1075 }
1076 
1077 
1079 {
1081  m_dataModel->Sort( m_grid->GetSortingColumn(), m_grid->IsSortOrderAscending() );
1082  m_grid->ForceRefresh();
1083 }
1084 
1085 
1086 void DIALOG_FIELDS_EDITOR_GLOBAL::OnColSort( wxGridEvent& aEvent )
1087 {
1088  int sortCol = aEvent.GetCol();
1089  bool ascending;
1090 
1091  // This is bonkers, but wxWidgets doesn't tell us ascending/descending in the event, and
1092  // if we ask it will give us pre-event info.
1093  if( m_grid->IsSortingBy( sortCol ) )
1094  {
1095  // same column; invert ascending
1096  ascending = !m_grid->IsSortOrderAscending();
1097  }
1098  else
1099  {
1100  // different column; start with ascending
1101  ascending = true;
1102  }
1103 
1104  m_dataModel->Sort( sortCol, ascending );
1105  m_grid->ForceRefresh();
1106 }
1107 
1108 
1110 {
1111  m_grid->ForceRefresh();
1112 }
1113 
1114 
1115 void DIALOG_FIELDS_EDITOR_GLOBAL::OnTableColSize( wxGridSizeEvent& aEvent )
1116 {
1117  EESCHEMA_SETTINGS* cfg = static_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
1118  int col = aEvent.GetRowOrCol();
1119  std::string key( m_dataModel->GetCanonicalColLabel( col ).ToUTF8() );
1120 
1121  if( m_grid->GetColSize( col ) )
1122  cfg->m_FieldEditorPanel.column_widths[ key ] = m_grid->GetColSize( col );
1123 
1124  aEvent.Skip();
1125 }
1126 
1127 
1129 {
1131  m_dataModel->Sort( m_grid->GetSortingColumn(), m_grid->IsSortOrderAscending() );
1132  m_grid->ForceRefresh();
1133 }
1134 
1135 
1137 {
1138  if( event.GetCol() == REFERENCE_FIELD )
1139  {
1140  m_grid->ClearSelection();
1141  m_grid->SetGridCursor( event.GetRow(), event.GetCol() );
1142 
1143  m_dataModel->ExpandCollapseRow( event.GetRow() );
1144  std::vector<SCH_REFERENCE> refs = m_dataModel->GetRowReferences( event.GetRow() );
1145 
1146  // Focus Eeschema view on the symbol selected in the dialog
1147  if( refs.size() == 1 )
1148  {
1150 
1151  editor->FindSymbolAndItem( refs[ 0 ].GetRef() + refs[ 0 ].GetRefNumber(), true,
1152  HIGHLIGHT_SYMBOL, wxEmptyString );
1153  }
1154  }
1155  else
1156  {
1157  event.Skip();
1158  }
1159 }
1160 
1161 
1163 {
1164  // TODO: Option to select footprint if FOOTPRINT column selected
1165 
1166  event.Skip();
1167 }
1168 
1169 
1171 {
1172  int nameColWidth = event.GetSize().GetX() - m_showColWidth - m_groupByColWidth - 8;
1173 
1174  // GTK loses its head and messes these up when resizing the splitter bar:
1175  m_fieldsCtrl->GetColumn( SHOW_FIELD_COLUMN )->SetWidth( m_showColWidth );
1176  m_fieldsCtrl->GetColumn( GROUP_BY_COLUMN )->SetWidth( m_groupByColWidth );
1177 
1178  m_fieldsCtrl->GetColumn( CANONICAL_NAME_COLUMN )->SetWidth( 0 );
1179  m_fieldsCtrl->GetColumn( DISPLAY_NAME_COLUMN )->SetWidth( nameColWidth );
1180 
1181  event.Skip();
1182 }
1183 
1184 
1186 {
1187  if( TransferDataFromWindow() )
1188  m_parent->SaveProject();
1189 }
1190 
1191 
1192 void DIALOG_FIELDS_EDITOR_GLOBAL::OnCancel( wxCommandEvent& event )
1193 {
1194  Close();
1195 }
1196 
1197 
1198 void DIALOG_FIELDS_EDITOR_GLOBAL::OnClose( wxCloseEvent& event )
1199 {
1200  // This is a cancel, so commit quietly as we're going to throw the results away anyway.
1201  m_grid->CommitPendingChanges( true );
1202 
1203  if( m_dataModel->IsEdited() )
1204  {
1205  if( !HandleUnsavedChanges( this, _( "Save changes?" ),
1206  [&]()->bool
1207  {
1208  return TransferDataFromWindow();
1209  } ) )
1210  {
1211  event.Veto();
1212  return;
1213  }
1214  }
1215 
1216  event.Skip();
1217 }
Field Reference of part, i.e. "IC21".
void SetCurrentSheet(const SCH_SHEET_PATH &aSheet)
virtual bool ShowModal(wxString *aResult=nullptr, wxWindow *aResultantFocusWindow=nullptr)
Show this wxFrame as if it were a modal dialog, with all other instantiated wxFrames disabled until t...
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:252
void doPopupSelection(wxCommandEvent &event) override
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:49
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:207
bool GetAssociatedDocument(wxWindow *aParent, const wxString &aDocName, PROJECT *aProject)
Open a document (file) with the suitable browser.
Definition: eda_doc.cpp:79
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Definition: kiway_player.h:64
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:53
void OnColumnItemToggled(wxDataViewEvent &event) override
void AddColumn(const wxString &aFieldName)
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
void GetSymbols(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets.
Implementation of conversion functions that require both schematic and board internal units.
This file is part of the common library.
wxString GetValue(const DATA_MODEL_ROW &group, int aCol)
This file is part of the common library.
FIELDS_EDITOR_GRID_TRICKS(DIALOG_SHIM *aParent, WX_GRID *aGrid, wxDataViewListCtrl *aFieldsCtrl)
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:129
void SetValue(const SCH_SHEET_PATH *sheet, const wxString &aValue)
Definition: sch_symbol.cpp:584
std::map< KIID, std::map< wxString, wxString > > m_dataStore
TEMPLATES m_TemplateFieldNames
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:701
void OnAddField(wxCommandEvent &event) override
Collection of utility functions for component reference designators (refdes)
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition: grid_tricks.h:52
int GetId() const
Definition: sch_field.h:113
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:373
Schematic editor (Eeschema) main window.
static wxString Shorthand(std::vector< SCH_REFERENCE > aList)
Return a shorthand string representing all the references in the list.
void AddField(const wxString &displayName, const wxString &aCanonicalName, bool defaultShow, bool defaultSortBy)
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition: dialog_shim.h:82
SCH_SYMBOL * GetSymbol() const
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:65
bool IsEmptyCell(int aRow, int aCol) override
void SetFootprint(const SCH_SHEET_PATH *sheet, const wxString &aFootprint)
Definition: sch_symbol.cpp:635
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:97
std::vector< SCH_REFERENCE > GetRowReferences(int aRow) const
void OnGroupSymbolsToggled(wxCommandEvent &event) override
name of datasheet
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
DIALOG_FIELDS_EDITOR_GLOBAL(SCH_EDIT_FRAME *parent)
void OnCancel(wxCommandEvent &event) override
PANEL_FIELD_EDITOR m_FieldEditorPanel
WX_GRID * m_grid
I don't own the grid, but he owns me.
Definition: grid_tricks.h:81
EE_SELECTION & GetSelection()
Return the set of currently selected items.
int RefDesStringCompare(const wxString &aFirst, const wxString &aSecond)
Acts just like the strcmp function but treats numbers within the string text correctly for sorting.
Handle actions specific to the schematic editor.
wxString GetRef() const
Master controller class:
Definition: tool_manager.h:54
void OnRegroupSymbols(wxCommandEvent &aEvent) override
FIELDS_EDITOR_GRID_DATA_MODEL(SCH_EDIT_FRAME *aFrame, SCH_REFERENCE_LIST &aSymbolsList)
Definition: kiid.h:44
void OnSizeFieldList(wxSizeEvent &event) override
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a field to the symbol.
Definition: sch_symbol.cpp:711
Field Value of part, i.e. "3.3K".
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:114
#define NULL
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:695
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: ui_common.cpp:59
void SyncView()
Mark all items for refresh.
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: sch_symbol.h:421
SCHEMATIC & Schematic() const
void OnClose(wxCloseEvent &event) override
void OnTableCellClick(wxGridEvent &event) override
size_t GetCount() const
Definition for symbol library class.
EDA_ITEM * GetParent() const
Definition: eda_item.h:115
void showPopupMenu(wxMenu &menu) override
#define _(s)
bool unitMatch(const SCH_REFERENCE &lhRef, const SCH_REFERENCE &rhRef)
static const wxString GetDefaultFieldName(int aFieldNdx, bool aTranslate=true)
Return a default symbol field name for field aFieldNdx for all components.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
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:182
void Sort(int aColumn, bool ascending)
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
std::map< std::string, int > column_widths
SCH_FIELD * FindField(const wxString &aFieldName, bool aIncludeDefaultFields=true)
Search for a SCH_FIELD with aFieldName.
Definition: sch_symbol.cpp:733
wxString GetFieldText(const wxString &aFieldName, SCH_EDIT_FRAME *aFrame) const
Search for a field named aFieldName and returns text associated with this field.
Definition: sch_symbol.cpp:689
#define SHOW_FIELD_COLUMN
const KIID m_Uuid
Definition: eda_item.h:475
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
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...
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:87
void OnSaveAndContinue(wxCommandEvent &aEvent) override
void RebuildRows(wxCheckBox *aGroupSymbolsBox, wxDataViewListCtrl *aFieldsCtrl)
FIELDS_EDITOR_GRID_DATA_MODEL * m_dataModel
virtual void doPopupSelection(wxCommandEvent &event)
#define QUANTITY_COLUMN
Schematic symbol object.
Definition: sch_symbol.h:78
virtual void showPopupMenu(wxMenu &menu)
void SplitReferences()
Attempt to split all reference designators into a name (U) and number (1).
void SaveCopyInUndoList(SCH_SCREEN *aScreen, SCH_ITEM *aItemToCopy, UNDO_REDO aTypeCommand, bool aAppend)
Create a copy of the current schematic item, and put it in the undo list.
static bool cmp(const DATA_MODEL_ROW &lhGroup, const DATA_MODEL_ROW &rhGroup, FIELDS_EDITOR_GRID_DATA_MODEL *dataModel, int sortCol, bool ascending)
wxPoint GetPosition() const override
Definition: sch_symbol.h:641
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:100
#define COLUMN_MARGIN
Hold a name of a symbol'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
SCH_SHEET_PATH & GetCurrentSheet() const
void OnTableColSize(wxGridSizeEvent &event) override
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current screen and u...
Class DIALOG_FIELDS_EDITOR_GLOBAL_BASE.
wxString GetValue(int aRow, int aCol) override
std::map< std::string, bool > fields_group_by
std::map< std::string, bool > fields_show
#define INDETERMINATE_STATE
Used for holding indeterminate values, such as with multiple selections holding different values or c...
Definition: base_units.h:47
#define CANONICAL_NAME_COLUMN
void OnTableItemContextMenu(wxGridEvent &event) override
void RemoveField(const wxString &aFieldName)
Remove a user field from the symbol.
Definition: sch_symbol.cpp:720
void OnTableValueChanged(wxGridEvent &event) override
#define DISPLAY_NAME_COLUMN
const TEMPLATE_FIELDNAMES & GetTemplateFieldNames()
Return a template field name list for read only access.
std::vector< DATA_MODEL_ROW > m_rows
A helper to define a symbol's reference designator in a schematic.
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113
Field Name Module PCB, i.e. "16DIP300".