KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_board_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 modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * 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 <boost/test/unit_test.hpp>
21#include <tool/tool_manager.h>
23#include <board.h>
24#include <board_commit.h>
25#include <footprint.h>
26#include <pad.h>
27#include <pcb_shape.h>
28#include <pcb_text.h>
29#include <pcb_group.h>
30#include <pcb_view.h>
32
33BOOST_AUTO_TEST_SUITE( BoardCommit )
34
35BOOST_AUTO_TEST_CASE( RecursesThroughGroups )
36{
37 BOARD board;
38 TOOL_MANAGER mgr;
39 mgr.SetEnvironment( &board, nullptr, nullptr, nullptr, nullptr );
41 mgr.RegisterTool( dummyTool );
42 BOARD_COMMIT commit( dummyTool );
43
44 PCB_SHAPE s1( nullptr, SHAPE_T::SEGMENT );
45 PCB_SHAPE s2( nullptr, SHAPE_T::SEGMENT );
46 PCB_GROUP group( nullptr );
47 group.AddItem( &s1 );
48 group.AddItem( &s2 );
49
50 commit.Stage( &group, CHT_MODIFY, nullptr, RECURSE_MODE::RECURSE );
51
52 BOOST_CHECK_EQUAL( commit.GetStatus( &s1 ), CHT_MODIFY );
53 BOOST_CHECK_EQUAL( commit.GetStatus( &s2 ), CHT_MODIFY );
54}
55
56BOOST_AUTO_TEST_CASE( MakeImageCreatesTransientCopy )
57{
58 PCB_SHAPE shape( nullptr, SHAPE_T::SEGMENT );
60
62 BOOST_CHECK( copy != &shape );
63 BOOST_CHECK( copy->HasFlag( UR_TRANSIENT ) );
64
65 delete copy;
66}
67
68BOOST_AUTO_TEST_CASE( ReturnsBoardFromManager )
69{
70 BOARD board;
71 TOOL_MANAGER mgr;
72 mgr.SetEnvironment( &board, nullptr, nullptr, nullptr, nullptr );
74 mgr.RegisterTool( dummyTool );
75
76 BOARD_COMMIT commit( dummyTool );
77
78 BOOST_CHECK_EQUAL( commit.GetBoard(), &board );
79}
80
81BOOST_AUTO_TEST_CASE( RemoveFootprintTextFromBoardEditor )
82{
83 BOARD board;
84 TOOL_MANAGER mgr;
85 mgr.SetEnvironment( &board, nullptr, nullptr, nullptr, nullptr );
87 mgr.RegisterTool( dummyTool );
88
89 FOOTPRINT* fp = new FOOTPRINT( &board );
90 PCB_TEXT* text = new PCB_TEXT( fp );
91 text->SetText( wxT( "${REFERENCE}" ) );
92 text->SetLayer( F_Fab );
93 fp->Add( text );
94 board.Add( fp );
95
96 BOOST_REQUIRE_EQUAL( fp->GraphicalItems().size(), 1 );
97
98 {
99 BOARD_COMMIT commit( &mgr, true, false );
100 commit.Remove( text );
101 commit.Push( wxT( "Delete" ), SKIP_UNDO );
102 }
103
104 BOOST_CHECK_EQUAL( fp->GraphicalItems().size(), 0 );
105}
106
107// A COMMIT object reused across Push() calls (such as the group tool's persistent commit)
108// must not carry m_addedItems from one commit into the next. If it does, modifying a
109// previously-added item in a later commit is silently dropped and no undo entry is created.
110// This is the root cause of nested-group undo corruption (work item 24146).
111BOOST_AUTO_TEST_CASE( ReusedCommitModifyAfterAdd )
112{
113 BOARD board;
114 TOOL_MANAGER mgr;
115 mgr.SetEnvironment( &board, nullptr, nullptr, nullptr, nullptr );
116 KI_TEST::DUMMY_TOOL* dummyTool = new KI_TEST::DUMMY_TOOL();
117 mgr.RegisterTool( dummyTool );
118
119 BOARD_COMMIT commit( &mgr, true, false );
120
121 PCB_SHAPE* shape = new PCB_SHAPE( &board, SHAPE_T::SEGMENT );
122
123 // First commit adds the shape. After Push the commit is reused.
124 commit.Add( shape );
125 commit.Push( wxT( "Add" ), SKIP_UNDO );
126
127 // Modifying the already-added shape in the next commit must record a change.
128 commit.Modify( shape );
129 BOOST_CHECK_EQUAL( commit.GetStatus( shape ), CHT_MODIFY );
130}
131
132// Removing a footprint frees its pads, fields and other owned children with it. A child that
133// sits in the selection on its own (the footprint itself unselected) must be pruned as well, or
134// PCB_SELECTION::updateDrawList() dereferences the freed child on the next repaint.
135BOOST_AUTO_TEST_CASE( RemoveFootprintPrunesSelectedChildren )
136{
137 BOARD board;
138 KIGFX::PCB_VIEW view;
139 TOOL_MANAGER mgr;
140 mgr.SetEnvironment( &board, &view, nullptr, nullptr, nullptr );
141
143 mgr.RegisterTool( selTool );
144
145 FOOTPRINT* fp = new FOOTPRINT( &board );
146 PAD* pad = new PAD( fp );
147 fp->Add( pad );
148 board.Add( fp );
149
150 selTool->AddItemToSel( pad, true );
151
152 BOOST_REQUIRE( selTool->GetSelection().Contains( pad ) );
153 BOOST_REQUIRE( !fp->IsSelected() );
154
155 BOARD_COMMIT commit( &mgr, true, false );
156 commit.Remove( fp );
157 commit.Push( wxT( "Delete footprint" ), SKIP_UNDO | SKIP_TEARDROPS );
158
159 BOOST_CHECK( !selTool->GetSelection().Contains( pad ) );
160
161 // With SKIP_UNDO the removed footprint is ours to free
162 delete fp;
163}
164
166
#define SKIP_TEARDROPS
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
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.
BOARD * GetBoard() const
static EDA_ITEM * MakeImage(EDA_ITEM *aItem)
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:373
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition board.cpp:1355
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
Definition commit.h:86
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 & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
Definition commit.h:74
int GetStatus(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Returns status of an item.
Definition commit.cpp:191
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:96
bool IsSelected() const
Definition eda_item.h:132
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
DRAWINGS & GraphicalItems()
Definition footprint.h:378
Definition pad.h:61
A set of BOARD_ITEMs (i.e., without duplicates).
Definition pcb_group.h:51
The selection tool: currently supports:
PCB_SELECTION & GetSelection()
int AddItemToSel(const TOOL_EVENT &aEvent)
bool Contains(EDA_ITEM *aItem) const
Definition selection.cpp:84
Master controller class:
void RegisterTool(TOOL_BASE *aTool)
Add a tool to the manager set and sets it up.
void SetEnvironment(EDA_ITEM *aModel, KIGFX::VIEW *aView, KIGFX::VIEW_CONTROLS *aViewControls, APP_SETTINGS_BASE *aSettings, TOOLS_HOLDER *aFrame)
Set the work environment (model, view, view controls and the parent window).
@ CHT_MODIFY
Definition commit.h:40
@ RECURSE
Definition eda_item.h:49
#define UR_TRANSIENT
indicates the item is owned by the undo/redo stack
@ SEGMENT
Definition eda_shape.h:46
@ F_Fab
Definition layer_ids.h:115
Class to handle a set of BOARD_ITEMs.
#define SKIP_UNDO
Definition sch_commit.h:36
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_CASE(RecursesThroughGroups)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_CHECK_EQUAL(result, "25.4")