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, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <sch_draw_panel.h>
26#include <trigo.h>
27#include <widgets/msgpanel.h>
28#include <bitmaps.h>
29#include <base_units.h>
30#include <eda_draw_frame.h>
31#include <erc/erc_settings.h>
32#include <sch_marker.h>
33#include <schematic.h>
34#include <widgets/ui_common.h>
35#include <pgm_base.h>
38#include <erc/erc_item.h>
39#include <sch_screen.h>
40
42#define SCALING_FACTOR schIUScale.mmToIU( 0.15 )
43
44
45SCH_MARKER::SCH_MARKER( std::shared_ptr<ERC_ITEM> aItem, const VECTOR2I& aPos ) :
46 SCH_ITEM( nullptr, SCH_MARKER_T ),
48{
49 if( m_rcItem )
50 m_rcItem->SetParent( this );
51
52 m_Pos = aPos;
53
54 m_isLegacyMarker = false;
55}
56
57
59{
60 if( m_rcItem )
61 m_rcItem->SetParent( nullptr );
62}
63
64
66{
67 return new SCH_MARKER( *this );
68}
69
70
72{
73 SCH_MARKER* item = static_cast<SCH_MARKER*>( aItem );
74
75 std::swap( m_isLegacyMarker, item->m_isLegacyMarker );
76 std::swap( m_Pos, item->m_Pos );
77
78 std::swap( m_markerType, item->m_markerType );
79 std::swap( m_excluded, item->m_excluded );
80 std::swap( m_comment, item->m_comment );
81 std::swap( m_rcItem, item->m_rcItem );
82
83 std::swap( m_scalingFactor, item->m_scalingFactor );
84 std::swap( m_shapeBoundingBox, item->m_shapeBoundingBox );
85}
86
87
89{
90 std::shared_ptr<ERC_ITEM> erc = std::static_pointer_cast<ERC_ITEM>( m_rcItem );
91 wxString sheetSpecificPath, mainItemPath, auxItemPath;
92
93 if( erc->IsSheetSpecific() )
94 sheetSpecificPath = erc->GetSpecificSheetPath().Path().AsString();
95
96 if( erc->MainItemHasSheetPath() )
97 mainItemPath = erc->GetMainItemSheetPath().Path().AsString();
98
99 if( erc->AuxItemHasSheetPath() )
100 auxItemPath = erc->GetAuxItemSheetPath().Path().AsString();
101
102 if( m_rcItem->GetErrorCode() == ERCE_GENERIC_WARNING
103 || m_rcItem->GetErrorCode() == ERCE_GENERIC_ERROR
104 || m_rcItem->GetErrorCode() == ERCE_UNRESOLVED_VARIABLE )
105 {
106 SCH_ITEM* sch_item = Schematic()->ResolveItem( erc->GetMainItemID() );
107 SCH_ITEM* parent = static_cast<SCH_ITEM*>( sch_item->GetParent() );
108 EDA_TEXT* text_item = dynamic_cast<EDA_TEXT*>( sch_item );
109
110 // SCH_FIELDs and SCH_ITEMs inside LIB_SYMBOLs don't have persistent KIIDs. So the
111 // exclusion must refer to the parent's KIID, and include the text of the original text
112 // item for later look-up.
113
114 if( parent && parent->IsType( { SCH_SYMBOL_T, SCH_LABEL_T, SCH_SHEET_T } ) )
115 {
116 if( text_item ) // should always be true, but Coverity doesn't know that
117 {
118 return wxString::Format( wxT( "%s|%d|%d|%s|%s|%s|%s|%s" ),
119 m_rcItem->GetSettingsKey(),
120 m_Pos.x,
121 m_Pos.y,
122 parent->m_Uuid.AsString(),
123 text_item->GetText(),
124 sheetSpecificPath,
125 mainItemPath,
126 wxEmptyString );
127 }
128 }
129 }
130
131 return wxString::Format( wxT( "%s|%d|%d|%s|%s|%s|%s|%s" ),
132 m_rcItem->GetSettingsKey(),
133 m_Pos.x,
134 m_Pos.y,
135 m_rcItem->GetMainItemID().AsString(),
136 m_rcItem->GetAuxItemID().AsString(),
137 sheetSpecificPath,
138 mainItemPath,
139 auxItemPath );
140}
141
142
144 const wxString& data )
145{
146 wxArrayString props = wxSplit( data, '|' );
147 VECTOR2I markerPos( (int) strtol( props[1].c_str(), nullptr, 10 ),
148 (int) strtol( props[2].c_str(), nullptr, 10 ) );
149
150 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( props[0] );
151
152 if( !ercItem )
153 return nullptr;
154
155 if( ercItem->GetErrorCode() == ERCE_GENERIC_WARNING
156 || ercItem->GetErrorCode() == ERCE_GENERIC_ERROR
157 || ercItem->GetErrorCode() == ERCE_UNRESOLVED_VARIABLE )
158 {
159 // SCH_FIELDs and SCH_ITEMs inside LIB_SYMBOLs don't have persistent KIIDs. So the
160 // exclusion will contain the parent's KIID in prop[3], and the text of the original
161 // text item in prop[4].
162
163 if( !props[4].IsEmpty() )
164 {
165 KIID uuid = niluuid;
166 SCH_ITEM* parent = aSheetList.ResolveItem( KIID( props[3] ) );
167
168 // Check fields and pins for a match
169 parent->RunOnChildren(
170 [&]( SCH_ITEM* child )
171 {
172 if( EDA_TEXT* text_item = dynamic_cast<EDA_TEXT*>( child ) )
173 {
174 if( text_item->GetText() == props[4] )
175 uuid = child->m_Uuid;
176 }
177 },
179
180 // If it's a symbol, we must also check non-overridden LIB_SYMBOL text children
181 if( uuid == niluuid && parent->Type() == SCH_SYMBOL_T )
182 {
183 static_cast<SCH_SYMBOL*>( parent )->GetLibSymbolRef()->RunOnChildren(
184 [&]( SCH_ITEM* child )
185 {
186 if( child->Type() == SCH_FIELD_T )
187 {
188 // Match only on SCH_SYMBOL fields, not LIB_SYMBOL fields.
189 }
190 else if( EDA_TEXT* text_item = dynamic_cast<EDA_TEXT*>( child ) )
191 {
192 if( text_item->GetText() == props[4] )
193 uuid = child->m_Uuid;
194 }
195 },
197 }
198
199 if( uuid != niluuid )
200 ercItem->SetItems( uuid );
201 else
202 return nullptr;
203 }
204 else
205 {
206 ercItem->SetItems( KIID( props[3] ) );
207 }
208 }
209 else
210 {
211 ercItem->SetItems( KIID( props[3] ), KIID( props[4] ) );
212 }
213
214 bool isLegacyMarker = true;
215
216 // Deserialize sheet / item specific paths - we are not able to use the file version to
217 // determine if markers are legacy as there could be a file opened with a prior version
218 // but which has new markers - this code is called not just during schematic load, but
219 // also to match new ERC exceptions to exclusions.
220 if( props.size() == 8 )
221 {
222 isLegacyMarker = false;
223
224 if( !props[5].IsEmpty() )
225 {
226 KIID_PATH sheetSpecificKiidPath( props[5] );
227 std::optional<SCH_SHEET_PATH> sheetSpecificPath =
228 aSheetList.GetSheetPathByKIIDPath( sheetSpecificKiidPath, true );
229
230 if( sheetSpecificPath.has_value() )
231 ercItem->SetSheetSpecificPath( sheetSpecificPath.value() );
232 }
233
234 if( !props[6].IsEmpty() )
235 {
236 KIID_PATH mainItemKiidPath( props[6] );
237 std::optional<SCH_SHEET_PATH> mainItemPath =
238 aSheetList.GetSheetPathByKIIDPath( mainItemKiidPath, true );
239
240 if( mainItemPath.has_value() )
241 {
242 if( props[7].IsEmpty() )
243 {
244 ercItem->SetItemsSheetPaths( mainItemPath.value() );
245 }
246 else
247 {
248 KIID_PATH auxItemKiidPath( props[7] );
249 std::optional<SCH_SHEET_PATH> auxItemPath =
250 aSheetList.GetSheetPathByKIIDPath( auxItemKiidPath, true );
251
252 if( auxItemPath.has_value() )
253 ercItem->SetItemsSheetPaths( mainItemPath.value(), auxItemPath.value() );
254 }
255 }
256 }
257 }
258
259 SCH_MARKER* marker = new SCH_MARKER( std::move( ercItem ), markerPos );
260 marker->SetIsLegacyMarker( isLegacyMarker );
261
262 return marker;
263}
264
265
266#if defined(DEBUG)
267
268void SCH_MARKER::Show( int nestLevel, std::ostream& os ) const
269{
270 // for now, make it look like XML:
271 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << GetPos() << "/>\n";
272}
273
274#endif
275
276
277std::vector<int> SCH_MARKER::ViewGetLayers() const
278{
279 wxCHECK2_MSG( Schematic(), return {}, "No SCHEMATIC set for SCH_MARKER!" );
280
281 // Don't display sheet-specific markers when SCH_SHEET_PATHs do not match
282 std::shared_ptr<ERC_ITEM> ercItem = std::static_pointer_cast<ERC_ITEM>( GetRCItem() );
283
284 if( ercItem->IsSheetSpecific()
285 && ( ercItem->GetSpecificSheetPath() != Schematic()->CurrentSheet() ) )
286 {
287 return {};
288 }
289
290 std::vector<int> layers( 2 );
291
292 if( IsExcluded() )
293 {
294 layers[0] = LAYER_ERC_EXCLUSION;
295 }
296 else
297 {
298 switch( Schematic()->ErcSettings().GetSeverity( m_rcItem->GetErrorCode() ) )
299 {
300 default:
301 case SEVERITY::RPT_SEVERITY_ERROR: layers[0] = LAYER_ERC_ERR; break;
302 case SEVERITY::RPT_SEVERITY_WARNING: layers[0] = LAYER_ERC_WARN; break;
303 }
304 }
305
306 layers[1] = LAYER_SELECTION_SHADOWS;
307 return layers;
308}
309
310
312{
313 if( IsExcluded() )
314 return LAYER_ERC_EXCLUSION;
315
316 wxCHECK_MSG( Schematic(), LAYER_ERC_ERR, "No SCHEMATIC set for SCH_MARKER!" );
317
318 switch( Schematic()->ErcSettings().GetSeverity( m_rcItem->GetErrorCode() ) )
319 {
320 default:
323 }
324}
325
326
328{
329 return ::GetColorSettings( DEFAULT_THEME )->GetColor( GetColorLayer() );
330}
331
332
334{
335 if( IsExcluded() )
337
338 ERC_ITEM* item = static_cast<ERC_ITEM*>( m_rcItem.get() );
339
340 return Schematic()->ErcSettings().GetSeverity( item->GetErrorCode() );
341}
342
343
344bool SCH_MARKER::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
345{
346 return SCH_ITEM::Matches( m_rcItem->GetErrorMessage( true ), aSearchData );
347}
348
349
351{
352 return GetBoundingBoxMarker();
353}
354
355
356void SCH_MARKER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
357{
358 aList.emplace_back( _( "Type" ), _( "Marker" ) );
359 aList.emplace_back( _( "Violation" ), m_rcItem->GetErrorMessage( true ) );
360
361 switch( GetSeverity() )
362 {
364 aList.emplace_back( _( "Severity" ), _( "Ignore" ) );
365 break;
367 aList.emplace_back( _( "Severity" ), _( "Warning" ) );
368 break;
370 aList.emplace_back( _( "Severity" ), _( "Error" ) );
371 break;
372 default:
373 break;
374 }
375
377 {
378 aList.emplace_back( _( "Drawing Sheet" ), wxEmptyString );
379 }
380 else
381 {
382 wxString mainText;
383 wxString auxText;
384 EDA_ITEM* mainItem = nullptr;
385 EDA_ITEM* auxItem = nullptr;
386
387 if( m_rcItem->GetMainItemID() != niluuid )
388 mainItem = aFrame->ResolveItem( m_rcItem->GetMainItemID() );
389
390 if( m_rcItem->GetAuxItemID() != niluuid )
391 auxItem = aFrame->ResolveItem( m_rcItem->GetAuxItemID() );
392
393 if( mainItem )
394 mainText = mainItem->GetItemDescription( aFrame, true );
395
396 if( auxItem )
397 auxText = auxItem->GetItemDescription( aFrame, true );
398
399 aList.emplace_back( mainText, auxText );
400 }
401
402 if( IsExcluded() )
403 aList.emplace_back( _( "Excluded" ), m_comment );
404}
405
406
408{
409 return BITMAPS::erc;
410}
411
412
413void SCH_MARKER::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
414{
415 // Marker geometry isn't user-editable
416}
417
418
420{
421 // Marker geometry isn't user-editable
422}
423
424
426{
427 // Marker geometry isn't user-editable
428}
429
430
431bool SCH_MARKER::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
432{
433 return HitTestMarker( aPosition, aAccuracy );
434}
BITMAPS
A list of all bitmap identifiers.
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
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:154
const KIID m_Uuid
Definition eda_item.h:522
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:111
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition eda_item.h:407
EDA_ITEM * GetParent() const
Definition eda_item.h:113
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:41
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:80
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:98
static std::shared_ptr< ERC_ITEM > Create(int aErrorCode)
Constructs an ERC_ITEM for the given error code.
Definition erc_item.cpp:312
SEVERITY GetSeverity(int aErrorCode) const
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:105
Definition kiid.h:49
wxString AsString() const
Definition kiid.cpp:244
bool IsExcluded() const
Definition marker_base.h:93
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:83
VECTOR2I m_Pos
Position of the marker.
@ MARKER_DRAWING_SHEET
Definition marker_base.h:56
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:91
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:158
SCH_ITEM * ResolveItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr, bool aAllowNullptrReturn=false) const
Definition schematic.h:126
ERC_SETTINGS & ErcSettings() const
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
Definition sch_item.h:631
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:254
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:56
bool IsType(const std::vector< KICAD_T > &aScanTypes) const override
Check whether the item is one of the listed types.
Definition sch_item.h:183
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:47
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:142
void SetIsLegacyMarker(bool isLegacyMarker=true)
Set this marker as a legacy artifact.
Definition sch_marker.h:114
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:76
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode) override
#define _(s)
@ NO_RECURSE
Definition eda_item.h:53
@ 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:449
@ LAYER_ERC_WARN
Definition layer_ids.h:479
@ LAYER_ERC_EXCLUSION
Definition layer_ids.h:481
@ LAYER_ERC_ERR
Definition layer_ids.h:480
@ LAYER_SELECTION_SHADOWS
Definition layer_ids.h:495
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:176
@ SCH_FIELD_T
Definition typeinfo.h:154
@ SCH_MARKER_T
Definition typeinfo.h:162
Functions to provide common constants and other functions to assist in making a consistent UI.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695