# HG changeset patch # User Teemu Piippo # Date 1635064412 -10800 # Node ID 37f936073cac97b11c1ae8eecebec88eefed78ef # Parent 235941b7322f4d85a3b5fd28470589bff4605a01 update diff -r 235941b7322f -r 37f936073cac src/documentmanager.cpp --- 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 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& referenced, const QString &name, const Model *model) +{ + if (not referenced.contains(name)) + { + referenced.insert(name); + model->apply([&](const ldraw::SubfileReference* referenceObject) + { + const ldraw::id_t id = referenceObject->id; + const QString& referenceName = model->getObjectProperty(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( diff -r 235941b7322f -r 37f936073cac src/documentmanager.h --- a/src/documentmanager.h Tue Sep 28 23:09:09 2021 +0300 +++ b/src/documentmanager.h Sun Oct 24 11:33:32 2021 +0300 @@ -23,20 +23,31 @@ class DocumentManager : public QObject { Q_OBJECT - using ModelPointer = std::unique_ptr; public: + enum OpenType + { + ManuallyOpened, + AutomaticallyOpened, + }; DocumentManager(QObject* parent = nullptr); QString newModel(); Model* findModelByName(const QString& name); - QString openModel(const QString& path, QTextStream& errorStream); + QString openModel(const QString& path, QTextStream& errorStream, const OpenType openType); QString makeNewModelName(); void loadDependenciesForModel(const QString& modelName, const QString& path, const LibraryManager& libraries, QTextStream& errorStream); + void closeDocument(const QString& name); private: + void collectReferences(QSet &referenced, const QString& name, const Model* model); + struct ModelInfo + { + std::unique_ptr model; + OpenType opentype; + }; int untitledNameCounter = 0; - std::map openModels; + std::map openModels; void loadDependenciesForModel(const QString& modelName, const QString& path, const LibraryManager& libraries, @@ -44,3 +55,5 @@ QStringList& processed, QTextStream& errorStream); }; + +QString pathToName(const QFileInfo& path); diff -r 235941b7322f -r 37f936073cac src/mainwindow.cpp --- a/src/mainwindow.cpp Tue Sep 28 23:09:09 2021 +0300 +++ b/src/mainwindow.cpp Sun Oct 24 11:33:32 2021 +0300 @@ -209,6 +209,26 @@ return qobject_cast(this->ui->tabs->currentWidget()); } +void MainWindow::closeDocument(Document *document) +{ + const int tabIndex = this->ui->tabs->indexOf(document); + if (tabIndex != -1) + { + this->ui->tabs->removeTab(tabIndex); + const QString closedDocumentName = pathToName(document->modelPath()); + delete document; + } + QSet openedDocumentNames; + for (int i = 0; i < this->ui->tabs->count(); i += 1) + { + Document* document = qobject_cast(this->ui->tabs->widget(i)); + if (document != nullptr) + { + openedDocumentNames.insert(pathToName(document->modelPath())); + } + } +} + void MainWindow::handleDocumentSplitterChange() { Document* currentDocument = this->currentDocument(); diff -r 235941b7322f -r 37f936073cac src/mainwindow.h --- a/src/mainwindow.h Tue Sep 28 23:09:09 2021 +0300 +++ b/src/mainwindow.h Sun Oct 24 11:33:32 2021 +0300 @@ -75,4 +75,5 @@ static QString pathToTranslation(const QString& localeCode); void loadColors(); Document *currentDocument(); + void closeDocument(Document* document); }; diff -r 235941b7322f -r 37f936073cac src/model.cpp --- a/src/model.cpp Tue Sep 28 23:09:09 2021 +0300 +++ b/src/model.cpp Sun Oct 24 11:33:32 2021 +0300 @@ -366,4 +366,4 @@ } } } -} \ No newline at end of file +} diff -r 235941b7322f -r 37f936073cac src/model.h --- a/src/model.h Tue Sep 28 23:09:09 2021 +0300 +++ b/src/model.h Sun Oct 24 11:33:32 2021 +0300 @@ -46,6 +46,8 @@ QVariant getHeaderProperty(const HeaderProperty property); const QString& getName() const; QVariant getObjectProperty(const int index, const ldraw::Property property) const; + template + ldraw::PropertyType getObjectProperty(const ldraw::id_t id) const; std::vector getPolygons(class DocumentManager* documents) const; QModelIndex lookup(ldraw::id_t id) const; ldraw::id_t resolve(const QModelIndex& index) const; @@ -220,4 +222,22 @@ const T* Model::objectAt(ldraw::Id id) const { return static_cast(this->objectAt(this->lookup(id))); +} + +/** + * @brief Gets an object property by id + * @tparam Property Property to obtain + * @param id ID of object + * @returns property or default value + */ +template +ldraw::PropertyType Model::getObjectProperty(const ldraw::id_t id) const +{ + const ldraw::Object* const object = this->objectAt(id); + ldraw::PropertyType result; + if (object != nullptr) + { + result = object->getProperty() + } + return result; } \ No newline at end of file