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 auto part = component->GetPartRef().lock();
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  PART_SPTR libPart = aComponent->GetPartRef().lock();
149 
150  if( libPart == nullptr ) // the symbol is not found in lib: cannot update fields
151  return;
152 
153  LIB_ALIAS* alias = m_frame->GetLibAlias( 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  if( !m_removeExtraBox->IsChecked() || libPart->FindField( compField->GetName() ) )
161  newFields.push_back( *compField );
162  }
163 
164  // Update the requested field values
165  for( const auto& partField : m_fields )
166  {
167  LIB_FIELD* libField = libPart->FindField( partField );
168 
169  if( !libField )
170  continue;
171 
172  SCH_FIELD* field = nullptr;
173  auto it = std::find_if( newFields.begin(), newFields.end(), [&] ( const SCH_FIELD& f )
174  { return f.GetName() == partField; } );
175 
176  if( it != newFields.end() )
177  {
178  field = &*it;
179  }
180  else
181  {
182  // Missing field, it has to be added to the component
183  SCH_FIELD f( wxPoint( 0, 0 ), newFields.size(), aComponent, partField );
184  newFields.push_back( f );
185  field = &newFields.back();
186  }
187 
188  wxString fieldValue = libField->GetText();
189 
190  if( alias )
191  {
192  if( partField == TEMPLATE_FIELDNAME::GetDefaultFieldName( VALUE ) )
193  fieldValue = alias->GetName();
194  else if( partField == TEMPLATE_FIELDNAME::GetDefaultFieldName( DATASHEET ) )
195  fieldValue = alias->GetDocFileName();
196  }
197 
198  // If the library field is empty an update would clear an existing entry.
199  // Check if this is the desired behavior.
200  if( !libField->GetText().empty() || m_resetEmpty->IsChecked() )
201  field->SetText( fieldValue );
202 
203  if( m_resetVisibility->IsChecked() )
204  field->SetVisible( libField->IsVisible() );
205 
206  if( m_resetPosition->IsChecked() )
207  {
208  field->SetTextAngle( libField->GetTextAngle() );
209 
210  // Board fields are board-relative; symbol editor fields are component-relative
211  if( m_createUndo )
212  field->SetTextPos( libField->GetTextPos() + aComponent->GetPosition() );
213  else
214  field->SetTextPos( libField->GetTextPos() );
215  }
216 
217  if( m_resetSizeAndStyle->IsChecked() )
218  {
219  field->SetHorizJustify( libField->GetHorizJustify() );
220  field->SetVertJustify( libField->GetVertJustify() );
221  field->SetTextSize( libField->GetTextSize() );
222  field->SetItalic( libField->IsItalic() );
223  field->SetBold( libField->IsBold() );
224  }
225  }
226 
227  // Apply changes & clean-up
228  aComponent->SetFields( newFields );
229 }
230 
231 
233 {
234  for( unsigned i = 0; i < m_fieldsBox->GetCount(); ++i )
235  m_fieldsBox->Check( i, aCheck );
236 }
void SetTextAngle(double aAngle)
Definition: eda_text.h:169
set< wxString > m_fields
Set of field names that should have values updated
Class SCH_FIELD instances are attached to a component and provide a place for the component&#39;s value...
Definition: sch_field.h:56
Part library alias object definition.
PART_REF & GetPartRef()
void checkAll(bool aCheck)
Selects or deselects all fields in the listbox widget
name of datasheet
const wxPoint & GetTextPos() const
Definition: eda_text.h:237
bool IsItalic() const
Definition: eda_text.h:183
bool TransferDataFromWindow() override
void OnModify()
Must be called after a schematic change in order to set the "modify" flag of the current screen* and ...
void SetItalic(bool isItalic)
Definition: eda_text.h:182
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:236
void SetVisible(bool aVisible)
Definition: eda_text.h:188
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
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:227
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...
EDA_TEXT_HJUSTIFY_T GetHorizJustify() const
Definition: eda_text.h:203
Field Reference of part, i.e. "IC21".
bool IsBold() const
Definition: eda_text.h:186
double GetTextAngle() const
Definition: eda_text.h:177
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populates a std::vector with SCH_FIELDs.
list< SCH_COMPONENT * > m_components
Components to update
void SetFields(const SCH_FIELDS &aFields)
Set multiple schematic fields.
int GetId() const
Definition: lib_field.h:138
void SyncView()
Mark all items for refresh.
int ShowQuasiModal()
Class LIB_ITEM definition.
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:143
std::vector< SCH_FIELD > SCH_FIELDS
A container for several SCH_FIELD items.
Definition: sch_component.h:53
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:207
std::shared_ptr< LIB_PART > PART_SPTR
shared pointer to LIB_PART
SCH_DRAW_PANEL * GetCanvas() const override
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)
LIB_ALIAS * GetLibAlias(const LIB_ID &aLibId, bool aUseCacheLib=false, bool aShowError=false)
Load symbol from symbol library table.
Class 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)
wxString GetName(bool aTranslate=true) const
Returns the field name.
Definition: lib_field.cpp:440
const wxString & GetDocFileName() const
EDA_TEXT_VJUSTIFY_T GetVertJustify() const
Definition: eda_text.h:204
Definition the SCH_COMPONENT class for Eeschema.
const wxString & GetName() const override
bool IsVisible() const
Definition: lib_field.h:166
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:206
Class DIALOG_UPDATE_FIELDS_BASE.
size_t i
Definition: json11.cpp:597
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:69
SCH_EDIT_FRAME * m_frame
Parent frame
wxPoint GetPosition() const override
Function GetPosition.
const LIB_ID & GetLibId() const
const wxSize & GetTextSize() const
Definition: eda_text.h:228
void updateFields(SCH_COMPONENT *aComponent)
Update fields for a single component
#define VALUE
void SetBold(bool aBold)
Definition: eda_text.h:185
virtual void SetText(const wxString &aText)
Definition: eda_text.h:154