Saving works now

Tue, 28 Sep 2021 00:10:29 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Tue, 28 Sep 2021 00:10:29 +0300
changeset 141
185eb297dc1e
parent 140
2f383e88acf4
child 142
e085f36e4d9f

Saving works now

src/document.cpp file | annotate | diff | comparison | revisions
src/document.h file | annotate | diff | comparison | revisions
src/linetypes/comment.cpp file | annotate | diff | comparison | revisions
src/linetypes/comment.h file | annotate | diff | comparison | revisions
src/linetypes/conditionaledge.cpp file | annotate | diff | comparison | revisions
src/linetypes/conditionaledge.h file | annotate | diff | comparison | revisions
src/linetypes/edge.cpp file | annotate | diff | comparison | revisions
src/linetypes/edge.h file | annotate | diff | comparison | revisions
src/linetypes/errorline.cpp file | annotate | diff | comparison | revisions
src/linetypes/errorline.h file | annotate | diff | comparison | revisions
src/linetypes/metacommand.cpp file | annotate | diff | comparison | revisions
src/linetypes/metacommand.h file | annotate | diff | comparison | revisions
src/linetypes/object.cpp file | annotate | diff | comparison | revisions
src/linetypes/object.h file | annotate | diff | comparison | revisions
src/linetypes/quadrilateral.cpp file | annotate | diff | comparison | revisions
src/linetypes/quadrilateral.h file | annotate | diff | comparison | revisions
src/linetypes/subfilereference.cpp file | annotate | diff | comparison | revisions
src/linetypes/subfilereference.h file | annotate | diff | comparison | revisions
src/linetypes/triangle.cpp file | annotate | diff | comparison | revisions
src/linetypes/triangle.h file | annotate | diff | comparison | revisions
src/main.h file | annotate | diff | comparison | revisions
src/mainwindow.cpp file | annotate | diff | comparison | revisions
src/mainwindow.h file | annotate | diff | comparison | revisions
src/mainwindow.ui 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
src/utility.h file | annotate | diff | comparison | revisions
--- a/src/document.cpp	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/document.cpp	Tue Sep 28 00:10:29 2021 +0300
@@ -239,3 +239,33 @@
 {
 	this->renderer->adjustGridToView();
 }
+
+/**
+ * @brief Attempts to save the document
+ * @param errors Where to report any errors that might occurr
+ * @return whether or not it succeeded
+ */
+bool Document::save(QTextStream& errors)
+{
+	this->model->makeUnofficial();
+	return this->model->save(errors);
+}
+
+/**
+ * @brief Gets the current path
+ * @return string
+ */
+const QString &Document::modelPath() const
+{
+	return this->model->path();
+}
+
+/**
+ * @brief Sets the path of the model
+ * @param newPath
+ */
+void Document::setModelPath(const QString &newPath)
+{
+	this->model->setPath(newPath);
+}
+
--- a/src/document.h	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/document.h	Tue Sep 28 00:10:29 2021 +0300
@@ -48,6 +48,9 @@
 	void applyToVertices(VertexMap::ApplyFunction fn) const;
 	void handleKeyPress(QKeyEvent* event);
 	void adjustGridToView();
+	bool save(QTextStream &errors);
+	const QString& modelPath() const;
+	void setModelPath(const QString& newPath);
 Q_SIGNALS:
 	void newStatusText(const QString& newStatusText);
 	void splitterChanged();
--- a/src/linetypes/comment.cpp	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/linetypes/comment.cpp	Tue Sep 28 00:10:29 2021 +0300
@@ -13,3 +13,8 @@
 	return Type::Comment;
 }
 
+QString ldraw::Comment::toLDrawCode() const
+{
+	return ("0 // " + this->storedText).trimmed();
+}
+
--- a/src/linetypes/comment.h	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/linetypes/comment.h	Tue Sep 28 00:10:29 2021 +0300
@@ -12,4 +12,5 @@
 	using MetaCommand::MetaCommand;
 	QFont textRepresentationFont() const override;
 	Type typeIdentifier() const override;
+	QString toLDrawCode() const override;
 };
--- a/src/linetypes/conditionaledge.cpp	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/linetypes/conditionaledge.cpp	Tue Sep 28 00:10:29 2021 +0300
@@ -13,3 +13,14 @@
 {
 	return Type::ConditionalEdge;
 }
+
+QString ldraw::ConditionalEdge::toLDrawCode() const
+{
+	return utility::format(
+		"5 %1 %2 %3 %4 %5",
+		this->colorIndex.index,
+		utility::vertexToString(this->points[0]),
+		utility::vertexToString(this->points[1]),
+		utility::vertexToString(this->points[2]),
+		utility::vertexToString(this->points[3]));
+}
--- a/src/linetypes/conditionaledge.h	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/linetypes/conditionaledge.h	Tue Sep 28 00:10:29 2021 +0300
@@ -12,4 +12,5 @@
 	using PolygonObject<4>::PolygonObject;
 	QString textRepresentation() const override;
 	Type typeIdentifier() const override;
+	QString toLDrawCode() const override;
 };
--- a/src/linetypes/edge.cpp	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/linetypes/edge.cpp	Tue Sep 28 00:10:29 2021 +0300
@@ -20,3 +20,12 @@
 {
 	return Type::EdgeLine;
 }
+
+QString ldraw::Edge::toLDrawCode() const
+{
+	return utility::format(
+		"2 %1 %2 %3",
+		this->colorIndex.index,
+		utility::vertexToString(this->points[0]),
+		utility::vertexToString(this->points[1]));
+}
--- a/src/linetypes/edge.h	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/linetypes/edge.h	Tue Sep 28 00:10:29 2021 +0300
@@ -13,4 +13,5 @@
 	QString textRepresentation() const override;
 	void getPolygons(std::vector<gl::Polygon>& polygons, GetPolygonsContext* context) const override;
 	Type typeIdentifier() const override;
+	QString toLDrawCode() const override;
 };
--- a/src/linetypes/errorline.cpp	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/linetypes/errorline.cpp	Tue Sep 28 00:10:29 2021 +0300
@@ -56,3 +56,8 @@
 {
 	return ldraw::Object::deserialize(stream) >> this->text;
 }
+
+QString ldraw::ErrorLine::toLDrawCode() const
+{
+	return this->text;
+}
--- a/src/linetypes/errorline.h	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/linetypes/errorline.h	Tue Sep 28 00:10:29 2021 +0300
@@ -18,6 +18,7 @@
 	Type typeIdentifier() const override;
 	QDataStream& serialize(QDataStream& stream) const override;
 	QDataStream& deserialize(QDataStream& stream) override;
+	QString toLDrawCode() const override;
 	QString text;
 	QString message;
 protected:
--- a/src/linetypes/metacommand.cpp	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/linetypes/metacommand.cpp	Tue Sep 28 00:10:29 2021 +0300
@@ -51,3 +51,8 @@
 	return ldraw::Object::deserialize(stream) >> this->storedText;
 }
 
+QString ldraw::MetaCommand::toLDrawCode() const
+{
+	return "0 " + this->storedText;
+}
+
--- a/src/linetypes/metacommand.h	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/linetypes/metacommand.h	Tue Sep 28 00:10:29 2021 +0300
@@ -17,6 +17,7 @@
 	Type typeIdentifier() const override;
 	QDataStream& serialize(QDataStream& stream) const override;
 	QDataStream& deserialize(QDataStream& stream) override;
+	QString toLDrawCode() const override;
 protected:
 	void setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) override;
 };
--- a/src/linetypes/object.cpp	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/linetypes/object.cpp	Tue Sep 28 00:10:29 2021 +0300
@@ -151,3 +151,8 @@
 {
 	return Type::Empty;
 }
+
+QString ldraw::Empty::toLDrawCode() const
+{
+	return "";
+}
--- a/src/linetypes/object.h	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/linetypes/object.h	Tue Sep 28 00:10:29 2021 +0300
@@ -62,6 +62,8 @@
 	virtual bool hasColor() const;
 	virtual QVariant getProperty(Property id) const;
 	template<ldraw::Property property>
+	PropertyType<property> getProperty() const;
+	template<ldraw::Property property>
 	SetPropertyResult setProperty(const PropertyType<property>& value);
 	SetPropertyResult setProperty(const PropertyKeyValue& pair);
 	virtual QString textRepresentation() const = 0;
@@ -75,6 +77,7 @@
 	virtual QDataStream& serialize(QDataStream& stream) const;
 	virtual QDataStream& deserialize(QDataStream& stream);
 	virtual Type typeIdentifier() const = 0;
+	virtual QString toLDrawCode() const = 0;
 
 protected:
 	template<Property property, typename Function>
@@ -100,6 +103,12 @@
 	}
 }
 
+template<ldraw::Property property>
+ldraw::PropertyType<property> ldraw::Object::getProperty() const
+{
+	return this->getProperty(property).value<ldraw::PropertyType<property>>();
+}
+
 class ldraw::ColoredObject : public Object
 {
 public:
@@ -120,4 +129,5 @@
 {
 	QString textRepresentation() const override;
 	Type typeIdentifier() const override;
+	QString toLDrawCode() const override;
 };
--- a/src/linetypes/quadrilateral.cpp	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/linetypes/quadrilateral.cpp	Tue Sep 28 00:10:29 2021 +0300
@@ -34,3 +34,14 @@
 {
 	return Type::Quadrilateral;
 }
+
+QString ldraw::Quadrilateral::toLDrawCode() const
+{
+	return utility::format(
+		"4 %1 %2 %3 %4 %5",
+		this->colorIndex.index,
+		utility::vertexToString(this->points[0]),
+		utility::vertexToString(this->points[1]),
+		utility::vertexToString(this->points[2]),
+		utility::vertexToString(this->points[3]));
+}
--- a/src/linetypes/quadrilateral.h	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/linetypes/quadrilateral.h	Tue Sep 28 00:10:29 2021 +0300
@@ -14,4 +14,5 @@
 	void getPolygons(std::vector<gl::Polygon>& polygons, GetPolygonsContext* context) const override;
 	void invert() override;
 	Type typeIdentifier() const override;
+	QString toLDrawCode() const override;
 };
--- a/src/linetypes/subfilereference.cpp	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/linetypes/subfilereference.cpp	Tue Sep 28 00:10:29 2021 +0300
@@ -36,13 +36,7 @@
 
 QString ldraw::SubfileReference::textRepresentation() const
 {
-	QString out;
-	if (this->isInverted)
-	{
-		out += "0 BFC INVERTNEXT\r\n";
-	}
-	out += referenceName + " " + utility::vertexToStringParens(this->position());
-	return out;
+	return this->referenceName + " " + utility::vertexToStringParens(this->position());
 }
 
 void ldraw::SubfileReference::getPolygons
@@ -108,3 +102,29 @@
 {
 	return ColoredObject::deserialize(stream) >> this->transformation >> this->referenceName >> this->isInverted;
 }
+
+QString ldraw::SubfileReference::toLDrawCode() const
+{
+	QString result;
+	if (this->isInverted)
+	{
+		result += "0 BFC INVERTNEXT\r\n";
+	}
+	result += utility::format(
+		"1 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14",
+		this->colorIndex.index,
+		this->transformation[3][0],
+		this->transformation[3][1],
+		this->transformation[3][2],
+		this->transformation[0][0],
+		this->transformation[1][0],
+		this->transformation[2][0],
+		this->transformation[0][1],
+		this->transformation[1][1],
+		this->transformation[2][1],
+		this->transformation[0][2],
+		this->transformation[1][2],
+		this->transformation[2][2],
+		this->referenceName);
+	return result;
+}
--- a/src/linetypes/subfilereference.h	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/linetypes/subfilereference.h	Tue Sep 28 00:10:29 2021 +0300
@@ -25,6 +25,7 @@
 	Type typeIdentifier() const override;
 	QDataStream& serialize(QDataStream& stream) const override;
 	QDataStream& deserialize(QDataStream& stream) override;
+	QString toLDrawCode() const override;
 	glm::mat4 transformation;
 	QString referenceName;
 	bool isInverted = false;
--- a/src/linetypes/triangle.cpp	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/linetypes/triangle.cpp	Tue Sep 28 00:10:29 2021 +0300
@@ -32,3 +32,13 @@
 {
 	return Type::Triangle;
 }
+
+QString ldraw::Triangle::toLDrawCode() const
+{
+	return utility::format(
+		"3 %1 %2 %3 %4",
+		this->colorIndex.index,
+		utility::vertexToString(this->points[0]),
+		utility::vertexToString(this->points[1]),
+		utility::vertexToString(this->points[2]));
+}
--- a/src/linetypes/triangle.h	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/linetypes/triangle.h	Tue Sep 28 00:10:29 2021 +0300
@@ -14,5 +14,6 @@
 	void getPolygons(std::vector<gl::Polygon>& polygons, GetPolygonsContext* context) const override;
 	void invert() override;
 	Type typeIdentifier() const override;
+	QString toLDrawCode() const override;
 };
 
--- a/src/main.h	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/main.h	Tue Sep 28 00:10:29 2021 +0300
@@ -74,6 +74,8 @@
 	using edgeid_t = Id<class EdgeLine>;
 	using conditionaledgeid_t = Id<class ConditionalEdge>;
 	using subfileid_t = Id<class SubfileReference>;
+	using commentid_t = Id<class Comment>;
+	using metacommandid_t = Id<class MetaCommand>;
 
 	constexpr struct NullId
 	{
--- a/src/mainwindow.cpp	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/mainwindow.cpp	Tue Sep 28 00:10:29 2021 +0300
@@ -72,6 +72,10 @@
 			this->currentDocument()->adjustGridToView();
 		}
 	});
+	connect(this->ui->actionSave, &QAction::triggered,
+		this, &MainWindow::actionSave);
+	connect(this->ui->actionSaveAs, &QAction::triggered,
+		this, &MainWindow::actionSaveAs);
 	for (auto data : ::renderStyleButtons)
 	{
 		QAction* action = data.memberInstance(this->ui.get());
@@ -252,6 +256,56 @@
 	this->updateRenderPreferences();
 }
 
+/**
+ * @brief Handles the "Save" (Ctrl+S) action
+ */
+void MainWindow::actionSave()
+{
+	if (this->currentDocument() != nullptr)
+	{
+		if (this->currentDocument()->modelPath().isEmpty())
+		{
+			this->actionSaveAs();
+		}
+		else
+		{
+			QString error;
+			QTextStream errorStream{&error};
+			const bool succeeded = this->currentDocument()->save(errorStream);
+			if (not succeeded)
+			{
+				QMessageBox::critical(this, tr("Save error"), error);
+			}
+			else
+			{
+				this->addRecentlyOpenedFile(this->currentDocument()->modelPath());
+			}
+		}
+	}
+}
+
+/**
+ * @brief Handles the "Save as…" (Ctrl+Shift+S) action
+ */
+void MainWindow::actionSaveAs()
+{
+	if (this->currentDocument() != nullptr)
+	{
+		const QString dir = QFileInfo{this->currentDocument()->modelPath()}.absoluteDir().path();
+		const QString newPath = QFileDialog::getSaveFileName(
+			this,
+			tr("Save as…"),
+			dir, 
+			tr("LDraw files (*.ldr *dat);;All files (*)")
+		);
+		if (not newPath.isEmpty())
+		{
+			this->currentDocument()->setModelPath(newPath);
+			this->actionSave();
+		}
+	}
+}
+
 void MainWindow::changeEvent(QEvent* event)
 {
 	if (event != nullptr)
--- a/src/mainwindow.h	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/mainwindow.h	Tue Sep 28 00:10:29 2021 +0300
@@ -44,6 +44,8 @@
 	void updateRecentlyOpenedDocumentsMenu();
 	void openRecentFile();
 	void setRenderStyle(gl::RenderStyle renderStyle);
+	void actionSave();
+	void actionSaveAs();
 protected:
 	void changeEvent(QEvent* event) override;
 	void closeEvent(QCloseEvent* event) override;
--- a/src/mainwindow.ui	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/mainwindow.ui	Tue Sep 28 00:10:29 2021 +0300
@@ -40,6 +40,8 @@
     </widget>
     <addaction name="actionNew"/>
     <addaction name="actionOpen"/>
+    <addaction name="actionSave"/>
+    <addaction name="actionSaveAs"/>
     <addaction name="menuRecentFiles"/>
     <addaction name="separator"/>
     <addaction name="actionSettingsEditor"/>
@@ -127,6 +129,22 @@
     <string>Ctrl+G</string>
    </property>
   </action>
+  <action name="actionSave">
+   <property name="text">
+    <string>Save</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+S</string>
+   </property>
+  </action>
+  <action name="actionSaveAs">
+   <property name="text">
+    <string>Save as…</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+Shift+S</string>
+   </property>
+  </action>
  </widget>
  <resources/>
  <connections/>
--- a/src/model.cpp	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/model.cpp	Tue Sep 28 00:10:29 2021 +0300
@@ -18,6 +18,7 @@
 
 #include <QBrush>
 #include <QFile>
+#include <QFileInfo>
 #include <QFont>
 #include "model.h"
 #include "modeleditcontext.h"
@@ -36,7 +37,7 @@
  */
 Model::Model(const QString& path, QObject *parent) :
 	QAbstractListModel{parent},
-	path{path}
+	storedPath{path}
 {
 	connect(this, &Model::dataChanged, [&](){ this->needRecache = true; });
 }
@@ -187,6 +188,39 @@
 }
 
 /**
+ * @brief Gets the path to the model
+ * @return path
+ */
+const QString& Model::path() const
+{
+	return this->storedPath;
+}
+
+/**
+ * @brief Sets the path to the model
+ * @param path New path to use
+ */
+void Model::setPath(const QString &path)
+{
+	this->storedPath = path;
+	this->header.name = QFileInfo{path}.fileName();
+	// Update the "Name: 1234.dat" comment
+	if (this->body.size() >= 2)
+	{
+		const ldraw::id_t id = this->body[1]->id;
+		if (this->isA<ldraw::MetaCommand>(id))
+		{
+			const QString& textBody = this->body[1]->getProperty<ldraw::Property::Text>();
+			if (textBody.startsWith("Name: "))
+			{
+				auto editor = this->edit();
+				editor.setObjectProperty<ldraw::Property::Text>(id, "Name: " + this->header.name);
+			}
+		}
+	}
+}
+
+/**
  * @brief Gets the GL polygons of the object at the specified position in the model
  * @param index Index of object in the model
  * @param polygons_out Vector to add polygons into
@@ -270,16 +304,60 @@
 /**
  * @brief Write out the model as text
  */
-void Model::save() const
+bool Model::save(QTextStream &errors) const
 {
-	QFile file{this->path};
+	QFile file{this->storedPath};
 	if (file.open(QIODevice::WriteOnly))
 	{
 		QTextStream out{&file};
 		for (const ModelObjectPointer& object : this->body)
 		{
-			out << object.get()->textRepresentation() << "\r\n";
+			out << object.get()->toLDrawCode() << "\r\n";
 		}
 		file.close();
+		if (out.status() != QTextStream::Ok)
+		{
+			errors << tr("Write error while writing to %1").arg(this->storedPath);
+			return false;
+		}
+		else
+		{
+			return true;
+		}
+	}
+	else
+	{
+		errors << tr("Could not open %1 for writing: %2")
+			.arg(this->storedPath)
+			.arg(file.errorString());
+		return false;
+	}
+}
+
+/**
+ * @brief Modifies the !LDRAW_ORG line so that it becomes unofficial
+ */
+void Model::makeUnofficial()
+{
+	if (this->body.size() >= 4)
+	{
+		const ldraw::id_t id = this->body[3]->id;
+		if (this->isA<ldraw::MetaCommand>(id))
+		{
+			const QString& body = this->body[3]->getProperty<ldraw::Property::Text>();
+			if (body.startsWith("!LDRAW_ORG ") and not body.startsWith("!LDRAW_ORG Unofficial_"))
+			{
+				QStringList tokens = body.split(" ");
+				tokens[1] = "Unofficial_" + tokens[1];
+				// Remove the UPDATE tag
+				if (tokens.size() >= 4 && tokens[2] == "UPDATE")
+				{
+					tokens.removeAt(3);
+					tokens.removeAt(2);
+				}
+				EditContext editor = this->edit();
+				editor.setObjectProperty<ldraw::Property::Text>(id, tokens.join(" "));
+			}
+		}
 	}
 }
\ No newline at end of file
--- a/src/model.h	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/model.h	Tue Sep 28 00:10:29 2021 +0300
@@ -22,6 +22,7 @@
 #include "main.h"
 #include "header.h"
 #include "linetypes/object.h"
+#include "linetypes/metacommand.h"
 #include "gl/common.h"
 
 enum class HeaderProperty
@@ -51,6 +52,8 @@
 	template<typename R>
 	ldraw::Id<R> checkType(ldraw::id_t id) const;
 	template<typename R>
+	bool isA(ldraw::id_t id) const;
+	template<typename R>
 	const R* get(ldraw::Id<R> id) const;
 	template<typename R>
 	struct Get2Result
@@ -62,7 +65,10 @@
 	Get2Result<R> get2(ldraw::Id<R> id) const;
 	template<typename R, typename Fn>
 	void apply(Fn f) const;
-	void save() const;
+	const QString& path() const;
+	void setPath(const QString& path);
+	bool save(QTextStream& errors) const;
+	void makeUnofficial();
 Q_SIGNALS:
 	void objectAdded(ldraw::id_t id, int position);
 	void objectModified(ldraw::id_t id, int position);
@@ -87,7 +93,7 @@
 	void editFinished();
 	void objectModified(ldraw::id_t id);
 	bool modified = false;
-	QString path;
+	QString storedPath;
 	LDHeader header;
 	std::vector<ModelObjectPointer> body;
 	std::map<ldraw::id_t, ldraw::Object*> objectsById;
@@ -100,6 +106,21 @@
 };
 
 /**
+ * @brief Checks whether the id is exactly of the specified type
+ * @tparam R Type of LDraw line type object to test for
+ * @param id Id of object to test
+ * @returns whether the type of the object specified by @c id is the same type as R. Returns false if it is a subclass.
+ */
+template<typename R>
+bool Model::isA(ldraw::id_t id) const
+{
+	const ldraw::Object* object = this->objectAt(this->lookup(id));
+	const std::type_info& a = typeid(*object);
+	const std::type_info& b = typeid(R);
+	return a == b;
+}
+
+/**
  * @brief Calls the specified function to all matching objects in the model
  * @tparam R Type of LDraw line type object to filter by
  * @param fn Function to call.
--- a/src/parser.cpp	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/parser.cpp	Tue Sep 28 00:10:29 2021 +0300
@@ -253,6 +253,7 @@
 		}
 		invertNext = false;
 	}
+	/*
 	// Test quadrilateral splitting by splitting all the quadrilaterals
 	QVector<ldraw::quadrilateralid_t> quadrilateral_ids;
 	for (int i = 0; i < editor.model().size(); i += 1)
@@ -268,6 +269,7 @@
 	{
 		ldraw::splitQuadrilateral(editor, id);
 	}
+	*/
 }
 
 static ldraw::Color colorFromString(const QString& colorString)
@@ -344,11 +346,12 @@
 	Q_UNUSED(tokens)
 	if (line.startsWith("0 //"))
 	{
-		return std::make_unique<ldraw::Comment>(line.mid(std::strlen("0 //")).simplified());
+		// lol wut
+		return std::make_unique<ldraw::Comment>(line.mid(std::strlen("0 //")).trimmed());
 	}
 	else
 	{
-		return std::make_unique<ldraw::MetaCommand>(line.mid(1).simplified());
+		return std::make_unique<ldraw::MetaCommand>(line.mid(1).trimmed());
 	}
 }
 
@@ -394,7 +397,7 @@
 
 std::unique_ptr<ldraw::Object> Parser::parseFromString(QString line)
 {
-	line = line.simplified();
+	line = line.trimmed();
 	try
 	{
 		const QStringList tokens = line.split(QRegExp{R"(\s+)"});
--- a/src/utility.h	Mon Sep 27 21:04:45 2021 +0300
+++ b/src/utility.h	Tue Sep 28 00:10:29 2021 +0300
@@ -71,6 +71,16 @@
 		return std::find(std::begin(container), std::end(container), value) != std::end(container);
 	}
 
+	/**
+	 * @brief Converts the specified vertex to a simple string
+	 * @param vertex vertex to convert
+	 * @return "x y z"-formatted string
+	 */
+	inline QString vertexToString(const glm::vec3& vertex)
+	{
+		return utility::format("%1 %2 %3", vertex.x, vertex.y, vertex.z);
+	}
+
 	inline QString vertexToStringParens(const glm::vec3& vertex)
 	{
 		return utility::format("(%1, %2, %3)", vertex.x, vertex.y, vertex.z);

mercurial