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  switch( aItem->Type() )
256  {
257  case PCB_MODULE_T:
258  module = (MODULE*) aItem;
259  return StrPrintf( "$PART: \"%s\"", TO_UTF8( module->GetReference() ) );
260 
261  case PCB_PAD_T:
262  {
263  module = (MODULE*) aItem->GetParent();
264  wxString pad = ((D_PAD*)aItem)->GetName();
265 
266  return StrPrintf( "$PART: \"%s\" $PAD: \"%s\"",
267  TO_UTF8( module->GetReference() ),
268  TO_UTF8( pad ) );
269  }
270 
271  case PCB_MODULE_TEXT_T:
272  {
273  module = static_cast<MODULE*>( aItem->GetParent() );
274 
275  TEXTE_MODULE* text_mod = static_cast<TEXTE_MODULE*>( aItem );
276 
277  const char* text_key;
278 
279  /* This can't be a switch since the break need to pull out
280  * from the outer switch! */
281  if( text_mod->GetType() == TEXTE_MODULE::TEXT_is_REFERENCE )
282  text_key = "$REF:";
283  else if( text_mod->GetType() == TEXTE_MODULE::TEXT_is_VALUE )
284  text_key = "$VAL:";
285  else
286  break;
287 
288  return StrPrintf( "$PART: \"%s\" %s \"%s\"",
289  TO_UTF8( module->GetReference() ),
290  text_key,
291  TO_UTF8( text_mod->GetText() ) );
292  }
293 
294  default:
295  break;
296  }
297 
298  return "";
299 }
300 
301 
302 /* Send a remote command to Eeschema via a socket,
303  * aSyncItem = item to be located on schematic (module, pin or text)
304  * Commands are
305  * $PART: "reference" put cursor on component anchor
306  * $PART: "reference" $PAD: "pad number" put cursor on the component pin
307  * $PART: "reference" $REF: "reference" put cursor on the component ref
308  * $PART: "reference" $VAL: "value" put cursor on the component value
309  */
311 {
312 #if 1
313  wxASSERT( aSyncItem ); // can't we fix the caller?
314 #else
315  if( !aSyncItem )
316  return;
317 #endif
318 
319  std::string packet = FormatProbeItem( aSyncItem );
320 
321  if( packet.size() )
322  {
323  if( Kiface().IsSingle() )
324  SendCommand( MSG_TO_SCH, packet.c_str() );
325  else
326  {
327  // Typically ExpressMail is going to be s-expression packets, but since
328  // we have existing interpreter of the cross probe packet on the other
329  // side in place, we use that here.
330  Kiway().ExpressMail( FRAME_SCH, MAIL_CROSS_PROBE, packet, this );
331  }
332  }
333 }
334 
335 
336 void PCB_EDIT_FRAME::SendCrossProbeNetName( const wxString& aNetName )
337 {
338  std::string packet = StrPrintf( "$NET: \"%s\"", TO_UTF8( aNetName ) );
339 
340  if( packet.size() )
341  {
342  if( Kiface().IsSingle() )
343  SendCommand( MSG_TO_SCH, packet.c_str() );
344  else
345  {
346  // Typically ExpressMail is going to be s-expression packets, but since
347  // we have existing interpreter of the cross probe packet on the other
348  // side in place, we use that here.
349  Kiway().ExpressMail( FRAME_SCH, MAIL_CROSS_PROBE, packet, this );
350  }
351  }
352 }
353 
354 
356 {
357  const std::string& payload = mail.GetPayload();
358 
359  switch( mail.Command() )
360  {
361  case MAIL_CROSS_PROBE:
362  ExecuteRemoteCommand( payload.c_str() );
363  break;
364 
365  case MAIL_SCH_PCB_UPDATE:
366  {
367  NETLIST netlist;
368  size_t split = payload.find( '\n' );
369  wxCHECK( split != std::string::npos, /*void*/ );
370 
371  // Extract options and netlist
372  std::string options = payload.substr( 0, split );
373  std::string netlistData = payload.substr( split + 1 );
374 
375  // Quiet update options
376  bool by_reference = options.find( "by-reference" ) != std::string::npos;
377  bool by_timestamp = options.find( "by-timestamp" ) != std::string::npos;
378  wxASSERT( !( by_reference && by_timestamp ) ); // only one at a time please
379 
380  try
381  {
382  STRING_LINE_READER* lineReader = new STRING_LINE_READER( netlistData, _( "Eeschema netlist" ) );
383  KICAD_NETLIST_READER netlistReader( lineReader, &netlist );
384  netlistReader.LoadNetlist();
385  }
386  catch( const IO_ERROR& )
387  {
388  assert( false ); // should never happen
389  }
390 
391  if( by_reference || by_timestamp )
392  {
393  netlist.SetDeleteExtraFootprints( false );
394  netlist.SetFindByTimeStamp( by_timestamp );
395  netlist.SetReplaceFootprints( true );
396 
397  BOARD_NETLIST_UPDATER updater( this, GetBoard() );
398  updater.SetLookupByTimestamp( by_timestamp );
399  updater.SetDeleteUnusedComponents( false );
400  updater.SetReplaceFootprints( true );
401  updater.SetDeleteSinglePadNets( false );
402  updater.UpdateNetlist( netlist );
403  }
404  else
405  {
406  DIALOG_UPDATE_PCB updateDialog( this, &netlist );
407  updateDialog.ShowModal();
408 
409  auto selectionTool = static_cast<SELECTION_TOOL*>(
410  m_toolManager->FindTool( "pcbnew.InteractiveSelection" ) );
411 
412  if( !selectionTool->GetSelection().Empty() )
413  GetToolManager()->InvokeTool( "pcbnew.InteractiveEdit" );
414  }
415 
416  break;
417  }
418 
419  case MAIL_IMPORT_FILE:
420  {
421  // Extract file format type and path (plugin type and path separated with \n)
422  size_t split = payload.find( '\n' );
423  wxCHECK( split != std::string::npos, /*void*/ );
424  int importFormat;
425 
426  try
427  {
428  importFormat = std::stoi( payload.substr( 0, split ) );
429  }
430  catch( std::invalid_argument& )
431  {
432  wxFAIL;
433  importFormat = -1;
434  }
435 
436  std::string path = payload.substr( split + 1 );
437  wxASSERT( !path.empty() );
438 
439  if( importFormat >= 0 )
440  importFile( path, importFormat );
441  }
442 
443  // many many others.
444  default:
445  ;
446  }
447 }
448 
TOOL_MANAGER * m_toolManager
Definition: draw_frame.h:109
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
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:393
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:392
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:254
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:893
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:201
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:227
std::string FormatProbeItem(BOARD_ITEM *aItem)
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:400
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:378
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...
void RedrawScreen(const wxPoint &aCenterPoint, bool aWarpPointer)
Function RedrawScreen redraws the entire screen area by updating the scroll bars and mouse pointer in...
Definition: zoom.cpp:46
TOOL_MANAGER * GetToolManager() const
Function GetToolManager returns the tool manager instance, if any.
Definition: draw_frame.h:908
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:256
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:170
const wxString & GetReference() const
Function GetReference.
Definition: class_module.h:460
int GetToolId() const
Definition: draw_frame.h:511
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
Function GetGalCanvas returns a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:901
PCB<->SCH, CVPCB->SCH cross-probing.
Definition: mail_type.h:39
DLIST_ITERATOR_WRAPPER< TRACK > Tracks()
Definition: class_board.h:253
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)
Function SetCrossHairPosition sets the screen cross hair position to aPosition in logical (drawing) u...
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:184
#define mod(a, n)
Definition: greymap.cpp:24