KiCad PCB EDA Suite
dialog_update_fields.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 CERN
5  * @author Maciej Suminski <maciej.suminski@cern.ch>
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 3
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  * https://www.gnu.org/licenses/gpl-3.0.html
20  * or you may search the http://www.gnu.org website for the version 3 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 #include "dialog_update_fields.h"
26 
27 #include <sch_edit_frame.h>
28 #include <sch_component.h>
29 #include <class_libentry.h>
30 #include <algorithm>
31 
32 
34  const list<SCH_COMPONENT*> aComponents, bool aCreateUndoEntry )
35 {
36  DIALOG_UPDATE_FIELDS dlg( aCaller, aComponents, aCreateUndoEntry );
37  return dlg.ShowQuasiModal();
38 }
39 
40 
42  const list<SCH_COMPONENT*>& aComponents, bool aCreateUndoEntry )
43  : DIALOG_UPDATE_FIELDS_BASE( aParent ), m_frame( aParent ),
44  m_components( aComponents ), m_createUndo( aCreateUndoEntry )
45 {
46  m_sdbSizerOK->SetDefault();
47 }
48 
49 
51 {
52  if( !wxDialog::TransferDataFromWindow() )
53  return false;
54 
55  if( m_components.empty() )
56  return true; // nothing to process
57 
58 
59  // Create the set of fields to be updated
60  m_fields.clear();
61 
62  for( unsigned i = 0; i < m_fieldsBox->GetCount(); ++i )
63  {
64  if( m_fieldsBox->IsChecked( i ) )
65  m_fields.insert( m_fieldsBox->GetString( i ) );
66  }
67 
68 
69  // Undo buffer entry
70  if( m_createUndo )
71  {
72  PICKED_ITEMS_LIST itemsList;
73 
74  for( auto component : m_components )
75  itemsList.PushItem( ITEM_PICKER( component, UR_CHANGED ) );
76 
77  m_frame->SaveCopyInUndoList( itemsList, UR_CHANGED );
78  }
79 
80 
81  // Do it!
82  for( auto component : m_components )
83  updateFields( component );
84 
85  m_frame->SyncView();
87  m_frame->OnModify();
88 
89  return true;
90 }
91 
92 
94 {
95  if( !wxDialog::TransferDataToWindow() || !m_components.size() )
96  return false;
97 
98  // Collect all user field names from library parts of components that are going to be updated
99  {
100  for( auto component : m_components )
101  {
102  const std::unique_ptr< LIB_PART >& part = component->GetPartRef();
103 
104  if( !part )
105  continue;
106 
107  const auto& drawItems = part->GetDrawItems();
108 
109  for( auto it = drawItems.begin( LIB_FIELD_T ); it != drawItems.end( LIB_FIELD_T ); ++it )
110  {
111  const LIB_FIELD* field = static_cast<const LIB_FIELD*>( &( *it ) );
112 
113  if( field->GetId() >= MANDATORY_FIELDS )
114  m_fields.insert( field->GetName( false ) );
115  }
116  }
117  }
118 
119  // Update the listbox widget
120  m_fieldsBox->Clear();
121 
122  for( int i = 0; i < MANDATORY_FIELDS; ++i )
123  {
124  m_fieldsBox->Append( m_components.front()->GetField( i )->GetName( false ) );
125 
126  if( i != REFERENCE && i != VALUE )
127  m_fieldsBox->Check( i, true );
128  }
129 
130  for( const auto& field : m_fields )
131  {
132  int idx = m_fieldsBox->Append( field );
133  m_fieldsBox->Check( idx, true );
134  }
135 
136  // Now all widgets have the size fixed, call FinishDialogSettings
138 
139  return true;
140 }
141 
142 
144 {
145  std::vector<SCH_FIELD*> oldFields;
146  SCH_FIELDS newFields;
147 
148  std::unique_ptr< LIB_PART >& libPart = aComponent->GetPartRef();
149 
150  if( !libPart ) // the symbol is not found in lib: cannot update fields
151  return;
152 
153  LIB_PART* alias = m_frame->GetLibPart( aComponent->GetLibId() );
154 
155  aComponent->GetFields( oldFields, false );
156 
157  for( auto compField : oldFields )
158  {
159  // If requested, transfer only fields that occur also in the original library part
160  // and obviously mandatory fields
161  if( compField->GetId() < MANDATORY_FIELDS
162  || !m_removeExtraBox->IsChecked()
163  || libPart->FindField( compField->GetName() ) )
164  newFields.push_back( *compField );
165  }
166 
167  // Update the requested field values
168  for( const auto& partField : m_fields )
169  {
170  LIB_FIELD* libField = libPart->FindField( partField );
171 
172  if( !libField )
173  continue;
174 
175  SCH_FIELD* field = nullptr;
176 
177  auto it = std::find_if( newFields.begin(), newFields.end(), [&] ( const SCH_FIELD& f )
178  { return f.GetName() == partField; } );
179 
180  if( it != newFields.end() )
181  {
182  field = &*it;
183  }
184  else
185  {
186  // Missing field, it has to be added to the component
187  SCH_FIELD f( wxPoint( 0, 0 ), newFields.size(), aComponent, partField );
188  newFields.push_back( f );
189  field = &newFields.back();
190  }
191 
192  wxString fieldValue = libField->GetText();
193 
194  if( alias )
195  {
196  if( partField == TEMPLATE_FIELDNAME::GetDefaultFieldName( VALUE ) )
197  fieldValue = alias->GetName();
198  else if( partField == TEMPLATE_FIELDNAME::GetDefaultFieldName( DATASHEET ) )
199  fieldValue = alias->GetDocFileName();
200  }
201 
202  // If the library field is empty an update would clear an existing entry.
203  // Check if this is the desired behavior.
204  if( !fieldValue.empty() || m_resetEmpty->IsChecked() )
205  field->SetText( fieldValue );
206 
207  if( m_resetVisibility->IsChecked() )
208  field->SetVisible( libField->IsVisible() );
209 
210  if( m_resetPosition->IsChecked() )
211  {
212  field->SetTextAngle( libField->GetTextAngle() );
213 
214  // Board fields are board-relative; symbol editor fields are component-relative
215  if( m_createUndo )
216  field->SetTextPos( libField->GetTextPos() + aComponent->GetPosition() );
217  else
218  field->SetTextPos( libField->GetTextPos() );
219  }
220 
221  if( m_resetSizeAndStyle->IsChecked() )
222  {
223  field->SetHorizJustify( libField->GetHorizJustify() );
224  field->SetVertJustify( libField->GetVertJustify() );
225  field->SetTextSize( libField->GetTextSize() );
226  field->SetItalic( libField->IsItalic() );
227  field->SetBold( libField->IsBold() );
228  }
229  }
230 
231  // Apply changes & clean-up
232  aComponent->SetFields( newFields );
233 }
234 
235 
237 {
238  for( unsigned i = 0; i < m_fieldsBox->GetCount(); ++i )
239  m_fieldsBox->Check( i, aCheck );
240 }
void SetTextAngle(double aAngle)
Definition: eda_text.h:150
set< wxString > m_fields
Set of field names that should have values updated
bool IsBold() const
Definition: eda_text.h:167
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:52
EDA_TEXT_VJUSTIFY_T GetVertJustify() const
Definition: eda_text.h:184
void checkAll(bool aCheck)
Selects or deselects all fields in the listbox widget
name of datasheet
bool TransferDataFromWindow() override
wxString GetName() const override
bool IsVisible() const
Definition: eda_text.h:170
void SetItalic(bool isItalic)
Definition: eda_text.h:163
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
Dialog to update component fields (i.e.
Field object used in symbol libraries.
Definition: lib_field.h:59
void FinishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:231
void SetVisible(bool aVisible)
Definition: eda_text.h:169
double GetTextAngle() const
Definition: eda_text.h:158
void PushItem(const ITEM_PICKER &aItem)
Function PushItem pushes aItem to the top of the list.
static const wxString GetDefaultFieldName(int aFieldNdx)
Function GetDefaultFieldName returns a default symbol field name for field aFieldNdx for all componen...
Schematic editor (Eeschema) main window.
bool TransferDataToWindow() override
LIB_PART * GetLibPart(const LIB_ID &aLibId, bool aUseCacheLib=false, bool aShowErrorMsg=false)
Load symbol from symbol library table.
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:222
int GetId() const
Definition: lib_field.h:139
Field Reference of part, i.e. "IC21".
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populates a std::vector with SCH_FIELDs.
bool IsItalic() const
Definition: eda_text.h:164
list< SCH_COMPONENT * > m_components
Components to update
#define VALUE
EDA_TEXT_HJUSTIFY_T GetHorizJustify() const
Definition: eda_text.h:183
void SetFields(const SCH_FIELDS &aFields)
Set multiple schematic fields.
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:111
void SyncView()
Mark all items for refresh.
int ShowQuasiModal()
Class LIB_PIN definition.
const wxSize & GetTextSize() const
Definition: eda_text.h:223
std::vector< SCH_FIELD > SCH_FIELDS
A container for several SCH_FIELD items.
Definition: sch_component.h:79
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:187
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
bool m_createUndo
Flag indicating whether an undo buffer entry should be created
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.
DIALOG_UPDATE_FIELDS(SCH_EDIT_FRAME *aParent, const list< SCH_COMPONENT * > &aComponents, bool aCreateUndoEntry=true)
Define a library symbol object.
wxString GetDocFileName() const
std::unique_ptr< LIB_PART > & GetPartRef()
PICKED_ITEMS_LIST is a holder to handle information on schematic or board items.
int InvokeDialogUpdateFields(SCH_EDIT_FRAME *aCaller, const list< SCH_COMPONENT * > aComponents, bool aCreateUndoEntry)
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...
wxString GetName(bool aTranslate) const
Definition: lib_field.cpp:387
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:186
Class DIALOG_UPDATE_FIELDS_BASE.
SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:99
SCH_EDIT_FRAME * m_frame
Parent frame
wxPoint GetPosition() const override
Function GetPosition.
const wxPoint & GetTextPos() const
Definition: eda_text.h:232
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current screen and u...
const LIB_ID & GetLibId() const
void updateFields(SCH_COMPONENT *aComponent)
Update fields for a single component
void SetBold(bool aBold)
Definition: eda_text.h:166
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:123