update

Sun, 24 Oct 2021 11:33:32 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Sun, 24 Oct 2021 11:33:32 +0300
changeset 147
37f936073cac
parent 146
235941b7322f
child 148
e1ced2523cad

update

src/documentmanager.cpp file | annotate | diff | comparison | revisions
src/documentmanager.h file | annotate | diff | comparison | revisions
src/mainwindow.cpp file | annotate | diff | comparison | revisions
src/mainwindow.h file | annotate | diff | comparison | revisions
src/model.cpp file | annotate | diff | comparison | revisions
src/model.h file | annotate | diff | comparison | revisions
--- 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(
--- 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<Model>;
 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<QString> &referenced, const QString& name, const Model* model);
+	struct ModelInfo
+	{
+		std::unique_ptr<Model> model;
+		OpenType opentype;
+	};
 	int untitledNameCounter = 0;
-	std::map<QString, ModelPointer> openModels;
+	std::map<QString, ModelInfo> 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);
--- 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<Document*>(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<QString> openedDocumentNames;
+	for (int i = 0; i < this->ui->tabs->count(); i += 1)
+	{
+		Document* document = qobject_cast<Document*>(this->ui->tabs->widget(i));
+		if (document != nullptr)
+		{
+			openedDocumentNames.insert(pathToName(document->modelPath()));
+		}
+	}
+}
+
 void MainWindow::handleDocumentSplitterChange()
 {
 	Document* currentDocument = this->currentDocument();
--- 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);
 };
--- 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
+}
--- 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::Property Property>
+	ldraw::PropertyType<Property> getObjectProperty(const ldraw::id_t id) const;
 	std::vector<gl::Polygon> 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<T> id) const
 {
 	return static_cast<const T*>(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::Property Property>
+ldraw::PropertyType<Property> Model::getObjectProperty(const ldraw::id_t id) const
+{
+	const ldraw::Object* const object = this->objectAt(id);
+	ldraw::PropertyType<Property> result;
+	if (object != nullptr)
+	{
+		result = object->getProperty<Property>()
+	}
+	return result;
 }
\ No newline at end of file

mercurial