1 /*
2  *  This file is part of Calligra tests
3  *
4  *  Copyright (C) 2006-2010 Thomas Zander <zander@kde.org>
5  *  Copyright (C) 2010 Adam Celarek <kdedev@xibo.at>
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (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, write to the Free Software
19  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 #include "TestShapeContainer.h"
22 #include <MockShapes.h>
23 
24 #include <KoShape.h>
25 #include <KoShapeGroupCommand.h>
26 #include <KoShapeUngroupCommand.h>
27 #include <KoShapeTransformCommand.h>
28 #include <KoShapeGroup.h>
29 #include <KoSelection.h>
30 
31 #include <QTest>
32 
33 
testModel()34 void TestShapeContainer::testModel()
35 {
36     MockContainerModel *model = new MockContainerModel();
37     MockContainer container(model);
38     MockShape *shape1 = new MockShape();
39 
40     container.addShape(shape1);
41     QCOMPARE(model->containerChangedCalled(), 0);
42     QCOMPARE(model->childChangedCalled(), 1);
43     QCOMPARE(model->proposeMoveCalled(), 0);
44 
45     shape1->setPosition(QPointF(300, 300));
46     QCOMPARE(model->containerChangedCalled(), 0);
47     QCOMPARE(model->childChangedCalled(), 2);
48     QCOMPARE(model->proposeMoveCalled(), 0);
49 
50     shape1->rotate(10);
51     QCOMPARE(model->containerChangedCalled(), 0);
52     QCOMPARE(model->childChangedCalled(), 3);
53     QCOMPARE(model->proposeMoveCalled(), 0);
54 
55     shape1->setAbsolutePosition(shape1->absolutePosition() + QPointF(10., 40.));
56     QCOMPARE(model->containerChangedCalled(), 0);
57     QCOMPARE(model->childChangedCalled(), 5); // we get a generic Matrix as well as a position change...
58     QCOMPARE(model->proposeMoveCalled(), 0);
59 
60     shape1->setTransformation(QTransform());
61     QCOMPARE(model->containerChangedCalled(), 0);
62     QCOMPARE(model->childChangedCalled(), 6);
63     QCOMPARE(model->proposeMoveCalled(), 0);
64 
65     model->resetCounts();
66     container.setPosition(QPointF(30, 30));
67     QCOMPARE(model->containerChangedCalled(), 1);
68     QCOMPARE(model->childChangedCalled(), 0);
69     QCOMPARE(model->proposeMoveCalled(), 0);
70 }
71 
testSetParent()72 void TestShapeContainer::testSetParent()
73 {
74     MockContainerModel *model1 = new MockContainerModel();
75     MockContainer container1(model1);
76     MockContainerModel *model2 = new MockContainerModel();
77     MockContainer container2(model2);
78     MockShape shape;
79     // init test
80     QCOMPARE(model1->shapes().count(), 0);
81     QCOMPARE(model2->shapes().count(), 0);
82 
83     shape.setParent(&container1);
84     QCOMPARE(model1->shapes().count(), 1);
85     QCOMPARE(model2->shapes().count(), 0);
86     QCOMPARE(shape.parent(), &container1);
87 
88     shape.setParent(&container2);
89     QCOMPARE(model1->shapes().count(), 0);
90     QCOMPARE(container1.shapes().count(), 0);
91     QCOMPARE(model2->shapes().count(), 1);
92     QCOMPARE(container2.shapes().count(), 1);
93     QCOMPARE(shape.parent(), &container2);
94 
95     // on destruction shape should have no parent
96     shape.setParent(0);
97 }
98 
testSetParent2()99 void TestShapeContainer::testSetParent2()
100 {
101     MockContainerModel *model = new MockContainerModel();
102     MockContainer container(model);
103     MockShape *shape = new MockShape();
104     shape->setParent(&container);
105     QCOMPARE(model->shapes().count(), 1);
106 
107     shape->setParent(0);
108     QCOMPARE(model->shapes().count(), 0);
109 }
110 
testScaling()111 void TestShapeContainer::testScaling()
112 {
113     KoShape *shape1 = new MockShape();
114     KoShape *shape2 = new MockShape();
115 
116     shape1->setSize(QSizeF(10., 10.));
117     shape1->setPosition(QPointF(20., 20.));
118 
119     shape2->setSize(QSizeF(30., 10.));
120     shape2->setPosition(QPointF(10., 40.));
121 
122     QList<KoShape*> groupedShapes;
123     groupedShapes.append(shape1);
124     groupedShapes.append(shape2);
125 
126     KoShapeGroup *group = new KoShapeGroup();
127     KoShapeGroupCommand* groupCommand = KoShapeGroupCommand::createCommand(group, groupedShapes);
128     groupCommand->redo();
129 
130     QList<KoShape*> transformShapes;
131     transformShapes.append(groupedShapes);
132 
133     QTransform matrix;
134     matrix.scale(0.5, 0.5);
135 
136     QList<QTransform> oldTransformations;
137     QList<QTransform> newTransformations;
138     Q_FOREACH (const KoShape* shape, transformShapes) {
139         QTransform oldTransform = shape->transformation();
140         oldTransformations.append(oldTransform);
141         QTransform globalTransform = shape->absoluteTransformation();
142         QTransform localTransform = globalTransform * matrix * globalTransform.inverted();
143         newTransformations.append(localTransform*oldTransform);
144     }
145 
146     QList<QPointF> oldPositions;
147     for(int i=0; i< transformShapes.size(); i++) {
148         oldPositions.append(transformShapes.at(i)->absolutePosition(KoFlake::TopLeft));
149     }
150 
151     KoShapeTransformCommand* transformCommand;
152     transformCommand = new KoShapeTransformCommand(transformShapes, oldTransformations, newTransformations);
153     transformCommand->redo();
154 
155     for(int i=0; i< transformShapes.size(); i++) {
156         QCOMPARE(transformShapes.at(i)->absolutePosition(KoFlake::TopLeft), oldPositions.at(i)*0.5);
157     }
158 
159     transformShapes.takeLast();
160     KoShapeUngroupCommand* ungroupCmd = new KoShapeUngroupCommand(group, transformShapes);
161     ungroupCmd->redo();
162 
163     for(int i=0; i< transformShapes.size(); i++) {
164         QCOMPARE(transformShapes.at(i)->absolutePosition(KoFlake::TopLeft), oldPositions.at(i)*0.5);
165     }
166 }
167 
testScaling2()168 void TestShapeContainer::testScaling2()
169 {
170     KoShape *shape1 = new MockShape();
171     KoShape *shape2 = new MockShape();
172 
173     shape1->setPosition(QPointF(20., 20.));
174     shape1->setSize(QSizeF(10., 10.));
175 
176     shape2->setPosition(QPointF(10., 40.));
177     shape2->setSize(QSizeF(30., 10.));
178 
179     QList<KoShape*> groupedShapes;
180     groupedShapes.append(shape1);
181     groupedShapes.append(shape2);
182 
183     QScopedPointer<KoShapeGroup> group(new KoShapeGroup());
184     QScopedPointer<KoShapeGroupCommand> groupCommand(
185         KoShapeGroupCommand::createCommand(group.data(), groupedShapes));
186     groupCommand->redo();
187 
188     QScopedPointer<KoSelection> selection(new KoSelection());
189 
190     // the topmost shape is selected, not shape1!
191     selection->select(shape1);
192 
193     QList<KoShape*> transformShapes;
194     transformShapes.append(selection->selectedShapes());
195 
196     QTransform matrix;
197     matrix.scale(0.5, 0.5);
198 
199     QList<QTransform> oldTransformations;
200     QList<QTransform> newTransformations;
201     Q_FOREACH (const KoShape* shape, transformShapes) {
202         QTransform oldTransform = shape->transformation();
203         oldTransformations.append(oldTransform);
204         newTransformations.append(oldTransform*matrix);
205     }
206 
207     QList<QPointF> oldPositions;
208     for(int i=0; i< transformShapes.size(); i++) {
209         oldPositions.append(transformShapes.at(i)->absolutePosition(KoFlake::TopLeft));
210     }
211 
212     QScopedPointer<KoShapeTransformCommand> transformCommand(
213         new KoShapeTransformCommand(transformShapes, oldTransformations, newTransformations));
214     transformCommand->redo();
215 
216     QCOMPARE(selection->boundingRect(), group->boundingRect());
217 
218     selection->deselectAll();
219 
220     // the topmost shape is selected, not shape1!
221     selection->select(shape1);
222     QCOMPARE(selection->boundingRect(), group->boundingRect());
223 }
224 
225 QTEST_MAIN(TestShapeContainer)
226