added dependency loading

Sun, 03 Nov 2019 17:57:21 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Sun, 03 Nov 2019 17:57:21 +0200
changeset 12
fe67489523b5
parent 11
771168ee2c76
child 13
6e838748867b

added dependency loading

locale/fi.ts file | annotate | diff | comparison | revisions
locale/sv.ts file | annotate | diff | comparison | revisions
src/documentmanager.cpp file | annotate | diff | comparison | revisions
src/documentmanager.h file | annotate | diff | comparison | revisions
src/libraries.cpp file | annotate | diff | comparison | revisions
src/libraries.h file | annotate | diff | comparison | revisions
src/mainwindow.cpp file | annotate | diff | comparison | revisions
src/model.cpp file | annotate | diff | comparison | revisions
src/model.h file | annotate | diff | comparison | revisions
src/parser.cpp file | annotate | diff | comparison | revisions
--- a/locale/fi.ts	Sun Nov 03 13:18:55 2019 +0200
+++ b/locale/fi.ts	Sun Nov 03 17:57:21 2019 +0200
@@ -1,9 +1,10 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE TS>
-<TS version="2.1" language="fi">
+<TS version="2.1">
 <context>
     <name>Document</name>
     <message>
+        <location filename="../src/document.ui" line="14"/>
         <source>Form</source>
         <translation type="unfinished"></translation>
     </message>
@@ -11,50 +12,62 @@
 <context>
     <name>LibrariesEditor</name>
     <message>
+        <location filename="../src/settingseditor/librarieseditor.ui" line="14"/>
         <source>Form</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/settingseditor/librarieseditor.ui" line="25"/>
         <source>…</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/settingseditor/librarieseditor.ui" line="32"/>
         <source>Add</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/settingseditor/librarieseditor.cpp" line="39"/>
         <source>Browse LDraw library</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/settingseditor/librarieseditor.cpp" line="52"/>
         <source>Library does not exist</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/settingseditor/librarieseditor.cpp" line="54"/>
         <source>The directory %1 does not exist.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/settingseditor/librarieseditor.cpp" line="62"/>
         <source>Unreadable library</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/settingseditor/librarieseditor.cpp" line="64"/>
         <source>The directory %1 cannot be read.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/settingseditor/librarieseditor.cpp" line="78"/>
         <source>Remove library</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/settingseditor/librarieseditor.cpp" line="84"/>
         <source>Set role</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/settingseditor/librarieseditor.cpp" line="96"/>
         <source>Move up</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/settingseditor/librarieseditor.cpp" line="102"/>
         <source>Move down</source>
         <translation type="unfinished"></translation>
     </message>
@@ -62,22 +75,27 @@
 <context>
     <name>LibraryManager</name>
     <message>
+        <location filename="../src/libraries.cpp" line="210"/>
         <source>Official library</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/libraries.cpp" line="212"/>
         <source>Unofficial library</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/libraries.cpp" line="214"/>
         <source>Working library</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/libraries.cpp" line="274"/>
         <source>Path</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/libraries.cpp" line="276"/>
         <source>Role</source>
         <translation type="unfinished"></translation>
     </message>
@@ -85,85 +103,106 @@
 <context>
     <name>MainWindow</name>
     <message>
-        <source>File</source>
-        <translation>Tiedosto</translation>
-    </message>
-    <message>
-        <source>Quit</source>
-        <translation>Poistu</translation>
-    </message>
-    <message>
-        <source>Open…</source>
-        <translation>Avaa...</translation>
-    </message>
-    <message>
-        <source>Ctrl+O</source>
-        <translation>Ctrl+O</translation>
-    </message>
-    <message>
-        <source>New</source>
-        <translation>Uusi</translation>
-    </message>
-    <message>
-        <source>Ctrl+N</source>
-        <translation>Ctrl+N</translation>
-    </message>
-    <message>
-        <source>Language</source>
-        <translation type="vanished">Kieli</translation>
-    </message>
-    <message>
-        <source>Open model</source>
-        <translation type="unfinished">Avaa malli</translation>
-    </message>
-    <message>
-        <source>LDraw models (*.ldr *.dat)</source>
-        <translation>LDraw-mallit (*.ldr *.dat)</translation>
-    </message>
-    <message>
-        <source>Problem opening file</source>
-        <translation>Ongelma tiedoston avaamisessa</translation>
-    </message>
-    <message>
-        <source>Could not open %1: %2</source>
-        <translation>Ei voitu avata %1: %2</translation>
-    </message>
-    <message>
+        <location filename="../src/mainwindow.ui" line="14"/>
         <source>LDForge</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/mainwindow.ui" line="34"/>
+        <source>File</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/mainwindow.ui" line="38"/>
         <source>Recent files</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/mainwindow.ui" line="54"/>
+        <source>Quit</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/mainwindow.ui" line="59"/>
+        <source>Open…</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/mainwindow.ui" line="62"/>
+        <source>Ctrl+O</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/mainwindow.ui" line="67"/>
+        <source>New</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/mainwindow.ui" line="70"/>
+        <source>Ctrl+N</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/mainwindow.ui" line="75"/>
         <source>Preferences…</source>
         <translation type="unfinished"></translation>
     </message>
+    <message>
+        <location filename="../src/mainwindow.cpp" line="42"/>
+        <source>Open model</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/mainwindow.cpp" line="44"/>
+        <source>LDraw models (*.ldr *.dat)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/mainwindow.cpp" line="63"/>
+        <source>Problem loading references</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/mainwindow.cpp" line="73"/>
+        <source>Problem opening file</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/mainwindow.cpp" line="75"/>
+        <source>Could not open %1: %2</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>SettingsEditor</name>
     <message>
+        <location filename="../src/settingseditor/settingseditor.ui" line="14"/>
         <source>Dialog</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/settingseditor/settingseditor.ui" line="24"/>
         <source>General</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/settingseditor/settingseditor.ui" line="30"/>
         <source>Language:</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/settingseditor/settingseditor.ui" line="38"/>
+        <location filename="../src/settingseditor/settingseditor.cpp" line="47"/>
         <source>System language</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/settingseditor/settingseditor.ui" line="43"/>
         <source>English</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../src/settingseditor/settingseditor.ui" line="52"/>
         <source>LDraw parts libraries</source>
         <translation type="unfinished"></translation>
     </message>
--- a/locale/sv.ts	Sun Nov 03 13:18:55 2019 +0200
+++ b/locale/sv.ts	Sun Nov 03 17:57:21 2019 +0200
@@ -193,6 +193,10 @@
         <source>Recent files</source>
         <translation type="unfinished"></translation>
     </message>
+    <message>
+        <source>Problem loading references</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>SettingsEditor</name>
--- a/src/documentmanager.cpp	Sun Nov 03 13:18:55 2019 +0200
+++ b/src/documentmanager.cpp	Sun Nov 03 17:57:21 2019 +0200
@@ -94,3 +94,72 @@
 	untitledNameCounter += 1;
 	return "untitled-" + QString::number(untitledNameCounter);
 }
+
+void DocumentManager::loadDependenciesForModel(
+	const QString& modelName,
+	const LibraryManager& libraries,
+	QTextStream& errorStream)
+{
+	QStringList missing;
+	QStringList processed;
+	loadDependenciesForModel(modelName, libraries, missing, processed, errorStream);
+	if (not missing.empty())
+	{
+		missing.sort(Qt::CaseInsensitive);
+		errorStream << utility::format(
+			"The following files could not be opened: %1",
+			missing.join(", "));
+	}
+}
+
+void DocumentManager::loadDependenciesForModel(
+	const QString& modelName,
+	const LibraryManager& libraries,
+	QStringList& missing,
+	QStringList& processed,
+	QTextStream& errorStream)
+{
+	struct LoadingError
+	{
+		QString message;
+	};
+	processed.append(modelName);
+	Model* model = this->findModelByName(modelName);
+	for (int i = 0; i < model->size(); i += 1)
+	{
+		const QString referenceName = model->getObjectProperty(i, modelobjects::Property::ReferenceName).toString();
+		if (not referenceName.isEmpty()
+			and openModels.find(referenceName) == std::end(openModels)
+			and not missing.contains(referenceName))
+		{
+			try
+			{
+				const QString path = libraries.findFile(referenceName);
+				if (path.isEmpty())
+				{
+					throw LoadingError{utility::format("'%1' was not found.", referenceName)};
+				}
+				QString errorString;
+				QTextStream localErrorStream{&errorString};
+				QString resultName = this->openModel(path, localErrorStream);
+				if (resultName.isEmpty())
+				{
+					throw LoadingError{utility::format(
+						"could not load '%1': %2",
+						path,
+						errorString)};
+				}
+				if (not processed.contains(referenceName))
+				{
+					loadDependenciesForModel(referenceName, libraries, missing, processed, errorStream);
+				}
+			}
+			catch(const LoadingError& error)
+			{
+				errorStream << error.message << "\n";
+				missing.append(referenceName);
+				processed.append(referenceName);
+			}
+		}
+	}
+}
--- a/src/documentmanager.h	Sun Nov 03 13:18:55 2019 +0200
+++ b/src/documentmanager.h	Sun Nov 03 17:57:21 2019 +0200
@@ -1,5 +1,5 @@
 #pragma once
-#include "main.h"
+#include "libraries.h"
 #include "model.h"
 
 class DocumentManager : public QObject
@@ -16,7 +16,15 @@
 	Model* findModelByName(const QString& name);
 	QString openModel(const QString& path, QTextStream& errorStream);
 	QString makeNewModelName();
+	void loadDependenciesForModel(const QString& modelName,
+		const LibraryManager& libraries,
+		QTextStream& errorStream);
 private:
 	int untitledNameCounter = 0;
 	std::map<QString, ModelPointer> openModels;
+	void loadDependenciesForModel(const QString& modelName,
+		const LibraryManager& libraries,
+		QStringList& missing,
+		QStringList& processed,
+		QTextStream& errorStream);
 };
--- a/src/libraries.cpp	Sun Nov 03 13:18:55 2019 +0200
+++ b/src/libraries.cpp	Sun Nov 03 17:57:21 2019 +0200
@@ -44,22 +44,30 @@
  * @param fileName File to search for
  * @return Full path to the file, or empty string if not found.
  */
-QFileInfo LibraryManager::findFile(QString fileName) const
+QString LibraryManager::findFile(QString fileName) const
 {
-	QFileInfo path;
+	QString path;
 	fileName.replace("\\", "/");
 	bool found = false;
 	for (const Library& library : this->libraries)
 	{
-		path = library.path.absoluteFilePath(fileName);
-		if (path.exists() && path.isFile())
+		for (const QString& subdirectory : {"parts", "p"})
 		{
-			found = true;
+			QDir directory = library.path;
+			directory.cd(subdirectory);
+			QFileInfo fileInfo = directory.absoluteFilePath(fileName);
+			if (fileInfo.exists() && fileInfo.isFile())
+			{
+				path = fileInfo.absoluteFilePath();
+				found = true;
+				break;
+			}
+		}
+		if (found)
+		{
 			break;
 		}
 	}
-	if (not found)
-		path = {};
 	return path;
 }
 
--- a/src/libraries.h	Sun Nov 03 13:18:55 2019 +0200
+++ b/src/libraries.h	Sun Nov 03 17:57:21 2019 +0200
@@ -35,7 +35,7 @@
 	LibraryManager(QSettings* settings, QObject* parent = nullptr);
 	QVector<Library>::const_iterator begin() const;
 	QVector<Library>::const_iterator end() const;
-	QFileInfo findFile(QString fileName) const;
+	QString findFile(QString fileName) const;
 	void addLibrary(const Library& library);
 	void removeLibrary(const int libraryIndex);
 	const Library& library(int libraryIndex) const;
--- a/src/mainwindow.cpp	Sun Nov 03 13:18:55 2019 +0200
+++ b/src/mainwindow.cpp	Sun Nov 03 17:57:21 2019 +0200
@@ -55,6 +55,14 @@
 	QString modelName = this->documents.openModel(path, errorStream);
 	if (not modelName.isEmpty())
 	{
+		this->documents.loadDependenciesForModel(modelName, this->libraries, errorStream);
+		if (not errorString.isEmpty())
+		{
+			QMessageBox::warning(
+				this,
+				tr("Problem loading references"),
+				errorString);
+		}
 		this->openModelForEditing(modelName);
 		this->addRecentlyOpenedFile(path);
 	}
--- a/src/model.cpp	Sun Nov 03 13:18:55 2019 +0200
+++ b/src/model.cpp	Sun Nov 03 17:57:21 2019 +0200
@@ -53,6 +53,12 @@
 	}
 }
 
+QVariant Model::getObjectProperty(const int index, const modelobjects::Property property) const
+{
+	const modelobjects::BaseObject* object = this->body[index].get();
+	return object->getProperty(property);
+}
+
 void Model::append(ModelObjectPointer&& object)
 {
 	this->body.push_back(std::move(object));
--- a/src/model.h	Sun Nov 03 13:18:55 2019 +0200
+++ b/src/model.h	Sun Nov 03 17:57:21 2019 +0200
@@ -23,6 +23,7 @@
 	QVariant data(const QModelIndex& index, int role) const override;
 	QVariant getHeaderProperty(const HeaderProperty property);
 	const QString& getName() const;
+	QVariant getObjectProperty(const int index, const modelobjects::Property property) const;
 signals:
 	void objectAdded(modelobjects::Id id, int position);
 private:
--- a/src/parser.cpp	Sun Nov 03 13:18:55 2019 +0200
+++ b/src/parser.cpp	Sun Nov 03 17:57:21 2019 +0200
@@ -380,7 +380,7 @@
 	try
 	{
 		const QStringList tokens = line.split(QRegExp{R"(\s+)"});
-		if (tokens.empty())
+		if (tokens.empty() or tokens == QStringList{{""}})
 		{
 			return std::make_unique<modelobjects::Empty>();
 		}

mercurial