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>
35 #include <project/net_settings.h>
36 #include <template_fieldnames.h>
37 
38 
39 SCH_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 
83 bool 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 $_^~
206 wxRegEx SCH_NETNAME_VALIDATOR::m_busGroupRegex( R"((^|[^$_\^~]){)", wxRE_ADVANCED );
207 
208 
209 wxString 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 }
Field Reference of part, i.e. "IC21".
#define SHEETNAME_V
name of datasheet
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.
wxString IsValid(const wxString &aVal) const override
Field Value of part, i.e. "3.3K".
static wxRegEx m_busGroupRegex
Definitions of control validators for schematic dialogs.
#define SHEETFILENAME_V
#define FIELD_NAME
#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
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.
wxString IsValid(const wxString &aVal) const override
Definition: validators.cpp:364
virtual bool Validate(wxWindow *aParent) override
Override the default Validate() function provided by wxTextValidator to provide better error messages...
SCH_FIELD_VALIDATOR(bool aIsLibEditor, int aFieldId, wxString *aValue=nullptr)
Field Name Module PCB, i.e. "16DIP300".