KiCad PCB EDA Suite
pcbnew/cross-probing.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2019-2020 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-3.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 
34 #include <fctsys.h>
35 #include <pgm_base.h>
36 #include <kiface_i.h>
37 #include <kiway_express.h>
38 #include <pcb_edit_frame.h>
39 #include <eda_dde.h>
40 #include <macros.h>
41 #include <class_board.h>
42 #include <class_module.h>
43 #include <class_track.h>
44 #include <class_zone.h>
45 #include <collectors.h>
46 #include <pcbnew.h>
48 #include <tools/pcb_actions.h>
49 #include <tool/tool_manager.h>
50 #include <tools/selection_tool.h>
51 #include <pcb_painter.h>
52 
53 /* Execute a remote command send by Eeschema via a socket,
54  * port KICAD_PCB_PORT_SERVICE_NUMBER
55  * cmdline = received command from Eeschema
56  * Commands are
57  * $PART: "reference" put cursor on component
58  * $PIN: "pin name" $PART: "reference" put cursor on the footprint pin
59  * $NET: "net name" highlight the given net (if highlight tool is active)
60  * $CLEAR Clear existing highlight
61  * They are a keyword followed by a quoted string.
62  */
63 void PCB_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
64 {
65  char line[1024];
66  wxString msg;
67  wxString modName;
68  char* idcmd;
69  char* text;
70  int netcode = -1;
71  MODULE* module = NULL;
72  D_PAD* pad = NULL;
73  BOARD* pcb = GetBoard();
74 
76  KIGFX::RENDER_SETTINGS* renderSettings = view->GetPainter()->GetSettings();
77 
78  strncpy( line, cmdline, sizeof(line) - 1 );
79  line[sizeof(line) - 1] = 0;
80 
81  idcmd = strtok( line, " \n\r" );
82  text = strtok( NULL, "\"\n\r" );
83 
84  if( idcmd == NULL )
85  return;
86 
87  if( strcmp( idcmd, "$NET:" ) == 0 )
88  {
89  wxString net_name = FROM_UTF8( text );
90 
91  NETINFO_ITEM* netinfo = pcb->FindNet( net_name );
92 
93  if( netinfo )
94  {
95  netcode = netinfo->GetNet();
96 
97  MSG_PANEL_ITEMS items;
98  netinfo->GetMsgPanelInfo( GetUserUnits(), items );
99  SetMsgPanel( items );
100  }
101  }
102  else if( strcmp( idcmd, "$PIN:" ) == 0 )
103  {
104  wxString pinName = FROM_UTF8( text );
105 
106  text = strtok( NULL, " \n\r" );
107 
108  if( text && strcmp( text, "$PART:" ) == 0 )
109  text = strtok( NULL, "\"\n\r" );
110 
111  modName = FROM_UTF8( text );
112 
113  module = pcb->FindModuleByReference( modName );
114 
115  if( module )
116  pad = module->FindPadByName( pinName );
117 
118  if( pad )
119  netcode = pad->GetNetCode();
120 
121  if( module == NULL )
122  msg.Printf( _( "%s not found" ), modName );
123  else if( pad == NULL )
124  msg.Printf( _( "%s pin %s not found" ), modName, pinName );
125  else
126  msg.Printf( _( "%s pin %s found" ), modName, pinName );
127 
128  SetStatusText( msg );
129  }
130  else if( strcmp( idcmd, "$PART:" ) == 0 )
131  {
132  pcb->ResetNetHighLight();
133 
134  modName = FROM_UTF8( text );
135 
136  module = pcb->FindModuleByReference( modName );
137 
138  if( module )
139  msg.Printf( _( "%s found" ), modName );
140  else
141  msg.Printf( _( "%s not found" ), modName );
142 
143  SetStatusText( msg );
144  }
145  else if( strcmp( idcmd, "$SHEET:" ) == 0 )
146  {
147  msg.Printf( _( "Selecting all from sheet \"%s\"" ), FROM_UTF8( text ) );
148  wxString sheetUIID( FROM_UTF8( text ) );
149  SetStatusText( msg );
151  static_cast<void*>( &sheetUIID ) );
152  return;
153  }
154  else if( strcmp( idcmd, "$CLEAR" ) == 0 )
155  {
156  renderSettings->SetHighlight( false );
157  view->UpdateAllLayersColor();
158 
159  pcb->ResetNetHighLight();
160  SetMsgPanel( pcb );
161 
162  GetCanvas()->Refresh();
163  return;
164  }
165 
166  BOX2I bbox = { { 0, 0 }, { 0, 0 } };
167 
168  if( module )
169  {
170  bbox = module->GetBoundingBox();
171 
172  if( pad )
173  m_toolManager->RunAction( PCB_ACTIONS::highlightItem, true, (void*) pad );
174  else
175  m_toolManager->RunAction( PCB_ACTIONS::highlightItem, true, (void*) module );
176  }
177  else if( netcode > 0 )
178  {
179  renderSettings->SetHighlight( ( netcode >= 0 ), netcode );
180 
181  pcb->SetHighLightNet( netcode );
182 
183  auto merge_area = [netcode, &bbox]( BOARD_CONNECTED_ITEM* aItem )
184  {
185  if( aItem->GetNetCode() == netcode )
186  {
187  if( bbox.GetWidth() == 0 )
188  bbox = aItem->GetBoundingBox();
189  else
190  bbox.Merge( aItem->GetBoundingBox() );
191  }
192  };
193 
194  for( auto zone : pcb->Zones() )
195  merge_area( zone );
196 
197  for( auto track : pcb->Tracks() )
198  merge_area( track );
199 
200  for( auto mod : pcb->Modules() )
201  for ( auto mod_pad : mod->Pads() )
202  merge_area( mod_pad );
203  }
204  else
205  {
206  renderSettings->SetHighlight( false );
207  }
208 
209  if( bbox.GetWidth() > 0 && bbox.GetHeight() > 0 )
210  {
211  auto bbSize = bbox.Inflate( bbox.GetWidth() * 0.2f ).GetSize();
212  auto screenSize = view->ToWorld( GetCanvas()->GetClientSize(), false );
213  screenSize.x = std::max( 10.0, screenSize.x );
214  screenSize.y = std::max( 10.0, screenSize.y );
215  double ratio = std::max( fabs( bbSize.x / screenSize.x ),
216  fabs( bbSize.y / screenSize.y ) );
217 
218  // Try not to zoom on every cross-probe; it gets very noisy
219  if( ratio < 0.1 || ratio > 1.0 )
220  view->SetScale( view->GetScale() / ratio );
221 
222  view->SetCenter( bbox.Centre() );
223  }
224 
225  view->UpdateAllLayersColor();
226  // Ensure the display is refreshed, because in some installs the refresh is done only
227  // when the gal canvas has the focus, and that is not the case when crossprobing from
228  // Eeschema:
229  GetCanvas()->Refresh();
230 }
231 
232 
233 std::string FormatProbeItem( BOARD_ITEM* aItem )
234 {
235  MODULE* module;
236 
237  if( !aItem )
238  return "$CLEAR: \"HIGHLIGHTED\""; // message to clear highlight state
239 
240  switch( aItem->Type() )
241  {
242  case PCB_MODULE_T:
243  module = (MODULE*) aItem;
244  return StrPrintf( "$PART: \"%s\"", TO_UTF8( module->GetReference() ) );
245 
246  case PCB_PAD_T:
247  {
248  module = (MODULE*) aItem->GetParent();
249  wxString pad = ((D_PAD*)aItem)->GetName();
250 
251  return StrPrintf( "$PART: \"%s\" $PAD: \"%s\"",
252  TO_UTF8( module->GetReference() ),
253  TO_UTF8( pad ) );
254  }
255 
256  case PCB_MODULE_TEXT_T:
257  {
258  module = static_cast<MODULE*>( aItem->GetParent() );
259 
260  TEXTE_MODULE* text_mod = static_cast<TEXTE_MODULE*>( aItem );
261 
262  const char* text_key;
263 
264  /* This can't be a switch since the break need to pull out
265  * from the outer switch! */
266  if( text_mod->GetType() == TEXTE_MODULE::TEXT_is_REFERENCE )
267  text_key = "$REF:";
268  else if( text_mod->GetType() == TEXTE_MODULE::TEXT_is_VALUE )
269  text_key = "$VAL:";
270  else
271  break;
272 
273  return StrPrintf( "$PART: \"%s\" %s \"%s\"",
274  TO_UTF8( module->GetReference() ),
275  text_key,
276  TO_UTF8( text_mod->GetText() ) );
277  }
278 
279  default:
280  break;
281  }
282 
283  return "";
284 }
285 
286 
287 /* Send a remote command to Eeschema via a socket,
288  * aSyncItem = item to be located on schematic (module, pin or text)
289  * Commands are
290  * $PART: "reference" put cursor on component anchor
291  * $PART: "reference" $PAD: "pad number" put cursor on the component pin
292  * $PART: "reference" $REF: "reference" put cursor on the component ref
293  * $PART: "reference" $VAL: "value" put cursor on the component value
294  */
296 {
297  std::string packet = FormatProbeItem( aSyncItem );
298 
299  if( !packet.empty() )
300  {
301  if( Kiface().IsSingle() )
302  SendCommand( MSG_TO_SCH, packet.c_str() );
303  else
304  {
305  // Typically ExpressMail is going to be s-expression packets, but since
306  // we have existing interpreter of the cross probe packet on the other
307  // side in place, we use that here.
308  Kiway().ExpressMail( FRAME_SCH, MAIL_CROSS_PROBE, packet, this );
309  }
310  }
311 }
312 
313 
314 void PCB_EDIT_FRAME::SendCrossProbeNetName( const wxString& aNetName )
315 {
316  std::string packet = StrPrintf( "$NET: \"%s\"", TO_UTF8( aNetName ) );
317 
318  if( !packet.empty() )
319  {
320  if( Kiface().IsSingle() )
321  SendCommand( MSG_TO_SCH, packet.c_str() );
322  else
323  {
324  // Typically ExpressMail is going to be s-expression packets, but since
325  // we have existing interpreter of the cross probe packet on the other
326  // side in place, we use that here.
327  Kiway().ExpressMail( FRAME_SCH, MAIL_CROSS_PROBE, packet, this );
328  }
329  }
330 }
331 
332 
334 {
335  std::string& payload = mail.GetPayload();
336 
337  switch( mail.Command() )
338  {
340  {
341  NETLIST netlist;
342  STRING_FORMATTER sf;
343  for( auto& module : this->GetBoard()->Modules() )
344  {
345  netlist.AddComponent( new COMPONENT( module->GetFPID(), module->GetReference(),
346  module->GetValue(), module->GetPath() ) );
347  }
348  netlist.Format(
349  "pcb_netlist", &sf, 0, CTL_OMIT_FILTERS | CTL_OMIT_NETS | CTL_OMIT_FILTERS );
350  payload = sf.GetString();
351  break;
352  }
353  case MAIL_CROSS_PROBE:
354  ExecuteRemoteCommand( payload.c_str() );
355  break;
356 
357  case MAIL_PCB_UPDATE:
359  break;
360 
361  case MAIL_IMPORT_FILE:
362  {
363  // Extract file format type and path (plugin type and path separated with \n)
364  size_t split = payload.find( '\n' );
365  wxCHECK( split != std::string::npos, /*void*/ );
366  int importFormat;
367 
368  try
369  {
370  importFormat = std::stoi( payload.substr( 0, split ) );
371  }
372  catch( std::invalid_argument& )
373  {
374  wxFAIL;
375  importFormat = -1;
376  }
377 
378  std::string path = payload.substr( split + 1 );
379  wxASSERT( !path.empty() );
380 
381  if( importFormat >= 0 )
382  importFile( path, importFormat );
383  }
384 
385  // many many others.
386  default:
387  ;
388  }
389 }
390 
NETINFO_ITEM * FindNet(int aNetcode) const
Function FindNet searches for a net with the given netcode.
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:280
KIWAY_EXPRESS carries a payload from one KIWAY_PLAYER to another within a PROJECT.
Definition: kiway_express.h:39
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_holder.h:56
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
int GetNetCode() const
Function GetNetCode.
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:62
bool importFile(const wxString &aFileName, int aFileType)
Load the given filename but sets the path to the current project path.
RENDER_SETTINGS Contains all the knowledge about how graphical objects are drawn on any output surfac...
Definition: painter.h:56
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
VECTOR2D ToWorld(const VECTOR2D &aCoord, bool aAbsolute=true) const
Function ToWorld() Converts a screen space point/vector to a point/vector in world space coordinates.
Definition: view.cpp:475
static TOOL_ACTION highlightItem
Definition: pcb_actions.h:413
#define MSG_TO_SCH
Definition: eda_dde.h:46
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:139
class D_PAD, a pad in a footprint
Definition: typeinfo.h:90
static TOOL_ACTION updatePcbFromSchematic
Definition: actions.h:156
Fetch a netlist from PCB layout.
Definition: mail_type.h:47
bool SendCommand(int service, const char *cmdline)
Definition: eda_dde.cpp:132
BOARD_CONNECTED_ITEM is a base class derived from BOARD_ITEM for items that can be connected and have...
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:199
Definitions for tracks, vias and zones.
This file contains miscellaneous commonly used macros and functions.
const wxString GetReference() const
Function GetReference.
Definition: class_module.h:436
void AddComponent(COMPONENT *aComponent)
Function AddComponent adds aComponent to the NETLIST.
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:48
void KiwayMailIn(KIWAY_EXPRESS &aEvent) override
Function KiwayMailIn receives KIWAY_EXPRESS messages from other players.
class MODULE, a footprint
Definition: typeinfo.h:89
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
D_PAD * FindPadByName(const wxString &aPadName) const
Function FindPadByName returns a D_PAD* with a matching name.
void ResetNetHighLight()
Function ResetNetHighLight Reset all high light data to the init state.
Definition: class_board.h:348
void SetCenter(const VECTOR2D &aCenter)
Function SetCenter() Sets the center point of the VIEW (i.e.
Definition: view.cpp:604
NETLIST stores all of information read from a netlist along with the flags used to update the NETLIST...
Definition: pcb_netlist.h:212
#define NULL
bool IsSingle() const
Function IsSingle is this KIFACE_I running under single_top?
Definition: kiface_i.h:117
MODULES & Modules()
Definition: class_board.h:229
void SetHighlight(bool aEnabled, int aNetcode=-1, bool aHighlightItems=false)
Function SetHighlight Turns on/off highlighting - it may be done for the active layer,...
Definition: painter.h:136
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
void ExecuteRemoteCommand(const char *cmdline) override
Execute a remote command send by Eeschema via a socket, port KICAD_PCB_PORT_SERVICE_NUMBER (currently...
coord_type GetWidth() const
Definition: box2.h:196
#define CTL_OMIT_FILTERS
Definition: pcb_netlist.h:349
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
void GetMsgPanelInfo(EDA_UNITS aUnits, std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo returns the information about the NETINFO_ITEM in aList to display in the me...
const std::string & GetString()
Definition: richio.h:475
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:385
#define CTL_OMIT_NETS
Omit pads net names (useless in library)
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...
COMPONENT is used to store components and all of their related information found in a netlist.
Definition: pcb_netlist.h:80
virtual void SetScale(double aScale, VECTOR2D aAnchor={ 0, 0 })
Function SetScale() Sets the scaling factor, zooming around a given anchor point.
Definition: view.cpp:578
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
void SetHighLightNet(int aNetCode)
Function SetHighLightNet.
Definition: class_board.h:364
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:427
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...
NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:65
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:301
ZONE_CONTAINERS & Zones()
Definition: class_board.h:243
see class PGM_BASE
Vec Centre() const
Definition: box2.h:78
int GetNet() const
Function GetNet.
Definition: netinfo.h:224
static TOOL_ACTION selectOnSheetFromEeschema
Selects all components on sheet from Eeschema crossprobing.
Definition: pcb_actions.h:94
Import a different format file.
Definition: mail_type.h:45
BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:163
#define _(s)
Definition: 3d_actions.cpp:33
void Format(const char *aDocName, OUTPUTFORMATTER *aOut, int aNestLevel, int aCtl=0)
coord_type GetHeight() const
Definition: box2.h:197
MODULE * FindModuleByReference(const wxString &aReference) const
Function FindModuleByReference searches for a MODULE within this board with the given reference desig...
std::vector< MSG_PANEL_ITEM > MSG_PANEL_ITEMS
Definition: msgpanel.h:102
PCB<->SCH, CVPCB->SCH cross-probing.
Definition: mail_type.h:39
TOOL_MANAGER * m_toolManager
Module description (excepted pads)
BOARD * GetBoard() const
VIEW.
Definition: view.h:61
MAIL_T Command()
Function Command returns the MAIL_T associated with this mail.
Definition: kiway_express.h:52
void UpdateAllLayersColor()
Function UpdateAllLayersColor() Applies the new coloring scheme to all layers.
Definition: view.cpp:798
double GetScale() const
Function GetScale()
Definition: view.h:257
BOARD_ITEM_CONTAINER * GetParent() const
STRING_FORMATTER implements OUTPUTFORMATTER to a memory buffer.
Definition: richio.h:445
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
SCH->PCB forward update.
Definition: mail_type.h:43
TRACKS & Tracks()
Definition: class_board.h:220
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
KICAD_T Type() const
Function Type()
Definition: base_struct.h:212