src/model.cpp

changeset 150
b6cbba6e29a1
parent 148
e1ced2523cad
child 151
e628fc2e0c72
equal deleted inserted replaced
148:e1ced2523cad 150:b6cbba6e29a1
30 * @param parent QObject parent to pass forward 30 * @param parent QObject parent to pass forward
31 */ 31 */
32 Model::Model(QObject *parent) : 32 Model::Model(QObject *parent) :
33 QAbstractListModel{parent} 33 QAbstractListModel{parent}
34 { 34 {
35 connect(this, &Model::dataChanged, [&](){ this->needRecache = true; });
36 } 35 }
37 36
38 /** 37 /**
39 * @returns the amount of elements in the model 38 * @returns the amount of elements in the model
40 */ 39 */
130 const ldraw::Object* object = this->body[unsigned_cast(index)].get(); 129 const ldraw::Object* object = this->body[unsigned_cast(index)].get();
131 return object->getProperty(property); 130 return object->getProperty(property);
132 } 131 }
133 132
134 /** 133 /**
135 * @brief Gets a list of GL polygons that are used to represent this model.
136 * @details Will build polygons if polygons are outdated.
137 * @param documents Documents to use to resolve subfile references
138 * @return vector of GL polygons
139 */
140 std::vector<gl::Polygon> Model::getPolygons(DocumentManager* documents) const
141 {
142 if (this->needRecache)
143 {
144 this->cachedPolygons.clear();
145 const std::optional<ModelId> modelId = documents->findIdForModel(this);
146 if (modelId.has_value())
147 {
148 ldraw::GetPolygonsContext context{modelId.value(), documents};
149 for (int i = 0; i < this->size(); i += 1)
150 {
151 this->getObjectPolygons(i, this->cachedPolygons, &context);
152 }
153 }
154 this->needRecache = false;
155 }
156 return this->cachedPolygons;
157 }
158
159 /**
160 * @brief Finds the position of the specified object in the model 134 * @brief Finds the position of the specified object in the model
161 * @param id Object id to look for 135 * @param id Object id to look for
162 * @return model index 136 * @return model index
163 */ 137 */
164 QModelIndex Model::lookup(ldraw::id_t id) const 138 QModelIndex Model::find(ldraw::id_t id) const
165 { 139 {
166 // FIXME: This linear search will probably cause performance issues 140 // FIXME: This linear search will probably cause performance issues
167 for (std::size_t i = 0; i < this->body.size(); i += 1) 141 for (std::size_t i = 0; i < this->body.size(); i += 1)
168 { 142 {
169 if (this->body[i]->id == id) 143 if (this->body[i]->id == id)
177 /** 151 /**
178 * @brief Gets an object id by position in the model 152 * @brief Gets an object id by position in the model
179 * @param index Position of the object in the model 153 * @param index Position of the object in the model
180 * @return id 154 * @return id
181 */ 155 */
182 ldraw::id_t Model::resolve(const QModelIndex& index) const 156 ldraw::id_t Model::idAt(const QModelIndex& index) const
183 { 157 {
184 return this->objectAt(index)->id; 158 return this->objectAt(index)->id;
185 } 159 }
186 160
187 #if 0 161 #if 0
209 } 183 }
210 } 184 }
211 #endif 185 #endif
212 186
213 /** 187 /**
214 * @brief Gets the GL polygons of the object at the specified position in the model
215 * @param index Index of object in the model
216 * @param polygons_out Vector to add polygons into
217 * @param context Context to use to resolve subfile references
218 */
219 void Model::getObjectPolygons(
220 const int index,
221 std::vector<gl::Polygon>& polygons_out,
222 ldraw::GetPolygonsContext* context) const
223 {
224 const ldraw::Object* object = this->body[unsigned_cast(index)].get();
225 object->getPolygons(polygons_out, context);
226 }
227
228 /**
229 * @brief Called by the editing context to signal to the model that editing is done. 188 * @brief Called by the editing context to signal to the model that editing is done.
230 */ 189 */
231 void Model::editFinished() 190 void Model::editFinished()
232 { 191 {
233 this->editCounter -= 1; 192 this->editCounter -= 1;
237 * @brief Called by the editing context to indicate that the specified object has been modified. 196 * @brief Called by the editing context to indicate that the specified object has been modified.
238 * @param id ID of the object that has been modified 197 * @param id ID of the object that has been modified
239 */ 198 */
240 void Model::objectModified(ldraw::id_t id) 199 void Model::objectModified(ldraw::id_t id)
241 { 200 {
242 const QModelIndex index = this->lookup(id); 201 const QModelIndex index = this->find(id);
243 Q_EMIT this->dataChanged(index, index); 202 Q_EMIT this->dataChanged(index, index);
244 } 203 }
245 204
246 /** 205 /**
247 * @brief Adds the given object into the model. 206 * @brief Adds the given object into the model.
248 * @param object r-value reference to the object 207 * @param object r-value reference to the object
249 */ 208 */
250 void Model::append(ModelObjectPointer&& object) 209 void Model::append(ModelObjectPointer&& object)
251 { 210 {
252 const int position = static_cast<int>(this->body.size()); 211 const int position = static_cast<int>(this->body.size());
253 Q_EMIT beginInsertRows({}, position, position); 212 Q_EMIT this->beginInsertRows({}, position, position);
254 this->body.push_back(std::move(object)); 213 this->body.push_back(std::move(object));
255 Q_EMIT endInsertRows(); 214 Q_EMIT this->endInsertRows();
256 this->needRecache = true; 215 Q_EMIT this->objectAdded(position);
257 } 216 }
258 217
259 /** 218 /**
260 * @brief Removes the object at the specified position 219 * @brief Removes the object at the specified position
261 * @param position 220 * @param position
262 */ 221 */
263 void Model::remove(int position) 222 void Model::remove(int position)
264 { 223 {
265 if (position >= 0 and position < signed_cast(this->body.size())) 224 if (position >= 0 and position < signed_cast(this->body.size()))
266 { 225 {
267 Q_EMIT beginRemoveRows({}, position, position); 226 Q_EMIT this->beginRemoveRows({}, position, position);
227 const ldraw::id_t id = this->body[position]->id;
268 this->body.erase(std::begin(this->body) + position); 228 this->body.erase(std::begin(this->body) + position);
269 Q_EMIT endRemoveRows(); 229 Q_EMIT this->endRemoveRows();
270 this->needRecache = true; 230 Q_EMIT this->objectRemoved(id);
271 } 231 }
272 } 232 }
273 233
274 /** 234 /**
275 * @brief Gets the object pointer at the specified position 235 * @brief Gets the object pointer at the specified position
301 { 261 {
302 out << object.get()->toLDrawCode() << "\r\n"; 262 out << object.get()->toLDrawCode() << "\r\n";
303 } 263 }
304 } 264 }
305 265
266 ldraw::Object* Model::operator[](int index)
267 {
268 if (index >= 0 and index < this->size())
269 {
270 return this->body[index].get();
271 }
272 else
273 {
274 throw std::out_of_range{"index out of range"};
275 }
276 }
277
306 /** 278 /**
307 * @brief Modifies the !LDRAW_ORG line so that it becomes unofficial 279 * @brief Modifies the !LDRAW_ORG line so that it becomes unofficial
308 */ 280 */
309 void Model::makeUnofficial() 281 void makeUnofficial(Model& model)
310 { 282 {
311 if (this->body.size() >= 4) 283 if (model.size() >= 4)
312 { 284 {
313 const ldraw::id_t id = this->body[3]->id; 285 const ldraw::Object* ldrawOrgLine = model[3];
314 if (this->isA<ldraw::MetaCommand>(id)) 286 if (isA<ldraw::MetaCommand>(ldrawOrgLine))
315 { 287 {
316 const QString& body = this->body[3]->getProperty<ldraw::Property::Text>(); 288 const QString& body = ldrawOrgLine->getProperty<ldraw::Property::Text>();
317 if (body.startsWith("!LDRAW_ORG ") and not body.startsWith("!LDRAW_ORG Unofficial_")) 289 if (body.startsWith("!LDRAW_ORG ") and not body.startsWith("!LDRAW_ORG Unofficial_"))
318 { 290 {
291 // Add Unofficial_ to part type
319 QStringList tokens = body.split(" "); 292 QStringList tokens = body.split(" ");
320 tokens[1] = "Unofficial_" + tokens[1]; 293 tokens[1] = "Unofficial_" + tokens[1];
321 // Remove the UPDATE tag 294 // Remove the UPDATE tag if it's there
322 if (tokens.size() >= 4 && tokens[2] == "UPDATE") 295 if (tokens.size() >= 4 && tokens[2] == "UPDATE")
323 { 296 {
324 tokens.removeAt(3); 297 tokens.removeAt(3);
325 tokens.removeAt(2); 298 tokens.removeAt(2);
326 } 299 }
327 EditContext editor = this->edit(); 300 Model::EditContext editor = model.edit();
328 editor.setObjectProperty<ldraw::Property::Text>(id, tokens.join(" ")); 301 editor.setObjectProperty<ldraw::Property::Text>(ldrawOrgLine->id, tokens.join(" "));
329 } 302 }
330 } 303 }
331 } 304 }
332 } 305 }

mercurial