KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_commit.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <macros.h>
21#include <tool/tool_manager.h>
22#include <tools/sch_tool_base.h>
23
24#include <lib_symbol.h>
25
26#include <sch_group.h>
27#include <sch_screen.h>
28#include <schematic.h>
29
30#include <view/view.h>
31#include <sch_commit.h>
32#include <connection_graph.h>
33
34#include <functional>
35#include <memory>
36#include <set>
37#include <wx/log.h>
38
39
41 COMMIT(),
42 m_toolMgr( aToolMgr ),
43 m_isLibEditor( false )
44{
45 SCH_BASE_FRAME* frame = static_cast<SCH_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
46 m_isLibEditor = frame && frame->IsType( FRAME_SCH_SYMBOL_EDITOR );
47}
48
49
55
56
62
63
67
68
70 RECURSE_MODE aRecurse )
71{
72 wxCHECK( aItem, *this );
73
74 if( aRecurse == RECURSE_MODE::RECURSE )
75 {
76 if( SCH_GROUP* group = dynamic_cast<SCH_GROUP*>( aItem ) )
77 {
78 for( EDA_ITEM* member : group->GetItems() )
79 Stage( member, aChangeType, aScreen, aRecurse );
80 }
81 }
82
83 // IS_SELECTED flag should not be set on undo items which were added for a drag operation.
84 if( aItem->IsSelected() && aItem->HasFlag( SELECTED_BY_DRAG ) )
85 {
86 aItem->ClearSelected();
87 COMMIT::Stage( aItem, aChangeType, aScreen );
88 aItem->SetSelected();
89 }
90 else
91 {
92 COMMIT::Stage( aItem, aChangeType, aScreen );
93 }
94
95 return *this;
96}
97
98
99COMMIT& SCH_COMMIT::Stage( std::vector<EDA_ITEM*> &container, CHANGE_TYPE aChangeType,
100 BASE_SCREEN *aScreen )
101{
102 for( EDA_ITEM* item : container )
103 Stage( item, aChangeType, aScreen );
104
105 return *this;
106}
107
108
110{
111 wxASSERT( !aScreen->CheckIfOnDrawList( aItem ) );
112
113 if( COMMIT_LINE* entry = findEntry( aItem, aScreen ); entry && ( entry->m_type & CHT_TYPE ) == CHT_MODIFY )
114 {
115 // Staging REMOVE discards MODIFY, so preserve the original geometry on the removed item
116 // before its image is discarded. Cleanup must still skip it until the commit is processed.
117 aItem->SwapItemData( static_cast<SCH_ITEM*>( entry->m_copy ) );
118 aItem->SetFlags( STRUCT_DELETED );
119 }
120
121 Removed( aItem, aScreen );
122}
123
124
125void SCH_COMMIT::pushLibEdit( const wxString& aMessage, int aCommitFlags )
126{
127 // Symbol editor just saves copies of the whole symbol, so grab the first and discard the rest
128 LIB_SYMBOL* symbol = dynamic_cast<LIB_SYMBOL*>( m_entries.front().m_item );
129 LIB_SYMBOL* copy = dynamic_cast<LIB_SYMBOL*>( m_entries.front().m_copy );
130
131 if( symbol )
132 {
133 if( KIGFX::VIEW* view = m_toolMgr->GetView() )
134 {
135 view->Update( symbol );
136
137 symbol->RunOnChildren(
138 [&]( SCH_ITEM* aChild )
139 {
140 view->Update( aChild );
141 },
143 }
144
145 if( SYMBOL_EDIT_FRAME* frame = static_cast<SYMBOL_EDIT_FRAME*>( m_toolMgr->GetToolHolder() ) )
146 {
147 if( !( aCommitFlags & SKIP_UNDO ) )
148 {
149 if( copy )
150 {
151 frame->PushSymbolToUndoList( aMessage, copy );
152 copy = nullptr; // we've transferred ownership to the undo stack
153 }
154 }
155 }
156
157 if( copy )
158 {
159 // if no undo entry was needed, the copy would create a memory leak
160 delete copy;
161 copy = nullptr;
162 }
163 }
164
165 m_toolMgr->PostEvent( { TC_MESSAGE, TA_MODEL_CHANGE, AS_GLOBAL } );
167}
168
169
170void SCH_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
171{
172
173 // Objects potentially interested in changes:
174 PICKED_ITEMS_LIST undoList;
175 KIGFX::VIEW* view = m_toolMgr->GetView();
176
177 SCH_EDIT_FRAME* frame = static_cast<SCH_EDIT_FRAME*>( m_toolMgr->GetToolHolder() );
178 SCH_SCREEN* currentScreen = frame ? frame->GetScreen() : nullptr;
179 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
180 SCH_GROUP* enteredGroup = selTool ? selTool->GetEnteredGroup() : nullptr;
181 bool itemsDeselected = false;
182 bool selectedModified = false;
183 bool dirtyConnectivity = false;
184 bool refreshConnectivity = false;
185 bool refreshHierarchy = false;
186 SCH_CLEANUP_FLAGS connectivityCleanUp = NO_CLEANUP;
187
188 if( Empty() )
189 {
190 return;
191 }
192
193 if( !frame )
194 aCommitFlags |= SKIP_UNDO;
195
196 undoList.SetDescription( aMessage );
197
198 SCHEMATIC* schematic = nullptr;
199 std::vector<SCH_ITEM*> bulkAddedItems;
200 std::vector<SCH_ITEM*> bulkRemovedItems;
201 std::vector<SCH_ITEM*> itemsChanged;
202 std::vector<std::unique_ptr<SCH_ITEM>> cleanupRemovedItems;
203
204 auto notifyModel = [&]()
205 {
206 if( !schematic )
207 return;
208
209
210 if( !bulkAddedItems.empty() )
211 schematic->OnItemsAdded( bulkAddedItems );
212
213
214 if( !bulkRemovedItems.empty() )
215 schematic->OnItemsRemoved( bulkRemovedItems );
216
217
218 if( !itemsChanged.empty() )
219 schematic->OnItemsChanged( itemsChanged );
220
221
222 if( refreshHierarchy )
223 schematic->RefreshHierarchy();
224
225 bulkAddedItems.clear();
226 bulkRemovedItems.clear();
227 itemsChanged.clear();
228 };
229
230 auto updateConnectivityFlag =
231 [&]( SCH_ITEM* schItem )
232 {
233 if( schItem->IsConnectable() || ( schItem->Type() == SCH_RULE_AREA_T ) )
234 {
235 dirtyConnectivity = true;
236
237 // Do a local clean up if there are any connectable objects in the commit.
238 if( connectivityCleanUp == NO_CLEANUP )
239 connectivityCleanUp = LOCAL_CLEANUP;
240
241 if( schItem->Type() == SCH_SHEET_T )
242 connectivityCleanUp = GLOBAL_CLEANUP;
243 }
244 };
245
246 // We don't know that anything will be added to the entered group, but it does no harm to
247 // add it to the commit anyway.
248 if( enteredGroup && frame )
249 Modify( enteredGroup, frame->GetScreen() );
250
251
252 // Handle wires with Hop Over shapes (view update only; skipped headless):
253 if( frame )
254 {
255 for( COMMIT_LINE& entry : m_entries )
256 {
257 SCH_ITEM* schCopyItem = dynamic_cast<SCH_ITEM*>( entry.m_copy );
258 SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( entry.m_item );
259
260 if( schCopyItem && schCopyItem->Type() == SCH_LINE_T )
261 frame->UpdateHopOveredWires( schCopyItem );
262
263 if( schItem && schItem->Type() == SCH_LINE_T )
264 frame->UpdateHopOveredWires( schItem );
265 }
266 }
267
268
269 auto stageRemovedGroups = [&]()
270 {
271 // Modify() appends to m_entries, so collect before staging group changes.
272 std::vector<std::pair<EDA_GROUP*, BASE_SCREEN*>> removedItemGroups;
273
274 for( COMMIT_LINE& entry : m_entries )
275 {
276 SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( entry.m_item );
277 int changeType = entry.m_type & CHT_TYPE;
278
279 wxCHECK2( schItem, continue );
280
281 if( changeType == CHT_REMOVE && schItem->GetParentGroup() )
282 removedItemGroups.emplace_back( schItem->GetParentGroup(), entry.m_screen );
283 }
284
285 for( const auto& [group, screen] : removedItemGroups )
286 Modify( group->AsEdaItem(), screen );
287 };
288 stageRemovedGroups();
289 bool cleanupPending = true;
290 std::set<SCH_SCREEN*> touchedScreens;
291
292 for( size_t index = 0; ; )
293 {
294 if( index == m_entries.size() )
295 {
296 if( !cleanupPending || !dirtyConnectivity || ( aCommitFlags & SKIP_CONNECTIVITY ) || !schematic )
297 break;
298
299 cleanupPending = false;
300 notifyModel();
301
302 // Cleanup can replace a MODIFY with REMOVE. Keep its staging separate from processed
303 // entries while retaining their undo records, so both phases form one user action.
304 clear();
305 schematic->CleanUpConnections( this, connectivityCleanUp );
306
307 stageRemovedGroups();
308 index = 0;
309 continue;
310 }
311
312 COMMIT_LINE& entry = m_entries[index++];
313 int changeType = entry.m_type & CHT_TYPE;
314 int changeFlags = entry.m_type & CHT_FLAGS;
315 SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( entry.m_item );
316 SCH_SCREEN* screen = dynamic_cast<SCH_SCREEN*>( entry.m_screen );
317
318 wxCHECK2( schItem, continue );
319 wxCHECK2( screen, continue );
320
321 touchedScreens.insert( screen );
322
323 if( !schematic )
324 schematic = schItem->Schematic();
325
326 if( schItem->IsSelected() )
327 {
328 selectedModified = true;
329 }
330 else
331 {
332 schItem->RunOnChildren(
333 [&selectedModified]( SCH_ITEM* aChild )
334 {
335 if( aChild->IsSelected() )
336 selectedModified = true;
337 },
339 }
340
341 switch( changeType )
342 {
343 case CHT_ADD:
344 {
345 if( enteredGroup && schItem->IsGroupableType() && !schItem->GetParentGroup() )
346 selTool->GetEnteredGroup()->AddItem( schItem );
347
348 updateConnectivityFlag( schItem );
349
350 if( !( aCommitFlags & SKIP_UNDO ) )
351 undoList.PushItem( ITEM_PICKER( screen, schItem, UNDO_REDO::NEWITEM ) );
352
353 if( !( changeFlags & CHT_DONE ) )
354 {
355 if( !screen->CheckIfOnDrawList( schItem ) ) // don't want a loop!
356 screen->Append( schItem );
357
358 if( view && screen == currentScreen )
359 view->Add( schItem );
360 }
361
362 if( frame && screen == currentScreen )
363 frame->UpdateItem( schItem, true, true );
364 else if( screen )
365 screen->Update( schItem );
366
367 bulkAddedItems.push_back( schItem );
368
369 if( schItem->Type() == SCH_SHEET_T )
370 refreshHierarchy = true;
371
372 break;
373 }
374
375 case CHT_REMOVE:
376 {
377 updateConnectivityFlag( schItem );
378
379 if( !( aCommitFlags & SKIP_UNDO ) )
380 {
381 ITEM_PICKER itemWrapper( screen, schItem, UNDO_REDO::DELETED );
382 itemWrapper.SetLink( entry.m_copy );
383 entry.m_copy = nullptr; // We've transferred ownership to the undo list
384 undoList.PushItem( itemWrapper );
385 }
386
387 if( schItem->IsSelected() )
388 {
389 if( selTool )
390 selTool->RemoveItemFromSel( schItem, true /* quiet mode */ );
391
392 itemsDeselected = true;
393 }
394
395 if( schItem->Type() == SCH_FIELD_T )
396 {
397 static_cast<SCH_FIELD*>( schItem )->SetVisible( false );
398 break;
399 }
400
401 if( ( aCommitFlags & SKIP_UNDO ) && ( !cleanupPending || ( aCommitFlags & DELETE_REMOVED_ITEMS ) ) )
402 cleanupRemovedItems.emplace_back( schItem );
403
404 if( EDA_GROUP* group = schItem->GetParentGroup() )
405 group->RemoveItem( schItem );
406
407 if( !( changeFlags & CHT_DONE ) )
408 {
409 screen->Remove( schItem );
410
411 if( view && screen == currentScreen )
412 view->Remove( schItem );
413 }
414
415 if( frame && screen == currentScreen )
416 frame->UpdateItem( schItem, true, true );
417 else if( screen )
418 screen->Update( schItem );
419
420 if( schItem->Type() == SCH_SHEET_T )
421 refreshHierarchy = true;
422
423 bulkRemovedItems.push_back( schItem );
424 break;
425 }
426
427 case CHT_MODIFY:
428 {
429 const SCH_ITEM* itemCopy = static_cast<const SCH_ITEM*>( entry.m_copy );
430 SCH_SHEET_PATH currentSheet;
431
432 if( frame )
433 currentSheet = frame->GetCurrentSheet();
434
435 if( itemCopy->HasConnectivityChanges( schItem, &currentSheet )
436 || ( itemCopy->Type() == SCH_RULE_AREA_T ) )
437 {
438 updateConnectivityFlag( schItem );
439 }
440 else if( schItem->IsConnectable() && schItem->IsConnectivityDirty() )
441 {
442 // Move previews can change dangling flags without changing the final geometry.
443 refreshConnectivity = true;
444 }
445
446
447 if( schItem->Type() == SCH_SYMBOL_T )
448 {
449 const SCH_SYMBOL* origSymbol = static_cast<const SCH_SYMBOL*>( itemCopy );
450 const SCH_SYMBOL* modSymbol = static_cast<const SCH_SYMBOL*>( schItem );
451
452 if( origSymbol->GetPins().size() != modSymbol->GetPins().size() )
453 connectivityCleanUp = GLOBAL_CLEANUP;
454 }
455
456 if( !( aCommitFlags & SKIP_UNDO ) )
457 {
458#if 0
459 // While this keeps us from marking documents modified when someone OK's a dialog with
460 // no changes, it depends on our various SCH_ITEM::operator=='s being bullet-proof. They
461 // currently aren't.
462 if( *itemCopy == *schItem )
463 {
464 // No actual changes made; short-circuit undo
465 delete entry.m_copy;
466 entry.m_copy = nullptr;
467 break;
468 }
469#endif
470
471 ITEM_PICKER itemWrapper( screen, schItem, UNDO_REDO::CHANGED );
472 itemWrapper.SetLink( entry.m_copy );
473 entry.m_copy = nullptr; // We've transferred ownership to the undo list
474 undoList.PushItem( itemWrapper );
475 }
476
477 if( schItem->Type() == SCH_SHEET_T )
478 {
479 const SCH_SHEET* modifiedSheet = static_cast<const SCH_SHEET*>( schItem );
480 const SCH_SHEET* originalSheet = static_cast<const SCH_SHEET*>( itemCopy );
481 wxCHECK2( modifiedSheet && originalSheet, continue );
482
483 if( originalSheet->HasHierarchyChanges( *modifiedSheet ) )
484 refreshHierarchy = true;
485 }
486
487 if( frame && screen == currentScreen )
488 frame->UpdateItem( schItem, false, true );
489 else if( screen )
490 screen->Update( schItem );
491
492 itemsChanged.push_back( schItem );
493 break;
494 }
495
496 default:
497 wxASSERT( false );
498 break;
499 }
500
501 // Delete any copies we still have ownership of
502 delete entry.m_copy;
503 entry.m_copy = nullptr;
504
505 // Clear all flags but SELECTED and others used to move and rotate commands,
506 // after edition (selected items must keep their selection flag).
507 const int selected_mask = ( SELECTED | STARTPOINT | ENDPOINT );
508 schItem->ClearFlags( EDA_ITEM_ALL_FLAGS - selected_mask );
509
510 if( schItem->Type() == SCH_SHEET_T || schItem->Type() == SCH_SYMBOL_T )
511 {
512 schItem->RunOnChildren(
513 [&]( SCH_ITEM* child )
514 {
515 child->ClearFlags( EDA_ITEM_ALL_FLAGS - selected_mask );
516 },
518 }
519 }
520
521 notifyModel();
522
523 // Mark the touched screens dirty so that the state is tracked even in headless API server mode
524 if( !( aCommitFlags & SKIP_SET_DIRTY ) )
525 {
526 for( SCH_SCREEN* screen : touchedScreens )
527 screen->SetContentModified();
528 }
529
530 if( !( aCommitFlags & SKIP_UNDO ) && frame && undoList.GetCount() > 0 )
531 frame->SaveCopyInUndoList( undoList, UNDO_REDO::UNSPECIFIED, false );
532
533 cleanupRemovedItems.clear();
534
535 if( ( dirtyConnectivity || refreshConnectivity ) && !( aCommitFlags & SKIP_CONNECTIVITY ) )
536 {
537 wxLogTrace( wxS( "CONN_PROFILE" ),
538 wxS( "SCH_COMMIT::pushSchEdit() connectivity refresh, cleanup=%d." ),
539 static_cast<int>( connectivityCleanUp ) );
540
541 if( frame )
542 frame->RecalculateConnections( this, connectivityCleanUp, nullptr, true );
543 else if( schematic )
544 schematic->RecalculateConnections( this, connectivityCleanUp, m_toolMgr,
545 nullptr, nullptr, nullptr, nullptr, true );
546 }
547
548
549 if( refreshHierarchy && frame )
551
552
553 m_toolMgr->PostEvent( { TC_MESSAGE, TA_MODEL_CHANGE, AS_GLOBAL } );
554
555 if( itemsDeselected )
557
558 if( selectedModified )
560
561}
562
563
564void SCH_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
565{
566 if( Empty() )
567 return;
568
569 if( m_isLibEditor )
570 pushLibEdit( aMessage, aCommitFlags );
571 else
572 pushSchEdit( aMessage, aCommitFlags );
573
574 if( SCH_BASE_FRAME* frame = static_cast<SCH_BASE_FRAME*>( m_toolMgr->GetToolHolder() ) )
575 {
576 if( !( aCommitFlags & SKIP_SET_DIRTY ) )
577 frame->OnModify();
578
579 if( frame && frame->GetCanvas() )
580 frame->GetCanvas()->Refresh();
581 }
582
583 clear();
584}
585
586
588{
589 EDA_ITEM* parent = aItem->GetParent();
590
591 if( m_isLibEditor )
592 return static_cast<SYMBOL_EDIT_FRAME*>( m_toolMgr->GetToolHolder() )->GetCurSymbol();
593
594 if( parent && parent->IsType( { SCH_SYMBOL_T, SCH_TABLE_T, SCH_SHEET_T, SCH_LABEL_LOCATE_ANY_T } ) )
595 return parent;
596
597 return aItem;
598}
599
600
602{
603 if( m_isLibEditor )
604 {
605 SYMBOL_EDIT_FRAME* frame = static_cast<SYMBOL_EDIT_FRAME*>( m_toolMgr->GetToolHolder() );
606 LIB_SYMBOL* symbol = frame->GetCurSymbol();
607 std::vector<KIID> selected;
608
609 // Cloning will clear the selected flags, but we want to keep them.
610 for( const SCH_ITEM& item : symbol->GetDrawItems() )
611 {
612 if( item.IsSelected() )
613 selected.push_back( item.m_Uuid );
614 }
615
616 symbol = new LIB_SYMBOL( *symbol );
617
618 // Restore selected flags.
619 for( SCH_ITEM& item : symbol->GetDrawItems() )
620 {
621 if( alg::contains( selected, item.m_Uuid ) )
622 item.SetSelected();
623 }
624
625 return symbol;
626 }
627
628 return aItem->Clone();
629}
630
631
633{
634 if( Empty() )
635 return;
636
637 // Symbol editor just saves copies of the whole symbol, so grab the first and discard the rest
638 SYMBOL_EDIT_FRAME* frame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_toolMgr->GetToolHolder() );
639 LIB_SYMBOL* copy = dynamic_cast<LIB_SYMBOL*>( m_entries.front().m_copy );
640 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
641
642 if( frame && copy )
643 {
644 frame->SetCurSymbol( copy, false );
645 m_toolMgr->ResetTools( TOOL_BASE::MODEL_RELOAD );
646 }
647
648 if( selTool )
649 selTool->RebuildSelection();
650
651 clear();
652}
653
654
656{
657 KIGFX::VIEW* view = m_toolMgr->GetView();
658 SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( m_toolMgr->GetToolHolder() );
659 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
660 SCH_SHEET_LIST sheets;
661
662 if( m_entries.empty() )
663 return;
664
665 if( m_isLibEditor )
666 {
668 return;
669 }
670
671 SCHEMATIC* schematic = nullptr;
672 std::vector<SCH_ITEM*> bulkAddedItems;
673 std::vector<SCH_ITEM*> bulkRemovedItems;
674 std::vector<SCH_ITEM*> itemsChanged;
675
676 for( COMMIT_LINE& ent : m_entries )
677 {
678 int changeType = ent.m_type & CHT_TYPE;
679 int changeFlags = ent.m_type & CHT_FLAGS;
680 SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( ent.m_item );
681 SCH_ITEM* copy = dynamic_cast<SCH_ITEM*>( ent.m_copy );
682 SCH_SCREEN* screen = dynamic_cast<SCH_SCREEN*>( ent.m_screen );
683
684 wxCHECK2( item && screen, continue );
685
686 if( !schematic )
687 schematic = item->Schematic();
688
689 switch( changeType )
690 {
691 case CHT_ADD:
692 if( !( changeFlags & CHT_DONE ) )
693 break;
694
695 if( view )
696 view->Remove( item );
697
698 screen->Remove( item );
699 bulkRemovedItems.push_back( item );
700 break;
701
702 case CHT_REMOVE:
703 item->SetConnectivityDirty();
704
705 if( !( changeFlags & CHT_DONE ) )
706 break;
707
708 item->ClearFlags( STRUCT_DELETED );
709
710 if( view )
711 view->Add( item );
712
713 screen->Append( item );
714 bulkAddedItems.push_back( item );
715 break;
716
717 case CHT_MODIFY:
718 {
719 wxCHECK2( copy, break );
720
721 if( view )
722 view->Remove( item );
723
724 bool unselect = !item->IsSelected();
725
726 item->SwapItemData( copy );
727
728 if( unselect )
729 {
730 item->ClearSelected();
731 item->RunOnChildren( []( SCH_ITEM* aChild )
732 {
733 aChild->ClearSelected();
734 },
736 }
737
738 // Special cases for items which have instance data
739 if( item->GetParent() && item->GetParent()->Type() == SCH_SYMBOL_T && item->Type() == SCH_FIELD_T )
740 {
741 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
742 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item->GetParent() );
743
744 if( field->GetId() == FIELD_T::REFERENCE )
745 {
746 // Lazy eval of sheet list; this is expensive even when unsorted
747 if( sheets.empty() )
748 sheets = schematic->Hierarchy();
749
750 SCH_SHEET_PATH sheet = sheets.FindSheetForScreen( screen );
751 symbol->SetRef( &sheet, field->GetText() );
752 }
753 }
754
755 // This must be called before any calls that require stable object pointers.
756 screen->Update( item );
757
758 // This hack is to prevent incorrectly parented symbol pins from breaking the
759 // connectivity algorithm.
760 if( item->Type() == SCH_SYMBOL_T )
761 {
762 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
763 symbol->UpdatePins();
764
765 CONNECTION_GRAPH* graph = schematic->ConnectionGraph();
766
767 SCH_SYMBOL* symbolCopy = static_cast<SCH_SYMBOL*>( copy );
768 graph->RemoveItem( symbolCopy );
769
770 for( SCH_PIN* pin : symbolCopy->GetPins() )
771 graph->RemoveItem( pin );
772 }
773
774 item->SetConnectivityDirty();
775
776 if( view )
777 view->Add( item );
778
779 break;
780 }
781
782 default:
783 wxASSERT( false );
784 break;
785 }
786
787 delete copy;
788 ent.m_copy = nullptr;
789 }
790
791 if( schematic )
792 {
793 if( bulkAddedItems.size() > 0 )
794 schematic->OnItemsAdded( bulkAddedItems );
795
796 if( bulkRemovedItems.size() > 0 )
797 schematic->OnItemsRemoved( bulkRemovedItems );
798
799 if( itemsChanged.size() > 0 )
800 schematic->OnItemsChanged( itemsChanged );
801 }
802
803 if( selTool )
804 selTool->RebuildSelection();
805
806 if( frame )
807 frame->RecalculateConnections( nullptr, NO_CLEANUP );
808
809 clear();
810}
811
813{
814 if( aID == niluuid )
815 return nullptr;
816
817 for( COMMIT_LINE& entry : m_entries )
818 {
819 if( entry.m_item && entry.m_item->IsSCH_ITEM() && entry.m_item->m_Uuid == aID )
820 return entry.m_item;
821 }
822
823 return nullptr;
824}
int index
Handles how to draw a screen (a board, a schematic ...)
Definition base_screen.h:37
bool Empty() const
Definition commit.h:142
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:102
COMMIT()
Definition commit.cpp:30
COMMIT_LINE * findEntry(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Search for an entry describing change for a particular item.
Definition commit.cpp:264
std::vector< COMMIT_LINE > m_entries
Definition commit.h:191
COMMIT & Removed(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Definition commit.h:92
void clear()
Should be called in Push() & Revert() methods.
Definition commit.h:162
virtual COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Add a change of the item aItem of type aChangeType to the change list.
Definition commit.cpp:42
Calculate the connectivity of a schematic and generate netlists.
void RemoveItem(SCH_ITEM *aItem)
bool IsType(FRAME_T aType) const
The base class for create windows for drawing purpose.
A set of EDA_ITEMs (i.e., without duplicates).
Definition eda_group.h:43
void AddItem(EDA_ITEM *aItem)
Add item to group.
Definition eda_group.cpp:58
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:158
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:116
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
void ClearSelected()
Definition eda_item.h:153
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition eda_item.h:160
bool IsSelected() const
Definition eda_item.h:134
void SetSelected()
Definition eda_item.h:150
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition eda_item.h:214
EDA_ITEM * GetParent() const
Definition eda_item.h:112
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition eda_item.cpp:278
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition eda_item.h:168
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition actions.h:350
static const TOOL_EVENT UnselectedEvent
Definition actions.h:344
void SetLink(EDA_ITEM *aItem)
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:63
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition view.cpp:301
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition view.cpp:416
Definition kiid.h:46
Define a library symbol object.
Definition lib_symbol.h:119
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition lib_symbol.h:832
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode) override
A holder to handle information on schematic or board items.
void PushItem(const ITEM_PICKER &aItem)
Push aItem to the top of the list.
void SetDescription(const wxString &aDescription)
unsigned GetCount() const
Holds all the data relating to one schematic.
Definition schematic.h:148
void OnItemsAdded(std::vector< SCH_ITEM * > &aNewItems)
Must be used if Add() is used using a BULK_x ADD_MODE to generate a change event for listeners.
void OnItemsRemoved(std::vector< SCH_ITEM * > &aRemovedItems)
Must be used if Remove() is used using a BULK_x REMOVE_MODE to generate a change event for listeners.
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
void CleanUpConnections(SCH_COMMIT *aCommit, SCH_CLEANUP_FLAGS aCleanupFlags, const std::set< SCH_SCREEN * > &aLocalScreens={})
Prepare source geometry and intersheet references before rebuilding connectivity.
CONNECTION_GRAPH * ConnectionGraph() const
Definition schematic.h:317
void RecalculateConnections(SCH_COMMIT *aCommit, SCH_CLEANUP_FLAGS aCleanupFlags, TOOL_MANAGER *aToolManager, PROGRESS_REPORTER *aProgressReporter=nullptr, KIGFX::SCH_VIEW *aSchView=nullptr, std::function< void(SCH_ITEM *)> *aChangedItemHandler=nullptr, PICKED_ITEMS_LIST *aLastChangeList=nullptr, bool aCleanupDone=false)
Generate the connection data for the entire schematic hierarchy.
void RefreshHierarchy()
void OnItemsChanged(std::vector< SCH_ITEM * > &aItems)
Notify the schematic and its listeners that an item on the schematic has been modified in some way.
A shim class between EDA_DRAW_FRAME and several derived classes: SYMBOL_EDIT_FRAME,...
COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE) override
Add a change of the item aItem of type aChangeType to the change list.
bool m_isLibEditor
Definition sch_commit.h:79
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
EDA_ITEM * undoLevelItem(EDA_ITEM *aItem) const override
virtual void Revert() override
Revert the commit by restoring the modified items state.
TOOL_MANAGER * m_toolMgr
Definition sch_commit.h:78
virtual EDA_ITEM * ResolveItem(KIID &aID) override
Search for an item in this commit that matches the provided KIID.
void RemovedForCleanup(SCH_ITEM *aItem, SCH_SCREEN *aScreen)
Retain the pre-edit state of an item already removed from its screen by cleanup.
SCH_COMMIT(TOOL_MANAGER *aToolMgr)
virtual ~SCH_COMMIT()
void pushLibEdit(const wxString &aMessage, int aCommitFlags)
void revertLibEdit()
EDA_ITEM * makeImage(EDA_ITEM *aItem) const override
void pushSchEdit(const wxString &aMessage, int aCommitFlags)
Schematic editor (Eeschema) main window.
void RecalculateConnections(SCH_COMMIT *aCommit, SCH_CLEANUP_FLAGS aCleanupFlags, PROGRESS_REPORTER *aProgressReporter=nullptr, bool aCleanupDone=false)
Generate the connection data for the entire schematic hierarchy.
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
void SaveCopyInUndoList(SCH_SCREEN *aScreen, SCH_ITEM *aItemToCopy, UNDO_REDO aTypeCommand, bool aAppend)
Create a copy of the current schematic item, and put it in the undo list.
SCH_SHEET_PATH & GetCurrentSheet() const
void UpdateHierarchyNavigator(bool aRefreshNetNavigator=true, bool aClear=false)
Update the hierarchy navigation tree and history.
void UpdateItem(EDA_ITEM *aItem, bool isAddOrDelete=false, bool aUpdateRtree=false) override
Mark an item for refresh.
void UpdateHopOveredWires(SCH_ITEM *aItem)
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:138
FIELD_T GetId() const
Definition sch_field.h:142
A set of SCH_ITEMs (i.e., without duplicates).
Definition sch_group.h:48
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:165
virtual bool IsConnectable() const
Definition sch_item.h:531
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
Definition sch_item.h:641
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:281
void SetConnectivityDirty(bool aDirty=true)
Definition sch_item.h:600
bool IsConnectivityDirty() const
Definition sch_item.h:598
virtual bool HasConnectivityChanges(const SCH_ITEM *aItem, const SCH_SHEET_PATH *aInstance=nullptr) const
Check if aItem has connectivity changes against this object.
Definition sch_item.h:617
bool IsGroupableType() const
Definition sch_item.cpp:123
void SwapItemData(SCH_ITEM *aImage)
Swap data between aItem and aImage.
Definition sch_item.cpp:665
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
bool Remove(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Remove aItem from the schematic associated with this screen.
void Update(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Update aItem's bounding box in the tree.
bool CheckIfOnDrawList(const SCH_ITEM *aItem) const
void RebuildSelection()
Rebuild the selection from the EDA_ITEMs' selection flags.
SCH_GROUP * GetEnteredGroup()
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
bool HasHierarchyChanges(const SCH_SHEET &aOther) const
Schematic symbol object.
Definition sch_symbol.h:75
std::vector< const SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
void UpdatePins()
Updates the cache of SCH_PIN objects for each pin.
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
A foundation class for a tool operating on a schematic or symbol.
bool IsSymbolEditor() const
Returns true if the tool is running in the symbol editor.
int RemoveItemFromSel(const TOOL_EVENT &aEvent)
The symbol library editor main window.
void SetCurSymbol(LIB_SYMBOL *aSymbol, bool aUpdateZoom)
Take ownership of aSymbol and notes that it is the one currently being edited.
LIB_SYMBOL * GetCurSymbol() const
Return the current symbol being edited or NULL if none selected.
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
TOOL_MANAGER * GetManager() const
Return the instance of TOOL_MANAGER that takes care of the tool.
Definition tool_base.h:142
@ MODEL_RELOAD
Model changes (the sheet for a schematic)
Definition tool_base.h:76
Master controller class:
CHANGE_TYPE
Types of changes.
Definition commit.h:37
@ CHT_MODIFY
Definition commit.h:40
@ CHT_REMOVE
Definition commit.h:39
@ CHT_DONE
Flag to indicate the change is already applied.
Definition commit.h:43
@ CHT_TYPE
Definition commit.h:41
@ CHT_ADD
Definition commit.h:38
@ CHT_FLAGS
Definition commit.h:44
RECURSE_MODE
Definition eda_item.h:50
@ RECURSE
Definition eda_item.h:51
@ NO_RECURSE
Definition eda_item.h:52
#define SELECTED
Item was manually selected by the user.
#define SELECTED_BY_DRAG
Item was algorithmically selected as a dragged item.
#define EDA_ITEM_ALL_FLAGS
#define STRUCT_DELETED
flag indication structures to be erased
#define ENDPOINT
ends. (Used to support dragging.)
#define STARTPOINT
When a line is selected, these flags indicate which.
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:31
KIID niluuid(0)
This file contains miscellaneous commonly used macros and functions.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:96
#define SKIP_CONNECTIVITY
Definition sch_commit.h:41
#define SKIP_SET_DIRTY
Definition sch_commit.h:40
#define DELETE_REMOVED_ITEMS
Definition sch_commit.h:43
#define SKIP_UNDO
Definition sch_commit.h:38
Class to handle a set of SCH_ITEMs.
SCH_CLEANUP_FLAGS
Definition schematic.h:91
@ LOCAL_CLEANUP
Definition schematic.h:93
@ NO_CLEANUP
Definition schematic.h:92
@ GLOBAL_CLEANUP
Definition schematic.h:94
EDA_ITEM * m_copy
Optional copy of the item.
Definition commit.h:156
CHANGE_TYPE m_type
Modification type.
Definition commit.h:157
EDA_ITEM * m_item
Main item that is added/deleted/modified.
Definition commit.h:155
BASE_SCREEN * m_screen
Definition commit.h:158
@ REFERENCE
Field Reference of part, i.e. "IC21".
KIBIS_PIN * pin
@ AS_GLOBAL
Global action (toolbar/main menu event, global shortcut)
Definition tool_action.h:45
@ TA_MODEL_CHANGE
Model has changed (partial update).
Definition tool_event.h:117
@ TC_MESSAGE
Definition tool_event.h:54
@ SCH_LINE_T
Definition typeinfo.h:159
@ SCH_SYMBOL_T
Definition typeinfo.h:168
@ SCH_FIELD_T
Definition typeinfo.h:146
@ SCH_SHEET_T
Definition typeinfo.h:171
@ SCH_RULE_AREA_T
Definition typeinfo.h:166