KiCad PCB EDA Suite
pcbnew/cross-probing.cpp
Go to the documentation of this file.
1 
13 #include <fctsys.h>
14 #include <pgm_base.h>
15 #include <kiface_i.h>
16 #include <kiway_express.h>
17 #include <pcb_edit_frame.h>
18 #include <eda_dde.h>
19 #include <macros.h>
20 
21 #include <pcbnew_id.h>
22 #include <class_board.h>
23 #include <class_module.h>
24 #include <class_track.h>
25 #include <class_zone.h>
26 
27 #include <collectors.h>
28 #include <pcbnew.h>
29 #include <board_netlist_updater.h>
30 #include <netlist_reader.h>
31 #include <pcb_netlist.h>
33 
34 #include <tools/pcb_actions.h>
35 #include <tool/tool_manager.h>
36 #include <tools/selection_tool.h>
37 #include <pcb_draw_panel_gal.h>
38 #include <pcb_painter.h>
39 
40 /* Execute a remote command send by Eeschema via a socket,
41  * port KICAD_PCB_PORT_SERVICE_NUMBER
42  * cmdline = received command from Eeschema
43  * Commands are
44  * $PART: "reference" put cursor on component
45  * $PIN: "pin name" $PART: "reference" put cursor on the footprint pin
46  * $NET: "net name" highlight the given net (if highlight tool is active)
47  */
48 void PCB_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
49 {
50  char line[1024];
51  wxString msg;
52  wxString modName;
53  char* idcmd;
54  char* text;
55  MODULE* module = NULL;
56  D_PAD* pad = NULL;
57  BOARD* pcb = GetBoard();
58  wxPoint pos;
59 
60  strncpy( line, cmdline, sizeof(line) - 1 );
61  line[sizeof(line) - 1] = 0;
62 
63  idcmd = strtok( line, " \n\r" );
64  text = strtok( NULL, " \n\r" );
65 
66  if( idcmd == NULL )
67  return;
68 
69  if( strcmp( idcmd, "$NET:" ) == 0 )
70  {
72  {
73  wxString net_name = FROM_UTF8( text );
74  NETINFO_ITEM* netinfo = pcb->FindNet( net_name );
75  int netcode = 0;
76 
77  if( netinfo )
78  netcode = netinfo->GetNet();
79 
80  if( IsGalCanvasActive() )
81  {
82  auto view = m_toolManager->GetView();
83  auto rs = view->GetPainter()->GetSettings();
84  rs->SetHighlight( true, netcode );
85  view->UpdateAllLayersColor();
86 
87  BOX2I bbox;
88  bool first = true;
89 
90  auto merge_area = [netcode, &bbox, &first]( BOARD_CONNECTED_ITEM* aItem )
91  {
92  if( aItem->GetNetCode() == netcode )
93  {
94  if( first )
95  {
96  bbox = aItem->GetBoundingBox();
97  first = false;
98  }
99  else
100  {
101  bbox.Merge( aItem->GetBoundingBox() );
102  }
103  }
104  };
105 
106  for( auto zone : pcb->Zones() )
107  merge_area( zone );
108 
109  for( auto track : pcb->Tracks() )
110  merge_area( track );
111 
112  for( auto mod : pcb->Modules() )
113  for ( auto mod_pad : mod->Pads() )
114  merge_area( mod_pad );
115 
116  if( netcode > 0 && bbox.GetWidth() > 0 && bbox.GetHeight() > 0 )
117  {
118  auto bbSize = bbox.Inflate( bbox.GetWidth() * 0.2f ).GetSize();
119  auto screenSize = view->ToWorld( GetGalCanvas()->GetClientSize(), false );
120  double ratio = std::max( fabs( bbSize.x / screenSize.x ),
121  fabs( bbSize.y / screenSize.y ) );
122  double scale = view->GetScale() / ratio;
123 
124  view->SetScale( scale );
125  view->SetCenter( bbox.Centre() );
126  }
127 
128  GetGalCanvas()->Refresh();
129  }
130  else
131  {
132  if( netcode > 0 )
133  {
134  pcb->HighLightON();
135  pcb->SetHighLightNet( netcode );
136  }
137  else
138  {
139  pcb->HighLightOFF();
140  pcb->SetHighLightNet( -1 );
141  }
142  }
143  }
144 
145  return;
146  }
147 
148  if( text == NULL )
149  return;
150 
151  if( strcmp( idcmd, "$PART:" ) == 0 )
152  {
153  modName = FROM_UTF8( text );
154 
155  module = pcb->FindModuleByReference( modName );
156 
157  if( module )
158  msg.Printf( _( "%s found" ), GetChars( modName ) );
159  else
160  msg.Printf( _( "%s not found" ), GetChars( modName ) );
161 
162  SetStatusText( msg );
163 
164  if( module )
165  pos = module->GetPosition();
166  }
167  else if( strcmp( idcmd, "$SHEET:" ) == 0 )
168  {
169  msg.Printf( _( "Selecting all from sheet \"%s\"" ), FROM_UTF8( text ) );
170  wxString sheetStamp( FROM_UTF8( text ) );
171  SetStatusText( msg );
173  static_cast<void*>( &sheetStamp ) );
174  return;
175  }
176  else if( strcmp( idcmd, "$PIN:" ) == 0 )
177  {
178  wxString pinName;
179  int netcode = -1;
180 
181  pinName = FROM_UTF8( text );
182 
183  text = strtok( NULL, " \n\r" );
184  if( text && strcmp( text, "$PART:" ) == 0 )
185  text = strtok( NULL, "\n\r" );
186 
187  modName = FROM_UTF8( text );
188 
189  module = pcb->FindModuleByReference( modName );
190 
191  if( module )
192  pad = module->FindPadByName( pinName );
193 
194  if( pad )
195  {
196  netcode = pad->GetNetCode();
197 
198  // put cursor on the pad:
199  pos = pad->GetPosition();
200  }
201 
202  if( netcode > 0 ) // highlight the pad net
203  {
204  pcb->HighLightON();
205  pcb->SetHighLightNet( netcode );
206  }
207  else
208  {
209  pcb->HighLightOFF();
210  pcb->SetHighLightNet( -1 );
211  }
212 
213  if( module == NULL )
214  {
215  msg.Printf( _( "%s not found" ), GetChars( modName ) );
216  }
217  else if( pad == NULL )
218  {
219  msg.Printf( _( "%s pin %s not found" ), GetChars( modName ), GetChars( pinName ) );
220  SetCurItem( module );
221  }
222  else
223  {
224  msg.Printf( _( "%s pin %s found" ), GetChars( modName ), GetChars( pinName ) );
225  SetCurItem( pad );
226  }
227 
228  SetStatusText( msg );
229  }
230 
231  if( module ) // if found, center the module on screen, and redraw the screen.
232  {
233  if( IsGalCanvasActive() )
234  {
236  true,
237  pad ?
238  static_cast<BOARD_ITEM*>( pad ) :
239  static_cast<BOARD_ITEM*>( module )
240  );
241  }
242  else
243  {
244  SetCrossHairPosition( pos );
245  RedrawScreen( pos, false );
246  }
247  }
248 }
249 
250 
251 std::string FormatProbeItem( BOARD_ITEM* aItem )
252 {
253  MODULE* module;
254 
255  if( !aItem )
256  return "$CLEAR: \"HIGHLIGHTED\""; // message to clear highlight state
257 
258  switch( aItem->Type() )
259  {
260  case PCB_MODULE_T:
261  module = (MODULE*) aItem;
262  return StrPrintf( "$PART: \"%s\"", TO_UTF8( module->GetReference() ) );
263 
264  case PCB_PAD_T:
265  {
266  module = (MODULE*) aItem->GetParent();
267  wxString pad = ((D_PAD*)aItem)->GetName();
268 
269  return StrPrintf( "$PART: \"%s\" $PAD: \"%s\"",
270  TO_UTF8( module->GetReference() ),
271  TO_UTF8( pad ) );
272  }
273 
274  case PCB_MODULE_TEXT_T:
275  {
276  module = static_cast<MODULE*>( aItem->GetParent() );
277 
278  TEXTE_MODULE* text_mod = static_cast<TEXTE_MODULE*>( aItem );
279 
280  const char* text_key;
281 
282  /* This can't be a switch since the break need to pull out
283  * from the outer switch! */
284  if( text_mod->GetType() == TEXTE_MODULE::TEXT_is_REFERENCE )
285  text_key = "$REF:";
286  else if( text_mod->GetType() == TEXTE_MODULE::TEXT_is_VALUE )
287  text_key = "$VAL:";
288  else
289  break;
290 
291  return StrPrintf( "$PART: \"%s\" %s \"%s\"",
292  TO_UTF8( module->GetReference() ),
293  text_key,
294  TO_UTF8( text_mod->GetText() ) );
295  }
296 
297  default:
298  break;
299  }
300 
301  return "";
302 }
303 
304 
305 /* Send a remote command to Eeschema via a socket,
306  * aSyncItem = item to be located on schematic (module, pin or text)
307  * Commands are
308  * $PART: "reference" put cursor on component anchor
309  * $PART: "reference" $PAD: "pad number" put cursor on the component pin
310  * $PART: "reference" $REF: "reference" put cursor on the component ref
311  * $PART: "reference" $VAL: "value" put cursor on the component value
312  */
314 {
315  std::string packet = FormatProbeItem( aSyncItem );
316 
317  if( packet.size() )
318  {
319  if( Kiface().IsSingle() )
320  SendCommand( MSG_TO_SCH, packet.c_str() );
321  else
322  {
323  // Typically ExpressMail is going to be s-expression packets, but since
324  // we have existing interpreter of the cross probe packet on the other
325  // side in place, we use that here.
326  Kiway().ExpressMail( FRAME_SCH, MAIL_CROSS_PROBE, packet, this );
327  }
328  }
329 }
330 
331 
332 void PCB_EDIT_FRAME::SendCrossProbeNetName( const wxString& aNetName )
333 {
334  std::string packet = StrPrintf( "$NET: \"%s\"", TO_UTF8( aNetName ) );
335 
336  if( packet.size() )
337  {
338  if( Kiface().IsSingle() )
339  SendCommand( MSG_TO_SCH, packet.c_str() );
340  else
341  {
342  // Typically ExpressMail is going to be s-expression packets, but since
343  // we have existing interpreter of the cross probe packet on the other
344  // side in place, we use that here.
345  Kiway().ExpressMail( FRAME_SCH, MAIL_CROSS_PROBE, packet, this );
346  }
347  }
348 }
349 
350 
352 {
353  const std::string& payload = mail.GetPayload();
354 
355  switch( mail.Command() )
356  {
357  case MAIL_CROSS_PROBE:
358  ExecuteRemoteCommand( payload.c_str() );
359  break;
360 
361  case MAIL_SCH_PCB_UPDATE:
362  {
363  NETLIST netlist;
364  size_t split = payload.find( '\n' );
365  wxCHECK( split != std::string::npos, /*void*/ );
366 
367  // Extract options and netlist
368  std::string options = payload.substr( 0, split );
369  std::string netlistData = payload.substr( split + 1 );
370 
371  // Quiet update options
372  bool by_reference = options.find( "by-reference" ) != std::string::npos;
373  bool by_timestamp = options.find( "by-timestamp" ) != std::string::npos;
374  wxASSERT( !( by_reference && by_timestamp ) ); // only one at a time please
375 
376  try
377  {
378  STRING_LINE_READER* lineReader = new STRING_LINE_READER( netlistData, _( "Eeschema netlist" ) );
379  KICAD_NETLIST_READER netlistReader( lineReader, &netlist );
380  netlistReader.LoadNetlist();
381  }
382  catch( const IO_ERROR& )
383  {
384  assert( false ); // should never happen
385  }
386 
387  if( by_reference || by_timestamp )
388  {
389  netlist.SetDeleteExtraFootprints( false );
390  netlist.SetFindByTimeStamp( by_timestamp );
391  netlist.SetReplaceFootprints( true );
392 
393  BOARD_NETLIST_UPDATER updater( this, GetBoard() );
394  updater.SetLookupByTimestamp( by_timestamp );
395  updater.SetDeleteUnusedComponents( false );
396  updater.SetReplaceFootprints( true );
397  updater.SetDeleteSinglePadNets( false );
398  updater.UpdateNetlist( netlist );
399  }
400  else
401  {
402  DIALOG_UPDATE_PCB updateDialog( this, &netlist );
403  updateDialog.ShowModal();
404 
405  auto selectionTool = static_cast<SELECTION_TOOL*>(
406  m_toolManager->FindTool( "pcbnew.InteractiveSelection" ) );
407 
408  if( !selectionTool->GetSelection().Empty() )
409  GetToolManager()->InvokeTool( "pcbnew.InteractiveEdit" );
410  }
411 
412  break;
413  }
414 
415  case MAIL_IMPORT_FILE:
416  {
417  // Extract file format type and path (plugin type and path separated with \n)
418  size_t split = payload.find( '\n' );
419  wxCHECK( split != std::string::npos, /*void*/ );
420  int importFormat;
421 
422  try
423  {
424  importFormat = std::stoi( payload.substr( 0, split ) );
425  }
426  catch( std::invalid_argument& )
427  {
428  wxFAIL;
429  importFormat = -1;
430  }
431 
432  std::string path = payload.substr( split + 1 );
433  wxASSERT( !path.empty() );
434 
435  if( importFormat >= 0 )
436  importFile( path, importFormat );
437  }
438 
439  // many many others.
440  default:
441  ;
442  }
443 }
444 
TOOL_MANAGER * m_toolManager
Definition: draw_frame.h:125
KICAD_T Type() const
Function Type()
Definition: base_struct.h:201
BOARD_ITEM_CONTAINER * GetParent() const
Class KIWAY_EXPRESS carries a payload from one KIWAY_PLAYER to another within a PROJECT.
Definition: kiway_express.h:39
TOOL_BASE * FindTool(int aId) const
Function FindTool() Searches for a tool with given ID.
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_player.h:60
DDE server & client.
void SendCrossProbeNetName(const wxString &aNetName)
Sends a net name to eeschema for highlighting.
int StrPrintf(std::string *aResult, const char *aFormat,...)
Function StrPrintf is like sprintf() but the output is appended to a std::string instead of to a char...
Definition: richio.cpp:74
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes...
Definition: macros.h:53
Class KICAD_NETLIST_READER read the new s-expression based KiCad netlist format.
bool importFile(const wxString &aFileName, int aFileType)
Load the given filename but sets the path to the current project path.
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
Class BOARD_NETLIST_UPDATER updates the BOARD with a new netlist.
TEXT_TYPE GetType() const
Class SELECTION_TOOL.
Class BOARD to handle a board.
void SetDeleteSinglePadNets(bool aEnabled)
Enables "delete single pad nets" option
#define MSG_TO_SCH
Definition: eda_dde.h:46
D_PAD * FindPadByName(const wxString &aPadName) const
Function FindPadByName returns a D_PAD* with a matching name.
void SetCurItem(BOARD_ITEM *aItem, bool aDisplayInfo=true)
Function SetCurItem sets the currently selected item and displays it in the MsgPanel.
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:125
void HighLightOFF()
Function HighLightOFF Disable highlight.
Definition: class_board.h:394
MODULE * FindModuleByReference(const wxString &aReference) const
Function FindModuleByReference searches for a MODULE within this board with the given reference desig...
BOARD * GetBoard() const
Classes to handle copper zones.
BOARD_NETLIST_UPDATER class definition.
class D_PAD, a pad in a footprint
Definition: typeinfo.h:90
void SetFindByTimeStamp(bool aFindByTimeStamp)
Definition: pcb_netlist.h:311
bool SendCommand(int service, const char *cmdline)
Definition: eda_dde.cpp:132
void SetLookupByTimestamp(bool aEnabled)
Enables component lookup by timestamp instead of reference
Class BOARD_CONNECTED_ITEM is a base class derived from BOARD_ITEM for items that can be connected an...
bool UpdateNetlist(NETLIST &aNetlist)
Function UpdateNetlist()
bool InvokeTool(TOOL_ID aToolId)
Function InvokeTool() Calls a tool by sending a tool activation event to tool of given ID...
static TOOL_ACTION crossProbeSchToPcb
Definition: pcb_actions.h:380
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
Definition: kicad.cpp:52
Functions relatives to tracks, vias and segments used to fill zones.
This file contains miscellaneous commonly used macros and functions.
VTBL_ENTRY void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string aPayload, wxWindow *aSource=NULL)
Function ExpressMail send aPayload to aDestination from aSource.
Definition: kiway.cpp:386
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
void KiwayMailIn(KIWAY_EXPRESS &aEvent) override
Function KiwayMailIn receives KIWAY_EXPRESS messages from other players.
class MODULE, a footprint
Definition: typeinfo.h:89
virtual void LoadNetlist() override
Function LoadNetlist loads the contents of the netlist file into aNetlist.
void SetReplaceFootprints(bool aReplaceFootprints)
Definition: pcb_netlist.h:315
Class NETLIST stores all of information read from a netlist along with the flags used to update the N...
Definition: pcb_netlist.h:214
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:255
virtual void ExecuteRemoteCommand(const char *cmdline) override
Execute a remote command send by Eeschema via a socket, port KICAD_PCB_PORT_SERVICE_NUMBER (currently...
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:143
void SetReplaceFootprints(bool aEnabled)
Enables replacing footprints with new ones
SCH->PCB forward update.
Definition: mail_type.h:43
bool IsGalCanvasActive() const
Function IsGalCanvasActive is used to check which canvas (GAL-based or standard) is currently in use...
Definition: draw_frame.h:918
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:199
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Function Merge modifies the position and size of the rectangle in order to contain aRect...
Definition: box2.h:384
int GetNet() const
Function GetNet.
Definition: netinfo.h:231
std::string FormatProbeItem(BOARD_ITEM *aItem)
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
void HighLightON()
Function HighLightON Enable highlight.
Definition: class_board.h:401
const std::string & GetPayload()
Function Payload returns the payload, which can be any text but it typicall self identifying s-expres...
Definition: kiway_express.h:62
int GetNetCode() const
Function GetNetCode.
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
bool IsSingle() const
Function IsSingle is this KIFACE_I running under single_top?
Definition: kiface_i.h:115
void SetHighLightNet(int aNetCode)
Function SetHighLightNet.
Definition: class_board.h:379
void SendMessageToEESCHEMA(BOARD_ITEM *objectToSync)
Function SendMessageToEESCHEMA sends a message to the schematic editor so that it may move its cursor...
virtual RENDER_SETTINGS * GetSettings()=0
Function GetSettings Returns pointer to current settings that are going to be used when drawing items...
virtual void RedrawScreen(const wxPoint &aCenterPoint, bool aWarpPointer)
Redraw the entire screen area by updating the scroll bars and mouse pointer in order to have aCenterP...
TOOL_MANAGER * GetToolManager() const
Return the tool manager instance, if any.
Definition: draw_frame.h:931
Class NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:69
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:300
ZONE_CONTAINERS & Zones()
Definition: class_board.h:257
const int scale
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
see class PGM_BASE
static TOOL_ACTION selectOnSheetFromEeschema
Selects all components on sheet from Eeschema crossprobing.
Definition: pcb_actions.h:83
#define max(a, b)
Definition: auxiliary.h:86
Import a different format file.
Definition: mail_type.h:44
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:171
const wxString & GetReference() const
Function GetReference.
Definition: class_module.h:462
int GetToolId() const
Definition: draw_frame.h:516
void SetDeleteUnusedComponents(bool aEnabled)
Enables removing unused components
NETINFO_ITEM * FindNet(int aNetcode) const
Function FindNet searches for a net with the given netcode.
EDA_DRAW_PANEL_GAL * GetGalCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:925
PCB<->SCH, CVPCB->SCH cross-probing.
Definition: mail_type.h:39
DLIST_ITERATOR_WRAPPER< TRACK > Tracks()
Definition: class_board.h:254
Module description (excepted pads)
void SetDeleteExtraFootprints(bool aDeleteExtraFootprints)
Definition: pcb_netlist.h:300
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:252
MAIL_T Command()
Function Command returns the MAIL_T associated with this mail.
Definition: kiway_express.h:52
void SetCrossHairPosition(const wxPoint &aPosition, bool aSnapToGrid=true)
Set the screen cross hair position to aPosition in logical (drawing) units.
const wxPoint GetPosition() const override
Definition: class_pad.h:220
Class STRING_LINE_READER is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition: richio.h:254
void SetHighlight(bool aEnabled, int aNetcode=-1)
Function SetHighlight Turns on/off highlighting - it may be done for the active layer or the specifie...
Definition: painter.h:140
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:76
const wxPoint GetPosition() const override
Definition: class_module.h:183
#define mod(a, n)
Definition: greymap.cpp:24