KiCad PCB EDA Suite
sch_validators.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) 2016 Wayne Stambaugh, [email protected]
5 * Copyright (C) 2016-2021 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
30#include <wx/combo.h>
31#include <wx/msgdlg.h>
32
33#include <sch_connection.h>
34#include <sch_validators.h>
36#include <template_fieldnames.h>
37
38
39SCH_FIELD_VALIDATOR::SCH_FIELD_VALIDATOR( bool aIsLibEditor, int aFieldId, wxString* aValue ) :
40 wxTextValidator( wxFILTER_EXCLUDE_CHAR_LIST, aValue )
41{
42 m_fieldId = aFieldId;
43 m_isLibEditor = aIsLibEditor;
44
45 // Fields cannot contain carriage returns, line feeds, or tabs.
46 wxString excludes( wxT( "\r\n\t" ) );
47
48 // The reference and sheet name fields cannot contain spaces.
49 if( aFieldId == REFERENCE_FIELD )
50 {
51 excludes += wxT( " " );
52 }
53 else if( m_fieldId == SHEETNAME_V )
54 {
55 excludes += wxT( "/" );
56 }
57
58 long style = GetStyle();
59
60 // The reference, value sheetname and sheetfilename fields cannot be empty.
61 if( aFieldId == REFERENCE_FIELD
62 || aFieldId == VALUE_FIELD
63 || aFieldId == SHEETNAME_V
64 || aFieldId == SHEETFILENAME_V
65 || aFieldId == FIELD_NAME )
66 {
67 style |= wxFILTER_EMPTY;
68 }
69
70 SetStyle( style );
71 SetCharExcludes( excludes );
72}
73
74
76 wxTextValidator( aValidator )
77{
78 m_fieldId = aValidator.m_fieldId;
79 m_isLibEditor = aValidator.m_isLibEditor;
80}
81
82
83bool SCH_FIELD_VALIDATOR::Validate( wxWindow* aParent )
84{
85 // If window is disabled, simply return
86 if( !m_validatorWindow->IsEnabled() )
87 return true;
88
89 wxTextEntry* const text = GetTextEntry();
90
91 if( !text )
92 return false;
93
94 wxString val( text->GetValue() );
95
96 // The format of the error message for not allowed chars
97 wxString fieldCharError;
98
99 switch( m_fieldId )
100 {
101 case REFERENCE_FIELD:
102 fieldCharError = _( "The reference designator cannot contain %s character(s)." );
103 break;
104
105 case VALUE_FIELD:
106 fieldCharError = _( "The value field cannot contain %s character(s)." );
107 break;
108
109 case FOOTPRINT_FIELD:
110 fieldCharError = _( "The footprint field cannot contain %s character(s)." );
111 break;
112
113 case DATASHEET_FIELD:
114 fieldCharError = _( "The datasheet field cannot contain %s character(s)." );
115 break;
116
117 case SHEETNAME_V:
118 fieldCharError = _( "The sheet name cannot contain %s character(s)." );
119 break;
120
121 case SHEETFILENAME_V:
122 fieldCharError = _( "The sheet filename cannot contain %s character(s)." );
123 break;
124
125 default:
126 fieldCharError = _( "The field cannot contain %s character(s)." );
127 break;
128 };
129
130 wxString msg;
131
132 // We can only do some kinds of validation once the input is complete, so
133 // check for them here:
134 if( HasFlag( wxFILTER_EMPTY ) && val.empty() )
135 {
136 // Some fields cannot have an empty value, and user fields require a name:
137 if( m_fieldId == FIELD_NAME )
138 msg.Printf( _( "The name of the field cannot be empty." ) );
139 else // the FIELD_VALUE id or REFERENCE_FIELD or VALUE_FIELD
140 msg.Printf( _( "The value of the field cannot be empty." ) );
141 }
142 else if( HasFlag( wxFILTER_EXCLUDE_CHAR_LIST ) && ContainsExcludedCharacters( val ) )
143 {
144 wxArrayString badCharsFound;
145
146 for( const wxString& excludeChar : GetExcludes() )
147 {
148 if( val.Find( excludeChar ) != wxNOT_FOUND )
149 {
150 if( excludeChar == wxT( "\r" ) )
151 badCharsFound.Add( _( "carriage return" ) );
152 else if( excludeChar == wxT( "\n" ) )
153 badCharsFound.Add( _( "line feed" ) );
154 else if( excludeChar == wxT( "\t" ) )
155 badCharsFound.Add( _( "tab" ) );
156 else if( excludeChar == wxT( " " ) )
157 badCharsFound.Add( _( "space" ) );
158 else
159 badCharsFound.Add( wxString::Format( wxT( "'%s'" ), excludeChar ) );
160 }
161 }
162
163 wxString badChars;
164
165 for( size_t i = 0; i < badCharsFound.GetCount(); i++ )
166 {
167 if( !badChars.IsEmpty() )
168 {
169 if( badCharsFound.GetCount() == 2 )
170 {
171 badChars += _( " or " );
172 }
173 else
174 {
175 if( i < badCharsFound.GetCount() - 2 )
176 badChars += _( ", or " );
177 else
178 badChars += wxT( ", " );
179 }
180 }
181
182 badChars += badCharsFound.Item( i );
183 }
184
185 msg.Printf( fieldCharError, badChars );
186 }
187 else if( m_fieldId == REFERENCE_FIELD && val.Contains( wxT( "${" ) ) )
188 {
189 msg.Printf( _( "The reference designator cannot contain text variable references" ) );
190 }
191
192 if ( !msg.empty() )
193 {
194 m_validatorWindow->SetFocus();
195
196 wxMessageBox( msg, _( "Field Validation Error" ), wxOK | wxICON_EXCLAMATION, aParent );
197
198 return false;
199 }
200
201 return true;
202}
203
204
205// Match opening curly brace, preceeded by start-of-line or by a character not including $_^~
206wxRegEx SCH_NETNAME_VALIDATOR::m_busGroupRegex( R"((^|[^$_\^~]){)", wxRE_ADVANCED );
207
208
209wxString SCH_NETNAME_VALIDATOR::IsValid( const wxString& str ) const
210{
211 wxString msg = NETNAME_VALIDATOR::IsValid( str );
212
213 if( !msg.IsEmpty() )
214 return msg;
215
216 // We don't do single-character validation here
217 if( str.Length() == 1 )
218 return wxString();
219
220 // Figuring out if the user "meant" to make a bus group is somewhat tricky because curly
221 // braces are also used for formatting and variable expansion
222
223 if( m_busGroupRegex.Matches( str ) && str.Contains( '}' ) )
224 {
225 if( !NET_SETTINGS::ParseBusGroup( str, nullptr, nullptr ) )
226 return _( "Signal name contains '{' and '}' but is not a valid bus name" );
227 }
228 else if( str.Contains( '[' ) || str.Contains( ']' ) )
229 {
230 if( !NET_SETTINGS::ParseBusVector( str, nullptr, nullptr ) )
231 return _( "Signal name contains '[' or ']' but is not a valid bus name." );
232 }
233
234 return wxString();
235}
wxString IsValid(const wxString &aVal) const override
Definition: validators.cpp:364
static bool ParseBusGroup(const wxString &aGroup, wxString *name, std::vector< wxString > *aMemberList)
Parse a bus group label into the name and a list of components.
static bool ParseBusVector(const wxString &aBus, wxString *aName, std::vector< wxString > *aMemberList)
Parse a bus vector (e.g.
A text control validator used for validating the text allowed in library and schematic symbol fields.
SCH_FIELD_VALIDATOR(bool aIsLibEditor, int aFieldId, wxString *aValue=nullptr)
virtual bool Validate(wxWindow *aParent) override
Override the default Validate() function provided by wxTextValidator to provide better error messages...
static wxRegEx m_busGroupRegex
wxString IsValid(const wxString &aVal) const override
#define _(s)
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
Definitions of control validators for schematic dialogs.
#define SHEETFILENAME_V
#define FIELD_NAME
#define SHEETNAME_V
@ DATASHEET_FIELD
name of datasheet
@ FOOTPRINT_FIELD
Field Name Module PCB, i.e. "16DIP300".
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".