--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/modeleditor.h Fri Mar 04 11:40:19 2022 +0200 @@ -0,0 +1,98 @@ +/* + * LDForge: LDraw parts authoring CAD + * Copyright (C) 2013 - 2020 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 "model.h" + +/** + * @brief Provides an interface for editing a model such that signals are emitted for each edit done. + * User edits to models should always be done through this class. + */ +class ModelEditor : public QObject +{ + Q_OBJECT +public: + ModelEditor(Model& model); + ~ModelEditor(); + template<typename T, typename... Args> + ldraw::Id<T> append(Args&&... args); + ldraw::id_t append(std::unique_ptr<ldraw::Object>&& object); + template<typename T, typename... Args> + ldraw::Id<T> insert(int position, Args&&... args); + void remove(int position); + template<ldraw::Property property> + void setObjectProperty(ldraw::id_t id, const ldraw::PropertyType<property>& value); + auto setObjectProperty(ldraw::id_t id, ldraw::Property property, const QVariant& value) + -> ldraw::Object::SetPropertyResult; + void setObjectPoint(ldraw::id_t id, int pointId, const glm::vec3& value); + template<typename T, typename Fn> + bool modifyObject(ldraw::Id<T> id, Fn&& function); + template<typename T, typename Fn> + bool modifyObjectAt(int position, Fn&& function); + const Model& model(); +Q_SIGNALS: + void objectAdded(int position); + void objectModified(int position); + void objectRemoved(ldraw::id_t id); +private: + QSet<ldraw::id_t> modifiedObjects; + Model& storedModel; +}; + +template<ldraw::Property Property> +void ModelEditor::setObjectProperty(const ldraw::id_t id, const ldraw::PropertyType<Property>& value) +{ + this->modifyObject(id, [&](ldraw::Object* object){ + object->setProperty<Property>(value); + }); +} + +template<typename T, typename... Args> +ldraw::Id<T> ModelEditor::append(Args&&... args) +{ + return this->storedModel.append<T>(args...); +} + +template<typename T, typename... Args> +ldraw::Id<T> ModelEditor::insert(int position, Args&&... args) +{ + return this->storedModel.insert<T>(position, args...); +} + +template<typename T, typename Fn> +bool ModelEditor::modifyObject(ldraw::Id<T> id, Fn&& function) +{ + QModelIndex index = this->model().find(id); + return this->modifyObjectAt<T>(index.row(), function); +} + +template<typename T, typename Fn> +bool ModelEditor::modifyObjectAt(int position, Fn&& function) +{ + if (position >= 0 and position < this->model().size()) + { + T* object = dynamic_cast<T*>(this->storedModel[position]); + if (object != nullptr) + { + Q_EMIT this->objectModified(position); + function(object); + return true; + } + } + return false; +} \ No newline at end of file