Commit f0b2565f authored by Wayne Stambaugh's avatar Wayne Stambaugh
Browse files

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
Loading
Loading
Loading
Loading
+26 −2
Original line number Diff line number Diff line
@@ -38,6 +38,10 @@

#include "../eeschema/dialogs/dialog_schematic_find.h"


const wxString traceFindReplace( wxT( "KicadFindReplace" ) );


enum textbox {
    ID_TEXTBOX_LIST = 8010
};
@@ -190,8 +194,28 @@ bool EDA_ITEM::Replace( wxFindReplaceData& aSearchData, wxString& aText )
    wxCHECK_MSG( IsReplaceable(), false,
                 wxT( "Attempt to replace text in <" ) + GetClass() + wxT( "> item." ) );

    return aText.Replace( aSearchData.GetFindString(),
                          aSearchData.GetReplaceString(), false ) != 0;
    wxString searchString = (aSearchData.GetFlags() & wxFR_MATCHCASE) ? aText.Upper() : aText;

    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;
}


+0 −2
Original line number Diff line number Diff line
@@ -39,8 +39,6 @@
#include <protos.h>


const wxString traceFindReplace( wxT( "KicadFindReplace" ) );

const wxString traceFindItem( wxT( "KicadFindItem" ) );


+1 −1
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@
 */
enum SchematicFindReplaceFlags
{
    // The last wxFindReplaceFlag enum is wxFR_MATCHCASE.
    // The last wxFindReplaceFlag enum is wxFR_MATCHCASE = 0x4.

    /// Search the current sheet only.
    FR_CURRENT_SHEET_ONLY    = wxFR_MATCHCASE << 1,
+91 −66
Original line number Diff line number Diff line
@@ -293,7 +293,6 @@ void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent )
    SCH_SHEET_LIST          schematic;
    wxString                msg;
    SCH_FIND_REPLACE_DATA   searchCriteria;
    bool warpCursor = !( aEvent.GetFlags() & FR_NO_WARP_CURSOR );
    SCH_FIND_COLLECTOR_DATA data;

    searchCriteria.SetFlags( aEvent.GetFlags() );
@@ -326,66 +325,52 @@ void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent )
        m_foundItems.UpdateIndex();
    }

    if( m_foundItems.GetItem( data ) != NULL )
    {
        wxLogTrace( traceFindReplace, wxT( "Found " ) + m_foundItems.GetText() );

        SCH_SHEET_PATH* sheet = schematic.GetSheet( data.GetSheetPath() );

        wxCHECK_RET( sheet != NULL, wxT( "Could not find sheet path " ) +
                     data.GetSheetPath() );
    updateFindReplaceView( aEvent );
}

        // 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
        // dialog event, clear the temporary visibility flag.
        if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_CLOSE )
            m_foundItems.GetItem( data )->SetForceVisible( false );
        else
            m_foundItems.GetItem( data )->SetForceVisible( true );

        if( sheet->PathHumanReadable() != m_CurrentSheet->PathHumanReadable() )
void SCH_EDIT_FRAME::OnFindReplace( wxFindDialogEvent& aEvent )
{
            sheet->LastScreen()->SetZoom( GetScreen()->GetZoom() );
            *m_CurrentSheet = *sheet;
            m_CurrentSheet->UpdateAllScreenReferences();
            SetScreen( sheet->LastScreen() );
        }
    SCH_ITEM*               item;
    SCH_SHEET_PATH*         sheet;
    SCH_SHEET_LIST          schematic;
    SCH_FIND_COLLECTOR_DATA data;

        // careful here
        SetCrossHairPosition( data.GetPosition() );
    if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_REPLACE_ALL )
    {
        while( ( item = (SCH_ITEM*) m_foundItems.GetItem( data ) ) != NULL )
        {
            SCH_ITEM* undoItem = data.GetParent();

        RedrawScreen( data.GetPosition(), warpCursor );
            // Don't save child items in undo list.
            if( undoItem == NULL )
                undoItem = item;

        msg = m_foundItems.GetText();
            SetUndoItem( undoItem );

        if( aEvent.GetFlags() & FR_SEARCH_REPLACE )
            aEvent.SetFlags( aEvent.GetFlags() | FR_REPLACE_ITEM_FOUND );
    }
    else
    {
        if( aEvent.GetFlags() & FR_SEARCH_REPLACE )
            aEvent.SetFlags( aEvent.GetFlags() & ~FR_REPLACE_ITEM_FOUND );
            sheet = schematic.GetSheet( data.GetSheetPath() );

        msg.Printf( _( "No item found matching %s." ), GetChars( aEvent.GetFindString() ) );
    }
            wxCHECK_RET( sheet != NULL, wxT( "Could not find sheet path " ) + data.GetSheetPath() );

    SetStatusText( msg );
            if( m_foundItems.ReplaceItem( sheet ) )
            {
                OnModify();
                SaveUndoItemInUndoList( undoItem );
                updateFindReplaceView( aEvent );
            }

            m_foundItems.IncrementIndex();

void SCH_EDIT_FRAME::OnFindReplace( wxFindDialogEvent& aEvent )
            if( m_foundItems.PassedEnd() )
                break;
        }
    }
    else
    {
    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 )
@@ -393,39 +378,79 @@ void SCH_EDIT_FRAME::OnFindReplace( wxFindDialogEvent& aEvent )

        SetUndoItem( undoItem );

    if( m_foundItems.ReplaceItem() )
        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 );
        RedrawScreen( data.GetPosition(), warpCursor );
            updateFindReplaceView( aEvent );
        }

    OnFindSchematicItem( aEvent );
        m_foundItems.IncrementIndex();
    }

    if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_REPLACE_ALL )
    // 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 )
{
        while( ( item = (SCH_ITEM*) m_foundItems.GetItem( data ) ) != NULL )
    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 )
    {
            wxLogTrace( traceFindReplace, wxT( "Replacing %s with %s in item %s" ),
                        GetChars( aEvent.GetFindString() ), GetChars( aEvent.GetReplaceString() ),
                        GetChars( m_foundItems.GetText() ) );
        wxLogTrace( traceFindReplace, wxT( "Found " ) + m_foundItems.GetText() );

            SCH_ITEM* undoItem = data.GetParent();
        SCH_SHEET_PATH* sheet = schematic.GetSheet( data.GetSheetPath() );

            // Don't save child items in undo list.
            if( undoItem == NULL )
                undoItem = item;
        wxCHECK_RET( sheet != NULL, wxT( "Could not find sheet path " ) +
                     data.GetSheetPath() );

            SetUndoItem( undoItem );
        SCH_ITEM* item = (SCH_ITEM*)m_foundItems.GetItem( data );

        // 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
        // dialog event, clear the temporary visibility flag.
        if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_CLOSE )
            item->SetForceVisible( false );
        else if( item->Type() == SCH_FIELD_T && !( (SCH_FIELD*) item )->IsVisible() )
            item->SetForceVisible( true );

            if( m_foundItems.ReplaceItem() )
        if( sheet->PathHumanReadable() != m_CurrentSheet->PathHumanReadable() )
        {
                OnModify();
                SaveUndoItemInUndoList( undoItem );
                RedrawScreen( data.GetPosition(), warpCursor );
            sheet->LastScreen()->SetZoom( GetScreen()->GetZoom() );
            *m_CurrentSheet = *sheet;
            m_CurrentSheet->UpdateAllScreenReferences();
            SetScreen( sheet->LastScreen() );
        }

            OnFindSchematicItem( aEvent );
        // careful here
        SetCrossHairPosition( data.GetPosition() );

        RedrawScreen( data.GetPosition(), warpCursor );

        msg = m_foundItems.GetText();

        if( aEvent.GetFlags() & FR_SEARCH_REPLACE )
            aEvent.SetFlags( aEvent.GetFlags() | FR_REPLACE_ITEM_FOUND );
    }
    else
    {
        if( aEvent.GetFlags() & FR_SEARCH_REPLACE )
            aEvent.SetFlags( aEvent.GetFlags() & ~FR_REPLACE_ITEM_FOUND );

        msg.Printf( _( "No item found matching %s." ), GetChars( aEvent.GetFindString() ) );
    }

    SetStatusText( msg );
}
+4 −9
Original line number Diff line number Diff line
@@ -347,7 +347,7 @@ bool SCH_FIND_COLLECTOR::PassedEnd() const
    if( GetCount() == 0 )
        return true;

    if( !(flags & FR_SEARCH_WRAP) )
    if( !(flags & FR_SEARCH_WRAP) || (flags & FR_SEARCH_REPLACE) )
    {
        if( flags & wxFR_DOWN )
        {
@@ -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() )
        return false;
@@ -464,15 +464,10 @@ bool SCH_FIND_COLLECTOR::ReplaceItem()

    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 )
    {
        Remove( m_foundIndex );
        m_data.erase( m_data.begin() + m_foundIndex );
    }
        m_forceSearch = true;

    return replaced;
}
Loading