# HG changeset patch # User Teemu Piippo # Date 1646146819 -7200 # Node ID 008989bc7d6e3f06f4bb5b35d4b718c0c71e3348 # Parent e1ced2523cadcafdebbc0b117f53f0f1deaa16b1 work on edit history diff -r e1ced2523cad -r 008989bc7d6e src/document.cpp --- 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) diff -r e1ced2523cad -r 008989bc7d6e src/document.h --- 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; }; diff -r e1ced2523cad -r 008989bc7d6e src/edithistory.cpp --- 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() +{ +} diff -r e1ced2523cad -r 008989bc7d6e src/edithistory.h --- 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 changesets; std::size_t position = 0; bool changesetOpen = false; -}; \ No newline at end of file +}; diff -r e1ced2523cad -r 008989bc7d6e src/main.cpp --- 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"); ::qRegisterMetaTypeStreamOperators("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() )); - */ MainWindow mainwindow; mainwindow.show(); return app.exec(); diff -r e1ced2523cad -r 008989bc7d6e src/main.h --- 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 +void mapapply(const QMap& map, Fn fn) +{ + for ( + typename QMap::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 struct TypeValue { diff -r e1ced2523cad -r 008989bc7d6e src/model.h --- 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; template @@ -155,7 +155,7 @@ } template -ldraw::Id Model::append(Args&&... args) +T* Model::append(Args&&... args) { const int position = static_cast(this->body.size()); Q_EMIT beginInsertRows({}, position, position); @@ -169,7 +169,7 @@ } template -ldraw::Id 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(args...)); diff -r e1ced2523cad -r 008989bc7d6e src/modeleditcontext.cpp --- 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(typeInteger)) + { + case ldraw::Object::Type::Empty: + this->storedModel.insert(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(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; diff -r e1ced2523cad -r 008989bc7d6e src/modeleditcontext.h --- 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 ldraw::Id append(Args&&... args); ldraw::id_t append(std::unique_ptr&& object); + void insertFromState(int position, QByteArray& state); template ldraw::Id 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 modifiedObjects; + QMap modifiedObjects; Model& storedModel; }; @@ -49,8 +53,8 @@ ldraw::Object* object = this->model().objectAt(id); if (object != nullptr) { + this->markObjectAsModified(id, object); object->setProperty(value); - modifiedObjects.insert(id); } }