src/model.h

changeset 200
ca23936b455b
parent 173
8a3047468994
child 206
654661eab7f3
--- a/src/model.h	Wed May 25 20:36:34 2022 +0300
+++ b/src/model.h	Mon Jun 06 22:01:22 2022 +0300
@@ -20,120 +20,96 @@
 #include <QAbstractListModel>
 #include <memory>
 #include "main.h"
-#include "header.h"
-#include "linetypes/object.h"
-#include "linetypes/metacommand.h"
-#include "gl/common.h"
+#include "colors.h"
+
+struct SubfileReference
+{
+	QString name;
+	glm::mat4 transformation;
+	bool inverted = false;
+};
+
+template<typename T>
+struct Colored : T
+{
+	ldraw::Color color;
+};
+
+struct Comment
+{
+	QString text;
+};
 
-enum class HeaderProperty
+struct ParseError
 {
-	Name
+	QString code;
 };
 
+struct Empty {};
+
+using ModelElement = std::variant<
+	Colored<SubfileReference>,
+	Colored<LineSegment>,
+	Colored<Triangle>,
+	Colored<Quadrilateral>,
+	Colored<ConditionalEdge>,
+	Comment,
+	Empty,
+	ParseError>;
+
+QString modelElementToString(const ModelElement& element);
+struct ModelId
+{
+	std::int32_t value;
+	constexpr auto operator<=>(const ModelId& other) const = default;
+};
+
+constexpr int qHash(ModelId id)
+{
+	return qHash(id.value);
+}
+
 class Model : public QAbstractListModel
 {
 	Q_OBJECT
+	struct Entry {
+		ModelElement data;
+		ModelId id;
+	};
+	std::vector<Entry> body;
+	std::map<ModelId, int> positions;
+	ModelId runningId = {1};
 public:
-	Model(QObject* parent = nullptr);
-	Model(const Model&) = delete;
-
-	int size() const;
-	ldraw::id_t at(int index) const;
+	Model(QObject* parent);
+	virtual ~Model();
+	ModelId append(const ModelElement& value);
+	const ModelElement& at(int position) const;
+	ModelId idAt(int position) const;
+	void assignAt(int position, const ModelElement& element);
+	std::optional<int> find(ModelId id) const;
+	void remove(int index);
 	int rowCount(const QModelIndex&) const override;
 	QVariant data(const QModelIndex& index, int role) const override;
-	ldraw::Object* findObjectById(const ldraw::id_t id);
-	const ldraw::Object* findObjectById(const ldraw::id_t id) const;
-	QModelIndex find(ldraw::id_t id) const;
-	ldraw::id_t idAt(const QModelIndex& index) const;
-	template<typename R>
-	const R* get(ldraw::Id<R> id) const;
-	template<typename R>
-	struct Get2Result
-	{
-		QModelIndex index;
-		const R* object;
-	};
-	template<typename R>
-	Get2Result<R> get2(ldraw::Id<R> id) const;
-	ldraw::Object* operator[](int index);
-	const ldraw::Object* operator[](int index) const;
-	using ModelObjectPointer = std::unique_ptr<ldraw::Object>;
-	template<typename T, typename... Args>
-	ldraw::Id<T> append(Args&&... args);
-	ldraw::id_t append(ModelObjectPointer&& object);
-	template<typename T, typename... Args>
-	ldraw::Id<T> insert(std::size_t position, Args&&... args);
-	void remove(int position);
-	void emitDataChangedSignal(int position);
-private:
-	bool modified = false;
-	std::vector<ModelObjectPointer> body;
-	mutable std::map<ldraw::id_t, std::size_t> objectsById;
-	mutable bool needObjectsByIdRebuild = false;
+	const ModelElement& operator[](int index) const;
+	int size() const;
+	auto operator[](int index) {
+		struct {
+			Model& model;
+			int index;
+			operator const ModelElement&() {
+				return model.at(index);
+			}
+			auto& operator=(const ModelElement& newData) {
+				model.assignAt(index, newData);
+				return *this;
+			}
+			const auto* operator&() {
+				return &(this->operator const ModelElement&());
+			}
+		} result{*this, index};
+		return result;
+	}
 };
 
 void save(const Model& model, QIODevice *device);
-
-/**
- * @brief Calls the specified function to all matching objects in the model
- * @tparam R Type of LDraw line type object to filter by
- * @param fn Function to call.
- */
-template<typename R, typename Fn>
-void applyToModel(const Model& model, Fn&& f)
-{
-	for (int i = 0; i < model.size(); i += 1)
-	{
-		const ldraw::Object* object = model[i];
-		const R* subobject = dynamic_cast<const R*>(object);
-		if (subobject != nullptr)
-		{
-			f(subobject);
-		}
-	}
-}
-
-template<typename T, typename... Args>
-ldraw::Id<T> Model::append(Args&&... args)
-{
-	const int position = static_cast<int>(this->body.size());
-	Q_EMIT beginInsertRows({}, position, position);
-	this->body.push_back(std::make_unique<T>(args...));
-	ldraw::Object* pointer = this->body.back().get();
-	this->objectsById[pointer->id] = this->body.size() - 1;
-	Q_EMIT endInsertRows();
-	return ldraw::Id<T>{pointer->id.value};
-}
-
-template<typename T, typename... Args>
-ldraw::Id<T> Model::insert(const std::size_t position, Args&&... args)
-{
-	Q_EMIT beginInsertRows({}, position, position);
-	this->body.insert(std::begin(this->body) + position, std::make_unique<T>(args...));
-	ldraw::Object* pointer = this->body[position].get();
-	this->objectsById[pointer->id] = position;
-	Q_EMIT endInsertRows();
-	return ldraw::Id<T>{pointer->id.value};
-}
-
-template<typename R>
-const R* Model::get(ldraw::Id<R> id) const
-{
-	return this->get2(id).object;
-}
-
-template<typename R>
-Model::Get2Result<R> Model::get2(const ldraw::Id<R> id) const
-{
-	Get2Result<R> result;
-	result.index = this->find(id);
-	if (result.index.isValid())
-	{
-		result.object = static_cast<const R*>((*this)[result.index.row()]);
-	}
-	else
-	{
-		result.object = nullptr;
-	}
-	return result;
-}
+void updateHeaderNameField(Model& model, const QString &name);

mercurial