Commit f0b2565f authored by Wayne Stambaugh's avatar Wayne Stambaugh

Eeschema find/replace bug fixes and improvements (fixes 1208616).

* Fix replace bug to handle case sensitivity properly.
* Fix replace bug where the item index was getting updated incorrectly.
* Fix replace infinite loop bug on replace all.
* Make find/replace view update code a separate function.
* Rearrange find/replace trace string to add tracing to EDA_ITEM::Replace().
* Add IsComplexHierarchy method to SCH_SHEET_LIST for future find/replace
  improvements.
parent 2229b5ff
...@@ -38,6 +38,10 @@ ...@@ -38,6 +38,10 @@
#include "../eeschema/dialogs/dialog_schematic_find.h" #include "../eeschema/dialogs/dialog_schematic_find.h"
const wxString traceFindReplace( wxT( "KicadFindReplace" ) );
enum textbox { enum textbox {
ID_TEXTBOX_LIST = 8010 ID_TEXTBOX_LIST = 8010
}; };
...@@ -190,8 +194,28 @@ bool EDA_ITEM::Replace( wxFindReplaceData& aSearchData, wxString& aText ) ...@@ -190,8 +194,28 @@ bool EDA_ITEM::Replace( wxFindReplaceData& aSearchData, wxString& aText )
wxCHECK_MSG( IsReplaceable(), false, wxCHECK_MSG( IsReplaceable(), false,
wxT( "Attempt to replace text in <" ) + GetClass() + wxT( "> item." ) ); wxT( "Attempt to replace text in <" ) + GetClass() + wxT( "> item." ) );
return aText.Replace( aSearchData.GetFindString(), wxString searchString = (aSearchData.GetFlags() & wxFR_MATCHCASE) ? aText.Upper() : aText;
aSearchData.GetReplaceString(), false ) != 0;
int result = searchString.Find( (aSearchData.GetFlags() & wxFR_MATCHCASE) ?
aSearchData.GetFindString() :
aSearchData.GetFindString().Upper() );
if( result == wxNOT_FOUND )
return false;
wxString prefix = aText.Left( result );
wxString suffix;
if( aSearchData.GetFindString().length() + result < aText.length() )
suffix = aText.Right( aText.length() - ( aSearchData.GetFindString().length() + result ) );
wxLogTrace( traceFindReplace, wxT( "Replacing '%s', prefix '%s', replace '%s', suffix '%s'." ),
GetChars( aText ), GetChars( prefix ), GetChars( aSearchData.GetReplaceString() ),
GetChars( suffix ) );
aText = prefix + aSearchData.GetReplaceString() + suffix;
return true;
} }
......
...@@ -39,8 +39,6 @@ ...@@ -39,8 +39,6 @@
#include <protos.h> #include <protos.h>
const wxString traceFindReplace( wxT( "KicadFindReplace" ) );
const wxString traceFindItem( wxT( "KicadFindItem" ) ); const wxString traceFindItem( wxT( "KicadFindItem" ) );
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
*/ */
enum SchematicFindReplaceFlags enum SchematicFindReplaceFlags
{ {
// The last wxFindReplaceFlag enum is wxFR_MATCHCASE. // The last wxFindReplaceFlag enum is wxFR_MATCHCASE = 0x4.
/// Search the current sheet only. /// Search the current sheet only.
FR_CURRENT_SHEET_ONLY = wxFR_MATCHCASE << 1, FR_CURRENT_SHEET_ONLY = wxFR_MATCHCASE << 1,
......
...@@ -288,12 +288,11 @@ SCH_ITEM* SCH_EDIT_FRAME::FindComponentAndItem( const wxString& aReference, ...@@ -288,12 +288,11 @@ SCH_ITEM* SCH_EDIT_FRAME::FindComponentAndItem( const wxString& aReference,
void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent ) void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent )
{ {
static wxPoint itemPosition; // the actual position of the matched item. static wxPoint itemPosition; // the actual position of the matched item.
SCH_SHEET_LIST schematic; SCH_SHEET_LIST schematic;
wxString msg; wxString msg;
SCH_FIND_REPLACE_DATA searchCriteria; SCH_FIND_REPLACE_DATA searchCriteria;
bool warpCursor = !( aEvent.GetFlags() & FR_NO_WARP_CURSOR );
SCH_FIND_COLLECTOR_DATA data; SCH_FIND_COLLECTOR_DATA data;
searchCriteria.SetFlags( aEvent.GetFlags() ); searchCriteria.SetFlags( aEvent.GetFlags() );
...@@ -326,6 +325,88 @@ void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent ) ...@@ -326,6 +325,88 @@ void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent )
m_foundItems.UpdateIndex(); m_foundItems.UpdateIndex();
} }
updateFindReplaceView( aEvent );
}
void SCH_EDIT_FRAME::OnFindReplace( wxFindDialogEvent& aEvent )
{
SCH_ITEM* item;
SCH_SHEET_PATH* sheet;
SCH_SHEET_LIST schematic;
SCH_FIND_COLLECTOR_DATA data;
if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_REPLACE_ALL )
{
while( ( item = (SCH_ITEM*) m_foundItems.GetItem( data ) ) != NULL )
{
SCH_ITEM* undoItem = data.GetParent();
// Don't save child items in undo list.
if( undoItem == NULL )
undoItem = item;
SetUndoItem( undoItem );
sheet = schematic.GetSheet( data.GetSheetPath() );
wxCHECK_RET( sheet != NULL, wxT( "Could not find sheet path " ) + data.GetSheetPath() );
if( m_foundItems.ReplaceItem( sheet ) )
{
OnModify();
SaveUndoItemInUndoList( undoItem );
updateFindReplaceView( aEvent );
}
m_foundItems.IncrementIndex();
if( m_foundItems.PassedEnd() )
break;
}
}
else
{
SCH_ITEM* item = (SCH_ITEM*) m_foundItems.GetItem( data );
wxCHECK_RET( item != NULL, wxT( "Invalid replace item in find collector list." ) );
SCH_ITEM* undoItem = data.GetParent();
if( undoItem == NULL )
undoItem = item;
SetUndoItem( undoItem );
sheet = schematic.GetSheet( data.GetSheetPath() );
wxCHECK_RET( sheet != NULL, wxT( "Could not find sheet path " ) + data.GetSheetPath() );
if( m_foundItems.ReplaceItem( sheet ) )
{
OnModify();
SaveUndoItemInUndoList( undoItem );
updateFindReplaceView( aEvent );
}
m_foundItems.IncrementIndex();
}
// End the replace if we are at the end if the list. This prevents an infinite loop if
// wrap search is selected and all of the items have been replaced with a value that
// still satisfies the search criteria.
if( m_foundItems.PassedEnd() )
aEvent.SetFlags( aEvent.GetFlags() & ~FR_REPLACE_ITEM_FOUND );
}
void SCH_EDIT_FRAME::updateFindReplaceView( wxFindDialogEvent& aEvent )
{
wxString msg;
SCH_SHEET_LIST schematic;
SCH_FIND_COLLECTOR_DATA data;
bool warpCursor = !( aEvent.GetFlags() & FR_NO_WARP_CURSOR );
if( m_foundItems.GetItem( data ) != NULL ) if( m_foundItems.GetItem( data ) != NULL )
{ {
wxLogTrace( traceFindReplace, wxT( "Found " ) + m_foundItems.GetText() ); wxLogTrace( traceFindReplace, wxT( "Found " ) + m_foundItems.GetText() );
...@@ -335,13 +416,15 @@ void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent ) ...@@ -335,13 +416,15 @@ void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent )
wxCHECK_RET( sheet != NULL, wxT( "Could not find sheet path " ) + wxCHECK_RET( sheet != NULL, wxT( "Could not find sheet path " ) +
data.GetSheetPath() ); data.GetSheetPath() );
SCH_ITEM* item = (SCH_ITEM*)m_foundItems.GetItem( data );
// Make the item temporarily visible just in case it's hide flag is set. This // Make the item temporarily visible just in case it's hide flag is set. This
// has no effect on objects that don't support hiding. If this is a close find // has no effect on objects that don't support hiding. If this is a close find
// dialog event, clear the temporary visibility flag. // dialog event, clear the temporary visibility flag.
if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_CLOSE ) if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_CLOSE )
m_foundItems.GetItem( data )->SetForceVisible( false ); item->SetForceVisible( false );
else else if( item->Type() == SCH_FIELD_T && !( (SCH_FIELD*) item )->IsVisible() )
m_foundItems.GetItem( data )->SetForceVisible( true ); item->SetForceVisible( true );
if( sheet->PathHumanReadable() != m_CurrentSheet->PathHumanReadable() ) if( sheet->PathHumanReadable() != m_CurrentSheet->PathHumanReadable() )
{ {
...@@ -371,61 +454,3 @@ void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent ) ...@@ -371,61 +454,3 @@ void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent )
SetStatusText( msg ); SetStatusText( msg );
} }
void SCH_EDIT_FRAME::OnFindReplace( wxFindDialogEvent& aEvent )
{
SCH_FIND_COLLECTOR_DATA data;
bool warpCursor = !( aEvent.GetFlags() & FR_NO_WARP_CURSOR );
SCH_ITEM* item = (SCH_ITEM*) m_foundItems.GetItem( data );
wxCHECK_RET( item != NULL, wxT( "Invalid replace item in find collector list." ) );
wxLogTrace( traceFindReplace, wxT( "Replacing %s with %s in item %s" ),
GetChars( aEvent.GetFindString() ), GetChars( aEvent.GetReplaceString() ),
GetChars( m_foundItems.GetText() ) );
SCH_ITEM* undoItem = data.GetParent();
if( undoItem == NULL )
undoItem = item;
SetUndoItem( undoItem );
if( m_foundItems.ReplaceItem() )
{
OnModify();
SaveUndoItemInUndoList( undoItem );
RedrawScreen( data.GetPosition(), warpCursor );
}
OnFindSchematicItem( aEvent );
if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_REPLACE_ALL )
{
while( ( item = (SCH_ITEM*) m_foundItems.GetItem( data ) ) != NULL )
{
wxLogTrace( traceFindReplace, wxT( "Replacing %s with %s in item %s" ),
GetChars( aEvent.GetFindString() ), GetChars( aEvent.GetReplaceString() ),
GetChars( m_foundItems.GetText() ) );
SCH_ITEM* undoItem = data.GetParent();
// Don't save child items in undo list.
if( undoItem == NULL )
undoItem = item;
SetUndoItem( undoItem );
if( m_foundItems.ReplaceItem() )
{
OnModify();
SaveUndoItemInUndoList( undoItem );
RedrawScreen( data.GetPosition(), warpCursor );
}
OnFindSchematicItem( aEvent );
}
}
}
...@@ -347,7 +347,7 @@ bool SCH_FIND_COLLECTOR::PassedEnd() const ...@@ -347,7 +347,7 @@ bool SCH_FIND_COLLECTOR::PassedEnd() const
if( GetCount() == 0 ) if( GetCount() == 0 )
return true; return true;
if( !(flags & FR_SEARCH_WRAP) ) if( !(flags & FR_SEARCH_WRAP) || (flags & FR_SEARCH_REPLACE) )
{ {
if( flags & wxFR_DOWN ) if( flags & wxFR_DOWN )
{ {
...@@ -454,7 +454,7 @@ EDA_ITEM* SCH_FIND_COLLECTOR::GetItem( SCH_FIND_COLLECTOR_DATA& aData ) ...@@ -454,7 +454,7 @@ EDA_ITEM* SCH_FIND_COLLECTOR::GetItem( SCH_FIND_COLLECTOR_DATA& aData )
} }
bool SCH_FIND_COLLECTOR::ReplaceItem() bool SCH_FIND_COLLECTOR::ReplaceItem( SCH_SHEET_PATH* aSheetPath )
{ {
if( PassedEnd() ) if( PassedEnd() )
return false; return false;
...@@ -464,15 +464,10 @@ bool SCH_FIND_COLLECTOR::ReplaceItem() ...@@ -464,15 +464,10 @@ bool SCH_FIND_COLLECTOR::ReplaceItem()
EDA_ITEM* item = m_List[ m_foundIndex ]; EDA_ITEM* item = m_List[ m_foundIndex ];
bool replaced = item->Replace( m_findReplaceData ); bool replaced = item->Replace( m_findReplaceData, aSheetPath );
// If the replace was successful, remove the item from the find list to prevent
// iterating back over it again.
if( replaced ) if( replaced )
{ m_forceSearch = true;
Remove( m_foundIndex );
m_data.erase( m_data.begin() + m_foundIndex );
}
return replaced; return replaced;
} }
......
...@@ -237,15 +237,6 @@ class SCH_FIND_COLLECTOR : public COLLECTOR ...@@ -237,15 +237,6 @@ class SCH_FIND_COLLECTOR : public COLLECTOR
/// performed even if the search criteria hasn't changed. /// performed even if the search criteria hasn't changed.
bool m_forceSearch; bool m_forceSearch;
/**
* Function PassedEnd
* tests if #m_foundIndex is beyond the end of the list give the current
* find/replace criterial in #m_findReplaceData.
*
* @return True if #m_foundIndex has crossed the end of the found item list.
*/
bool PassedEnd() const;
/** /**
* Function dump * Function dump
* is a helper to dump the items in the find list for debugging purposes. * is a helper to dump the items in the find list for debugging purposes.
...@@ -266,8 +257,24 @@ public: ...@@ -266,8 +257,24 @@ public:
m_forceSearch = false; m_forceSearch = false;
} }
void Empty()
{
m_foundIndex = 0;
COLLECTOR::Empty();
m_data.clear();
}
void SetForceSearch() { m_forceSearch = true; } void SetForceSearch() { m_forceSearch = true; }
/**
* Function PassedEnd
* tests if #m_foundIndex is beyond the end of the list give the current
* find/replace criterial in #m_findReplaceData.
*
* @return True if #m_foundIndex has crossed the end of the found item list.
*/
bool PassedEnd() const;
/** /**
* Function UpdateIndex * Function UpdateIndex
* updates the list index according to the current find and replace criteria. * updates the list index according to the current find and replace criteria.
...@@ -326,7 +333,7 @@ public: ...@@ -326,7 +333,7 @@ public:
* *
* @return True if the text replace occurred otherwise false. * @return True if the text replace occurred otherwise false.
*/ */
bool ReplaceItem(); bool ReplaceItem( SCH_SHEET_PATH* aSheetPath = NULL );
SEARCH_RESULT Inspect( EDA_ITEM* aItem, const void* aTestData = NULL ); SEARCH_RESULT Inspect( EDA_ITEM* aItem, const void* aTestData = NULL );
...@@ -340,6 +347,8 @@ public: ...@@ -340,6 +347,8 @@ public:
* value searches the entire schematic hierarchy. * value searches the entire schematic hierarchy.
*/ */
void Collect( SCH_FIND_REPLACE_DATA& aFindReplaceData, SCH_SHEET_PATH* aSheetPath = NULL ); void Collect( SCH_FIND_REPLACE_DATA& aFindReplaceData, SCH_SHEET_PATH* aSheetPath = NULL );
void IncrementIndex() { m_foundIndex += 1; }
}; };
......
...@@ -431,8 +431,11 @@ bool SCH_FIELD::Replace( wxFindReplaceData& aSearchData, void* aAuxData ) ...@@ -431,8 +431,11 @@ bool SCH_FIELD::Replace( wxFindReplaceData& aSearchData, void* aAuxData )
bool isReplaced; bool isReplaced;
wxString text = GetFullyQualifiedText(); wxString text = GetFullyQualifiedText();
if( m_id == REFERENCE && aAuxData != NULL ) if( m_id == REFERENCE )
{ {
wxCHECK_MSG( aAuxData != NULL, false,
wxT( "Cannot replace reference designator without valid sheet path." ) );
wxCHECK_MSG( aSearchData.GetFlags() & FR_REPLACE_REFERENCES, false, wxCHECK_MSG( aSearchData.GetFlags() & FR_REPLACE_REFERENCES, false,
wxT( "Invalid replace component reference field call." ) ) ; wxT( "Invalid replace component reference field call." ) ) ;
...@@ -443,8 +446,8 @@ bool SCH_FIELD::Replace( wxFindReplaceData& aSearchData, void* aAuxData ) ...@@ -443,8 +446,8 @@ bool SCH_FIELD::Replace( wxFindReplaceData& aSearchData, void* aAuxData )
text = component->GetRef( (SCH_SHEET_PATH*) aAuxData ); text = component->GetRef( (SCH_SHEET_PATH*) aAuxData );
if( component->GetPartCount() > 1 ) // if( component->GetPartCount() > 1 )
text << LIB_COMPONENT::ReturnSubReference( component->GetUnit() ); // text << LIB_COMPONENT::ReturnSubReference( component->GetUnit() );
isReplaced = EDA_ITEM::Replace( aSearchData, text ); isReplaced = EDA_ITEM::Replace( aSearchData, text );
......
...@@ -438,6 +438,7 @@ SCH_SHEET_LIST::SCH_SHEET_LIST( SCH_SHEET* aSheet ) ...@@ -438,6 +438,7 @@ SCH_SHEET_LIST::SCH_SHEET_LIST( SCH_SHEET* aSheet )
m_index = 0; m_index = 0;
m_count = 0; m_count = 0;
m_List = NULL; m_List = NULL;
m_isRootSheet = false;
if( aSheet == NULL ) if( aSheet == NULL )
aSheet = g_RootSheet; aSheet = g_RootSheet;
...@@ -518,6 +519,9 @@ SCH_SHEET_PATH* SCH_SHEET_LIST::GetSheet( const wxString aPath, bool aHumanReada ...@@ -518,6 +519,9 @@ SCH_SHEET_PATH* SCH_SHEET_LIST::GetSheet( const wxString aPath, bool aHumanReada
void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet ) void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet )
{ {
if( aSheet == g_RootSheet )
m_isRootSheet = true;
if( m_List == NULL ) if( m_List == NULL )
{ {
int count = aSheet->CountSheets(); int count = aSheet->CountSheets();
...@@ -702,3 +706,25 @@ bool SCH_SHEET_LIST::SetComponentFootprint( const wxString& aReference, ...@@ -702,3 +706,25 @@ bool SCH_SHEET_LIST::SetComponentFootprint( const wxString& aReference,
return found; return found;
} }
bool SCH_SHEET_LIST::IsComplexHierarchy()
{
wxString fileName;
for( int i = 0; i < GetCount(); i++ )
{
fileName = GetSheet( i )->Last()->GetFileName();
for( int j = 0; j < GetCount(); j++ )
{
if( i == j )
continue;
if( fileName == GetSheet( j )->Last()->GetFileName() )
return true;
}
}
return false;
}
...@@ -292,6 +292,7 @@ private: ...@@ -292,6 +292,7 @@ private:
* returning the next item in m_List. Also used for * returning the next item in m_List. Also used for
* internal calculations in BuildSheetList() * internal calculations in BuildSheetList()
*/ */
bool m_isRootSheet;
SCH_SHEET_PATH m_currList; SCH_SHEET_PATH m_currList;
public: public:
...@@ -442,6 +443,15 @@ public: ...@@ -442,6 +443,15 @@ public:
bool SetComponentFootprint( const wxString& aReference, const wxString& aFootPrint, bool SetComponentFootprint( const wxString& aReference, const wxString& aFootPrint,
bool aSetVisible ); bool aSetVisible );
/**
* Function IsComplexHierarchy
* searches all of the sheets for duplicate files names which indicates a complex
* hierarchy.
*
* @return true if the #SCH_SHEET_LIST is a complex hierarchy.
*/
bool IsComplexHierarchy();
private: private:
/** /**
......
...@@ -46,6 +46,10 @@ extern std::ostream& operator <<( std::ostream& out, const wxPoint& pt ); ...@@ -46,6 +46,10 @@ extern std::ostream& operator <<( std::ostream& out, const wxPoint& pt );
#endif #endif
/// Flag to enable find and replace tracing using the WXTRACE environment variable.
extern const wxString traceFindReplace;
/** /**
* Enum KICAD_T * Enum KICAD_T
* is the set of class identification values, stored in EDA_ITEM::m_StructType * is the set of class identification values, stored in EDA_ITEM::m_StructType
......
...@@ -56,9 +56,6 @@ typedef vector< SCH_ITEMS_ITR > SCH_ITEMS_ITRS; ...@@ -56,9 +56,6 @@ typedef vector< SCH_ITEMS_ITR > SCH_ITEMS_ITRS;
#define FMT_ANGLE SCH_ITEM::FormatAngle #define FMT_ANGLE SCH_ITEM::FormatAngle
/// Flag to enable find and replace tracing using the WXTRACE environment variable.
extern const wxString traceFindReplace;
/// Flag to enable find item tracing using the WXTRACE environment variable. This /// Flag to enable find item tracing using the WXTRACE environment variable. This
/// flag generates a lot of debug output. /// flag generates a lot of debug output.
extern const wxString traceFindItem; extern const wxString traceFindItem;
......
...@@ -194,6 +194,8 @@ protected: ...@@ -194,6 +194,8 @@ protected:
*/ */
void addCurrentItemToList( wxDC* aDC ); void addCurrentItemToList( wxDC* aDC );
void updateFindReplaceView( wxFindDialogEvent& aEvent );
public: public:
SCH_EDIT_FRAME( wxWindow* aParent, const wxString& aTitle, SCH_EDIT_FRAME( wxWindow* aParent, const wxString& aTitle,
const wxPoint& aPosition, const wxSize& aSize, const wxPoint& aPosition, const wxSize& aSize,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment