diff --git a/src/tiled/editableworld.cpp b/src/tiled/editableworld.cpp index db6144b79c..dcd6a38af5 100644 --- a/src/tiled/editableworld.cpp +++ b/src/tiled/editableworld.cpp @@ -21,6 +21,7 @@ #include "editableworld.h" +#include "changeevents.h" #include "changeworld.h" #include "maprenderer.h" #include "scriptmanager.h" @@ -144,6 +145,20 @@ QSharedPointer EditableWorld::createDocument() return nullptr; } +void EditableWorld::documentChanged(const ChangeEvent &event) +{ + switch (event.type) { + case ChangeEvent::DocumentAboutToReload: + setObject(nullptr); + break; + case ChangeEvent::DocumentReloaded: + setObject(worldDocument()->world()); + break; + default: + break; + } +} + } // namespace Tiled #include "moc_editableworld.cpp" diff --git a/src/tiled/editableworld.h b/src/tiled/editableworld.h index 74ab5d8b60..6d5d3cf3c9 100644 --- a/src/tiled/editableworld.h +++ b/src/tiled/editableworld.h @@ -61,6 +61,9 @@ class EditableWorld final : public EditableAsset Q_INVOKABLE void removeMap(EditableMap *map); QSharedPointer createDocument() override; + +private: + void documentChanged(const ChangeEvent &event); }; inline World *EditableWorld::world() const diff --git a/src/tiled/worlddocument.cpp b/src/tiled/worlddocument.cpp index 8748ebf965..156e8cb4b8 100644 --- a/src/tiled/worlddocument.cpp +++ b/src/tiled/worlddocument.cpp @@ -21,6 +21,7 @@ #include "worlddocument.h" +#include "changeevents.h" #include "editableworld.h" #include "worldmanager.h" @@ -29,10 +30,30 @@ namespace Tiled { +class ReloadWorld : public QUndoCommand +{ +public: + ReloadWorld(WorldDocument *worldDocument, std::unique_ptr world) + : mWorldDocument(worldDocument) + , mWorld(std::move(world)) + { + setText(QCoreApplication::translate("Undo Commands", "Reload World")); + } + + void undo() override { mWorldDocument->swapWorld(mWorld); } + void redo() override { mWorldDocument->swapWorld(mWorld); } + +private: + WorldDocument *mWorldDocument; + std::unique_ptr mWorld; +}; + + WorldDocument::WorldDocument(std::unique_ptr world, QObject *parent) : Document(WorldDocumentType, world->fileName, parent) , mWorld(std::move(world)) { + setCurrentObject(mWorld.get()); } WorldDocument::~WorldDocument() @@ -77,18 +98,17 @@ bool WorldDocument::reload(QString *error) if (!canReload()) return false; - if (auto world = World::load(fileName(), error)) { - // todo: consider replacing the world using an undo command - mWorld->clearErrorsAndWarnings(); - mWorld = std::move(world); - undoStack()->clear(); - updateIsModified(); + auto world = World::load(fileName(), error); + if (!world) + return false; - emit worldChanged(); - return true; - } + undoStack()->push(new ReloadWorld(this, std::move(world))); + undoStack()->setClean(); - return false; + mLastSaved = QFileInfo(fileName()).lastModified(); + setChangedOnDisk(false); + + return true; } WorldDocumentPtr WorldDocument::load(const QString &fileName, QString *error) @@ -100,6 +120,22 @@ WorldDocumentPtr WorldDocument::load(const QString &fileName, QString *error) return WorldDocumentPtr::create(std::move(world)); } +void WorldDocument::swapWorld(std::unique_ptr &other) +{ + setCurrentObject(nullptr); + + emit changed(AboutToReloadEvent()); + + mWorld->clearErrorsAndWarnings(); + mWorld.swap(other); + updateIsModified(); + + emit changed(ReloadEvent()); + + setCurrentObject(mWorld.get()); + emit worldChanged(); +} + std::unique_ptr WorldDocument::createEditable() { return std::make_unique(this, this); diff --git a/src/tiled/worlddocument.h b/src/tiled/worlddocument.h index 8d4f165730..50e779a105 100644 --- a/src/tiled/worlddocument.h +++ b/src/tiled/worlddocument.h @@ -69,6 +69,8 @@ class WorldDocument final : public Document World *world() const { return mWorld.get(); } + void swapWorld(std::unique_ptr &other); + signals: void worldChanged();