src/modeleditcontext.h

changeset 152
03f8e6d42e13
parent 151
e628fc2e0c72
--- a/src/modeleditcontext.h	Thu Mar 03 21:13:16 2022 +0200
+++ b/src/modeleditcontext.h	Fri Mar 04 11:37:50 2022 +0200
@@ -19,10 +19,16 @@
 #pragma once
 #include "model.h"
 
-class Model::EditContext
+/**
+ * @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:
-	~EditContext();
+	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);
@@ -34,51 +40,59 @@
 	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);
-	void invertObject(ldraw::id_t id);
-	Model& model();
+	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:
-	EditContext(Model& model);
-	friend class Model;
 	QSet<ldraw::id_t> modifiedObjects;
 	Model& storedModel;
 };
 
 template<ldraw::Property Property>
-void Model::EditContext::setObjectProperty(const ldraw::id_t id, const ldraw::PropertyType<Property>& value)
+void ModelEditor::setObjectProperty(const ldraw::id_t id, const ldraw::PropertyType<Property>& value)
 {
-	ldraw::Object* object = this->model().findObjectById(id);
-	if (object != nullptr)
-	{
+	this->modifyObject(id, [&](ldraw::Object* object){
 		object->setProperty<Property>(value);
-		modifiedObjects.insert(id);
-	}
+	});
 }
 
 template<typename T, typename... Args>
-ldraw::Id<T> Model::EditContext::append(Args&&... args)
+ldraw::Id<T> ModelEditor::append(Args&&... args)
 {
 	return this->storedModel.append<T>(args...);
 }
 
 template<typename T, typename... Args>
-ldraw::Id<T> Model::EditContext::insert(int position, Args&&... args)
+ldraw::Id<T> ModelEditor::insert(int position, Args&&... args)
 {
 	return this->storedModel.insert<T>(position, args...);
 }
 
-namespace ldraw
+template<typename T, typename Fn>
+bool ModelEditor::modifyObject(ldraw::Id<T> id, Fn&& function)
 {
-	/// Determines how quadrilaterals are split into triangles
-	enum class Diagonal
+	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())
 	{
-		Diagonal_13,
-		Diagonal_24
-	};
-
-	// Splits the specified quadrilateral into triangles.
-	// If it is not a quadrilateral then no action is performed
-	auto splitQuadrilateral(Model::EditContext& editor,
-		quadrilateralid_t quadrilateral_id,
-		Diagonal splitType = Diagonal::Diagonal_13
-	) -> std::optional<std::pair<triangleid_t, triangleid_t>>;
-}
+		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

mercurial