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