kicad/pcbnew/cross-probing.cpp

290 lines
7.6 KiB
C++

/**
* @file pcbnew/cross-probing.cpp
* @brief Cross probing functions to handle communication to andfrom Eeschema.
*/
/**
* Handle messages between Pcbnew and Eeschema via a socket, the port numbers are
* KICAD_PCB_PORT_SERVICE_NUMBER (currently 4242) (Eeschema to Pcbnew)
* KICAD_SCH_PORT_SERVICE_NUMBER (currently 4243) (Pcbnew to Eeschema)
* Note: these ports must be enabled for firewall protection
*/
#include <fctsys.h>
#include <pgm_base.h>
#include <kiface_i.h>
#include <kiway_express.h>
#include <wxPcbStruct.h>
#include <eda_dde.h>
#include <macros.h>
#include <pcbnew_id.h>
#include <class_board.h>
#include <class_module.h>
#include <collectors.h>
#include <pcbnew.h>
#include <netlist_reader.h>
#include <pcb_netlist.h>
#include <dialogs/dialog_update_pcb.h>
#include <tools/pcb_actions.h>
#include <tool/tool_manager.h>
#include <tools/selection_tool.h>
#include <pcb_draw_panel_gal.h>
/* Execute a remote command send by Eeschema via a socket,
* port KICAD_PCB_PORT_SERVICE_NUMBER
* cmdline = received command from Eeschema
* Commands are
* $PART: "reference" put cursor on component
* $PIN: "pin name" $PART: "reference" put cursor on the footprint pin
*/
void PCB_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
{
char line[1024];
wxString msg;
wxString modName;
wxString *sheetStamp;
char* idcmd;
char* text;
MODULE* module = NULL;
D_PAD* pad = NULL;
BOARD* pcb = GetBoard();
wxPoint pos;
strncpy( line, cmdline, sizeof(line) - 1 );
line[sizeof(line) - 1] = 0;
idcmd = strtok( line, " \n\r" );
text = strtok( NULL, " \n\r" );
if( !idcmd || !text )
return;
if( strcmp( idcmd, "$PART:" ) == 0 )
{
modName = FROM_UTF8( text );
module = pcb->FindModuleByReference( modName );
if( module )
msg.Printf( _( "%s found" ), GetChars( modName ) );
else
msg.Printf( _( "%s not found" ), GetChars( modName ) );
SetStatusText( msg );
if( module )
pos = module->GetPosition();
}
else if( strcmp( idcmd, "$SHEET:" ) == 0 )
{
msg.Printf( _( "Selecting all from sheet '%s'" ), FROM_UTF8( text ) );
sheetStamp = new wxString( FROM_UTF8( text ) );
SetStatusText( msg );
GetToolManager()->RunAction( PCB_ACTIONS::selectOnSheet,
true,
static_cast<void*>( sheetStamp ) );
return;
}
else if( strcmp( idcmd, "$PIN:" ) == 0 )
{
wxString pinName;
int netcode = -1;
pinName = FROM_UTF8( text );
text = strtok( NULL, " \n\r" );
if( text && strcmp( text, "$PART:" ) == 0 )
text = strtok( NULL, "\n\r" );
modName = FROM_UTF8( text );
module = pcb->FindModuleByReference( modName );
if( module )
pad = module->FindPadByName( pinName );
if( pad )
{
netcode = pad->GetNetCode();
// put cursor on the pad:
pos = pad->GetPosition();
}
if( netcode > 0 ) // highlight the pad net
{
pcb->HighLightON();
pcb->SetHighLightNet( netcode );
}
else
{
pcb->HighLightOFF();
pcb->SetHighLightNet( -1 );
}
if( module == NULL )
{
msg.Printf( _( "%s not found" ), GetChars( modName ) );
}
else if( pad == NULL )
{
msg.Printf( _( "%s pin %s not found" ), GetChars( modName ), GetChars( pinName ) );
SetCurItem( module );
}
else
{
msg.Printf( _( "%s pin %s found" ), GetChars( modName ), GetChars( pinName ) );
SetCurItem( pad );
}
SetStatusText( msg );
}
if( module ) // if found, center the module on screen, and redraw the screen.
{
if( IsGalCanvasActive() )
{
GetToolManager()->RunAction( PCB_ACTIONS::crossProbeSchToPcb,
true,
pad ?
static_cast<BOARD_ITEM*>( pad ) :
static_cast<BOARD_ITEM*>( module )
);
}
else
{
SetCrossHairPosition( pos );
RedrawScreen( pos, false );
}
}
}
std::string FormatProbeItem( BOARD_ITEM* aItem )
{
MODULE* module;
switch( aItem->Type() )
{
case PCB_MODULE_T:
module = (MODULE*) aItem;
return StrPrintf( "$PART: \"%s\"", TO_UTF8( module->GetReference() ) );
case PCB_PAD_T:
{
module = (MODULE*) aItem->GetParent();
wxString pad = ((D_PAD*)aItem)->GetPadName();
return StrPrintf( "$PART: \"%s\" $PAD: \"%s\"",
TO_UTF8( module->GetReference() ),
TO_UTF8( pad ) );
}
case PCB_MODULE_TEXT_T:
{
module = static_cast<MODULE*>( aItem->GetParent() );
TEXTE_MODULE* text_mod = static_cast<TEXTE_MODULE*>( aItem );
const char* text_key;
/* This can't be a switch since the break need to pull out
* from the outer switch! */
if( text_mod->GetType() == TEXTE_MODULE::TEXT_is_REFERENCE )
text_key = "$REF:";
else if( text_mod->GetType() == TEXTE_MODULE::TEXT_is_VALUE )
text_key = "$VAL:";
else
break;
return StrPrintf( "$PART: \"%s\" %s \"%s\"",
TO_UTF8( module->GetReference() ),
text_key,
TO_UTF8( text_mod->GetText() ) );
}
default:
break;
}
return "";
}
/* Send a remote command to Eeschema via a socket,
* aSyncItem = item to be located on schematic (module, pin or text)
* Commands are
* $PART: "reference" put cursor on component anchor
* $PART: "reference" $PAD: "pad number" put cursor on the component pin
* $PART: "reference" $REF: "reference" put cursor on the component ref
* $PART: "reference" $VAL: "value" put cursor on the component value
*/
void PCB_EDIT_FRAME::SendMessageToEESCHEMA( BOARD_ITEM* aSyncItem )
{
#if 1
wxASSERT( aSyncItem ); // can't we fix the caller?
#else
if( !aSyncItem )
return;
#endif
std::string packet = FormatProbeItem( aSyncItem );
if( packet.size() )
{
if( Kiface().IsSingle() )
SendCommand( MSG_TO_SCH, packet.c_str() );
else
{
// Typically ExpressMail is going to be s-expression packets, but since
// we have existing interpreter of the cross probe packet on the other
// side in place, we use that here.
Kiway().ExpressMail( FRAME_SCH, MAIL_CROSS_PROBE, packet, this );
}
}
}
void PCB_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
{
const std::string& payload = mail.GetPayload();
switch( mail.Command() )
{
case MAIL_CROSS_PROBE:
ExecuteRemoteCommand( payload.c_str() );
break;
case MAIL_SCH_PCB_UPDATE:
{
NETLIST netlist;
try
{
STRING_LINE_READER* lineReader = new STRING_LINE_READER( payload, _( "EEschema netlist" ) );
KICAD_NETLIST_READER netlistReader( lineReader, &netlist );
netlistReader.LoadNetlist();
}
catch( const IO_ERROR& )
{
assert( false ); // should never happen
}
DIALOG_UPDATE_PCB updateDialog( this, &netlist );
updateDialog.PerformUpdate( true );
updateDialog.ShowModal();
break;
}
// many many others.
default:
;
}
}