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 <[email protected]>
5 * Copyright (C) 2015-2022 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
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
39const wxString TEMPLATE_FIELDNAME::GetDefaultFieldName( int aFieldNdx, bool aTranslateForHI )
40{
41 if( !aTranslateForHI )
42 {
43 switch( aFieldNdx )
44 {
45 case REFERENCE_FIELD: return REFERENCE_CANONICAL; // The symbol reference, R1, C1, etc.
46 case VALUE_FIELD: return VALUE_CANONICAL; // The symbol value
47 case FOOTPRINT_FIELD: return FOOTPRINT_CANONICAL; // The footprint for use with Pcbnew
48 case DATASHEET_FIELD: return DATASHEET_CANONICAL; // Link to a datasheet for symbol
49 default: return wxString::Format( wxT( "Field%d" ), aFieldNdx );
50 }
51 }
52
53 switch( aFieldNdx )
54 {
55 case REFERENCE_FIELD: return _( REFERENCE_CANONICAL ); // The symbol reference, R1, C1, etc.
56 case VALUE_FIELD: return _( VALUE_CANONICAL ); // The symbol value
57 case FOOTPRINT_FIELD: return _( FOOTPRINT_CANONICAL ); // The footprint for use with Pcbnew
58 case DATASHEET_FIELD: return _( DATASHEET_CANONICAL ); // Link to a datasheet for symbol
59 default: return wxString::Format( _( "Field%d" ), aFieldNdx );
60 }
61}
62
63
64void TEMPLATE_FIELDNAME::Format( OUTPUTFORMATTER* out, int nestLevel ) const
65{
66 out->Print( nestLevel, "(field (name %s)", out->Quotew( m_Name ).c_str() );
67
68 if( m_Visible )
69 out->Print( 0, " visible" );
70
71 if( m_URL )
72 out->Print( 0, " url" );
73
74 out->Print( 0, ")\n" );
75}
76
77
78void TEMPLATE_FIELDNAME::Parse( TEMPLATE_FIELDNAMES_LEXER* in )
79{
80 T tok;
81
82 in->NeedLEFT(); // begin (name ...)
83
84 if( ( tok = in->NextTok() ) != T_name )
85 in->Expecting( T_name );
86
87 in->NeedSYMBOLorNUMBER();
88
89 m_Name = FROM_UTF8( in->CurText() );
90
91 in->NeedRIGHT(); // end (name ...)
92
93 while( (tok = in->NextTok() ) != T_RIGHT && tok != T_EOF )
94 {
95 // "visible" has no '(' prefix, "value" does, so T_LEFT is optional.
96 if( tok == T_LEFT )
97 tok = in->NextTok();
98
99 switch( tok )
100 {
101 case T_value:
102 // older format; silently skip
103 in->NeedSYMBOLorNUMBER();
104 in->NeedRIGHT();
105 break;
106
107 case T_visible:
108 m_Visible = true;
109 break;
110
111 case T_url:
112 m_URL = true;
113 break;
114
115 default:
116 in->Expecting( "value|url|visible" );
117 break;
118 }
119 }
120}
121
122
123void TEMPLATES::Format( OUTPUTFORMATTER* out, int nestLevel, bool aGlobal ) const
124{
125 // We'll keep this general, and include the \n, even though the only known
126 // use at this time will not want the newlines or the indentation.
127 out->Print( nestLevel, "(templatefields" );
128
129 const TEMPLATE_FIELDNAMES& source = aGlobal ? m_globals : m_project;
130
131 for( const TEMPLATE_FIELDNAME& temp : source )
132 temp.Format( out, nestLevel+1 );
133
134 out->Print( 0, ")\n" );
135}
136
137
138void TEMPLATES::Parse( TEMPLATE_FIELDNAMES_LEXER* in, bool aGlobal )
139{
140 T tok;
141
142 while( ( tok = in->NextTok() ) != T_RIGHT && tok != T_EOF )
143 {
144 if( tok == T_LEFT )
145 tok = in->NextTok();
146
147 switch( tok )
148 {
149 case T_templatefields: // a token indicating class TEMPLATES.
150
151 // Be flexible regarding the starting point of the TEMPLATE_FIELDNAMES_LEXER
152 // stream. Caller may not have read the first two tokens out of the
153 // stream: T_LEFT and T_templatefields, so ignore them if seen here.
154 break;
155
156 case T_field:
157 {
158 // instantiate on stack, so if exception is thrown,
159 // destructor runs
160 TEMPLATE_FIELDNAME field;
161
162 field.Parse( in );
163
164 // add the field
165 AddTemplateFieldName( field, aGlobal );
166 }
167 break;
168
169 default:
170 in->Unexpected( in->CurText() );
171 break;
172 }
173 }
174}
175
176
177/*
178 * Flatten project and global templates into a single list. (Project templates take
179 * precedence.)
180 */
182{
184
185 // Note: order N^2 algorithm. Would need changing if fieldname template sets ever
186 // get large.
187
188 for( const TEMPLATE_FIELDNAME& global : m_globals )
189 {
190 for( const TEMPLATE_FIELDNAME& project : m_project )
191 {
192 if( global.m_Name == project.m_Name )
193 continue;
194 }
195
196 m_resolved.push_back( global );
197 }
198
199 m_resolvedDirty = false;
200}
201
202
203void TEMPLATES::AddTemplateFieldName( const TEMPLATE_FIELDNAME& aFieldName, bool aGlobal )
204{
205 // Ensure that the template fieldname does not match a fixed fieldname.
206 for( int i = 0; i < MANDATORY_FIELDS; ++i )
207 {
208 if( TEMPLATE_FIELDNAME::GetDefaultFieldName( i ) == aFieldName.m_Name )
209 return;
210 }
211
212 TEMPLATE_FIELDNAMES& target = aGlobal ? m_globals : m_project;
213
214 // ensure uniqueness, overwrite any template fieldname by the same name.
215 for( TEMPLATE_FIELDNAME& temp : target )
216 {
217 if( temp.m_Name == aFieldName.m_Name )
218 {
219 temp = aFieldName;
220 m_resolvedDirty = true;
221 return;
222 }
223 }
224
225 // the name is legal and not previously added to the config container, append
226 // it and return its index within the container.
227 target.push_back( aFieldName );
228 m_resolvedDirty = true;
229}
230
231
233{
234 if( aGlobal )
235 {
236 m_globals.clear();
238 }
239 else
240 {
241 m_project.clear();
243 }
244
245 m_resolvedDirty = false;
246}
247
248
250{
251 if( m_resolvedDirty )
253
254 return m_resolved;
255}
256
257
259{
260 if( aGlobal )
261 return m_globals;
262 else
263 return m_project;
264}
265
266
267const TEMPLATE_FIELDNAME* TEMPLATES::GetFieldName( const wxString& aName )
268{
269 if( m_resolvedDirty )
271
272 for( const TEMPLATE_FIELDNAME& field : m_resolved )
273 {
274 if( field.m_Name == aName )
275 return &field;
276 }
277
278 return nullptr;
279}
280
An interface used to output 8 bit text in a convenient way.
Definition: richio.h:310
std::string Quotew(const wxString &aWrapee) const
Definition: richio.cpp:499
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Format and write text to the output stream.
Definition: richio.cpp:431
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.
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.
void Parse(TEMPLATE_FIELDNAMES_LEXER *in, bool aGlobal)
Fill this object from information in the input stream handled by #TEMPLATE_FIELDNAMES_LEXER.
const TEMPLATE_FIELDNAMES & GetTemplateFieldNames()
Return a template field name list for read only access.
void Format(OUTPUTFORMATTER *out, int nestLevel, bool aGlobal) const
Serialize this object out as text into the given OUTPUTFORMATTER.
#define _(s)
This file contains miscellaneous commonly used macros and functions.
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
see class PGM_BASE
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
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
#define DATASHEET_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 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
std::vector< TEMPLATE_FIELDNAME > TEMPLATE_FIELDNAMES