KiCad PCB EDA Suite
template_fieldnames.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) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
5  * Copyright (C) 2015-2020 KiCad Developers, see CHANGELOG.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 #include <template_fieldnames.h>
26 #include <dsnlexer.h>
27 #include <fctsys.h>
28 #include <macros.h>
29 #include <pgm_base.h>
30 
31 using namespace TFIELD_T;
32 
33 
34 const wxString TEMPLATE_FIELDNAME::GetDefaultFieldName( int aFieldNdx )
35 {
36  static void* locale = nullptr;
37  static wxString referenceDefault;
38  static wxString valueDefault;
39  static wxString footprintDefault;
40  static wxString datasheetDefault;
41  static wxString fieldDefault;
42 
43  // Fetching translations can take a surprising amount of time when loading libraries,
44  // so only do it when necessary.
45  if( Pgm().GetLocale() != locale )
46  {
47  referenceDefault = _( "Reference" );
48  valueDefault = _( "Value" );
49  footprintDefault = _( "Footprint" );
50  datasheetDefault = _( "Datasheet" );
51  fieldDefault = _( "Field%d" );
52  locale = Pgm().GetLocale();
53  }
54 
55  // Fixed values for the mandatory fields
56  switch( aFieldNdx )
57  {
58  case REFERENCE: return referenceDefault; // The component reference, R1, C1, etc.
59  case VALUE: return valueDefault; // The component value + name
60  case FOOTPRINT: return footprintDefault; // The footprint for use with Pcbnew
61  case DATASHEET: return datasheetDefault; // Link to a datasheet for component
62  default: return wxString::Format( fieldDefault, aFieldNdx );
63  }
64 }
65 
66 void TEMPLATE_FIELDNAME::Format( OUTPUTFORMATTER* out, int nestLevel ) const
67 {
68  out->Print( nestLevel, "(field (name %s)", out->Quotew( m_Name ).c_str() );
69 
70  if( m_Visible )
71  out->Print( 0, " visible" );
72 
73  if( m_URL )
74  out->Print( 0, " url" );
75 
76  out->Print( 0, ")\n" );
77 }
78 
79 
80 void TEMPLATE_FIELDNAME::Parse( TEMPLATE_FIELDNAMES_LEXER* in )
81 {
82  T tok;
83 
84  in->NeedLEFT(); // begin (name ...)
85 
86  if( (tok = in->NextTok()) != T_name )
87  in->Expecting( T_name );
88 
89  in->NeedSYMBOLorNUMBER();
90 
91  m_Name = FROM_UTF8( in->CurText() );
92 
93  in->NeedRIGHT(); // end (name ...)
94 
95  while( (tok = in->NextTok() ) != T_RIGHT && tok != T_EOF )
96  {
97  // "visible" has no '(' prefix, "value" does, so T_LEFT is optional.
98  if( tok == T_LEFT )
99  tok = in->NextTok();
100 
101  switch( tok )
102  {
103  case T_value:
104  // older format; silently skip
105  in->NeedSYMBOLorNUMBER();
106  in->NeedRIGHT();
107  break;
108 
109  case T_visible:
110  m_Visible = true;
111  break;
112 
113  case T_url:
114  m_URL = true;
115  break;
116 
117  default:
118  in->Expecting( "value|url|visible" );
119  break;
120  }
121  }
122 }
123 
124 
125 void TEMPLATES::Format( OUTPUTFORMATTER* out, int nestLevel, bool aGlobal ) const
126 {
127  // We'll keep this general, and include the \n, even though the only known
128  // use at this time will not want the newlines or the indentation.
129  out->Print( nestLevel, "(templatefields" );
130 
131  const TEMPLATE_FIELDNAMES& source = aGlobal ? m_globals : m_project;
132 
133  for( const TEMPLATE_FIELDNAME& temp : source )
134  temp.Format( out, nestLevel+1 );
135 
136  out->Print( 0, ")\n" );
137 }
138 
139 
140 void TEMPLATES::Parse( TEMPLATE_FIELDNAMES_LEXER* in, bool aGlobal )
141 {
142  T tok;
143 
144  while( ( tok = in->NextTok() ) != T_RIGHT && tok != T_EOF )
145  {
146  if( tok == T_LEFT )
147  tok = in->NextTok();
148 
149  switch( tok )
150  {
151  case T_templatefields: // a token indicating class TEMPLATES.
152 
153  // Be flexible regarding the starting point of the TEMPLATE_FIELDNAMES_LEXER
154  // stream. Caller may not have read the first two tokens out of the
155  // stream: T_LEFT and T_templatefields, so ignore them if seen here.
156  break;
157 
158  case T_field:
159  {
160  // instantiate on stack, so if exception is thrown,
161  // destructor runs
162  TEMPLATE_FIELDNAME field;
163 
164  field.Parse( in );
165 
166  // add the field
167  AddTemplateFieldName( field, aGlobal );
168  }
169  break;
170 
171  default:
172  in->Unexpected( in->CurText() );
173  break;
174  }
175  }
176 }
177 
178 
179 /*
180  * Flatten project and global templates into a single list. (Project templates take
181  * precedence.)
182  */
184 {
185  m_resolved = m_project;
186 
187  // Note: order N^2 algorithm. Would need changing if fieldname template sets ever
188  // get large.
189 
190  for( const TEMPLATE_FIELDNAME& global : m_globals )
191  {
192  for( const TEMPLATE_FIELDNAME& project : m_project )
193  {
194  if( global.m_Name == project.m_Name )
195  continue;
196  }
197 
198  m_resolved.push_back( global );
199  }
200 
201  m_resolvedDirty = false;
202 }
203 
204 
205 void TEMPLATES::AddTemplateFieldName( const TEMPLATE_FIELDNAME& aFieldName, bool aGlobal )
206 {
207  // Ensure that the template fieldname does not match a fixed fieldname.
208  for( int i = 0; i < MANDATORY_FIELDS; ++i )
209  {
210  if( TEMPLATE_FIELDNAME::GetDefaultFieldName( i ) == aFieldName.m_Name )
211  return;
212  }
213 
214  TEMPLATE_FIELDNAMES& target = aGlobal ? m_globals : m_project;
215 
216  // ensure uniqueness, overwrite any template fieldname by the same name.
217  for( TEMPLATE_FIELDNAME& temp : target )
218  {
219  if( temp.m_Name == aFieldName.m_Name )
220  {
221  temp = aFieldName;
222  m_resolvedDirty = true;
223  return;
224  }
225  }
226 
227  // the name is legal and not previously added to the config container, append
228  // it and return its index within the container.
229  target.push_back( aFieldName );
230  m_resolvedDirty = true;
231 }
232 
233 
235 {
236  if( aGlobal )
237  {
238  m_globals.clear();
239  m_resolved = m_project;
240  }
241  else
242  {
243  m_project.clear();
244  m_resolved = m_globals;
245  }
246 
247  m_resolvedDirty = false;
248 }
249 
250 
252 {
253  if( m_resolvedDirty )
254  resolveTemplates();
255 
256  return m_resolved;
257 }
258 
259 
261 {
262  if( aGlobal )
263  return m_globals;
264  else
265  return m_project;
266 }
267 
268 
269 const TEMPLATE_FIELDNAME* TEMPLATES::GetFieldName( const wxString& aName )
270 {
271  if( m_resolvedDirty )
272  resolveTemplates();
273 
274  for( const TEMPLATE_FIELDNAME& field : m_resolved )
275  {
276  if( field.m_Name == aName )
277  return &field;
278  }
279 
280  return nullptr;
281 }
282 
void Format(OUTPUTFORMATTER *out, int nestLevel, bool aGlobal) const
Function Format serializes this object out as text into the given OUTPUTFORMATTER.
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:104
name of datasheet
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition: macros.h:114
void AddTemplateFieldName(const TEMPLATE_FIELDNAME &aFieldName, bool aGlobal)
Function AddTemplateFieldName inserts or appends a wanted symbol field name into the fieldnames templ...
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
void Parse(TEMPLATE_FIELDNAMES_LEXER *in, bool aGlobal)
Function Parse fills this object from information in the input stream handled by TEMPLATE_FIELDNAMES_...
void Parse(TEMPLATE_FIELDNAMES_LEXER *aSpec)
Function Parse fills this object from information in the input stream aSpec, which is a TEMPLATE_FIEL...
OUTPUTFORMATTER is an important interface (abstract class) used to output 8 bit text in a convenient ...
Definition: richio.h:327
static const wxString GetDefaultFieldName(int aFieldNdx)
Function GetDefaultFieldName returns a default symbol field name for field aFieldNdx for all componen...
T
enum T contains all this lexer's tokens.
void DeleteAllFieldNameTemplates(bool aGlobal)
Function DeleteAllFieldNameTemplates deletes the entire contents.
Field Name Module PCB, i.e. "16DIP300".
void Format(OUTPUTFORMATTER *out, int nestLevel) const
Function Format serializes this object out as text into the given OUTPUTFORMATTER.
Field Reference of part, i.e. "IC21".
This file contains miscellaneous commonly used macros and functions.
std::vector< TEMPLATE_FIELDNAME > TEMPLATE_FIELDNAMES
std::string Quotew(const wxString &aWrapee)
Definition: richio.cpp:472
const TEMPLATE_FIELDNAME * GetFieldName(const wxString &aName)
Function GetFieldName searches for aName in the the template field name list.
Field Value of part, i.e. "3.3K".
see class PGM_BASE
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
#define _(s)
Definition: 3d_actions.cpp:33
Struct TEMPLATE_FIELDNAME holds a name of a component's field, field value, and default visibility.
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Function Print formats and writes text to the output stream.
Definition: richio.cpp:404
const TEMPLATE_FIELDNAMES & GetTemplateFieldNames()
Function GetTemplateFieldName returns a template fieldnames list for read only access.