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 <google/protobuf/any.pb.h>
23#include <api/api_enums.h>
24#include <api/api_sch_utils.h>
25#include <api/api_utils.h>
26#include <api/schematic/schematic_rules.pb.h>
27#include <trigo.h>
28#include <widgets/msgpanel.h>
29#include <bitmaps.h>
30#include <base_units.h>
31#include <eda_draw_frame.h>
32#include <erc/erc_settings.h>
33#include <sch_marker.h>
34#include <schematic.h>
35#include <widgets/ui_common.h>
37#include <pgm_base.h>
40#include <erc/erc_item.h>
41#include <sch_screen.h>
42
44#define SCALING_FACTOR schIUScale.mmToIU( 0.15 )
45
46
47SCH_MARKER::SCH_MARKER( std::shared_ptr<ERC_ITEM> aItem, const VECTOR2I& aPos ) :
48 SCH_ITEM( nullptr, SCH_MARKER_T ),
50{
51 if( m_rcItem )
52 m_rcItem->SetParent( this );
53
54 m_Pos = aPos;
55}
56
57
59{
60 if( m_rcItem )
61 m_rcItem->SetParent( nullptr );
62}
63
64
66{
67 SCH_MARKER* res = new SCH_MARKER( *this );
68
69 // An RC_ITEM is shared between its marker and various tree views. It cannot be shared between
70 // two markers.
71 if( m_rcItem )
72 {
73 res->m_rcItem = std::make_shared<ERC_ITEM>( *std::static_pointer_cast<ERC_ITEM>( m_rcItem ) );
74 res->m_rcItem->SetParent( res );
75 }
76
77 return res;
78}
79
80
82{
83 SCH_MARKER* item = static_cast<SCH_MARKER*>( aItem );
84
85 std::swap( m_Pos, item->m_Pos );
86
87 std::swap( m_markerType, item->m_markerType );
88 std::swap( m_excluded, item->m_excluded );
89 std::swap( m_comment, item->m_comment );
90
91 std::swap( m_rcItem, item->m_rcItem );
92 {
93 if( m_rcItem )
94 m_rcItem->SetParent( this );
95
96 if( item->m_rcItem )
97 item->m_rcItem->SetParent( item );
98 }
99
100 std::swap( m_scalingFactor, item->m_scalingFactor );
101 std::swap( m_shapeBoundingBox, item->m_shapeBoundingBox );
102}
103
104
105static void ToProto( kiapi::schematic::ErcMarker& aMsg, const SCH_MARKER& aMarker )
106{
107 std::shared_ptr<ERC_ITEM> erc = std::static_pointer_cast<ERC_ITEM>( aMarker.GetRCItem() );
108
109 aMsg.set_error_type(
110 ToProtoEnum<ERCE_T, kiapi::schematic::ErcErrorType>( static_cast<ERCE_T>( erc->GetErrorCode() ) ) );
111
112 kiapi::common::PackVector2( *aMsg.mutable_position(), aMarker.GetPos(), schIUScale );
113
114 if( erc->IsSheetSpecific() )
115 PackSheetPath( *aMsg.mutable_sheet_specific_path(), erc->GetSpecificSheetPath() );
116
117 if( erc->MainItemHasSheetPath() )
118 PackSheetPath( *aMsg.mutable_main_item_sheet_path(), erc->GetMainItemSheetPath() );
119
120 if( erc->AuxItemHasSheetPath() )
121 PackSheetPath( *aMsg.mutable_aux_item_sheet_path(), erc->GetAuxItemSheetPath() );
122
123 if( erc->GetErrorCode() == ERCE_GENERIC_WARNING
124 || erc->GetErrorCode() == ERCE_GENERIC_ERROR
125 || erc->GetErrorCode() == ERCE_UNRESOLVED_VARIABLE )
126 {
127 SCH_ITEM* sch_item = aMarker.Schematic()->ResolveItem( erc->GetMainItemID() );
128 SCH_ITEM* parent = sch_item ? static_cast<SCH_ITEM*>( sch_item->GetParent() ) : nullptr;
129 EDA_TEXT* text_item = dynamic_cast<EDA_TEXT*>( sch_item );
130
131 // SCH_FIELDs and SCH_ITEMs inside LIB_SYMBOLs don't have persistent KIIDs. So the
132 // exclusion must refer to the parent's KIID, and include the text of the original text
133 // item for later look-up.
134 if( parent && parent->IsType( { SCH_SYMBOL_T, SCH_LABEL_T, SCH_SHEET_T } ) && text_item )
135 {
136 aMsg.add_items()->set_value( parent->m_Uuid.AsStdString() );
137 aMsg.mutable_child()->set_text_value( text_item->GetText().ToUTF8() );
138 }
139 }
140
141 for( const KIID& id : erc->GetIDs() )
142 {
143 if( id != niluuid )
144 aMsg.add_items()->set_value( id.AsStdString() );
145 }
146}
147
148
149SCH_MARKER* SCH_MARKER::FromProto( const kiapi::schematic::ErcMarker& aMsg, const SCH_SHEET_LIST& aSheetList )
150{
152
153 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( code );
154
155 if( !ercItem )
156 return nullptr;
157
158 VECTOR2I pos = kiapi::common::UnpackVector2( aMsg.position(), schIUScale );
159
160 if( aMsg.has_aux_item_sheet_path() && !aMsg.has_main_item_sheet_path() )
161 return nullptr;
162
163 if( aMsg.has_sheet_specific_path() )
164 {
165 KIID_PATH path = kiapi::common::UnpackSheetPath( aMsg.sheet_specific_path() );
166 std::optional<SCH_SHEET_PATH> sheetPath = aSheetList.GetSheetPathByKIIDPath( path, true );
167
168 if( sheetPath.has_value() )
169 ercItem->SetSheetSpecificPath( sheetPath.value() );
170 else
171 return nullptr;
172 }
173
174 if( aMsg.has_main_item_sheet_path() )
175 {
176 KIID_PATH path = kiapi::common::UnpackSheetPath( aMsg.main_item_sheet_path() );
177 std::optional<SCH_SHEET_PATH> mainPath = aSheetList.GetSheetPathByKIIDPath( path, true );
178
179 if( mainPath.has_value() )
180 {
181 if( aMsg.has_aux_item_sheet_path() )
182 {
183 KIID_PATH auxPath = kiapi::common::UnpackSheetPath( aMsg.aux_item_sheet_path() );
184 std::optional<SCH_SHEET_PATH> auxPathResolved = aSheetList.GetSheetPathByKIIDPath( auxPath, true );
185
186 if( auxPathResolved.has_value() )
187 ercItem->SetItemsSheetPaths( mainPath.value(), auxPathResolved.value() );
188 else
189 return nullptr;
190 }
191 else
192 {
193 ercItem->SetItemsSheetPaths( mainPath.value() );
194 }
195 }
196 else
197 {
198 return nullptr;
199 }
200 }
201
202 if( aMsg.has_child() && aMsg.items_size() > 0 )
203 {
204 SCH_ITEM* parent = aSheetList.ResolveItem( KIID( aMsg.items( 0 ).value() ) );
205
206 if( !parent )
207 return nullptr;
208
209 wxString text = wxString::FromUTF8( aMsg.child().text_value() );
210 KIID uuid = niluuid;
211
212 parent->RunOnChildren(
213 [&]( SCH_ITEM* child )
214 {
215 if( EDA_TEXT* text_item = dynamic_cast<EDA_TEXT*>( child ) )
216 {
217 if( text_item->GetText() == text )
218 uuid = child->m_Uuid;
219 }
220 },
222
223 if( uuid == niluuid && parent->Type() == SCH_SYMBOL_T )
224 {
225 static_cast<SCH_SYMBOL*>( parent )->GetLibSymbolRef()->RunOnChildren(
226 [&]( SCH_ITEM* child )
227 {
228 if( child->Type() == SCH_FIELD_T )
229 {
230 // Match only on SCH_SYMBOL fields, not LIB_SYMBOL fields.
231 }
232 else if( EDA_TEXT* text_item = dynamic_cast<EDA_TEXT*>( child ) )
233 {
234 if( text_item->GetText() == text )
235 uuid = child->m_Uuid;
236 }
237 },
239 }
240
241 if( uuid != niluuid )
242 ercItem->SetItems( uuid );
243 else
244 return nullptr;
245 }
246 else
247 {
248 std::vector<KIID> ids;
249 ids.reserve( aMsg.items_size() );
250
251 for( const auto& item : aMsg.items() )
252 ids.emplace_back( item.value() );
253
254 ercItem->SetItems( ids );
255 }
256
257 SCH_MARKER* marker = new SCH_MARKER( std::move( ercItem ), pos );
258
259 return marker;
260}
261
262
263void SCH_MARKER::Serialize( google::protobuf::Any& aContainer ) const
264{
265 kiapi::schematic::ErcMarker msg;
266 ToProto( msg, *this );
267 aContainer.PackFrom( msg );
268}
269
270
271bool SCH_MARKER::Deserialize( const google::protobuf::Any& aContainer )
272{
273 kiapi::schematic::ErcMarker msg;
274
275 if( !aContainer.UnpackTo( &msg ) )
276 return false;
277
278 if( !Schematic() )
279 return false;
280
281 std::unique_ptr<SCH_MARKER> tmp( SCH_MARKER::FromProto( msg, Schematic()->Hierarchy() ) );
282
283 if( !tmp )
284 return false;
285
286 swapData( tmp.get() );
287 return true;
288}
289
290
291#if defined(DEBUG)
292
293void SCH_MARKER::Show( int nestLevel, std::ostream& os ) const
294{
295 // for now, make it look like XML:
296 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << GetPos() << "/>\n";
297}
298
299#endif
300
301
302std::vector<int> SCH_MARKER::ViewGetLayers() const
303{
304 wxCHECK2_MSG( Schematic(), return {}, "No SCHEMATIC set for SCH_MARKER!" );
305
306 // Don't display sheet-specific markers when SCH_SHEET_PATHs do not match
307 std::shared_ptr<ERC_ITEM> ercItem = std::static_pointer_cast<ERC_ITEM>( GetRCItem() );
308
309 if( ercItem->IsSheetSpecific()
310 && ( ercItem->GetSpecificSheetPath() != Schematic()->CurrentSheet() ) )
311 {
312 return {};
313 }
314
315 std::vector<int> layers( 2 );
316
317 if( IsExcluded() )
318 {
319 layers[0] = LAYER_ERC_EXCLUSION;
320 }
321 else
322 {
323 switch( Schematic()->ErcSettings().GetSeverity( m_rcItem->GetErrorCode() ) )
324 {
325 case SEVERITY::RPT_SEVERITY_IGNORE: return {};
326 case SEVERITY::RPT_SEVERITY_WARNING: layers[0] = LAYER_ERC_WARN; break;
327 default:
328 case SEVERITY::RPT_SEVERITY_ERROR: layers[0] = LAYER_ERC_ERR; break;
329 }
330 }
331
332 layers[1] = LAYER_SELECTION_SHADOWS;
333 return layers;
334}
335
336
338{
339 if( IsExcluded() )
340 return LAYER_ERC_EXCLUSION;
341
342 wxCHECK_MSG( Schematic(), LAYER_ERC_ERR, "No SCHEMATIC set for SCH_MARKER!" );
343
344 switch( Schematic()->ErcSettings().GetSeverity( m_rcItem->GetErrorCode() ) )
345 {
346 default:
349 }
350}
351
352
354{
355 return ::GetColorSettings( DEFAULT_THEME )->GetColor( GetColorLayer() );
356}
357
358
360{
361 if( IsExcluded() )
363
364 ERC_ITEM* item = static_cast<ERC_ITEM*>( m_rcItem.get() );
365
366 return Schematic()->ErcSettings().GetSeverity( item->GetErrorCode() );
367}
368
369
370bool SCH_MARKER::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
371{
372 return SCH_ITEM::Matches( m_rcItem->GetErrorMessage( true ), aSearchData );
373}
374
375
377{
378 return GetBoundingBoxMarker();
379}
380
381
382void SCH_MARKER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
383{
384 aList.emplace_back( _( "Type" ), _( "Marker" ) );
385 aList.emplace_back( _( "Violation" ), HYPERLINK_DV_RENDERER::StripMarkup( m_rcItem->GetErrorMessage( true ) ) );
386
387 switch( GetSeverity() )
388 {
389 case RPT_SEVERITY_IGNORE: aList.emplace_back( _( "Severity" ), _( "Ignore" ) ); break;
390 case RPT_SEVERITY_WARNING: aList.emplace_back( _( "Severity" ), _( "Warning" ) ); break;
391 case RPT_SEVERITY_ERROR: aList.emplace_back( _( "Severity" ), _( "Error" ) ); break;
392 default: break;
393 }
394
396 {
397 aList.emplace_back( _( "Drawing Sheet" ), wxEmptyString );
398 }
399 else
400 {
401 wxString mainText;
402 wxString auxText;
403 EDA_ITEM* mainItem = nullptr;
404 EDA_ITEM* auxItem = nullptr;
405
406 if( m_rcItem->GetMainItemID() != niluuid )
407 mainItem = aFrame->ResolveItem( m_rcItem->GetMainItemID() );
408
409 if( m_rcItem->GetAuxItemID() != niluuid )
410 auxItem = aFrame->ResolveItem( m_rcItem->GetAuxItemID() );
411
412 if( mainItem )
413 mainText = mainItem->GetItemDescription( aFrame, true );
414
415 if( auxItem )
416 auxText = auxItem->GetItemDescription( aFrame, true );
417
418 aList.emplace_back( mainText, auxText );
419 }
420
421 if( IsExcluded() )
422 aList.emplace_back( _( "Excluded" ), m_comment );
423}
424
425
427{
428 return BITMAPS::erc;
429}
430
431
432void SCH_MARKER::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
433{
434 // Marker geometry isn't user-editable
435}
436
437
439{
440 // Marker geometry isn't user-editable
441}
442
443
445{
446 // Marker geometry isn't user-editable
447}
448
449
450bool SCH_MARKER::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
451{
452 return HitTestMarker( aPosition, aAccuracy );
453}
KICOMMON_API types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICOMMON_API KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:55
void PackSheetPath(types::SheetPath &aOutput, const SCH_SHEET_PATH &aInput)
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:130
BITMAPS
A list of all bitmap identifiers.
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
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:304
const KIID m_Uuid
Definition eda_item.h:599
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition eda_item.h:484
EDA_ITEM * GetParent() const
Definition eda_item.h:112
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:84
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:94
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:118
static std::shared_ptr< ERC_ITEM > Create(int aErrorCode)
Constructs an ERC_ITEM for the given error code.
Definition erc_item.cpp:309
SEVERITY GetSeverity(int aErrorCode) const
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
Definition kiid.h:46
std::string AsStdString() const
Definition kiid.cpp:270
bool IsExcluded() const
Definition marker_base.h:90
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:80
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:88
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
void SetParent(MARKER_BASE *aMarker)
Definition rc_item.h:135
SCH_ITEM * ResolveItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr, bool aAllowNullptrReturn=false) const
Definition schematic.h:194
ERC_SETTINGS & ErcSettings() const
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:170
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
Definition sch_item.h:678
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:302
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:65
bool IsType(const std::vector< KICAD_T > &aScanTypes) const override
Check whether the item is one of the listed types.
Definition sch_item.h:185
SEVERITY GetSeverity() const override
wxString GetClass() const override
Return the class name.
Definition sch_marker.h:47
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare DRC marker main and auxiliary text against search string.
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
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)
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.
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
static SCH_MARKER * FromProto(const kiapi::schematic::ErcMarker &aMsg, const SCH_SHEET_LIST &aSheetList)
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:73
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode) override
#define _(s)
@ NO_RECURSE
Definition eda_item.h:52
ERCE_T
ERC error codes.
@ 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:471
@ LAYER_ERC_WARN
Definition layer_ids.h:501
@ LAYER_ERC_EXCLUSION
Definition layer_ids.h:503
@ LAYER_ERC_ERR
Definition layer_ids.h:502
@ LAYER_SELECTION_SHADOWS
Definition layer_ids.h:517
Message panel definition file.
KICOMMON_API KIID_PATH UnpackSheetPath(const types::SheetPath &aInput)
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput, const EDA_IU_SCALE &aScale)
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:
static void ToProto(kiapi::schematic::ErcMarker &aMsg, const SCH_MARKER &aMarker)
#define DEFAULT_THEME
std::string path
VECTOR3I res
@ SCH_SYMBOL_T
Definition typeinfo.h:168
@ SCH_FIELD_T
Definition typeinfo.h:146
@ SCH_MARKER_T
Definition typeinfo.h:154
Functions to provide common constants and other functions to assist in making a consistent UI.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708