KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_marker.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) 2009 Jean-Pierre Charras, [email protected]
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <sch_draw_panel.h>
22#include <trigo.h>
23#include <widgets/msgpanel.h>
24#include <bitmaps.h>
25#include <base_units.h>
26#include <eda_draw_frame.h>
27#include <erc/erc_settings.h>
28#include <sch_marker.h>
29#include <schematic.h>
30#include <widgets/ui_common.h>
32#include <pgm_base.h>
35#include <erc/erc_item.h>
36#include <sch_screen.h>
37
39#define SCALING_FACTOR schIUScale.mmToIU( 0.15 )
40
41
42SCH_MARKER::SCH_MARKER( std::shared_ptr<ERC_ITEM> aItem, const VECTOR2I& aPos ) :
43 SCH_ITEM( nullptr, SCH_MARKER_T ),
45{
46 if( m_rcItem )
47 m_rcItem->SetParent( this );
48
49 m_Pos = aPos;
50
51 m_isLegacyMarker = false;
52}
53
54
56{
57 if( m_rcItem )
58 m_rcItem->SetParent( nullptr );
59}
60
61
63{
64 return new SCH_MARKER( *this );
65}
66
67
69{
70 SCH_MARKER* item = static_cast<SCH_MARKER*>( aItem );
71
72 std::swap( m_isLegacyMarker, item->m_isLegacyMarker );
73 std::swap( m_Pos, item->m_Pos );
74
75 std::swap( m_markerType, item->m_markerType );
76 std::swap( m_excluded, item->m_excluded );
77 std::swap( m_comment, item->m_comment );
78 std::swap( m_rcItem, item->m_rcItem );
79
80 std::swap( m_scalingFactor, item->m_scalingFactor );
81 std::swap( m_shapeBoundingBox, item->m_shapeBoundingBox );
82}
83
84
86{
87 std::shared_ptr<ERC_ITEM> erc = std::static_pointer_cast<ERC_ITEM>( m_rcItem );
88 wxString sheetSpecificPath, mainItemPath, auxItemPath;
89
90 if( erc->IsSheetSpecific() )
91 sheetSpecificPath = erc->GetSpecificSheetPath().Path().AsString();
92
93 if( erc->MainItemHasSheetPath() )
94 mainItemPath = erc->GetMainItemSheetPath().Path().AsString();
95
96 if( erc->AuxItemHasSheetPath() )
97 auxItemPath = erc->GetAuxItemSheetPath().Path().AsString();
98
99 if( m_rcItem->GetErrorCode() == ERCE_GENERIC_WARNING
100 || m_rcItem->GetErrorCode() == ERCE_GENERIC_ERROR
101 || m_rcItem->GetErrorCode() == ERCE_UNRESOLVED_VARIABLE )
102 {
103 SCH_ITEM* sch_item = Schematic()->ResolveItem( erc->GetMainItemID() );
104 SCH_ITEM* parent = static_cast<SCH_ITEM*>( sch_item->GetParent() );
105 EDA_TEXT* text_item = dynamic_cast<EDA_TEXT*>( sch_item );
106
107 // SCH_FIELDs and SCH_ITEMs inside LIB_SYMBOLs don't have persistent KIIDs. So the
108 // exclusion must refer to the parent's KIID, and include the text of the original text
109 // item for later look-up.
110
111 if( parent && parent->IsType( { SCH_SYMBOL_T, SCH_LABEL_T, SCH_SHEET_T } ) )
112 {
113 if( text_item ) // should always be true, but Coverity doesn't know that
114 {
115 return wxString::Format( wxT( "%s|%d|%d|%s|%s|%s|%s|%s" ),
116 m_rcItem->GetSettingsKey(),
117 m_Pos.x,
118 m_Pos.y,
119 parent->m_Uuid.AsString(),
120 text_item->GetText(),
121 sheetSpecificPath,
122 mainItemPath,
123 wxEmptyString );
124 }
125 }
126 }
127
128 return wxString::Format( wxT( "%s|%d|%d|%s|%s|%s|%s|%s" ),
129 m_rcItem->GetSettingsKey(),
130 m_Pos.x,
131 m_Pos.y,
132 m_rcItem->GetMainItemID().AsString(),
133 m_rcItem->GetAuxItemID().AsString(),
134 sheetSpecificPath,
135 mainItemPath,
136 auxItemPath );
137}
138
139
141 const wxString& data )
142{
143 wxArrayString props = wxSplit( data, '|' );
144 VECTOR2I markerPos( (int) strtol( props[1].c_str(), nullptr, 10 ),
145 (int) strtol( props[2].c_str(), nullptr, 10 ) );
146
147 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( props[0] );
148
149 if( !ercItem )
150 return nullptr;
151
152 if( ercItem->GetErrorCode() == ERCE_GENERIC_WARNING
153 || ercItem->GetErrorCode() == ERCE_GENERIC_ERROR
154 || ercItem->GetErrorCode() == ERCE_UNRESOLVED_VARIABLE )
155 {
156 // SCH_FIELDs and SCH_ITEMs inside LIB_SYMBOLs don't have persistent KIIDs. So the
157 // exclusion will contain the parent's KIID in prop[3], and the text of the original
158 // text item in prop[4].
159
160 if( !props[4].IsEmpty() )
161 {
162 KIID uuid = niluuid;
163 SCH_ITEM* parent = aSheetList.ResolveItem( KIID( props[3] ) );
164
165 // Check fields and pins for a match
166 parent->RunOnChildren(
167 [&]( SCH_ITEM* child )
168 {
169 if( EDA_TEXT* text_item = dynamic_cast<EDA_TEXT*>( child ) )
170 {
171 if( text_item->GetText() == props[4] )
172 uuid = child->m_Uuid;
173 }
174 },
176
177 // If it's a symbol, we must also check non-overridden LIB_SYMBOL text children
178 if( uuid == niluuid && parent->Type() == SCH_SYMBOL_T )
179 {
180 static_cast<SCH_SYMBOL*>( parent )->GetLibSymbolRef()->RunOnChildren(
181 [&]( SCH_ITEM* child )
182 {
183 if( child->Type() == SCH_FIELD_T )
184 {
185 // Match only on SCH_SYMBOL fields, not LIB_SYMBOL fields.
186 }
187 else if( EDA_TEXT* text_item = dynamic_cast<EDA_TEXT*>( child ) )
188 {
189 if( text_item->GetText() == props[4] )
190 uuid = child->m_Uuid;
191 }
192 },
194 }
195
196 if( uuid != niluuid )
197 ercItem->SetItems( uuid );
198 else
199 return nullptr;
200 }
201 else
202 {
203 ercItem->SetItems( KIID( props[3] ) );
204 }
205 }
206 else
207 {
208 ercItem->SetItems( KIID( props[3] ), KIID( props[4] ) );
209 }
210
211 bool isLegacyMarker = true;
212
213 // Deserialize sheet / item specific paths - we are not able to use the file version to
214 // determine if markers are legacy as there could be a file opened with a prior version
215 // but which has new markers - this code is called not just during schematic load, but
216 // also to match new ERC exceptions to exclusions.
217 if( props.size() == 8 )
218 {
219 isLegacyMarker = false;
220
221 if( !props[5].IsEmpty() )
222 {
223 KIID_PATH sheetSpecificKiidPath( props[5] );
224 std::optional<SCH_SHEET_PATH> sheetSpecificPath =
225 aSheetList.GetSheetPathByKIIDPath( sheetSpecificKiidPath, true );
226
227 if( sheetSpecificPath.has_value() )
228 ercItem->SetSheetSpecificPath( sheetSpecificPath.value() );
229 }
230
231 if( !props[6].IsEmpty() )
232 {
233 KIID_PATH mainItemKiidPath( props[6] );
234 std::optional<SCH_SHEET_PATH> mainItemPath =
235 aSheetList.GetSheetPathByKIIDPath( mainItemKiidPath, true );
236
237 if( mainItemPath.has_value() )
238 {
239 if( props[7].IsEmpty() )
240 {
241 ercItem->SetItemsSheetPaths( mainItemPath.value() );
242 }
243 else
244 {
245 KIID_PATH auxItemKiidPath( props[7] );
246 std::optional<SCH_SHEET_PATH> auxItemPath =
247 aSheetList.GetSheetPathByKIIDPath( auxItemKiidPath, true );
248
249 if( auxItemPath.has_value() )
250 ercItem->SetItemsSheetPaths( mainItemPath.value(), auxItemPath.value() );
251 }
252 }
253 }
254 }
255
256 SCH_MARKER* marker = new SCH_MARKER( std::move( ercItem ), markerPos );
257 marker->SetIsLegacyMarker( isLegacyMarker );
258
259 return marker;
260}
261
262
263#if defined(DEBUG)
264
265void SCH_MARKER::Show( int nestLevel, std::ostream& os ) const
266{
267 // for now, make it look like XML:
268 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << GetPos() << "/>\n";
269}
270
271#endif
272
273
274std::vector<int> SCH_MARKER::ViewGetLayers() const
275{
276 wxCHECK2_MSG( Schematic(), return {}, "No SCHEMATIC set for SCH_MARKER!" );
277
278 // Don't display sheet-specific markers when SCH_SHEET_PATHs do not match
279 std::shared_ptr<ERC_ITEM> ercItem = std::static_pointer_cast<ERC_ITEM>( GetRCItem() );
280
281 if( ercItem->IsSheetSpecific()
282 && ( ercItem->GetSpecificSheetPath() != Schematic()->CurrentSheet() ) )
283 {
284 return {};
285 }
286
287 std::vector<int> layers( 2 );
288
289 if( IsExcluded() )
290 {
291 layers[0] = LAYER_ERC_EXCLUSION;
292 }
293 else
294 {
295 switch( Schematic()->ErcSettings().GetSeverity( m_rcItem->GetErrorCode() ) )
296 {
297 case SEVERITY::RPT_SEVERITY_IGNORE: return {};
298 case SEVERITY::RPT_SEVERITY_WARNING: layers[0] = LAYER_ERC_WARN; break;
299 default:
300 case SEVERITY::RPT_SEVERITY_ERROR: layers[0] = LAYER_ERC_ERR; break;
301 }
302 }
303
304 layers[1] = LAYER_SELECTION_SHADOWS;
305 return layers;
306}
307
308
310{
311 if( IsExcluded() )
312 return LAYER_ERC_EXCLUSION;
313
314 wxCHECK_MSG( Schematic(), LAYER_ERC_ERR, "No SCHEMATIC set for SCH_MARKER!" );
315
316 switch( Schematic()->ErcSettings().GetSeverity( m_rcItem->GetErrorCode() ) )
317 {
318 default:
321 }
322}
323
324
326{
327 return ::GetColorSettings( DEFAULT_THEME )->GetColor( GetColorLayer() );
328}
329
330
332{
333 if( IsExcluded() )
335
336 ERC_ITEM* item = static_cast<ERC_ITEM*>( m_rcItem.get() );
337
338 return Schematic()->ErcSettings().GetSeverity( item->GetErrorCode() );
339}
340
341
342bool SCH_MARKER::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
343{
344 return SCH_ITEM::Matches( m_rcItem->GetErrorMessage( true ), aSearchData );
345}
346
347
349{
350 return GetBoundingBoxMarker();
351}
352
353
354void SCH_MARKER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
355{
356 aList.emplace_back( _( "Type" ), _( "Marker" ) );
357 aList.emplace_back( _( "Violation" ), HYPERLINK_DV_RENDERER::StripMarkup( m_rcItem->GetErrorMessage( true ) ) );
358
359 switch( GetSeverity() )
360 {
362 aList.emplace_back( _( "Severity" ), _( "Ignore" ) );
363 break;
365 aList.emplace_back( _( "Severity" ), _( "Warning" ) );
366 break;
368 aList.emplace_back( _( "Severity" ), _( "Error" ) );
369 break;
370 default:
371 break;
372 }
373
375 {
376 aList.emplace_back( _( "Drawing Sheet" ), wxEmptyString );
377 }
378 else
379 {
380 wxString mainText;
381 wxString auxText;
382 EDA_ITEM* mainItem = nullptr;
383 EDA_ITEM* auxItem = nullptr;
384
385 if( m_rcItem->GetMainItemID() != niluuid )
386 mainItem = aFrame->ResolveItem( m_rcItem->GetMainItemID() );
387
388 if( m_rcItem->GetAuxItemID() != niluuid )
389 auxItem = aFrame->ResolveItem( m_rcItem->GetAuxItemID() );
390
391 if( mainItem )
392 mainText = mainItem->GetItemDescription( aFrame, true );
393
394 if( auxItem )
395 auxText = auxItem->GetItemDescription( aFrame, true );
396
397 aList.emplace_back( mainText, auxText );
398 }
399
400 if( IsExcluded() )
401 aList.emplace_back( _( "Excluded" ), m_comment );
402}
403
404
406{
407 return BITMAPS::erc;
408}
409
410
411void SCH_MARKER::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
412{
413 // Marker geometry isn't user-editable
414}
415
416
418{
419 // Marker geometry isn't user-editable
420}
421
422
424{
425 // Marker geometry isn't user-editable
426}
427
428
429bool SCH_MARKER::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
430{
431 return HitTestMarker( aPosition, aAccuracy );
432}
BITMAPS
A list of all bitmap identifiers.
BOX2< VECTOR2I > BOX2I
Definition box2.h:918
The base class for create windows for drawing purpose.
virtual EDA_ITEM * ResolveItem(const KIID &aId, bool aAllowNullptrReturn=false) const
Fetch an item by KIID.
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
Definition eda_item.cpp:169
const KIID m_Uuid
Definition eda_item.h:531
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition eda_item.h:416
EDA_ITEM * GetParent() const
Definition eda_item.h:110
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:37
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:89
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:110
static std::shared_ptr< ERC_ITEM > Create(int aErrorCode)
Constructs an ERC_ITEM for the given error code.
Definition erc_item.cpp:292
SEVERITY GetSeverity(int aErrorCode) const
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
Definition kiid.h:44
wxString AsString() const
Definition kiid.cpp:242
bool IsExcluded() const
Definition marker_base.h:89
bool HitTestMarker(const VECTOR2I &aHitPosition, int aAccuracy) const
Test if the given VECTOR2I is within the bounds of this object.
std::shared_ptr< RC_ITEM > GetRCItem() const
int m_scalingFactor
Scaling factor to convert corners coordinates to internal units.
wxString m_comment
User supplied comment.
const VECTOR2I & GetPos() const
Definition marker_base.h:79
VECTOR2I m_Pos
Position of the marker.
@ MARKER_DRAWING_SHEET
Definition marker_base.h:52
MARKER_T m_markerType
The type of marker.
bool m_excluded
User has excluded this specific error.
std::shared_ptr< RC_ITEM > m_rcItem
enum MARKER_T GetMarkerType() const
Definition marker_base.h:87
BOX2I m_shapeBoundingBox
Bounding box of the graphic symbol relative to the position of the shape in marker shape units.
MARKER_BASE(int aScalingFactor, std::shared_ptr< RC_ITEM > aItem, MARKER_T aType=MARKER_UNSPEC)
BOX2I GetBoundingBoxMarker() const
Return the orthogonal, bounding box of this object for display purposes.
int GetErrorCode() const
Definition rc_item.h:157
SCH_ITEM * ResolveItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr, bool aAllowNullptrReturn=false) const
Definition schematic.h:128
ERC_SETTINGS & ErcSettings() const
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
Definition sch_item.h:628
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:268
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:52
bool IsType(const std::vector< KICAD_T > &aScanTypes) const override
Check whether the item is one of the listed types.
Definition sch_item.h:177
SEVERITY GetSeverity() const override
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxDat) const override
Compare DRC marker main and auxiliary text against search string.
wxString GetClass() const override
Return the class name.
Definition sch_marker.h:43
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
static SCH_MARKER * DeserializeFromString(const SCH_SHEET_LIST &aSheetList, const wxString &data)
bool m_isLegacyMarker
True if marker was deserialized from a file version < 20230121.
Definition sch_marker.h:138
void SetIsLegacyMarker(bool isLegacyMarker=true)
Set this marker as a legacy artifact.
Definition sch_marker.h:110
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
SCH_LAYER_ID GetColorLayer() const
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
std::vector< int > ViewGetLayers() const override
Return the layers the item is drawn on (which may be more than its "home" layer)
wxString SerializeToString() const
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
void swapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
KIGFX::COLOR4D getColor() const override
BOX2I const GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
SCH_MARKER(std::shared_ptr< ERC_ITEM > aItem, const VECTOR2I &aPos)
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
std::optional< SCH_SHEET_PATH > GetSheetPathByKIIDPath(const KIID_PATH &aPath, bool aIncludeLastSheet=true) const
Finds a SCH_SHEET_PATH that matches the provided KIID_PATH.
SCH_ITEM * ResolveItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr, bool aAllowNullptrReturn=false) const
Fetch a SCH_ITEM by ID.
Schematic symbol object.
Definition sch_symbol.h:69
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode) override
#define _(s)
@ NO_RECURSE
Definition eda_item.h:50
@ ERCE_UNRESOLVED_VARIABLE
A text variable could not be resolved.
@ ERCE_GENERIC_ERROR
@ ERCE_GENERIC_WARNING
KIID niluuid(0)
SCH_LAYER_ID
Eeschema drawing layers.
Definition layer_ids.h:447
@ LAYER_ERC_WARN
Definition layer_ids.h:477
@ LAYER_ERC_EXCLUSION
Definition layer_ids.h:479
@ LAYER_ERC_ERR
Definition layer_ids.h:478
@ LAYER_SELECTION_SHADOWS
Definition layer_ids.h:493
Message panel definition file.
see class PGM_BASE
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_EXCLUSION
@ RPT_SEVERITY_IGNORE
#define SCALING_FACTOR
Factor to convert the maker unit shape to internal units:
#define DEFAULT_THEME
@ SCH_SYMBOL_T
Definition typeinfo.h:169
@ SCH_FIELD_T
Definition typeinfo.h:147
@ SCH_MARKER_T
Definition typeinfo.h:155
Functions to provide common constants and other functions to assist in making a consistent UI.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683