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