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 (C) 2015-2023 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 <template_fieldnames.h>
28#include <pgm_base.h>
29#include <string_utils.h>
30
31using namespace TFIELD_T;
32
33// N.B. Do not change these values without transitioning the file format
34#define REFERENCE_CANONICAL "Reference"
35#define VALUE_CANONICAL "Value"
36#define FOOTPRINT_CANONICAL "Footprint"
37#define DATASHEET_CANONICAL "Datasheet"
38#define DESCRIPTION_CANONICAL "Description"
39
45
46const wxString TEMPLATE_FIELDNAME::GetDefaultFieldName( int aFieldNdx, bool aTranslateForHI )
47{
48 if( !aTranslateForHI )
49 {
50 switch( aFieldNdx )
51 {
52 case REFERENCE_FIELD: return s_CanonicalReference; // The symbol reference, R1, C1, etc.
53 case VALUE_FIELD: return s_CanonicalValue; // The symbol value
54 case FOOTPRINT_FIELD: return s_CanonicalFootprint; // The footprint for use with Pcbnew
55 case DATASHEET_FIELD: return s_CanonicalDatasheet; // Link to a datasheet for symbol
56 case DESCRIPTION_FIELD: return s_CanonicalDescription; // The symbol description
57 default: break;
58 }
59
60 wxString str( wxS( "Field" ) );
61#if wxUSE_UNICODE_WCHAR
62 str << std::to_wstring( aFieldNdx );
63#else
64 str << std::to_string( aFieldNdx );
65#endif
66 return str;
67 }
68
69 switch( aFieldNdx )
70 {
71 case REFERENCE_FIELD: return _( REFERENCE_CANONICAL ); // The symbol reference, R1, C1, etc.
72 case VALUE_FIELD: return _( VALUE_CANONICAL ); // The symbol value
73 case FOOTPRINT_FIELD: return _( FOOTPRINT_CANONICAL ); // The footprint for use with Pcbnew
74 case DATASHEET_FIELD: return _( DATASHEET_CANONICAL ); // Link to a datasheet for symbol
75 case DESCRIPTION_FIELD: return _( DESCRIPTION_CANONICAL ); // The symbol description
76 default: return wxString::Format( _( "Field%d" ), aFieldNdx );
77 }
78}
79
80
81void TEMPLATE_FIELDNAME::Format( OUTPUTFORMATTER* out, int nestLevel ) const
82{
83 out->Print( nestLevel, "(field (name %s)", out->Quotew( m_Name ).c_str() );
84
85 if( m_Visible )
86 out->Print( 0, " visible" );
87
88 if( m_URL )
89 out->Print( 0, " url" );
90
91 out->Print( 0, ")\n" );
92}
93
94
95void TEMPLATE_FIELDNAME::Parse( TEMPLATE_FIELDNAMES_LEXER* in )
96{
97 T tok;
98
99 in->NeedLEFT(); // begin (name ...)
100
101 if( ( tok = in->NextTok() ) != T_name )
102 in->Expecting( T_name );
103
104 in->NeedSYMBOLorNUMBER();
105
106 m_Name = From_UTF8( in->CurText() );
107
108 in->NeedRIGHT(); // end (name ...)
109
110 while( (tok = in->NextTok() ) != T_RIGHT && tok != T_EOF )
111 {
112 // "visible" has no '(' prefix, "value" does, so T_LEFT is optional.
113 if( tok == T_LEFT )
114 tok = in->NextTok();
115
116 switch( tok )
117 {
118 case T_value:
119 // older format; silently skip
120 in->NeedSYMBOLorNUMBER();
121 in->NeedRIGHT();
122 break;
123
124 case T_visible:
125 m_Visible = true;
126 break;
127
128 case T_url:
129 m_URL = true;
130 break;
131
132 default:
133 in->Expecting( "value|url|visible" );
134 break;
135 }
136 }
137}
138
139
140void TEMPLATES::Format( OUTPUTFORMATTER* out, int nestLevel, bool aGlobal ) const
141{
142 // We'll keep this general, and include the \n, even though the only known
143 // use at this time will not want the newlines or the indentation.
144 out->Print( nestLevel, "(templatefields" );
145
146 const TEMPLATE_FIELDNAMES& source = aGlobal ? m_globals : m_project;
147
148 for( const TEMPLATE_FIELDNAME& temp : source )
149 {
150 if( !temp.m_Name.IsEmpty() )
151 temp.Format( out, nestLevel+1 );
152 }
153
154 out->Print( 0, ")\n" );
155}
156
157
158void TEMPLATES::parse( TEMPLATE_FIELDNAMES_LEXER* in, bool aGlobal )
159{
160 T tok;
161
162 while( ( tok = in->NextTok() ) != T_RIGHT && tok != T_EOF )
163 {
164 if( tok == T_LEFT )
165 tok = in->NextTok();
166
167 switch( tok )
168 {
169 case T_templatefields: // a token indicating class TEMPLATES.
170
171 // Be flexible regarding the starting point of the TEMPLATE_FIELDNAMES_LEXER
172 // stream. Caller may not have read the first two tokens out of the
173 // stream: T_LEFT and T_templatefields, so ignore them if seen here.
174 break;
175
176 case T_field:
177 {
178 // instantiate on stack, so if exception is thrown,
179 // destructor runs
180 TEMPLATE_FIELDNAME field;
181
182 field.Parse( in );
183
184 // add the field
185 if( !field.m_Name.IsEmpty() )
186 AddTemplateFieldName( field, aGlobal );
187 }
188 break;
189
190 default:
191 in->Unexpected( in->CurText() );
192 break;
193 }
194 }
195}
196
197
198/*
199 * Flatten project and global templates into a single list. (Project templates take
200 * precedence.)
201 */
203{
205
206 // Note: order N^2 algorithm. Would need changing if fieldname template sets ever
207 // get large.
208
209 for( const TEMPLATE_FIELDNAME& global : m_globals )
210 {
211 bool overriddenInProject = false;
212
213 for( const TEMPLATE_FIELDNAME& project : m_project )
214 {
215 if( global.m_Name == project.m_Name )
216 {
217 overriddenInProject = true;
218 break;
219 }
220 }
221
222 if( !overriddenInProject )
223 m_resolved.push_back( global );
224 }
225
226 m_resolvedDirty = false;
227}
228
229
230void TEMPLATES::AddTemplateFieldName( const TEMPLATE_FIELDNAME& aFieldName, bool aGlobal )
231{
232 // Ensure that the template fieldname does not match a fixed fieldname.
233 for( int i = 0; i < MANDATORY_FIELDS; ++i )
234 {
235 if( GetCanonicalFieldName( i ) == aFieldName.m_Name )
236 return;
237 }
238
239 TEMPLATE_FIELDNAMES& target = aGlobal ? m_globals : m_project;
240
241 // ensure uniqueness, overwrite any template fieldname by the same name.
242 for( TEMPLATE_FIELDNAME& temp : target )
243 {
244 if( temp.m_Name == aFieldName.m_Name )
245 {
246 temp = aFieldName;
247 m_resolvedDirty = true;
248 return;
249 }
250 }
251
252 // the name is legal and not previously added to the config container, append
253 // it and return its index within the container.
254 target.push_back( aFieldName );
255 m_resolvedDirty = true;
256}
257
258
259void TEMPLATES::AddTemplateFieldNames( const wxString& aSerializedFieldNames )
260{
261 TEMPLATE_FIELDNAMES_LEXER field_lexer( TO_UTF8( aSerializedFieldNames ) );
262
263 try
264 {
265 parse( &field_lexer, true );
266 }
267 catch( const IO_ERROR& )
268 {
269 }
270}
271
272
274{
275 if( aGlobal )
276 {
277 m_globals.clear();
279 }
280 else
281 {
282 m_project.clear();
284 }
285
286 m_resolvedDirty = false;
287}
288
289
291{
292 if( m_resolvedDirty )
294
295 return m_resolved;
296}
297
298
300{
301 if( aGlobal )
302 return m_globals;
303 else
304 return m_project;
305}
306
307
308const TEMPLATE_FIELDNAME* TEMPLATES::GetFieldName( const wxString& aName )
309{
310 if( m_resolvedDirty )
312
313 for( const TEMPLATE_FIELDNAME& field : m_resolved )
314 {
315 if( field.m_Name == aName )
316 return &field;
317 }
318
319 return nullptr;
320}
321
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:526
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Format and write text to the output stream.
Definition: richio.cpp:458
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
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, int nestLevel, bool aGlobal) const
Serialize this object out as text into the given OUTPUTFORMATTER.
#define _(s)
see class PGM_BASE
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:391
Hold a name of a symbol's field, field value, and default visibility.
void Format(OUTPUTFORMATTER *out, int nestLevel) 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.
static const wxString GetDefaultFieldName(int aFieldNdx, bool aTranslateForHI=false)
Return a default symbol field name for field aFieldNdx for all components.
#define VALUE_CANONICAL
#define FOOTPRINT_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)
#define DATASHEET_CANONICAL
#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 and LIB_PART constructors.
@ 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