Fix re-entrancy problem in cross-probing.

Fixes: lp:1836940
* https://bugs.launchpad.net/kicad/+bug/1836940

Fixes: lp:1836937
* https://bugs.launchpad.net/kicad/+bug/1836937
This commit is contained in:
Jeff Young 2019-07-17 21:21:22 +01:00
parent 7c1049d86b
commit d67c2d13c7
10 changed files with 79 additions and 57 deletions

View File

@ -45,10 +45,10 @@
#include <tools/sch_editor_control.h> #include <tools/sch_editor_control.h>
SCH_ITEM* SCH_EDIT_FRAME::FindComponentAndItem( const wxString& aReference, SCH_ITEM* SCH_EDITOR_CONTROL::FindComponentAndItem( const wxString& aReference,
bool aSearchHierarchy, bool aSearchHierarchy,
SCH_SEARCH_T aSearchType, SCH_SEARCH_T aSearchType,
const wxString& aSearchText ) const wxString& aSearchText )
{ {
SCH_SHEET_PATH* sheetWithComponentFound = NULL; SCH_SHEET_PATH* sheetWithComponentFound = NULL;
SCH_ITEM* item = NULL; SCH_ITEM* item = NULL;
@ -107,9 +107,9 @@ SCH_ITEM* SCH_EDIT_FRAME::FindComponentAndItem( const wxString& aReference,
{ {
if( *sheetWithComponentFound != *g_CurrentSheet ) if( *sheetWithComponentFound != *g_CurrentSheet )
{ {
sheetWithComponentFound->LastScreen()->SetZoom( GetScreen()->GetZoom() ); sheetWithComponentFound->LastScreen()->SetZoom( m_frame->GetScreen()->GetZoom() );
*g_CurrentSheet = *sheetWithComponentFound; *g_CurrentSheet = *sheetWithComponentFound;
DisplayCurrentSheet(); m_frame->DisplayCurrentSheet();
} }
wxPoint delta; wxPoint delta;
@ -117,8 +117,8 @@ SCH_ITEM* SCH_EDIT_FRAME::FindComponentAndItem( const wxString& aReference,
delta = Component->GetTransform().TransformCoordinate( pos ); delta = Component->GetTransform().TransformCoordinate( pos );
pos = delta + Component->GetPosition(); pos = delta + Component->GetPosition();
GetCanvas()->GetViewControls()->SetCrossHairCursorPosition( pos, false ); m_frame->GetCanvas()->GetViewControls()->SetCrossHairCursorPosition( pos, false );
CenterScreen( pos, false ); m_frame->CenterScreen( pos, false );
} }
/* Print diag */ /* Print diag */
@ -140,16 +140,20 @@ SCH_ITEM* SCH_EDIT_FRAME::FindComponentAndItem( const wxString& aReference,
else else
msg.Printf( _( "Component %s not found" ), aReference ); msg.Printf( _( "Component %s not found" ), aReference );
SetStatusText( msg ); m_frame->SetStatusText( msg );
// Clear any existing highlighting m_probingPcbToSch = true; // recursion guard
GetToolManager()->RunAction( EE_ACTIONS::clearSelection, true ); {
GetCanvas()->GetView()->HighlightItem( nullptr, nullptr ); // Clear any existing highlighting
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
m_frame->GetCanvas()->GetView()->HighlightItem( nullptr, nullptr );
if( foundItem ) if( foundItem )
GetCanvas()->GetView()->HighlightItem( foundItem, pin ); m_frame->GetCanvas()->GetView()->HighlightItem( foundItem, pin );
}
m_probingPcbToSch = false;
GetCanvas()->Refresh(); m_frame->GetCanvas()->Refresh();
return item; return item;
} }
@ -175,7 +179,8 @@ SCH_ITEM* SCH_EDIT_FRAME::FindComponentAndItem( const wxString& aReference,
*/ */
void SCH_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline ) void SCH_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
{ {
char line[1024]; SCH_EDITOR_CONTROL* editor = m_toolManager->GetTool<SCH_EDITOR_CONTROL>();
char line[1024];
strncpy( line, cmdline, sizeof(line) - 1 ); strncpy( line, cmdline, sizeof(line) - 1 );
line[ sizeof(line) - 1 ] = '\0'; line[ sizeof(line) - 1 ] = '\0';
@ -220,7 +225,7 @@ void SCH_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
if( idcmd == NULL ) // Highlight component only (from Cvpcb or Pcbnew) if( idcmd == NULL ) // Highlight component only (from Cvpcb or Pcbnew)
{ {
// Highlight component part_ref, or clear Highlight, if part_ref is not existing // Highlight component part_ref, or clear Highlight, if part_ref is not existing
FindComponentAndItem( part_ref, true, HIGHLIGHT_COMPONENT, wxEmptyString ); editor->FindComponentAndItem( part_ref, true, HIGHLIGHT_COMPONENT, wxEmptyString );
return; return;
} }
@ -235,21 +240,21 @@ void SCH_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
{ {
// Highlighting the reference itself isn't actually that useful, and it's harder to // Highlighting the reference itself isn't actually that useful, and it's harder to
// see. Highlight the parent and display the message. // see. Highlight the parent and display the message.
FindComponentAndItem( part_ref, true, HIGHLIGHT_COMPONENT, msg ); editor->FindComponentAndItem( part_ref, true, HIGHLIGHT_COMPONENT, msg );
} }
else if( strcmp( idcmd, "$VAL:" ) == 0 ) else if( strcmp( idcmd, "$VAL:" ) == 0 )
{ {
// Highlighting the value itself isn't actually that useful, and it's harder to see. // Highlighting the value itself isn't actually that useful, and it's harder to see.
// Highlight the parent and display the message. // Highlight the parent and display the message.
FindComponentAndItem( part_ref, true, HIGHLIGHT_COMPONENT, msg ); editor->FindComponentAndItem( part_ref, true, HIGHLIGHT_COMPONENT, msg );
} }
else if( strcmp( idcmd, "$PAD:" ) == 0 ) else if( strcmp( idcmd, "$PAD:" ) == 0 )
{ {
FindComponentAndItem( part_ref, true, HIGHLIGHT_PIN, msg ); editor->FindComponentAndItem( part_ref, true, HIGHLIGHT_PIN, msg );
} }
else else
{ {
FindComponentAndItem( part_ref, true, HIGHLIGHT_COMPONENT, wxEmptyString ); editor->FindComponentAndItem( part_ref, true, HIGHLIGHT_COMPONENT, wxEmptyString );
} }
} }

View File

@ -38,6 +38,8 @@
#include <class_library.h> #include <class_library.h>
#include <sch_edit_frame.h> #include <sch_edit_frame.h>
#include <sch_reference_list.h> #include <sch_reference_list.h>
#include <tool/tool_manager.h>
#include <tools/sch_editor_control.h>
#include <kiface_i.h> #include <kiface_i.h>
#include <eda_doc.h> #include <eda_doc.h>
#include <widgets/grid_text_button_helpers.h> #include <widgets/grid_text_button_helpers.h>
@ -1035,8 +1037,10 @@ void DIALOG_FIELDS_EDITOR_GLOBAL::OnTableCellClick( wxGridEvent& event )
// Focus Eeschema view on the component selected in the dialog // Focus Eeschema view on the component selected in the dialog
if( refs.size() == 1 ) if( refs.size() == 1 )
{ {
m_parent->FindComponentAndItem( refs[0].GetRef() + refs[0].GetRefNumber(), SCH_EDITOR_CONTROL* editor = m_parent->GetToolManager()->GetTool<SCH_EDITOR_CONTROL>();
true, HIGHLIGHT_COMPONENT, wxEmptyString );
editor->FindComponentAndItem( refs[0].GetRef() + refs[0].GetRefNumber(), true,
HIGHLIGHT_COMPONENT, wxEmptyString );
} }
} }
else else

View File

@ -323,20 +323,6 @@ public:
*/ */
void AddItemToScreenAndUndoList( SCH_ITEM* aItem, bool aUndoAppend = false ); void AddItemToScreenAndUndoList( SCH_ITEM* aItem, bool aUndoAppend = false );
/**
* Finds a component in the schematic and an item in this component.
*
* @param aReference The component reference designator to find.
* @param aSearchHierarchy If false, search the current sheet only. Otherwise,
* the entire hierarchy
* @param aSearchType A #SCH_SEARCH_T value used to determine what to search for.
* @param aSearchText The text to search for, either in value, reference or elsewhere.
*/
SCH_ITEM* FindComponentAndItem( const wxString& aReference,
bool aSearchHierarchy,
SCH_SEARCH_T aSearchType,
const wxString& aSearchText );
/** /**
* Run the Find or Find & Replace dialog. * Run the Find or Find & Replace dialog.
*/ */

View File

@ -373,11 +373,8 @@ int SCH_EDITOR_CONTROL::ExplicitCrossProbeToPcb( const TOOL_EVENT& aEvent )
void SCH_EDITOR_CONTROL::doCrossProbeSchToPcb( const TOOL_EVENT& aEvent, bool aForce ) void SCH_EDITOR_CONTROL::doCrossProbeSchToPcb( const TOOL_EVENT& aEvent, bool aForce )
{ {
// Don't get in an infinite loop SCH -> PCB -> SCH -> PCB -> SCH -> ... // Don't get in an infinite loop SCH -> PCB -> SCH -> PCB -> SCH -> ...
if( m_probingSchToPcb ) if( m_probingPcbToSch )
{
m_probingSchToPcb = false;
return; return;
}
EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>(); EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
SCH_ITEM* item = nullptr; SCH_ITEM* item = nullptr;

View File

@ -40,8 +40,8 @@ class SCH_EDITOR_CONTROL : public wxEvtHandler, public EE_TOOL_BASE<SCH_EDIT_FRA
{ {
public: public:
SCH_EDITOR_CONTROL() : SCH_EDITOR_CONTROL() :
EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.EditorControl" ), EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.EditorControl" ),
m_probingSchToPcb( false ) m_probingPcbToSch( false )
{ } { }
~SCH_EDITOR_CONTROL() { } ~SCH_EDITOR_CONTROL() { }
@ -124,6 +124,20 @@ public:
void BackAnnotateFootprints( const std::string& aChangedSetOfReferences ); void BackAnnotateFootprints( const std::string& aChangedSetOfReferences );
/**
* Finds a component in the schematic and an item in this component.
*
* @param aReference The component reference designator to find.
* @param aSearchHierarchy If false, search the current sheet only. Otherwise,
* the entire hierarchy
* @param aSearchType A #SCH_SEARCH_T value used to determine what to search for.
* @param aSearchText The text to search for, either in value, reference or elsewhere.
*/
SCH_ITEM* FindComponentAndItem( const wxString& aReference,
bool aSearchHierarchy,
SCH_SEARCH_T aSearchType,
const wxString& aSearchText );
private: private:
///> copy selection to clipboard ///> copy selection to clipboard
bool doCopy(); bool doCopy();
@ -166,7 +180,7 @@ private:
void setTransitions() override; void setTransitions() override;
private: private:
bool m_probingSchToPcb; ///> Recursion guard when cross-probing to PCBNew bool m_probingPcbToSch; ///> Recursion guard when cross-probing to PCBNew
}; };

View File

@ -24,10 +24,7 @@
/** /**
* @file pcbnew/cross-probing.cpp * @file pcbnew/cross-probing.cpp
* @brief Cross probing functions to handle communication to andfrom Eeschema. * @brief Cross probing functions to handle communication to and from Eeschema.
*/
/**
* Handle messages between Pcbnew and Eeschema via a socket, the port numbers are * Handle messages between Pcbnew and Eeschema via a socket, the port numbers are
* KICAD_PCB_PORT_SERVICE_NUMBER (currently 4242) (Eeschema to Pcbnew) * KICAD_PCB_PORT_SERVICE_NUMBER (currently 4242) (Eeschema to Pcbnew)
* KICAD_SCH_PORT_SERVICE_NUMBER (currently 4243) (Pcbnew to Eeschema) * KICAD_SCH_PORT_SERVICE_NUMBER (currently 4243) (Pcbnew to Eeschema)
@ -41,7 +38,6 @@
#include <pcb_edit_frame.h> #include <pcb_edit_frame.h>
#include <eda_dde.h> #include <eda_dde.h>
#include <macros.h> #include <macros.h>
#include <pcbnew_id.h> #include <pcbnew_id.h>
#include <class_board.h> #include <class_board.h>
#include <class_module.h> #include <class_module.h>
@ -53,7 +49,6 @@
#include <tools/pcb_actions.h> #include <tools/pcb_actions.h>
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
#include <tools/selection_tool.h> #include <tools/selection_tool.h>
#include <pcb_draw_panel_gal.h>
#include <pcb_painter.h> #include <pcb_painter.h>
/* Execute a remote command send by Eeschema via a socket, /* Execute a remote command send by Eeschema via a socket,
@ -173,8 +168,7 @@ void PCB_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
if( module ) if( module )
{ {
m_toolManager->RunAction( PCB_ACTIONS::selectionClear, true ); m_toolManager->RunAction( PCB_ACTIONS::highlightItem, true, (void*) module );
m_toolManager->RunAction( PCB_ACTIONS::selectItem, true, (void*) module );
bbox = module->GetBoundingBox(); bbox = module->GetBoundingBox();
} }
else if( netcode > 0 ) else if( netcode > 0 )
@ -297,7 +291,7 @@ void PCB_EDIT_FRAME::SendMessageToEESCHEMA( BOARD_ITEM* aSyncItem )
{ {
std::string packet = FormatProbeItem( aSyncItem ); std::string packet = FormatProbeItem( aSyncItem );
if( packet.size() ) if( !packet.empty() )
{ {
if( Kiface().IsSingle() ) if( Kiface().IsSingle() )
SendCommand( MSG_TO_SCH, packet.c_str() ); SendCommand( MSG_TO_SCH, packet.c_str() );
@ -316,7 +310,7 @@ void PCB_EDIT_FRAME::SendCrossProbeNetName( const wxString& aNetName )
{ {
std::string packet = StrPrintf( "$NET: \"%s\"", TO_UTF8( aNetName ) ); std::string packet = StrPrintf( "$NET: \"%s\"", TO_UTF8( aNetName ) );
if( packet.size() ) if( !packet.empty() )
{ {
if( Kiface().IsSingle() ) if( Kiface().IsSingle() )
SendCommand( MSG_TO_SCH, packet.c_str() ); SendCommand( MSG_TO_SCH, packet.c_str() );

View File

@ -594,6 +594,9 @@ TOOL_ACTION PCB_ACTIONS::highlightNetSelection( "pcbnew.EditorControl.highlightN
_( "Highlight Net" ), _( "Highlight all copper items of a net" ), _( "Highlight Net" ), _( "Highlight all copper items of a net" ),
net_highlight_xpm ); net_highlight_xpm );
TOOL_ACTION PCB_ACTIONS::highlightItem( "pcbnew.EditorControl.highlightItem",
AS_GLOBAL );
TOOL_ACTION PCB_ACTIONS::showEeschema( "pcbnew.EditorControl.showEeschema", TOOL_ACTION PCB_ACTIONS::showEeschema( "pcbnew.EditorControl.showEeschema",
AS_GLOBAL, 0, "", AS_GLOBAL, 0, "",
_( "Switch to Schematic Editor" ), _( "Open schematic in Eeschema" ), _( "Switch to Schematic Editor" ), _( "Open schematic in Eeschema" ),

View File

@ -411,6 +411,7 @@ public:
static TOOL_ACTION toggleLastNetHighlight; static TOOL_ACTION toggleLastNetHighlight;
static TOOL_ACTION highlightNetTool; static TOOL_ACTION highlightNetTool;
static TOOL_ACTION highlightNetSelection; static TOOL_ACTION highlightNetSelection;
static TOOL_ACTION highlightItem;
static TOOL_ACTION drillOrigin; static TOOL_ACTION drillOrigin;
static TOOL_ACTION appendBoard; static TOOL_ACTION appendBoard;
static TOOL_ACTION showEeschema; static TOOL_ACTION showEeschema;

View File

@ -1084,10 +1084,7 @@ int PCB_EDITOR_CONTROL::CrossProbePcbToSch( const TOOL_EVENT& aEvent )
{ {
// Don't get in an infinite loop PCB -> SCH -> PCB -> SCH -> ... // Don't get in an infinite loop PCB -> SCH -> PCB -> SCH -> ...
if( m_probingSchToPcb ) if( m_probingSchToPcb )
{
m_probingSchToPcb = false;
return 0; return 0;
}
SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
const PCBNEW_SELECTION& selection = selTool->GetSelection(); const PCBNEW_SELECTION& selection = selTool->GetSelection();
@ -1101,6 +1098,23 @@ int PCB_EDITOR_CONTROL::CrossProbePcbToSch( const TOOL_EVENT& aEvent )
} }
int PCB_EDITOR_CONTROL::HighlightItem( const TOOL_EVENT& aEvent )
{
BOARD_ITEM* item = aEvent.Parameter<BOARD_ITEM*>();
m_probingSchToPcb = true; // recursion guard
{
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
if( item )
m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, (void*) item );
}
m_probingSchToPcb = false;
return 0;
}
void PCB_EDITOR_CONTROL::DoSetDrillOrigin( KIGFX::VIEW* aView, PCB_BASE_FRAME* aFrame, void PCB_EDITOR_CONTROL::DoSetDrillOrigin( KIGFX::VIEW* aView, PCB_BASE_FRAME* aFrame,
BOARD_ITEM* originViewItem, const VECTOR2D& aPosition ) BOARD_ITEM* originViewItem, const VECTOR2D& aPosition )
{ {
@ -1532,6 +1546,7 @@ void PCB_EDITOR_CONTROL::setTransitions()
Go( &PCB_EDITOR_CONTROL::ClearHighlight, PCB_ACTIONS::clearHighlight.MakeEvent() ); Go( &PCB_EDITOR_CONTROL::ClearHighlight, PCB_ACTIONS::clearHighlight.MakeEvent() );
Go( &PCB_EDITOR_CONTROL::HighlightNetTool, PCB_ACTIONS::highlightNetTool.MakeEvent() ); Go( &PCB_EDITOR_CONTROL::HighlightNetTool, PCB_ACTIONS::highlightNetTool.MakeEvent() );
Go( &PCB_EDITOR_CONTROL::ClearHighlight, ACTIONS::cancelInteractive.MakeEvent() ); Go( &PCB_EDITOR_CONTROL::ClearHighlight, ACTIONS::cancelInteractive.MakeEvent() );
Go( &PCB_EDITOR_CONTROL::HighlightItem, PCB_ACTIONS::highlightItem.MakeEvent() );
Go( &PCB_EDITOR_CONTROL::LocalRatsnestTool, PCB_ACTIONS::localRatsnestTool.MakeEvent() ); Go( &PCB_EDITOR_CONTROL::LocalRatsnestTool, PCB_ACTIONS::localRatsnestTool.MakeEvent() );
Go( &PCB_EDITOR_CONTROL::HideDynamicRatsnest, PCB_ACTIONS::hideDynamicRatsnest.MakeEvent() ); Go( &PCB_EDITOR_CONTROL::HideDynamicRatsnest, PCB_ACTIONS::hideDynamicRatsnest.MakeEvent() );

View File

@ -125,6 +125,9 @@ public:
///> Launches a tool to pick the item whose net is going to be highlighted. ///> Launches a tool to pick the item whose net is going to be highlighted.
int HighlightNetTool( const TOOL_EVENT& aEvent ); int HighlightNetTool( const TOOL_EVENT& aEvent );
///> Performs the appropriate action in response to an eeschema cross-probe.
int HighlightItem( const TOOL_EVENT& aEvent );
///> Updates ratsnest for selected items. ///> Updates ratsnest for selected items.
int UpdateSelectionRatsnest( const TOOL_EVENT& aEvent ); int UpdateSelectionRatsnest( const TOOL_EVENT& aEvent );