src/model.cpp

changeset 1186
eae8b3bce545
parent 1149
502c866b8512
child 1187
46dc716238fd
equal deleted inserted replaced
1185:c2e0db52ea07 1186:eae8b3bce545
14 * 14 *
15 * You should have received a copy of the GNU General Public License 15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */ 17 */
18 18
19 #include <cassert>
19 #include "model.h" 20 #include "model.h"
20 #include "linetypes/modelobject.h" 21 #include "linetypes/modelobject.h"
21 #include "documentmanager.h" 22 #include "documentmanager.h"
22 #include "linetypes/comment.h" 23 #include "linetypes/comment.h"
23 #include "linetypes/conditionaledge.h" 24 #include "linetypes/conditionaledge.h"
28 29
29 Model::Model(DocumentManager* manager) : 30 Model::Model(DocumentManager* manager) :
30 QObject {manager}, 31 QObject {manager},
31 _manager {manager} {} 32 _manager {manager} {}
32 33
33 Model::~Model()
34 {
35 for (int i = 0; i < countof(_objects); ++i)
36 delete _objects[i];
37 }
38
39 /*
40 * Takes an existing object and migrates it to the end of this model. The object is removed from its old model in the process.
41 */
42 void Model::addObject(LDObject *object)
43 {
44 insertObject(size(), object);
45 }
46
47 /* 34 /*
48 * Returns the amount of objects in this model. 35 * Returns the amount of objects in this model.
49 */ 36 */
50 int Model::size() const 37 int Model::size() const
51 { 38 {
53 } 40 }
54 41
55 /* 42 /*
56 * Returns the vector of objects in this model. 43 * Returns the vector of objects in this model.
57 */ 44 */
58 const QVector<LDObject*>& Model::objects() const 45 const ResourceVector<LDObject>& Model::objects() const
59 { 46 {
60 return _objects; 47 return _objects;
61 } 48 }
62 49
63 /* 50 /*
64 * Takes an existing object and migrates it to this model, at the specified position. 51 * Returns the vector of objects in this model (private mutable access)
65 */ 52 */
66 void Model::insertObject(int position, LDObject* object) 53 ResourceVector<LDObject>& Model::mutableObjects()
67 { 54 {
68 if (object->model() and object->model() != this) 55 return _objects;
69 object->model()->withdraw(object); 56 }
70 57
71 // TODO: check that the object isn't in the vector once there's a cheap way to do so! 58 /*
72 _objects.insert(position, object); 59 * Takes an existing object and adds it to this model, at the specified position.
60 * The object is assumed to be ownerless.
61 */
62 void Model::finalizeNewObject(int position, LDObject* object)
63 {
64 assert(object->model() == this);
73 _needsTriangleRecount = true; 65 _needsTriangleRecount = true;
74 object->setDocument(this); 66 object->setDocument(this);
75 emit objectAdded(object); 67
76 } 68 // Set default color. Relying on virtual functions, this cannot be done in the c-tor.
77 69 // TODO: store -1 as the default color
78 /* 70 if (object->isColored())
79 * Swaps one object with another, assuming they both are in this model. 71 object->setColor(object->defaultColor());
72
73 emit objectAdded(object, position);
74 }
75
76 /*
77 * Swaps one object with another, if they both are in this model.
80 */ 78 */
81 bool Model::swapObjects(LDObject* one, LDObject* other) 79 bool Model::swapObjects(LDObject* one, LDObject* other)
82 { 80 {
83 int a = _objects.indexOf(one); 81 int a = _objects.indexOf(one);
84 int b = _objects.indexOf(other); 82 int b = _objects.indexOf(other);
85 83
86 if (a != b and a != -1 and b != -1) 84 if (a != b and a != -1 and b != -1)
87 { 85 {
88 _objects[b] = one; 86 _objects.swap(a, b);
89 _objects[a] = other; 87 emit objectsSwapped(one, other);
90 return true; 88 return true;
91 } 89 }
92 else 90 else
93 { 91 {
94 return false; 92 return false;
95 }
96 }
97
98 /*
99 * Assigns a new object to the specified position in the model. The object that already is in the position is deleted in the process.
100 */
101 bool Model::setObjectAt(int idx, LDObject* obj)
102 {
103 if (idx < 0 or idx >= countof(_objects))
104 {
105 return false;
106 }
107 else
108 {
109 removeAt(idx);
110 insertObject(idx, obj);
111 return true;
112 } 93 }
113 } 94 }
114 95
115 /* 96 /*
116 * Returns the object at the specified position, or null if not found. 97 * Returns the object at the specified position, or null if not found.
136 /* 117 /*
137 * Removes the object at the provided position. 118 * Removes the object at the provided position.
138 */ 119 */
139 void Model::removeAt(int position) 120 void Model::removeAt(int position)
140 { 121 {
141 LDObject* object = withdrawAt(position); 122 emit aboutToRemoveObject(_objects[position], position);
142 delete object; 123 _objects.removeAt(position);
143 } 124 }
144 125
145 /* 126 /*
146 * Replaces the given object with the contents of a model. 127 * Replaces the given object with the contents of a model.
147 */ 128 */
148 void Model::replace(LDObject *object, Model &model) 129 void Model::replace(LDObject *object, Model &model)
149 { 130 {
150 if (object->model() == this) 131 if (object->model() == this)
151 { 132 {
152 int position = object->lineNumber(); 133 int position = object->lineNumber();
153 134 merge(model, position);
154 for (int i = countof(model.objects()) - 1; i >= 1; i -= 1) 135 remove(object);
155 insertObject(position + i, model.objects()[i]);
156
157 setObjectAt(position, model.objects()[0]);
158 } 136 }
159 } 137 }
160 138
161 /* 139 /*
162 * Signals the model to recount its triangles. 140 * Signals the model to recount its triangles.
184 return _triangleCount; 162 return _triangleCount;
185 } 163 }
186 164
187 /* 165 /*
188 * Merges the given model into this model, starting at the given position. The other model is emptied in the process. 166 * Merges the given model into this model, starting at the given position. The other model is emptied in the process.
189 */ 167 * If select is true, the new objects are added to the selection.
190 void Model::merge(Model& other, int position) 168 */
169 void Model::merge(Model& other, int position, Filter filter, Callback callback)
191 { 170 {
192 if (position < 0) 171 if (position < 0)
193 position = countof(_objects); 172 position = countof(_objects);
194 173
195 // Copy the vector of objects to copy, so that we don't change the vector while iterating over it. 174 if (filter == nullptr)
196 QVector<LDObject*> objectsCopy = other._objects; 175 filter = [](LDObject*){return true;};
197 176
198 // Inform the contents of their new owner 177 _objects.merge(other.mutableObjects(), position, [&](LDObject* object, int objectPosition)
199 for (LDObject* object : objectsCopy) 178 {
200 { 179 if (filter(object))
201 insertObject(position, object); 180 {
202 position += 1; 181 emit other.aboutToRemoveObject(object, objectPosition);
203 } 182 return true;
204 183 }
205 other.clear(); 184 else
185 {
186 return false;
187 }
188 }, [&](LDObject* object, int objectPosition)
189 {
190 _needsTriangleRecount = true;
191 object->setDocument(this);
192 emit objectAdded(object, objectPosition);
193
194 if (callback)
195 callback(object, position);
196 });
206 } 197 }
207 198
208 /* 199 /*
209 * Returns the begin-iterator into this model, so that models can be used in foreach-loops. 200 * Returns the begin-iterator into this model, so that models can be used in foreach-loops.
210 */ 201 */
211 QVector<LDObject*>::iterator Model::begin() 202 LDObject* const* Model::begin()
212 { 203 {
213 return _objects.begin(); 204 return _objects.begin();
214 } 205 }
215 206
216 /* 207 /*
217 * Returns the end-iterator into this mode, so that models can be used in foreach-loops. 208 * Returns the end-iterator into this mode, so that models can be used in foreach-loops.
218 */ 209 */
219 QVector<LDObject*>::iterator Model::end() 210 LDObject* const* Model::end()
220 { 211 {
221 return _objects.end(); 212 return _objects.end();
222 } 213 }
223 214
224 /* 215 /*
229 for (int i = _objects.size() - 1; i >= 0; i -= 1) 220 for (int i = _objects.size() - 1; i >= 0; i -= 1)
230 removeAt(i); 221 removeAt(i);
231 222
232 _triangleCount = 0; 223 _triangleCount = 0;
233 _needsTriangleRecount = false; 224 _needsTriangleRecount = false;
234 }
235
236 /*
237 * Drops the object from the model. The object becomes a free object as a result (thus violating the invariant that every object
238 * has a model!). The caller must immediately add the withdrawn object to another model.
239 *
240 * This private method is only used to implement public API.
241 */
242 void Model::withdraw(LDObject* object)
243 {
244 if (object->model() == this)
245 {
246 int position = object->lineNumber();
247
248 if (_objects[position] == object)
249 withdrawAt(position);
250 }
251 }
252
253 /*
254 * Drops an object from the model at the provided position. The caller must immediately put the result value object into a new model.
255 */
256 LDObject* Model::withdrawAt(int position)
257 {
258 LDObject* object = _objects[position];
259 emit aboutToRemoveObject(object);
260 _objects.removeAt(position);
261 _needsTriangleRecount = true;
262 return object;
263 } 225 }
264 226
265 /* 227 /*
266 * Returns whether or not this model is empty. 228 * Returns whether or not this model is empty.
267 */ 229 */

mercurial