KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 <[email protected]>
5 * Copyright The 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 "template_fieldnames.h"
26
27#include <mutex>
28
29#include <template_fieldnames_lexer.h>
30#include <string_utils.h>
31
32using namespace TFIELD_T;
33
34// N.B. Do not change these values without transitioning the file format
35#define REFERENCE_CANONICAL "Reference"
36#define VALUE_CANONICAL "Value"
37#define FOOTPRINT_CANONICAL "Footprint"
38#define DATASHEET_CANONICAL "Datasheet"
39#define DESCRIPTION_CANONICAL "Description"
40#define USER_FIELD_CANONICAL "Field%d"
41
47
48
49wxString GetDefaultFieldName( int aFieldNdx, bool aTranslateForHI )
50{
51 if( !aTranslateForHI )
52 {
53 switch( aFieldNdx )
54 {
55 case REFERENCE_FIELD: return s_CanonicalReference; // The symbol reference, R1, C1, etc.
56 case VALUE_FIELD: return s_CanonicalValue; // The symbol value
57 case FOOTPRINT_FIELD: return s_CanonicalFootprint; // The footprint for use with Pcbnew
58 case DATASHEET_FIELD: return s_CanonicalDatasheet; // Link to a datasheet for symbol
59 case DESCRIPTION_FIELD: return s_CanonicalDescription; // The symbol description
60 default: return GetUserFieldName( aFieldNdx, aTranslateForHI );
61 }
62 }
63 else
64 {
65 switch( aFieldNdx )
66 {
67 case REFERENCE_FIELD: return _( REFERENCE_CANONICAL ); // The symbol reference, R1, C1, etc.
68 case VALUE_FIELD: return _( VALUE_CANONICAL ); // The symbol value
69 case FOOTPRINT_FIELD: return _( FOOTPRINT_CANONICAL ); // The footprint for use with Pcbnew
70 case DATASHEET_FIELD: return _( DATASHEET_CANONICAL ); // Link to a datasheet for symbol
71 case DESCRIPTION_FIELD: return _( DESCRIPTION_CANONICAL ); // The symbol description
72 default: return GetUserFieldName( aFieldNdx, aTranslateForHI );
73 }
74 }
75}
76
77
78wxString GetUserFieldName( int aFieldNdx, bool aTranslateForHI )
79{
80 if( !aTranslateForHI )
81 return wxString::Format( wxS( USER_FIELD_CANONICAL ), aFieldNdx );
82 else
83 return wxString::Format( _( USER_FIELD_CANONICAL ), aFieldNdx );
84}
85
86
88{
89 out->Print( "(field (name %s)", out->Quotew( m_Name ).c_str() );
90
91 if( m_Visible )
92 out->Print( " visible" );
93
94 if( m_URL )
95 out->Print( " url" );
96
97 out->Print( ")" );
98}
99
100
101void TEMPLATE_FIELDNAME::Parse( TEMPLATE_FIELDNAMES_LEXER* in )
102{
103 T tok;
104
105 in->NeedLEFT(); // begin (name ...)
106
107 if( ( tok = in->NextTok() ) != T_name )
108 in->Expecting( T_name );
109
110 in->NeedSYMBOLorNUMBER();
111
112 m_Name = From_UTF8( in->CurText() );
113
114 in->NeedRIGHT(); // end (name ...)
115
116 while( (tok = in->NextTok() ) != T_RIGHT && tok != T_EOF )
117 {
118 // "visible" has no '(' prefix, "value" does, so T_LEFT is optional.
119 if( tok == T_LEFT )
120 tok = in->NextTok();
121
122 switch( tok )
123 {
124 case T_value:
125 // older format; silently skip
126 in->NeedSYMBOLorNUMBER();
127 in->NeedRIGHT();
128 break;
129
130 case T_visible:
131 m_Visible = true;
132 break;
133
134 case T_url:
135 m_URL = true;
136 break;
137
138 default:
139 in->Expecting( "value|url|visible" );
140 break;
141 }
142 }
143}
144
145
146void TEMPLATES::Format( OUTPUTFORMATTER* out, bool aGlobal ) const
147{
148 // We'll keep this general, and include the \n, even though the only known
149 // use at this time will not want the newlines or the indentation.
150 out->Print( "(templatefields" );
151
152 const TEMPLATE_FIELDNAMES& source = aGlobal ? m_globals : m_project;
153
154 for( const TEMPLATE_FIELDNAME& temp : source )
155 {
156 if( !temp.m_Name.IsEmpty() )
157 temp.Format( out );
158 }
159
160 out->Print( ")" );
161}
162
163
164void TEMPLATES::parse( TEMPLATE_FIELDNAMES_LEXER* in, bool aGlobal )
165{
166 T tok;
167
168 while( ( tok = in->NextTok() ) != T_RIGHT && tok != T_EOF )
169 {
170 if( tok == T_LEFT )
171 tok = in->NextTok();
172
173 switch( tok )
174 {
175 case T_templatefields: // a token indicating class TEMPLATES.
176
177 // Be flexible regarding the starting point of the TEMPLATE_FIELDNAMES_LEXER
178 // stream. Caller may not have read the first two tokens out of the
179 // stream: T_LEFT and T_templatefields, so ignore them if seen here.
180 break;
181
182 case T_field:
183 {
184 // instantiate on stack, so if exception is thrown,
185 // destructor runs
186 TEMPLATE_FIELDNAME field;
187
188 field.Parse( in );
189
190 // add the field
191 if( !field.m_Name.IsEmpty() )
192 AddTemplateFieldName( field, aGlobal );
193 }
194 break;
195
196 default:
197 in->Unexpected( in->CurText() );
198 break;
199 }
200 }
201}
202
203
209{
211
212 // Note: order N^2 algorithm. Would need changing if fieldname template sets ever
213 // get large.
214
215 for( const TEMPLATE_FIELDNAME& global : m_globals )
216 {
217 bool overriddenInProject = false;
218
219 for( const TEMPLATE_FIELDNAME& project : m_project )
220 {
221 if( global.m_Name == project.m_Name )
222 {
223 overriddenInProject = true;
224 break;
225 }
226 }
227
228 if( !overriddenInProject )
229 m_resolved.push_back( global );
230 }
231
232 m_resolvedDirty = false;
233}
234
235
236void TEMPLATES::AddTemplateFieldName( const TEMPLATE_FIELDNAME& aFieldName, bool aGlobal )
237{
238 // Ensure that the template fieldname does not match a fixed fieldname.
239 for( int i = 0; i < MANDATORY_FIELDS; ++i )
240 {
241 if( GetCanonicalFieldName( i ) == aFieldName.m_Name )
242 return;
243 }
244
245 TEMPLATE_FIELDNAMES& target = aGlobal ? m_globals : m_project;
246
247 // ensure uniqueness, overwrite any template fieldname by the same name.
248 for( TEMPLATE_FIELDNAME& temp : target )
249 {
250 if( temp.m_Name == aFieldName.m_Name )
251 {
252 temp = aFieldName;
253 m_resolvedDirty = true;
254 return;
255 }
256 }
257
258 // the name is legal and not previously added to the config container, append
259 // it and return its index within the container.
260 target.push_back( aFieldName );
261 m_resolvedDirty = true;
262}
263
264
265void TEMPLATES::AddTemplateFieldNames( const wxString& aSerializedFieldNames )
266{
267 TEMPLATE_FIELDNAMES_LEXER field_lexer( TO_UTF8( aSerializedFieldNames ) );
268
269 try
270 {
271 parse( &field_lexer, true );
272 }
273 catch( const IO_ERROR& )
274 {
275 }
276}
277
278
280{
281 if( aGlobal )
282 {
283 m_globals.clear();
285 }
286 else
287 {
288 m_project.clear();
290 }
291
292 m_resolvedDirty = false;
293}
294
295
297{
298 if( m_resolvedDirty )
300
301 return m_resolved;
302}
303
304
306{
307 if( aGlobal )
308 return m_globals;
309 else
310 return m_project;
311}
312
313
314const TEMPLATE_FIELDNAME* TEMPLATES::GetFieldName( const wxString& aName )
315{
316 if( m_resolvedDirty )
318
319 for( const TEMPLATE_FIELDNAME& field : m_resolved )
320 {
321 if( field.m_Name == aName )
322 return &field;
323 }
324
325 return nullptr;
326}
327
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
An interface used to output 8 bit text in a convenient way.
Definition: richio.h:322
std::string Quotew(const wxString &aWrapee) const
Definition: richio.cpp:545
int PRINTF_FUNC_N Print(int nestLevel, const char *fmt,...)
Format and write text to the output stream.
Definition: richio.cpp:460
TEMPLATE_FIELDNAMES m_globals
void AddTemplateFieldName(const TEMPLATE_FIELDNAME &aFieldName, bool aGlobal)
Insert or append a wanted symbol field name into the field names template.
void AddTemplateFieldNames(const wxString &aSerializedFieldNames)
Add a serialized list of template field names.
TEMPLATE_FIELDNAMES m_project
TEMPLATE_FIELDNAMES m_resolved
void resolveTemplates()
Flatten project and global templates into a single list.
const TEMPLATE_FIELDNAME * GetFieldName(const wxString &aName)
Search for aName in the template field name list.
void DeleteAllFieldNameTemplates(bool aGlobal)
Delete the entire contents.
const TEMPLATE_FIELDNAMES & GetTemplateFieldNames()
Return a template field name list for read only access.
void parse(TEMPLATE_FIELDNAMES_LEXER *in, bool aGlobal)
void Format(OUTPUTFORMATTER *out, bool aGlobal) const
Serialize this object out as text into the given OUTPUTFORMATTER.
#define _(s)
wxString From_UTF8(const char *cstring)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: string_utils.h:398
Hold a name of a symbol's field, field value, and default visibility.
void Format(OUTPUTFORMATTER *out) const
Serialize this object out as text into the given OUTPUTFORMATTER.
void Parse(TEMPLATE_FIELDNAMES_LEXER *aSpec)
Fill this object from information in the input stream aSpec, which is a #TEMPLATE_FIELDNAMES_LEXER.
#define VALUE_CANONICAL
#define FOOTPRINT_CANONICAL
#define USER_FIELD_CANONICAL
static wxString s_CanonicalReference(REFERENCE_CANONICAL)
static wxString s_CanonicalValue(VALUE_CANONICAL)
static wxString s_CanonicalFootprint(FOOTPRINT_CANONICAL)
static wxString s_CanonicalDatasheet(DATASHEET_CANONICAL)
wxString GetDefaultFieldName(int aFieldNdx, bool aTranslateForHI)
Return a default symbol field name for field aFieldNdx for all components.
#define DATASHEET_CANONICAL
wxString GetUserFieldName(int aFieldNdx, bool aTranslateForHI)
#define DESCRIPTION_CANONICAL
static wxString s_CanonicalDescription(DESCRIPTION_CANONICAL)
#define REFERENCE_CANONICAL
wxString GetCanonicalFieldName(int idx)
@ DATASHEET_FIELD
name of datasheet
@ FOOTPRINT_FIELD
Field Name Module PCB, i.e. "16DIP300".
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ MANDATORY_FIELDS
The first 5 are mandatory, and must be instantiated in SCH_COMPONENT, LIB_PART, and FOOTPRINT constru...
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
@ DESCRIPTION_FIELD
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
std::vector< TEMPLATE_FIELDNAME > TEMPLATE_FIELDNAMES