--- a/src/documentmanager.cpp Tue Sep 28 23:09:09 2021 +0300 +++ b/src/documentmanager.cpp Sun Oct 24 11:33:32 2021 +0300 @@ -22,6 +22,7 @@ #include "documentmanager.h" #include "modeleditcontext.h" #include "linetypes/comment.h" +#include "linetypes/subfilereference.h" #include "parser.h" /** @@ -59,7 +60,7 @@ } else { - return iterator->second.get(); + return iterator->second.model.get(); } } @@ -84,7 +85,14 @@ return result; } -QString DocumentManager::openModel(const QString& path, QTextStream& errorStream) +/** + * @brief Tries to open the model at the specified path + * @param path Path to the model to open + * @param errorStream Where to write any errors + * @param openType rationale behind opening this file + * @returns file name or "" on error + */ +QString DocumentManager::openModel(const QString& path, QTextStream& errorStream, const OpenType openType) { QFile file{path}; const QString name = pathToName(path); @@ -97,7 +105,7 @@ QString result; if (file.error() == QFile::NoError) { - openModels[name] = std::move(newModel); + openModels[name] = {std::move(newModel), openType}; result = name; } else @@ -131,6 +139,43 @@ } } +void DocumentManager::closeDocument(const QString &name) +{ + const auto& it = this->openModels.find(name); + if (it != this->openModels.end()) + { + this->openModels.erase(it); + } + QSet<QString> referenced; + for (const auto& it : this->openModels) + { + if (it.second.opentype == OpenType::ManuallyOpened) + { + this->collectReferences(referenced, it.first, it.second.model.get()); + } + } + +} + +void DocumentManager::collectReferences(QSet<QString>& referenced, const QString &name, const Model *model) +{ + if (not referenced.contains(name)) + { + referenced.insert(name); + model->apply<ldraw::SubfileReference>([&](const ldraw::SubfileReference* referenceObject) + { + const ldraw::id_t id = referenceObject->id; + const QString& referenceName = model->getObjectProperty<ldraw::Property::ReferenceName>(id); + auto it = this->openModels.find(referenceName); + if (it != this->openModels.end()) + { + const Model* const model = it->second.model.get(); + this->collectReferences(referenced, referenceName, model); + } + }); + } +} + static QString findFile(QString referenceName, const QString& path, const LibraryManager& libraries) { // Try to find the file in the same place as the model itself @@ -175,7 +220,10 @@ } QString errorString; QTextStream localErrorStream{&errorString}; - QString resultName = this->openModel(referencedFilePath, localErrorStream); + QString resultName = this->openModel( + referencedFilePath, + localErrorStream, + OpenType::AutomaticallyOpened); if (resultName.isEmpty()) { throw LoadingError{utility::format(