work on edit history

Tue, 01 Mar 2022 17:00:19 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Tue, 01 Mar 2022 17:00:19 +0200
changeset 149
008989bc7d6e
parent 148
e1ced2523cad

work on edit history

src/document.cpp file | annotate | diff | comparison | revisions
src/document.h file | annotate | diff | comparison | revisions
src/edithistory.cpp file | annotate | diff | comparison | revisions
src/edithistory.h file | annotate | diff | comparison | revisions
src/main.cpp file | annotate | diff | comparison | revisions
src/main.h file | annotate | diff | comparison | revisions
src/model.h file | annotate | diff | comparison | revisions
src/modeleditcontext.cpp file | annotate | diff | comparison | revisions
src/modeleditcontext.h file | annotate | diff | comparison | revisions
--- a/src/document.cpp	Tue Nov 02 15:43:57 2021 +0200
+++ b/src/document.cpp	Tue Mar 01 17:00:19 2022 +0200
@@ -97,6 +97,13 @@
 	{
 		this->renderer->rebuildVertices(this);
 	});
+	connect(this->model, &Model::objectStateChanged, [&](
+		ldraw::id_t id,
+		const QByteArray& stateBefore,
+		const QByteArray& stateAfter
+	){
+		this->editHistory.add(EditHistoryEntry{id, stateBefore, stateAfter});
+	});
 	this->setCanvasOverpaintCallback([&](Canvas* canvas, QPainter* painter)
 	{
 		if (this->selectedTool != nullptr)
--- a/src/document.h	Tue Nov 02 15:43:57 2021 +0200
+++ b/src/document.h	Tue Mar 01 17:00:19 2022 +0200
@@ -71,5 +71,5 @@
 	/**
 	 * @brief History information of edits to this model
 	 */
-	// EditHistory editHistory;
+	EditHistory editHistory;
 };
--- a/src/edithistory.cpp	Tue Nov 02 15:43:57 2021 +0200
+++ b/src/edithistory.cpp	Tue Mar 01 17:00:19 2022 +0200
@@ -46,10 +46,24 @@
 
 void EditHistoryEntry::undo(Model::EditContext &editContext)
 {
-	
+	this->doUndoRedo(editContext, this->stateAfter);
 }
 
 void EditHistoryEntry::redo(Model::EditContext &editContext)
 {
-	
+	this->doUndoRedo(editContext, this->stateBefore);
 }
+
+void EditHistoryEntry::doUndoRedo(Model::EditContext &editContext, QByteArray &state)
+{
+	const ldraw::id_t id = editContext.resolve(this->position);
+	if (id != ldraw::NULL_ID)
+	{
+		QDataStream stream{&state, QIODevice::ReadOnly};
+		editContext.deserialize(id, stream);
+	}
+}
+
+AbstractHistoryEntry::~AbstractHistoryEntry()
+{
+}
--- a/src/edithistory.h	Tue Nov 02 15:43:57 2021 +0200
+++ b/src/edithistory.h	Tue Mar 01 17:00:19 2022 +0200
@@ -23,6 +23,7 @@
 class AbstractHistoryEntry
 {
 public:
+	virtual ~AbstractHistoryEntry();
 	virtual void undo(Model::EditContext& editContext) = 0;
 	virtual void redo(Model::EditContext& editContext) = 0;
 };
@@ -57,6 +58,7 @@
 	void undo(Model::EditContext& editContext) override;
 	void redo(Model::EditContext& editContext) override;
 private:
+	void doUndoRedo(Model::EditContext &editContext, QByteArray& state);
 	int position;
 	QByteArray stateBefore;
 	QByteArray stateAfter;
@@ -97,4 +99,4 @@
 	std::vector<Changeset> changesets;
 	std::size_t position = 0;
 	bool changesetOpen = false;
-};
\ No newline at end of file
+};
--- a/src/main.cpp	Tue Nov 02 15:43:57 2021 +0200
+++ b/src/main.cpp	Tue Mar 01 17:00:19 2022 +0200
@@ -29,14 +29,7 @@
 	QCoreApplication::setOrganizationDomain("hecknology.net");
 	::qRegisterMetaTypeStreamOperators<Library>("Library");
 	::qRegisterMetaTypeStreamOperators<Libraries>("Libraries");
-	
-	glm::mat4 mat = glm::scale(glm::mat4{1}, {3, 3, 3});
-	glm::vec4 x = {1,2,3,4};
-	
 	QApplication app{argc, argv};
-	/*
-	QMessageBox::information(nullptr, "", QMetaType::typeName( qMetaTypeId<ldraw::Color>() ));
-	*/
 	MainWindow mainwindow;
 	mainwindow.show();
 	return app.exec();
--- a/src/main.h	Tue Nov 02 15:43:57 2021 +0200
+++ b/src/main.h	Tue Mar 01 17:00:19 2022 +0200
@@ -226,6 +226,21 @@
 	>{map};
 }
 
+template<typename K, typename V, typename Fn>
+void mapapply(const QMap<K, V>& map, Fn fn)
+{
+	for (
+		 typename QMap<K, V>::const_iterator it = map.constBegin();
+		 it != map.constEnd();
+		 ++it
+	) {
+		fn(it.key(), it.value());
+	}
+}
+
+#define MAP_PARMS(map) decltype(map)::key_type const& key, decltype(map)::mapped_type& value
+#define MAP_CPARMS(map) decltype(map)::key_type const& key, decltype(map)::mapped_type const& value
+
 template<typename T, typename IdentifierType>
 struct TypeValue
 {
--- a/src/model.h	Tue Nov 02 15:43:57 2021 +0200
+++ b/src/model.h	Tue Mar 01 17:00:19 2022 +0200
@@ -70,7 +70,7 @@
 	void makeUnofficial();
 Q_SIGNALS:
 	void objectAdded(ldraw::id_t id, int position);
-	void objectModified(ldraw::id_t id, int position);
+	void objectStateChanged(int position, const QByteArray& stateBefore, const QByteArray& stateAfter);
 private:
 	using ModelObjectPointer = std::unique_ptr<ldraw::Object>;
 	template<typename T, typename... Args>
@@ -155,7 +155,7 @@
 }
 
 template<typename T, typename... Args>
-ldraw::Id<T> Model::append(Args&&... args)
+T* Model::append(Args&&... args)
 {
 	const int position = static_cast<int>(this->body.size());
 	Q_EMIT beginInsertRows({}, position, position);
@@ -169,7 +169,7 @@
 }
 
 template<typename T, typename... Args>
-ldraw::Id<T> Model::insert(const std::size_t position, Args&&... args)
+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...));
--- a/src/modeleditcontext.cpp	Tue Nov 02 15:43:57 2021 +0200
+++ b/src/modeleditcontext.cpp	Tue Mar 01 17:00:19 2022 +0200
@@ -25,12 +25,29 @@
 {
 }
 
+void Model::EditContext::markObjectAsModified(ldraw::id_t id, ldraw::Object *object)
+{
+	if (not this->modifiedObjects.contains(id))
+	{
+		QDataStream stream{&this->modifiedObjects[id], QIODevice::WriteOnly};
+		object->serialize(stream);
+	}
+}
+
 Model::EditContext::~EditContext()
 {
-	for (ldraw::id_t id : this->modifiedObjects)
+	mapapply(this->modifiedObjects, [&](MAP_CPARMS(this->modifiedObjects))
 	{
-		this->model().objectModified(id);
-	}
+		ldraw::Object* object = this->model().objectAt(key);
+		if (object != nullptr)
+		{
+			QByteArray newState;
+			QDataStream stream{&newState, QIODevice::WriteOnly};
+			object->serialize(stream);
+			const int position = this->model().lookup(key).row();
+			Q_EMIT this->model().objectStateChanged(position, value, newState);
+		}
+	});
 	this->model().editFinished();
 }
 
@@ -42,6 +59,19 @@
 	return id;
 }
 
+void Model::EditContext::insertFromState(int position, QByteArray &state)
+{
+	int typeInteger;
+	QDataStream stream{&state, QIODevice::ReadOnly};
+	stream >> typeInteger;
+	switch (static_cast<ldraw::Object::Type>(typeInteger))
+	{
+	case ldraw::Object::Type::Empty:
+		this->storedModel.insert<ldraw::Empty>(position);
+		break;
+	}
+}
+
 void Model::EditContext::remove(int position)
 {
 	this->model().remove(position);
@@ -56,8 +86,8 @@
 	ldraw::Object* const object = this->model().objectAt(id);
 	if (object != nullptr)
 	{
+		this->markObjectAsModified(id, object);
 		const ldraw::Object::SetPropertyResult result = object->setProperty(ldraw::PropertyKeyValue{property, value});
-		modifiedObjects.insert(id);
 		return result;
 	}
 	else
@@ -71,8 +101,8 @@
 	ldraw::Object* object = this->model().objectAt(id);
 	if (object != nullptr)
 	{
+		this->markObjectAsModified(id, object);
 		object->setProperty(ldraw::PropertyKeyValue{ldraw::pointProperty(pointId), QVariant::fromValue(value)});
-		modifiedObjects.insert(id);
 	}
 }
 
@@ -82,10 +112,40 @@
 	if (it != this->model().objectsById.end())
 	{
 		ldraw::Object* object = it->second;
+		this->markObjectAsModified(id, object);
 		object->invert();
 	}
 }
 
+void Model::EditContext::deserialize(ldraw::id_t id, QDataStream &stream)
+{
+	auto it = this->model().objectsById.find(id);
+	if (it != this->model().objectsById.end())
+	{
+		ldraw::Object* object = it->second;
+		int typeInteger;
+		stream >> typeInteger;
+		const ldraw::Object::Type type = static_cast<ldraw::Object::Type>(typeInteger);
+		if (object->typeIdentifier() == type)
+		{
+			this->markObjectAsModified(id, object);
+			object->deserialize(stream);
+		}
+	}
+}
+
+ldraw::id_t Model::EditContext::resolve(int position) const
+{
+	if (position >= 0 and position < this->storedModel.rowCount({}))
+	{
+		return this->storedModel.objectAt(this->storedModel.index(position))->id;
+	}
+	else
+	{
+		return ldraw::NULL_ID;
+	}
+}
+
 Model& Model::EditContext::model()
 {
 	return this->storedModel;
--- a/src/modeleditcontext.h	Tue Nov 02 15:43:57 2021 +0200
+++ b/src/modeleditcontext.h	Tue Mar 01 17:00:19 2022 +0200
@@ -26,6 +26,7 @@
 	template<typename T, typename... Args>
 	ldraw::Id<T> append(Args&&... args);
 	ldraw::id_t append(std::unique_ptr<ldraw::Object>&& object);
+	void insertFromState(int position, QByteArray& state);
 	template<typename T, typename... Args>
 	ldraw::Id<T> insert(int position, Args&&... args);
 	void remove(int position);
@@ -35,11 +36,14 @@
 		-> ldraw::Object::SetPropertyResult;
 	void setObjectPoint(ldraw::id_t id, int pointId, const glm::vec3& value);
 	void invertObject(ldraw::id_t id);
+	void deserialize(ldraw::id_t id, QDataStream& stream);
+	ldraw::id_t resolve(int position) const;
 	Model& model();
 private:
 	EditContext(Model& model);
+	void markObjectAsModified(ldraw::id_t id, ldraw::Object* object);
 	friend class Model;
-	QSet<ldraw::id_t> modifiedObjects;
+	QMap<ldraw::id_t, QByteArray> modifiedObjects;
 	Model& storedModel;
 };
 
@@ -49,8 +53,8 @@
 	ldraw::Object* object = this->model().objectAt(id);
 	if (object != nullptr)
 	{
+		this->markObjectAsModified(id, object);
 		object->setProperty<Property>(value);
-		modifiedObjects.insert(id);
 	}
 }
 

mercurial