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 default:
298 case SEVERITY::RPT_SEVERITY_ERROR: layers[0] = LAYER_ERC_ERR; break;
299 case SEVERITY::RPT_SEVERITY_WARNING: layers[0] = LAYER_ERC_WARN; break;
300 }
301 }
302
303 layers[1] = LAYER_SELECTION_SHADOWS;
304 return layers;
305}
306
307
309{
310 if( IsExcluded() )
311 return LAYER_ERC_EXCLUSION;
312
313 wxCHECK_MSG( Schematic(), LAYER_ERC_ERR, "No SCHEMATIC set for SCH_MARKER!" );
314
315 switch( Schematic()->ErcSettings().GetSeverity( m_rcItem->GetErrorCode() ) )
316 {
317 default:
320 }
321}
322
323
325{
326 return ::GetColorSettings( DEFAULT_THEME )->GetColor( GetColorLayer() );
327}
328
329
331{
332 if( IsExcluded() )
334
335 ERC_ITEM* item = static_cast<ERC_ITEM*>( m_rcItem.get() );
336
337 return Schematic()->ErcSettings().GetSeverity( item->GetErrorCode() );
338}
339
340
341bool SCH_MARKER::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
342{
343 return SCH_ITEM::Matches( m_rcItem->GetErrorMessage( true ), aSearchData );
344}
345
346
348{
349 return GetBoundingBoxMarker();
350}
351
352
353void SCH_MARKER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
354{
355 aList.emplace_back( _( "Type" ), _( "Marker" ) );
356 aList.emplace_back( _( "Violation" ), HYPERLINK_DV_RENDERER::StripMarkup( m_rcItem->GetErrorMessage( true ) ) );
357
358 switch( GetSeverity() )
359 {
361 aList.emplace_back( _( "Severity" ), _( "Ignore" ) );
362 break;
364 aList.emplace_back( _( "Severity" ), _( "Warning" ) );
365 break;
367 aList.emplace_back( _( "Severity" ), _( "Error" ) );
368 break;
369 default:
370 break;
371 }
372
374 {
375 aList.emplace_back( _( "Drawing Sheet" ), wxEmptyString );
376 }
377 else
378 {
379 wxString mainText;
380 wxString auxText;
381 EDA_ITEM* mainItem = nullptr;
382 EDA_ITEM* auxItem = nullptr;
383
384 if( m_rcItem->GetMainItemID() != niluuid )
385 mainItem = aFrame->ResolveItem( m_rcItem->GetMainItemID() );
386
387 if( m_rcItem->GetAuxItemID() != niluuid )
388 auxItem = aFrame->ResolveItem( m_rcItem->GetAuxItemID() );
389
390 if( mainItem )
391 mainText = mainItem->GetItemDescription( aFrame, true );
392
393 if( auxItem )
394 auxText = auxItem->GetItemDescription( aFrame, true );
395
396 aList.emplace_back( mainText, auxText );
397 }
398
399 if( IsExcluded() )
400 aList.emplace_back( _( "Excluded" ), m_comment );
401}
402
403
405{
406 return BITMAPS::erc;
407}
408
409
410void SCH_MARKER::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
411{
412 // Marker geometry isn't user-editable
413}
414
415
417{
418 // Marker geometry isn't user-editable
419}
420
421
423{
424 // Marker geometry isn't user-editable
425}
426
427
428bool SCH_MARKER::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
429{
430 return HitTestMarker( aPosition, aAccuracy );
431}
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:315
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