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, see <https://www.gnu.org/licenses/>.
19 */
20
21#include "template_fieldnames.h"
22
23#include <mutex>
24
25#include <template_fieldnames_lexer.h>
26#include <string_utils.h>
27
28using namespace TFIELD_T;
29
30// N.B. Do not change these values without transitioning the file format
31#define REFERENCE_CANONICAL "Reference"
32#define VALUE_CANONICAL "Value"
33#define FOOTPRINT_CANONICAL "Footprint"
34#define DATASHEET_CANONICAL "Datasheet"
35#define DESCRIPTION_CANONICAL "Description"
36#define SHEET_NAME_CANONICAL "Sheetname"
37#define SHEET_FILE_CANONICAL "Sheetfile"
38#define INTERSHEET_REFS_CANONICAL "Intersheetrefs"
39#define USER_FIELD_CANONICAL "Field%d"
40
49
50
51wxString GetDefaultFieldName( FIELD_T aFieldId, bool aTranslateForHI )
52{
53 if( !aTranslateForHI )
54 {
55 switch( aFieldId )
56 {
57 case FIELD_T::REFERENCE: return s_CanonicalReference; // The symbol reference, R1, C1, etc.
58 case FIELD_T::VALUE: return s_CanonicalValue; // The symbol value
59 case FIELD_T::FOOTPRINT: return s_CanonicalFootprint; // The footprint for use with Pcbnew
60 case FIELD_T::DATASHEET: return s_CanonicalDatasheet; // Link to a datasheet for symbol
61 case FIELD_T::DESCRIPTION: return s_CanonicalDescription; // The symbol description
65 default: return GetUserFieldName( 42, aTranslateForHI );
66 }
67 }
68 else
69 {
70 switch( aFieldId )
71 {
72 case FIELD_T::REFERENCE: return _( REFERENCE_CANONICAL ); // The symbol reference, R1, C1, etc.
73 case FIELD_T::VALUE: return _( VALUE_CANONICAL ); // The symbol value
74 case FIELD_T::FOOTPRINT: return _( FOOTPRINT_CANONICAL ); // The footprint for use with Pcbnew
75 case FIELD_T::DATASHEET: return _( DATASHEET_CANONICAL ); // Link to a datasheet for symbol
76 case FIELD_T::DESCRIPTION: return _( DESCRIPTION_CANONICAL ); // The symbol description
80 default: return GetUserFieldName( 42, aTranslateForHI );
81 }
82 }
83}
84
85
86wxString GetUserFieldName( int aFieldNdx, bool aTranslateForHI )
87{
88 if( !aTranslateForHI )
89 return wxString::Format( wxS( USER_FIELD_CANONICAL ), aFieldNdx );
90 else
91 return wxString::Format( _( USER_FIELD_CANONICAL ), aFieldNdx );
92}
93
94
96{
97 out->Print( "(field (name %s)", out->Quotew( m_Name ).c_str() );
98
99 if( m_Visible )
100 out->Print( " visible" );
101
102 if( m_URL )
103 out->Print( " url" );
104
105 out->Print( ")" );
106}
107
108
109void TEMPLATE_FIELDNAME::Parse( TEMPLATE_FIELDNAMES_LEXER* in )
110{
111 T tok;
112
113 in->NeedLEFT(); // begin (name ...)
114
115 if( ( tok = in->NextTok() ) != T_name )
116 in->Expecting( T_name );
117
118 in->NeedSYMBOLorNUMBER();
119
120 m_Name = From_UTF8( in->CurText() );
121
122 in->NeedRIGHT(); // end (name ...)
123
124 while( (tok = in->NextTok() ) != T_RIGHT && tok != T_EOF )
125 {
126 // "visible" has no '(' prefix, "value" does, so T_LEFT is optional.
127 if( tok == T_LEFT )
128 tok = in->NextTok();
129
130 switch( tok )
131 {
132 case T_value:
133 // older format; silently skip
134 in->NeedSYMBOLorNUMBER();
135 in->NeedRIGHT();
136 break;
137
138 case T_visible:
139 m_Visible = true;
140 break;
141
142 case T_url:
143 m_URL = true;
144 break;
145
146 default:
147 in->Expecting( "value|url|visible" );
148 break;
149 }
150 }
151}
152
153
154void TEMPLATES::Format( OUTPUTFORMATTER* out, bool aGlobal ) const
155{
156 // We'll keep this general, and include the \n, even though the only known
157 // use at this time will not want the newlines or the indentation.
158 out->Print( "(templatefields" );
159
160 const std::vector<TEMPLATE_FIELDNAME>& source = aGlobal ? m_globals : m_project;
161
162 for( const TEMPLATE_FIELDNAME& temp : source )
163 {
164 if( !temp.m_Name.IsEmpty() )
165 temp.Format( out );
166 }
167
168 out->Print( ")" );
169}
170
171
172void TEMPLATES::parse( TEMPLATE_FIELDNAMES_LEXER* in, bool aGlobal )
173{
174 T tok;
175
176 while( ( tok = in->NextTok() ) != T_RIGHT && tok != T_EOF )
177 {
178 if( tok == T_LEFT )
179 tok = in->NextTok();
180
181 switch( tok )
182 {
183 case T_templatefields: // a token indicating class TEMPLATES.
184
185 // Be flexible regarding the starting point of the TEMPLATE_FIELDNAMES_LEXER
186 // stream. Caller may not have read the first two tokens out of the
187 // stream: T_LEFT and T_templatefields, so ignore them if seen here.
188 break;
189
190 case T_field:
191 {
192 // instantiate on stack, so if exception is thrown,
193 // destructor runs
194 TEMPLATE_FIELDNAME field;
195
196 field.Parse( in );
197
198 // add the field
199 if( !field.m_Name.IsEmpty() )
200 AddTemplateFieldName( field, aGlobal );
201 }
202 break;
203
204 default:
205 in->Unexpected( in->CurText() );
206 break;
207 }
208 }
209}
210
211
217{
219
220 // Note: order N^2 algorithm. Would need changing if fieldname template sets ever
221 // get large.
222
223 for( const TEMPLATE_FIELDNAME& global : m_globals )
224 {
225 bool overriddenInProject = false;
226
227 for( const TEMPLATE_FIELDNAME& project : m_project )
228 {
229 if( global.m_Name == project.m_Name )
230 {
231 overriddenInProject = true;
232 break;
233 }
234 }
235
236 if( !overriddenInProject )
237 m_resolved.push_back( global );
238 }
239
240 m_resolvedDirty = false;
241}
242
243
244void TEMPLATES::AddTemplateFieldName( const TEMPLATE_FIELDNAME& aFieldName, bool aGlobal )
245{
246 // Ensure that the template fieldname does not match a fixed fieldname.
247 for( FIELD_T fieldId : MANDATORY_FIELDS )
248 {
249 if( GetCanonicalFieldName( fieldId ) == aFieldName.m_Name )
250 return;
251 }
252
253 std::vector<TEMPLATE_FIELDNAME>& target = aGlobal ? m_globals : m_project;
254
255 // ensure uniqueness, overwrite any template fieldname by the same name.
256 for( TEMPLATE_FIELDNAME& temp : target )
257 {
258 if( temp.m_Name == aFieldName.m_Name )
259 {
260 temp = aFieldName;
261 m_resolvedDirty = true;
262 return;
263 }
264 }
265
266 // the name is legal and not previously added to the config container, append
267 // it and return its index within the container.
268 target.push_back( aFieldName );
269 m_resolvedDirty = true;
270}
271
272
273void TEMPLATES::AddTemplateFieldNames( const wxString& aSerializedFieldNames )
274{
275 TEMPLATE_FIELDNAMES_LEXER field_lexer( TO_UTF8( aSerializedFieldNames ) );
276
277 try
278 {
279 parse( &field_lexer, true );
280 }
281 catch( const IO_ERROR& )
282 {
283 }
284}
285
286
288{
289 if( aGlobal )
290 {
291 m_globals.clear();
293 }
294 else
295 {
296 m_project.clear();
298 }
299
300 m_resolvedDirty = false;
301}
302
303
304const std::vector<TEMPLATE_FIELDNAME>& TEMPLATES::GetTemplateFieldNames()
305{
306 if( m_resolvedDirty )
308
309 return m_resolved;
310}
311
312
313const std::vector<TEMPLATE_FIELDNAME>& TEMPLATES::GetTemplateFieldNames( bool aGlobal )
314{
315 if( aGlobal )
316 return m_globals;
317 else
318 return m_project;
319}
320
321
322const TEMPLATE_FIELDNAME* TEMPLATES::GetFieldName( const wxString& aName )
323{
324 if( m_resolvedDirty )
326
327 for( const TEMPLATE_FIELDNAME& field : m_resolved )
328 {
329 if( field.m_Name == aName )
330 return &field;
331 }
332
333 return nullptr;
334}
335
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
An interface used to output 8 bit text in a convenient way.
Definition richio.h:291
std::string Quotew(const wxString &aWrapee) const
Definition richio.cpp:507
int PRINTF_FUNC_N Print(int nestLevel, const char *fmt,...)
Format and write text to the output stream.
Definition richio.cpp:422
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.
const std::vector< TEMPLATE_FIELDNAME > & GetTemplateFieldNames()
Return a template field name list for read only access.
std::vector< TEMPLATE_FIELDNAME > m_resolved
void resolveTemplates()
Flatten project and global templates into a single list.
std::vector< TEMPLATE_FIELDNAME > m_project
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)
std::vector< TEMPLATE_FIELDNAME > m_globals
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.
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
static wxString s_CanonicalSheetFile(SHEET_FILE_CANONICAL)
#define FOOTPRINT_CANONICAL
#define USER_FIELD_CANONICAL
#define INTERSHEET_REFS_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
wxString GetUserFieldName(int aFieldNdx, bool aTranslateForHI)
static wxString s_CanonicalIntersheetRefs(INTERSHEET_REFS_CANONICAL)
#define SHEET_NAME_CANONICAL
static wxString s_CanonicalSheetName(SHEET_NAME_CANONICAL)
#define DESCRIPTION_CANONICAL
static wxString s_CanonicalDescription(DESCRIPTION_CANONICAL)
#define REFERENCE_CANONICAL
#define SHEET_FILE_CANONICAL
wxString GetDefaultFieldName(FIELD_T aFieldId, bool aTranslateForHI)
Return a default symbol field name for a mandatory field type.
#define MANDATORY_FIELDS
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ INTERSHEET_REFS
Global label cross-reference page numbers.
@ DESCRIPTION
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ DATASHEET
name of datasheet
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
wxString GetCanonicalFieldName(FIELD_T aFieldType)