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