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