Sun, 05 Mar 2017 16:57:49 +0200
Also removed the copy constructor and copy assignment because those only are bad news for a resource managing vector...
/* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 - 2017 Teemu Piippo * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #pragma once #include "main.h" #include "linetypes/modelobject.h" #include "types/resourcevector.h" /* * This class represents a LDraw model, consisting of a vector of objects. It manages LDObject ownership. */ class Model : public QObject { Q_OBJECT public: using Filter = std::function<bool(LDObject*)>; using Callback = std::function<void(LDObject*, int)>; Model(class DocumentManager* manager); Model(const Model& other) = delete; template<typename T, typename... Args> T* append(Args&& ...args); LDObject* appendFromString(QString line); LDObject* const* begin(); void clear(); class DocumentManager* documentManager() const; LDObject* const* end(); LDObject* getObject(int position) const; template<typename T, typename... Args> T* insert(int position, Args&& ...args); LDObject* insertFromString(int position, QString line); bool isEmpty() const; void merge(Model& other, int position = -1, Filter filter = nullptr, Callback callback = nullptr); const ResourceVector<LDObject>& objects() const; void recountTriangles(); void remove(LDObject* object); void removeAt(int position); template<typename T, typename... Args> T* replace(LDObject* object, Args&& ...args); void replace(LDObject* object, Model& model); LDObject* replaceWithFromString(LDObject* object, QString line); int size() const; bool swapObjects(LDObject* one, LDObject* other); int triangleCount() const; signals: void objectAdded(LDObject* object, int position); void aboutToRemoveObject(LDObject* object, int position); void objectModified(LDObject* object); void objectsSwapped(LDObject* one, LDObject* other); protected: template<typename T, typename... Args> T* constructObject(Args&& ...args); ResourceVector<LDObject> _objects; class DocumentManager* _manager; mutable int _triangleCount = 0; mutable bool _needsTriangleRecount; private: void finalizeNewObject(int position, LDObject* object); ResourceVector<LDObject>& mutableObjects(); }; int countof(Model& model); /* * Given an LDObject type as the template parameter, and any number of variadic parameters, constructs an LDObject derivative * and inserts it into this model. The variadic parameters and this model pointer are passed to the constructor. The constructed object * is added to the end of the model. * * For instance, the LDLine contains a constructor as such: * * LDLine(Vertex v1, Vertex v2, Model* model); * * This constructor can be invoked as such: * * model->append<LDLine>(v1, v2); */ template<typename T, typename... Args> T* Model::append(Args&& ...args) { T* object = _objects.append<T>(args..., this); finalizeNewObject(size() - 1, object); return object; } /* * Like append<>() but also takes a position as the first argument and emplaces the object at the given position instead of the * end of the model. */ template<typename T, typename... Args> T* Model::insert(int position, Args&& ...args) { T* object = _objects.insert<T>(position, args..., this); finalizeNewObject(position, object); return object; } /* * Like append<>() but instead of inserting the constructed object, the new object replaces the object given in the first parameter. * If the old object cannot be replaced, the new object will not be constructed at all. */ template<typename T, typename... Args> T* Model::replace(LDObject* object, Args&& ...args) { if (object->model() == this) { int position = object->lineNumber(); removeAt(position); T* replacement = _objects.insert<T>(position, args..., this); finalizeNewObject(position, replacement); return replacement; } else { return nullptr; } }