Eeschema: fix corrupted schematic and symbol library files.

Prevent user from pasting text with carriage return and/or line feed
characters in field value edit control in the schematic symbol and symbol
library properties dialogs.

Make all objects derived from GRID_CELL_TEXT_BUTTON use validators
correctly.

Add validators to FIELDS_GRID_TABLE object for field values other than
the mandatory fields.

Create a validator to check that a string is a valid LIB_ID.

Fixes lp:1828214

https://bugs.launchpad.net/kicad/+bug/1828214
(cherry picked from commit ae54f34392)
This commit is contained in:
Wayne Stambaugh 2019-05-10 08:21:08 -04:00
parent a6674ecd56
commit 8e93eda449
8 changed files with 310 additions and 75 deletions

View File

@ -2,7 +2,8 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 2004-2013 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2004-2019 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2018 CERN
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -27,6 +28,7 @@
* @brief Custom text control validator implementations.
*/
#include <confirm.h>
#include <kicad_string.h>
#include <validators.h>
@ -133,7 +135,7 @@ ENV_VAR_NAME_VALIDATOR::~ENV_VAR_NAME_VALIDATOR()
void ENV_VAR_NAME_VALIDATOR::OnChar( wxKeyEvent& aEvent )
{
if (!m_validatorWindow)
if( !m_validatorWindow )
{
aEvent.Skip();
return;
@ -142,7 +144,7 @@ void ENV_VAR_NAME_VALIDATOR::OnChar( wxKeyEvent& aEvent )
int keyCode = aEvent.GetKeyCode();
// we don't filter special keys and delete
if (keyCode < WXK_SPACE || keyCode == WXK_DELETE || keyCode >= WXK_START)
if( keyCode < WXK_SPACE || keyCode == WXK_DELETE || keyCode >= WXK_START )
{
aEvent.Skip();
return;
@ -160,6 +162,7 @@ void ENV_VAR_NAME_VALIDATOR::OnChar( wxKeyEvent& aEvent )
// not as first character
long from, to;
GetTextEntry()->GetSelection( &from, &to );
if( from < 1 )
wxBell();
else
@ -220,6 +223,101 @@ void ENV_VAR_NAME_VALIDATOR::OnTextChanged( wxCommandEvent& event )
}
bool REGEX_VALIDATOR::Validate( wxWindow* aParent )
{
// If window is disabled, simply return
if( !m_validatorWindow->IsEnabled() )
return true;
wxTextEntry* const textEntry = GetTextEntry();
if( !textEntry )
return false;
bool valid = true;
const wxString& value = textEntry->GetValue();
if( m_regEx.Matches( value ) )
{
size_t start, len;
m_regEx.GetMatch( &start, &len );
if( start != 0 || len != value.Length() ) // whole string must match
valid = false;
}
else // no match at all
{
valid = false;
}
if( !valid )
{
m_validatorWindow->SetFocus();
DisplayError( aParent, wxString::Format( _( "Incorrect value: %s" ), value ) );
return false;
}
return true;
}
void REGEX_VALIDATOR::compileRegEx( const wxString& aRegEx, int aFlags )
{
if( !m_regEx.Compile( aRegEx, aFlags ) )
{
throw std::runtime_error( "REGEX_VALIDATOR: Invalid regular expression: "
+ aRegEx.ToStdString() );
}
m_regExString = aRegEx;
m_regExFlags = aFlags;
}
bool LIB_ID_VALIDATOR::Validate( wxWindow *aParent )
{
LIB_ID dummy;
// If window is disabled, simply return
if( !m_validatorWindow->IsEnabled() )
return true;
wxTextEntry* const text = GetTextEntry();
if( !text )
return false;
wxString msg;
wxString val( text->GetValue() );
wxString tmp = val.Clone(); // For trailing and leading white space tests.
if( tmp.Trim() != val ) // Trailing white space.
{
msg = _( "Entry contains trailing white space." );
}
else if( tmp.Trim( false ) != val ) // Leading white space.
{
msg = _( "Entry contains leading white space." );
}
else if( dummy.Parse( val, m_idType ) != -1 || !dummy.IsValid() ) // Is valid LIB_ID.
{
msg.Printf( _( "\"%s\" is not a valid library identifier format." ), val );
}
if( !msg.empty() )
{
m_validatorWindow->SetFocus();
wxMessageBox( msg, _( "Library Identifier Validation Error" ),
wxOK | wxICON_EXCLAMATION, aParent );
return false;
}
return true;
}
void KIUI::ValidatorTransferToWindowWithoutEvents( wxValidator& aValidator )
{
wxWindow* ctrl = aValidator.GetWindow();
@ -228,4 +326,4 @@ void KIUI::ValidatorTransferToWindowWithoutEvents( wxValidator& aValidator )
wxEventBlocker orient_update_blocker( ctrl, wxEVT_ANY );
aValidator.TransferToWindow();
}
}

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2018-2019 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -47,6 +47,7 @@ wxString GRID_CELL_TEXT_BUTTON::GetValue() const
return Combo()->GetValue();
}
void GRID_CELL_TEXT_BUTTON::SetSize( const wxRect& aRect )
{
wxRect rect( aRect );
@ -76,7 +77,8 @@ void GRID_CELL_TEXT_BUTTON::StartingKey( wxKeyEvent& event )
#if wxUSE_UNICODE
ch = event.GetUnicodeKey();
if ( ch != WXK_NONE )
if( ch != WXK_NONE )
isPrintable = true;
else
#endif // wxUSE_UNICODE
@ -85,24 +87,24 @@ void GRID_CELL_TEXT_BUTTON::StartingKey( wxKeyEvent& event )
isPrintable = ch >= WXK_SPACE && ch < WXK_START;
}
switch (ch)
switch( ch )
{
case WXK_DELETE:
// Delete the initial character when starting to edit with DELETE.
textEntry->Remove(0, 1);
textEntry->Remove( 0, 1 );
break;
case WXK_BACK:
// Delete the last character when starting to edit with BACKSPACE.
{
const long pos = textEntry->GetLastPosition();
textEntry->Remove(pos - 1, pos);
textEntry->Remove( pos - 1, pos );
}
break;
default:
if ( isPrintable )
textEntry->WriteText(static_cast<wxChar>(ch));
if( isPrintable )
textEntry->WriteText( static_cast<wxChar>( ch ) );
break;
}
}
@ -110,7 +112,7 @@ void GRID_CELL_TEXT_BUTTON::StartingKey( wxKeyEvent& event )
void GRID_CELL_TEXT_BUTTON::BeginEdit( int aRow, int aCol, wxGrid* aGrid )
{
auto evtHandler = static_cast<wxGridCellEditorEvtHandler*>( m_control->GetEventHandler() );
auto evtHandler = static_cast< wxGridCellEditorEvtHandler* >( m_control->GetEventHandler() );
// Don't immediately end if we get a kill focus event within BeginEdit
evtHandler->SetInSetFocus( true );
@ -122,7 +124,7 @@ void GRID_CELL_TEXT_BUTTON::BeginEdit( int aRow, int aCol, wxGrid* aGrid )
}
bool GRID_CELL_TEXT_BUTTON::EndEdit( int , int , const wxGrid* , const wxString& , wxString *aNewVal )
bool GRID_CELL_TEXT_BUTTON::EndEdit( int, int, const wxGrid*, const wxString&, wxString *aNewVal )
{
const wxString value = Combo()->GetValue();
@ -150,9 +152,13 @@ void GRID_CELL_TEXT_BUTTON::Reset()
}
/**
* Symbol Picker
*/
#if wxUSE_VALIDATORS
void GRID_CELL_TEXT_BUTTON::SetValidator( const wxValidator& validator )
{
m_validator.reset( static_cast< wxValidator* >( validator.Clone() ) );
}
#endif
class TEXT_BUTTON_SYMBOL_CHOOSER : public wxComboCtrl
{
@ -198,14 +204,10 @@ void GRID_CELL_SYMBOL_ID_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
{
m_control = new TEXT_BUTTON_SYMBOL_CHOOSER( aParent, m_dlg, m_preselect );
wxGridCellEditor::Create(aParent, aId, aEventHandler);
wxGridCellEditor::Create( aParent, aId, aEventHandler );
}
/**
* Footprint Picker
*/
class TEXT_BUTTON_FP_CHOOSER : public wxComboCtrl
{
public:
@ -250,14 +252,18 @@ void GRID_CELL_FOOTPRINT_ID_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
{
m_control = new TEXT_BUTTON_FP_CHOOSER( aParent, m_dlg, m_preselect );
wxGridCellEditor::Create(aParent, aId, aEventHandler);
#if wxUSE_VALIDATORS
// validate text in textctrl, if validator is set
if ( m_validator )
{
Combo()->SetValidator( *m_validator );
}
#endif
wxGridCellEditor::Create( aParent, aId, aEventHandler );
}
/**
* URL Viewer
*/
class TEXT_BUTTON_URL : public wxComboCtrl
{
public:
@ -291,14 +297,18 @@ void GRID_CELL_URL_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
{
m_control = new TEXT_BUTTON_URL( aParent, m_dlg );
wxGridCellEditor::Create(aParent, aId, aEventHandler);
#if wxUSE_VALIDATORS
// validate text in textctrl, if validator is set
if ( m_validator )
{
Combo()->SetValidator( *m_validator );
}
#endif
wxGridCellEditor::Create( aParent, aId, aEventHandler );
}
/**
* Path Picker
*/
class TEXT_BUTTON_FILE_BROWSER : public wxComboCtrl
{
public:
@ -341,7 +351,7 @@ protected:
else
{
wxDirDialog dlg( nullptr, _( "Select Path" ), path,
wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST );
wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST );
if( dlg.ShowModal() == wxID_OK )
{
@ -362,16 +372,32 @@ void GRID_CELL_PATH_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
{
m_control = new TEXT_BUTTON_FILE_BROWSER( aParent, m_dlg, m_currentDir );
wxGridCellEditor::Create(aParent, aId, aEventHandler);
#if wxUSE_VALIDATORS
// validate text in textctrl, if validator is set
if ( m_validator )
{
Combo()->SetValidator( *m_validator );
}
#endif
wxGridCellEditor::Create( aParent, aId, aEventHandler );
}
void GRID_CELL_SYMLIB_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
wxEvtHandler* aEventHandler )
wxEvtHandler* aEventHandler )
{
m_control = new TEXT_BUTTON_FILE_BROWSER( aParent, m_dlg, m_currentDir, &m_ext );
wxGridCellEditor::Create(aParent, aId, aEventHandler);
#if wxUSE_VALIDATORS
// validate text in textctrl, if validator is set
if ( m_validator )
{
Combo()->SetValidator( *m_validator );
}
#endif
wxGridCellEditor::Create( aParent, aId, aEventHandler );
}

View File

@ -39,6 +39,7 @@
#include <sch_draw_panel.h>
#include <sch_edit_frame.h>
#include <sch_reference_list.h>
#include <sch_validators.h>
#include <symbol_lib_table.h>
#ifdef KICAD_SPICE
@ -97,7 +98,9 @@ DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::DIALOG_EDIT_COMPONENT_IN_SCHEMATIC( SCH_EDIT
m_bpMoveDown->SetBitmap( KiBitmap( small_down_xpm ) );
// wxFormBuilder doesn't include this event...
m_grid->Connect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnGridCellChanging ), NULL, this );
m_grid->Connect( wxEVT_GRID_CELL_CHANGING,
wxGridEventHandler( DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnGridCellChanging ),
NULL, this );
FinishDialogSettings();
}
@ -110,7 +113,9 @@ DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::~DIALOG_EDIT_COMPONENT_IN_SCHEMATIC()
// Prevents crash bug in wxGrid's d'tor
m_grid->DestroyTable( m_fields );
m_grid->Disconnect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnGridCellChanging ), NULL, this );
m_grid->Disconnect( wxEVT_GRID_CELL_CHANGING,
wxGridEventHandler( DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnGridCellChanging ),
NULL, this );
// Delete the GRID_TRICKS.
m_grid->PopEventHandler( true );
@ -316,7 +321,7 @@ bool DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::Validate()
wxString msg;
LIB_ID id;
if( !m_grid->CommitPendingChanges() )
if( !m_grid->CommitPendingChanges() || !m_grid->Validate() )
return false;
if( !SCH_COMPONENT::IsReferenceStringValid( m_fields->at( REFERENCE ).GetText() ) )
@ -388,7 +393,7 @@ bool DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::Validate()
bool DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::TransferDataFromWindow()
{
if( !Validate() )
if( !wxDialog::TransferDataFromWindow() ) // Calls our Validate() method.
return false;
// save old cmp in undo list if not already in edit, or moving ...
@ -485,9 +490,11 @@ bool DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::TransferDataFromWindow()
SCH_REFERENCE_LIST components;
GetParent()->GetCurrentSheet().GetComponents( components );
for( unsigned i = 0; i < components.GetCount(); i++ )
{
SCH_REFERENCE component = components[i];
if( component.GetLibPart()->GetLibId() == thisLibId
&& component.GetRef() == thisRef
&& component.GetUnit() != thisUnit )

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2018-2019 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -75,10 +75,21 @@ FIELDS_GRID_TABLE<T>::FIELDS_GRID_TABLE( DIALOG_SHIM* aDialog, SCH_BASE_FRAME* a
m_valueAttr->SetEditor( valueEditor );
m_footprintAttr = new wxGridCellAttr;
m_footprintAttr->SetEditor( new GRID_CELL_FOOTPRINT_ID_EDITOR( aDialog ) );
GRID_CELL_FOOTPRINT_ID_EDITOR* fpIdEditor = new GRID_CELL_FOOTPRINT_ID_EDITOR( aDialog );
fpIdEditor->SetValidator( LIB_ID_VALIDATOR( LIB_ID::ID_PCB ) );
m_footprintAttr->SetEditor( fpIdEditor );
m_urlAttr = new wxGridCellAttr;
m_urlAttr->SetEditor( new GRID_CELL_URL_EDITOR( aDialog ) );
GRID_CELL_URL_EDITOR* urlEditor = new GRID_CELL_URL_EDITOR( aDialog );
urlEditor->SetValidator( SCH_FIELD_VALIDATOR( aFrame->IsType( FRAME_SCH_LIB_EDITOR ),
DATASHEET ) );
m_urlAttr->SetEditor( urlEditor );
m_nonUrlAttr = new wxGridCellAttr;
wxGridCellTextEditor* nonUrlEditor = new wxGridCellTextEditor();
nonUrlEditor->SetValidator( SCH_FIELD_VALIDATOR( aFrame->IsType( FRAME_SCH_LIB_EDITOR ),
DATASHEET ) );
m_nonUrlAttr->SetEditor( nonUrlEditor );
m_boolAttr = new wxGridCellAttr;
m_boolAttr->SetRenderer( new wxGridCellBoolRenderer() );
@ -239,6 +250,11 @@ wxGridCellAttr* FIELDS_GRID_TABLE<T>::GetAttr( int aRow, int aCol, wxGridCellAtt
m_urlAttr->IncRef();
return m_urlAttr;
}
else
{
m_nonUrlAttr->IncRef();
return m_nonUrlAttr;
}
}
return nullptr;
@ -281,7 +297,7 @@ wxString FIELDS_GRID_TABLE<T>::GetValue( int aRow, int aCol )
switch( aCol )
{
case FDC_NAME:
// Use default field name for mandatory fields, because they are transalted
// Use default field name for mandatory fields, because they are translated
// according to the current locale
if( aRow < MANDATORY_FIELDS )
return TEMPLATE_FIELDNAME::GetDefaultFieldName( aRow );
@ -488,17 +504,18 @@ template class FIELDS_GRID_TABLE<SCH_FIELD>;
template class FIELDS_GRID_TABLE<LIB_FIELD>;
void FIELDS_GRID_TRICKS::showPopupMenu( wxMenu& menu )
{
if( m_grid->GetGridCursorRow() == FOOTPRINT && m_grid->GetGridCursorCol() == FDC_VALUE )
{
menu.Append( MYID_SELECT_FOOTPRINT, _( "Select Footprint..." ), _( "Browse for footprint" ) );
menu.Append( MYID_SELECT_FOOTPRINT, _( "Select Footprint..." ),
_( "Browse for footprint" ) );
menu.AppendSeparator();
}
else if( m_grid->GetGridCursorRow() == DATASHEET && m_grid->GetGridCursorCol() == FDC_VALUE )
{
menu.Append( MYID_SHOW_DATASHEET, _( "Show Datasheet" ), _( "Show datasheet in browser" ) );
menu.Append( MYID_SHOW_DATASHEET, _( "Show Datasheet" ),
_( "Show datasheet in browser" ) );
menu.AppendSeparator();
}
@ -530,6 +547,7 @@ void FIELDS_GRID_TRICKS::doPopupSelection( wxCommandEvent& event )
}
}
template <class T>
wxString FIELDS_GRID_TABLE<T>::StringFromBool( bool aValue )
{
@ -539,20 +557,22 @@ wxString FIELDS_GRID_TABLE<T>::StringFromBool( bool aValue )
return wxT( "0" );
}
template <class T>
bool FIELDS_GRID_TABLE<T>::BoolFromString( wxString aValue )
{
if( aValue == wxT( "1" ) )
if( aValue == "1" )
{
return true;
}
else if( aValue == wxT( "0" ) )
else if( aValue == "0" )
{
return false;
}
else
{
wxFAIL_MSG( wxString::Format( wxT( "string \"%s\" can't be converted to boolean correctly, it will have been perceived as FALSE" ), aValue ) );
wxFAIL_MSG( wxString::Format( "string \"%s\" can't be converted to boolean "
"correctly, it will have been perceived as FALSE", aValue ) );
return false;
}
}

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2018-2019 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -112,6 +112,7 @@ private:
wxGridCellAttr* m_valueAttr;
wxGridCellAttr* m_footprintAttr;
wxGridCellAttr* m_urlAttr;
wxGridCellAttr* m_nonUrlAttr;
wxGridCellAttr* m_boolAttr;
wxGridCellAttr* m_vAlignAttr;
wxGridCellAttr* m_hAlignAttr;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 Wayne Stambaugh, stambaughw@gmail.com
* Copyright (C) 2016 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2016-2019 KiCad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -24,7 +24,7 @@
/**
* @file sch_validators.h
* @brief Defintions of control validators for schematic dialogs.
* @brief Definitions of control validators for schematic dialogs.
*/
#ifndef _SCH_VALIDATORS_H_
@ -37,15 +37,12 @@
/**
* class SCH_FILED_VALIDATOR
*
* is the text control validator used for validating the text allowed in library and
* A text control validator used for validating the text allowed in library and
* schematic component fields.
* Note
* Reference field does not accept spaces
* Value field does not accept spaces in Component Library Editor, because in .lib component
* libraries, the value field is the component name in lib, and spaces are not allowed
* in component names in lib
*
* - The reference field does not accept spaces.
* - The value field does not accept spaces in the symbol library editor because in symbol
* libraries, the value field is the symbol name in the library.
*/
class SCH_FIELD_VALIDATOR : public wxTextValidator
{
@ -60,9 +57,7 @@ public:
virtual wxObject* Clone() const override { return new SCH_FIELD_VALIDATOR( *this ); }
/**
* Function Validate
*
* overrides the default Validate() function provided by wxTextValidate to provide
* Override the default Validate() function provided by wxTextValidator to provide
* better error messages.
*
* @param aParent - a pointer to the parent window of the error message dialog.

View File

@ -2,7 +2,8 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 2004-2013 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2004-2019 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2018 CERN
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -32,10 +33,11 @@
#include <wx/valtext.h>
#include <wx/grid.h>
#include <wx/regex.h>
#include <lib_id.h>
/**
* Class GRID_CELL_TEXT_EDITOR
*
* This class works around a bug in wxGrid where the first keystroke doesn't get sent through
* the validator if the editor wasn't already open.
*/
@ -53,8 +55,6 @@ protected:
/**
* Class FILE_NAME_CHAR_VALIDATOR
*
* This class provides a custom wxValidator object for limiting the allowable characters when
* defining footprint names. Since the introduction of the PRETTY footprint library format,
* footprint names cannot have any characters that would prevent file creation on any platform.
@ -68,8 +68,6 @@ public:
/**
* Class FILE_NAME_WITH_PATH_CHAR_VALIDATOR
*
* This class provides a custom wxValidator object for limiting the allowable characters when
* defining file names with path, for instance in schematic sheet file names.
* The characters *?|"<> are illegal and filtered by the validator,
@ -83,10 +81,8 @@ public:
/**
* Class ENV_VAR_NAME_VALIDATOR
*
* This class provides a custom wxValidator object for limiting the allowable characters
* when defining an environment varaible name in a text edit control. Only uppercase,
* when defining an environment variable name in a text edit control. Only uppercase,
* numbers, and underscore (_) characters are valid and the first character of the name
* cannot start with a number. This is according to IEEE Std 1003.1-2001. Even though
* most systems support other characters, these characters guarantee compatibility for
@ -112,10 +108,94 @@ public:
void OnTextChanged( wxCommandEvent& event );
};
/**
* Custom validator that checks verifies that a string *exactly* matches a
* regular expression.
*/
class REGEX_VALIDATOR : public wxTextValidator
{
public:
/**
* @param aRegEx is a regular expression to validate strings.
* @param aValue is a pointer to a wxString containing the value to validate.
*/
REGEX_VALIDATOR( const wxString& aRegEx, wxString* aValue = NULL )
: wxTextValidator( wxFILTER_NONE, aValue )
{
compileRegEx( aRegEx, wxRE_DEFAULT );
}
/**
* @param aRegEx is a regular expression to validate strings.
* @param aFlags are compilation flags (normally wxRE_DEFAULT).
* @param aValue is a pointer to a wxString containing the value to validate.
*/
REGEX_VALIDATOR( const wxString& aRegEx, int aFlags, wxString* aValue = NULL )
: wxTextValidator( wxFILTER_NONE, aValue )
{
compileRegEx( aRegEx, aFlags );
}
REGEX_VALIDATOR( const REGEX_VALIDATOR& aOther )
{
wxValidator::Copy( aOther );
compileRegEx( aOther.m_regExString, aOther.m_regExFlags );
}
virtual wxObject* Clone() const override
{
return new REGEX_VALIDATOR( *this );
}
bool Validate( wxWindow* aParent ) override;
protected:
///> Compiles and stores a regular expression
void compileRegEx( const wxString& aRegEx, int aFlags );
///> Original regular expression (for copy constructor)
wxString m_regExString;
///> Original compilation flags (for copy constructor)
int m_regExFlags;
///> Compiled regex
wxRegEx m_regEx;
};
/**
* Custom validator that verifies that a string defines a valid #LIB_ID.
*/
class LIB_ID_VALIDATOR : public wxTextValidator
{
public:
/**
* @param aLibIdType is the type of #LIB_ID object to validate.
* @param aValue is a pointer to a wxString containing the value to validate.
*/
LIB_ID_VALIDATOR( LIB_ID::LIB_ID_TYPE aLibIdType, wxString* aValue = NULL ) :
wxTextValidator( wxFILTER_EXCLUDE_CHAR_LIST, aValue ),
m_idType( aLibIdType )
{
SetCharExcludes( "\r\n\t" );
}
virtual wxObject* Clone() const override
{
return new LIB_ID_VALIDATOR( *this );
}
bool Validate( wxWindow* aParent ) override;
protected:
LIB_ID::LIB_ID_TYPE m_idType;
};
namespace KIUI
{
/**
* Call a text validator's TransferToWindow method without firing
* Call a text validator's TransferDataToWindow method without firing
* a text change event.
*
* This is useful when you want to keep a validator in sync with other data,

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2018-2019 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -48,9 +48,17 @@ public:
void ApplyEdit( int aRow, int aCol, wxGrid* aGrid ) override;
void Reset() override;
#if wxUSE_VALIDATORS
void SetValidator( const wxValidator& validator );
#endif
protected:
wxComboCtrl* Combo() const { return static_cast<wxComboCtrl*>( m_control ); }
#if wxUSE_VALIDATORS
wxScopedPtr< wxValidator > m_validator;
#endif
wxString m_value;
wxDECLARE_NO_COPY_CLASS( GRID_CELL_TEXT_BUTTON );