- Made it build under Qt6

Sun, 26 Jun 2022 19:44:45 +0300

author
Teemu Piippo <teemu.s.piippo@gmail.com>
date
Sun, 26 Jun 2022 19:44:45 +0300
changeset 259
c27612f0eac0
parent 258
fe094d0687ad
child 260
48c66a4b1fe5

- Made it build under Qt6
- Fix strangeness involving library path settings

CMakeLists.txt file | annotate | diff | comparison | revisions
src/basics.h file | annotate | diff | comparison | revisions
src/colors.cpp file | annotate | diff | comparison | revisions
src/documentmanager.cpp file | annotate | diff | comparison | revisions
src/functional.h file | annotate | diff | comparison | revisions
src/gl/axesprogram.cpp file | annotate | diff | comparison | revisions
src/gl/basicshaderprogram.cpp file | annotate | diff | comparison | revisions
src/gl/basicshaderprogram.h file | annotate | diff | comparison | revisions
src/gl/common.h file | annotate | diff | comparison | revisions
src/gl/compiler.cpp file | annotate | diff | comparison | revisions
src/gl/compiler.h file | annotate | diff | comparison | revisions
src/gl/partrenderer.cpp file | annotate | diff | comparison | revisions
src/libraries.cpp file | annotate | diff | comparison | revisions
src/libraries.h file | annotate | diff | comparison | revisions
src/main.cpp file | annotate | diff | comparison | revisions
src/mainwindow.h file | annotate | diff | comparison | revisions
src/model.h file | annotate | diff | comparison | revisions
src/parser.cpp file | annotate | diff | comparison | revisions
src/settings.h file | annotate | diff | comparison | revisions
src/settingseditor/keyboardshortcutseditor.cpp file | annotate | diff | comparison | revisions
src/settingseditor/keyboardshortcutseditor.h file | annotate | diff | comparison | revisions
src/settingseditor/librarieseditor.cpp file | annotate | diff | comparison | revisions
src/settingseditor/librarieseditor.h file | annotate | diff | comparison | revisions
src/settingseditor/settingseditor.cpp file | annotate | diff | comparison | revisions
src/settingseditor/settingseditor.h file | annotate | diff | comparison | revisions
src/uiutilities.cpp file | annotate | diff | comparison | revisions
src/uiutilities.h file | annotate | diff | comparison | revisions
src/vertexmap.cpp file | annotate | diff | comparison | revisions
src/vertexmap.h file | annotate | diff | comparison | revisions
widgets/CMakeLists.txt file | annotate | diff | comparison | revisions
widgets/doublespinbox.cpp file | annotate | diff | comparison | revisions
--- a/CMakeLists.txt	Wed Jun 22 23:51:06 2022 +0300
+++ b/CMakeLists.txt	Sun Jun 26 19:44:45 2022 +0300
@@ -1,22 +1,25 @@
 project(ldforge)
 cmake_minimum_required(VERSION 2.8.12)
 set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMake")
-#include(cotire)
 set(OpenGL_GL_PREFERENCE GLVND)
-find_package(Qt5Widgets REQUIRED)
-if (Qt5Widgets_VERSION VERSION_LESS 5.5.0)
-	message(FATAL_ERROR "Qt5 version 5.5 required")
+find_package(Qt6 COMPONENTS Core Widgets OpenGL UiPlugin OpenGLWidgets)
+if (Qt6_FOUND)
+	message(NOTICE "-- Using Qt6")
+	find_package(Qt6 REQUIRED COMPONENTS Core5Compat)
+	# Unfortunately "Qt::UiPlugin" doesn't seem to work so let's resolve
+	# it here instead...
+	add_library(QtUiPlugin ALIAS Qt6::UiPlugin)
+else()
+	message(NOTICE "-- Qt6 not found, using Qt5 instead")
+	find_package(Qt5 5.5 REQUIRED COMPONENTS Core Widgets OpenGL UiPlugin)
+	add_library(QtUiPlugin ALIAS Qt5::UiPlugin)
 endif()
-find_package(Qt5Core REQUIRED)
-find_package(Qt5OpenGL REQUIRED)
-find_package(Qt5Network REQUIRED)
-#find_package(Qt5LinguistTools REQUIRED)
+find_package(OpenGL REQUIRED)
 find_package(GLM REQUIRED)
 set(CMAKE_AUTOMOC ON)
 set(CMAKE_AUTOUIC ON)
 set(CMAKE_AUTORCC ON)
-find_package(OpenGL REQUIRED)
-include_directories(${QT_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR})
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
 include_directories(${GLM_INCLUDE_DIR})
 add_definitions(-DQT_NO_KEYWORDS)
 source_group("LDForge" REGULAR_EXPRESSION "src/.+\\.(cpp|h|ui)")
@@ -120,10 +123,6 @@
 include_directories("${PROJECT_BINARY_DIR}/src")
 include_directories("${PROJECT_SOURCE_DIR}")
 include_directories("${PROJECT_SOURCE_DIR}/src")
-
-# Translations
-#qt5_create_translation(QM_FILES ${LDFORGE_SOURCES} ${LDFORGE_HEADERS} ${LDFORGE_FORMS} ${LDFORGE_LOCALES})
-#add_custom_target(translations ALL DEPENDS ${QM_FILES})
 add_custom_target(resources ALL DEPENDS ${LDFORGE_RESOURCES})
 
 if (NOT MSVC)
@@ -133,9 +132,9 @@
 	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -Wunused")
 	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-implicit-fallthrough")
 	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-noexcept-type")
-	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat-nonliteral -Wnonnull -Wnonnull-compare -Wnull-dereference -Winfinite-recursion -Wunused-const-variable=1 -Wuninitialized -Wsuggest-attribute=noreturn -Wmissing-noreturn -Wsuggest-attribute=malloc")
-	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wduplicated-branches -Wshadow")
-	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunsafe-loop-optimizations -Wundef -Wmissing-field-initializers")
+	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat-nonliteral -Wnonnull -Wnull-dereference -Winfinite-recursion -Wuninitialized -Wmissing-noreturn")
+	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow")
+	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wundef -Wmissing-field-initializers")
 	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wcast-qual -Wcast-align -Wcast-function-type -Wconversion")
 	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wmissing-declarations -Wdate-time")
 endif()
@@ -145,25 +144,14 @@
 	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-override -Wundefined-func-template -Wundefined-reinterpret-cast")
 	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wuninitialized-const-reference -Wunreachable-code -Wunreachable-code-break -Wunreachable-code-return")
 endif()
-qt5_add_resources(LDFORGE_QRC ${LDFORGE_RESOURCES})
-qt5_wrap_ui(LDFORGE_FORMS_HEADERS ${LDFORGE_FORMS})
-
-# Move languages.qrc into the build directory to bake the .qm-files into LDForge
-# so that they don't have to be shipped separately
-# https://stackoverflow.com/a/34798124
-# https://gist.github.com/giraldeau/546ba5512a74dfe9d8ea0862d66db412
-set(LANGUAGES_QRC "languages.qrc")
-configure_file(${LANGUAGES_QRC} ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)
-qt5_add_resources(LDFORGE_QM_RC_FILE ${CMAKE_CURRENT_BINARY_DIR}/${LANGUAGES_QRC})
-set_source_files_properties(${LDFORGE_LOCALES} PROPERTIES HEADER_FILE_ONLY TRUE)
+qt_add_resources(LDFORGE_QRC ${LDFORGE_RESOURCES})
+qt_wrap_ui(LDFORGE_FORMS_HEADERS ${LDFORGE_FORMS})
 
 add_executable(ldforge WIN32
 	${LDFORGE_SOURCES}
 	${LDFORGE_HEADERS}
 	${LDFORGE_RESOURCES}
 	${LDFORGE_QRC}
-	#${LDFORGE_QM_RC_FILE}
-	${QM_FILES}
 	${LDFORGE_FORMS_HEADERS}
 	${LDFORGE_OTHER_FILES}
 )
@@ -172,10 +160,17 @@
 set_source_files_properties(${LDFORGE_RESOURCES} PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties(${LDFORGE_OTHER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE)
 set_target_properties(ldforge PROPERTIES AUTOMOC 1)
-target_link_libraries(ldforge Qt5::Widgets Qt5::Network Qt5::OpenGL ${OPENGL_LIBRARIES})
-target_link_libraries(ldforge ldforgewidgets)
+target_link_libraries(ldforge PRIVATE Qt::Core)
+target_link_libraries(ldforge PRIVATE Qt::Widgets)
+target_link_libraries(ldforge PRIVATE Qt::OpenGL)
+target_link_libraries(ldforge PRIVATE ${OPENGL_LIBRARIES})
+target_link_libraries(ldforge PRIVATE ${GLEW_LIBRARIES})
+target_link_libraries(ldforge PRIVATE ldforgewidgets)
 add_dependencies(ldforge resources)
-#cotire(ldforge)
+if (Qt6_FOUND)
+	target_link_libraries(ldforge PRIVATE Qt6::Core5Compat)
+	target_link_libraries(ldforge PRIVATE Qt6::OpenGLWidgets)
+endif()
 
 add_custom_target(linelength ALL
 	COMMAND python3
--- a/src/basics.h	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/basics.h	Sun Jun 26 19:44:45 2022 +0300
@@ -35,6 +35,7 @@
 #include <QStringList>
 #include <QVariant>
 #include <QVector>
+#include <QMdiArea>
 #include <glm/glm.hpp>
 #include "geometry.h"
 #include "functional.h"
@@ -43,8 +44,12 @@
 template<typename T>
 using opt = std::optional<T>;
 
+//! \brief Return type of qHash. unsigned int on Qt5, unsigned long on Qt6.
+using hash_t = decltype(qHash(0));
+
 Q_DECLARE_METATYPE(glm::vec3)
 Q_DECLARE_METATYPE(glm::mat4)
+Q_DECLARE_METATYPE(QMdiArea::ViewMode)
 
 //! \brief count the amount of elements in a basic array
 template<typename T, int N>
@@ -265,7 +270,7 @@
 }
 
 template<typename T, glm::qualifier Q>
-constexpr unsigned int qHash(const glm::vec<3, T, Q>& key)
+constexpr auto qHash(const glm::vec<3, T, Q>& key)
 {
 	return qHash(key.x) ^ rotl10(qHash(key.y)) ^ rotl20(qHash(key.z));
 }
--- a/src/colors.cpp	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/colors.cpp	Sun Jun 26 19:44:45 2022 +0300
@@ -1,3 +1,5 @@
+#include <QRegExp>
+#include <QIODevice>
 #include "colors.h"
 
 const ColorDefinition unknownColor{{}, {}, "Unknown", "???"};
--- a/src/documentmanager.cpp	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/documentmanager.cpp	Sun Jun 26 19:44:45 2022 +0300
@@ -117,7 +117,7 @@
 	const OpenType openType
 ) {
 	QFile file{path};
-	const QString name = pathToName(path);
+	const QString name = pathToName(QFileInfo{path});
 	file.open(QFile::ReadOnly | QFile::Text);
 	std::unique_ptr<Model> newModel = std::make_unique<Model>(nullptr);
 	QTextStream textStream{&file};
--- a/src/functional.h	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/functional.h	Sun Jun 26 19:44:45 2022 +0300
@@ -76,14 +76,16 @@
 		return std::back_inserter(vec);
 	}
 
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+	// In Qt6 QVector is now a QList instead, so we need to disable this
 	// Constructs a back_inserter for QVector
 	template<typename T>
 	auto makeDefaultInserter(QVector<T>& vec)
 	{
 		return std::back_inserter(vec);
 	}
+#endif
 
-	// Constructs a back_inserter for QList
 	template<typename T>
 	auto makeDefaultInserter(QList<T>& vec)
 	{
@@ -110,12 +112,14 @@
 		using type = std::vector<TT>;
 	};
 
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
 	// Changes the value type of QVector
 	template<typename T, typename TT>
 	struct ChangeContainerValueType<QVector<T>, TT>
 	{
 		using type = QVector<TT>;
 	};
+#endif
 
 	// Changes the value type of QSet
 	template<typename T, typename TT>
--- a/src/gl/axesprogram.cpp	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/gl/axesprogram.cpp	Sun Jun 26 19:44:45 2022 +0300
@@ -16,10 +16,10 @@
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "gl/partrenderer.h"
 #include <QPainter>
 #include <QPainterPath>
 #include "axesprogram.h"
-#include "gl/partrenderer.h"
 
 static constexpr char vertexShaderSource[] = R"(
 #version 330 core
--- a/src/gl/basicshaderprogram.cpp	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/gl/basicshaderprogram.cpp	Sun Jun 26 19:44:45 2022 +0300
@@ -40,7 +40,6 @@
 {
 	if (not this->isInitialized)
 	{
-		this->initializeOpenGLFunctions();
 		this->isInitialized = true;
 		this->program = std::make_unique<gl::ShaderProgram>();
 		gl::buildShaders(this->program.get(), vertexShaderSource, fragmentShaderSource);
--- a/src/gl/basicshaderprogram.h	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/gl/basicshaderprogram.h	Sun Jun 26 19:44:45 2022 +0300
@@ -11,7 +11,7 @@
 
 //! @brief A collection of a single VAO with a single VBO,
 //! a vertex shader and a fragment shader.
-class BasicShader final : protected QOpenGLFunctions
+class BasicShader final
 {
 	bool isInitialized = false;
 	QOpenGLBuffer buffer;
--- a/src/gl/common.h	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/gl/common.h	Sun Jun 26 19:44:45 2022 +0300
@@ -20,10 +20,10 @@
 #include <QWidget>
 #include <QColor>
 #include <QOpenGLBuffer>
-#include <QOpenGLFunctions>
 #include <QOpenGLShader>
 #include <QOpenGLShaderProgram>
 #include <QOpenGLVertexArrayObject>
+#include <QOpenGLFunctions>
 #include <glm/gtc/type_ptr.hpp>
 #include "basics.h"
 #include "colors.h"
@@ -47,6 +47,8 @@
 	}
 };
 
+QOpenGLFunctions& glfunc();
+
 namespace gl
 {
 	class ShaderProgram;
@@ -84,8 +86,6 @@
 	}
 };
 
-extern QOpenGLFunctions glfunc;
-
 namespace gl
 {
 	// Different ways to render the scene
--- a/src/gl/compiler.cpp	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/gl/compiler.cpp	Sun Jun 26 19:44:45 2022 +0300
@@ -16,9 +16,6 @@
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#define GL_GLEXT_PROTOTYPES
-#include <GL/glu.h>
-#include <GL/glext.h>
 #include <QMessageBox>
 #include "gl/compiler.h"
 #include "documentmanager.h"
@@ -213,8 +210,10 @@
 			shader.program->setAttributeBuffer(0, GL_FLOAT, offsetof(Vertex, position), 3, stride);
 			shader.program->setAttributeBuffer(1, GL_FLOAT, offsetof(Vertex, color), 4, stride);
 			shader.program->setAttributeBuffer(2, GL_FLOAT, offsetof(Vertex, normal), 3, stride);
-			glVertexAttribIPointer(3, 1, GL_INT, stride, reinterpret_cast<void*>(offsetof(Vertex, id)));
-			glVertexAttribIPointer(4, 1, GL_INT, stride, reinterpret_cast<void*>(offsetof(Vertex, selected)));
+			const void* vertexptr = reinterpret_cast<const void*>(offsetof(Vertex, id));
+			glfunc().glVertexAttribPointer(3, 1, GL_INT, GL_FALSE, stride, vertexptr);
+			const void* selectedptr = reinterpret_cast<const void*>(offsetof(Vertex, selected));
+			glfunc().glVertexAttribPointer(4, 1, GL_INT, GL_FALSE, stride, selectedptr);
 			shader.vertexArray.release();
 			shader.buffer.release();
 			shader.program->release();
@@ -350,7 +349,8 @@
 		}
 		const GLsizeiptr size = static_cast<int>(vector.size() * sizeof vector[0]);
 		object.buffer.bind();
-		glBufferSubData(GL_ARRAY_BUFFER, 0, size, vector.data());
+		QOpenGLFunctions glfunc;
+		glfunc.glBufferSubData(GL_ARRAY_BUFFER, 0, size, vector.data());
 		object.buffer.release();
 	}
 }
--- a/src/gl/compiler.h	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/gl/compiler.h	Sun Jun 26 19:44:45 2022 +0300
@@ -17,14 +17,13 @@
  */
 
 #pragma once
-#include "basics.h"
-#include "gl/common.h"
-#include "types/boundingbox.h"
 #include <glm/gtc/type_ptr.hpp>
 #include <QOpenGLVertexArrayObject>
 #include <QOpenGLBuffer>
 #include <QOpenGLShaderProgram>
-#include <QOpenGLExtraFunctions>
+#include "basics.h"
+#include "gl/common.h"
+#include "types/boundingbox.h"
 #include "model.h"
 
 class Model;
@@ -89,7 +88,7 @@
 		for (gl::ModelShaders::ShaderObject& shader : shaders->shaderObjects)
 		{
 			shader.program->bind();
-			const int location = glfunc.glGetUniformLocation(shader.program->programId(), uniformName);
+			const int location = glfunc().glGetUniformLocation(shader.program->programId(), uniformName);
 			Q_ASSERT(location != -1);
 			shader.program->setUniformValue(location, std::forward<T>(value));
 			shader.program->release();
--- a/src/gl/partrenderer.cpp	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/gl/partrenderer.cpp	Sun Jun 26 19:44:45 2022 +0300
@@ -33,7 +33,12 @@
 
 static constexpr double MIN_ZOOM = -3.0;
 static constexpr double MAX_ZOOM = 3.0;
-QOpenGLFunctions glfunc;
+
+QOpenGLFunctions& glfunc()
+{
+	static QOpenGLFunctions funcs;
+	return funcs;
+}
 
 PartRenderer::PartRenderer(
 	Model* model,
@@ -87,11 +92,7 @@
 
 void PartRenderer::initializeGL()
 {
-	::glfunc.initializeOpenGLFunctions();
-	if (glGetError() != GL_NO_ERROR)
-	{
-		abort();
-	}
+	glfunc().initializeOpenGLFunctions();
 	gl::initializeModelShaders(&this->shaders);
 	for (RenderLayer* layer : this->activeRenderLayers) {
 		layer->initializeGL();
@@ -468,7 +469,7 @@
 	this->renderScene();
 	std::array<GLubyte, 3> data;
 	this->checkForGLErrors();
-	glfunc.glReadPixels(where.x(), where.y(), 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &data[0]);
+	glReadPixels(where.x(), where.y(), 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &data[0]);
 	this->checkForGLErrors();
 	fbo.release();
 	this->renderPreferences.style = oldRenderStyle;
--- a/src/libraries.cpp	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/libraries.cpp	Sun Jun 26 19:44:45 2022 +0300
@@ -30,24 +30,6 @@
 }
 
 /**
- * @brief Yields a begin-terator for the libraries
- * @return iterator
- */
-QVector<Library>::const_iterator LibrariesModel::begin() const
-{
-	return this->libraries.begin();
-}
-
-/**
- * @brief Yields an end-iterator for the libraries
- * @return iterator
- */
-QVector<Library>::const_iterator LibrariesModel::end() const
-{
-	return this->libraries.end();
-}
-
-/**
  * @brief Searches the libraries for the specified file name.
  * @param fileName File to search for
  * @return Full path to the file, or empty string if not found.
@@ -63,7 +45,7 @@
 		{
 			QDir directory = library.path;
 			directory.cd(subdirectory);
-			QFileInfo fileInfo = directory.absoluteFilePath(fileName);
+			QFileInfo fileInfo{directory.absoluteFilePath(fileName)};
 			if (fileInfo.exists() && fileInfo.isFile())
 			{
 				path = fileInfo.absoluteFilePath();
@@ -86,7 +68,7 @@
 void LibrariesModel::addLibrary(const Library& library)
 {
 	Q_EMIT layoutAboutToBeChanged();
-	libraries.append(library);
+	this->libraries.push_back(library);
 	Q_EMIT layoutChanged();
 }
 
@@ -94,13 +76,13 @@
  * @brief Removes a library by index. Does nothing if the index is not valid.
  * @param libraryIndex Index of the library
  */
-void LibrariesModel::removeLibrary(const int libraryIndex)
+void LibrariesModel::removeLibrary(const std::size_t libraryIndex)
 {
 	Q_ASSERT(isValidIndex(libraryIndex));
 	if (isValidIndex(libraryIndex))
 	{
 		Q_EMIT layoutAboutToBeChanged();
-		libraries.remove(libraryIndex);
+		this->libraries.erase(this->libraries.begin() + static_cast<long>(libraryIndex));
 		Q_EMIT layoutChanged();
 	}
 }
@@ -111,7 +93,7 @@
  * @param libraryIndex Index of the library
  * @return const reference
  */
-const Library& LibrariesModel::library(int libraryIndex) const
+const Library& LibrariesModel::library(std::size_t libraryIndex) const
 {
 	Q_ASSERT(isValidIndex(libraryIndex));
 	return this->libraries[libraryIndex];
@@ -122,7 +104,7 @@
  * @param libraryIndex Index of the library
  * @param path New path
  */
-void LibrariesModel::setLibraryPath(int libraryIndex, const QDir& path)
+void LibrariesModel::setLibraryPath(std::size_t libraryIndex, const QDir& path)
 {
 	if (this->isValidIndex(libraryIndex))
 	{
@@ -136,7 +118,7 @@
  * @param libraryIndex Index of the library
  * @param role New role
  */
-void LibrariesModel::setLibraryRole(int libraryIndex, const Library::Role role)
+void LibrariesModel::setLibraryRole(std::size_t libraryIndex, const Library::Role role)
 {
 	if (this->isValidIndex(libraryIndex))
 	{
@@ -167,12 +149,12 @@
 /**
  * @returns the amount of libraries
  */
-int LibrariesModel::count() const
+std::size_t LibrariesModel::count() const
 {
 	return this->libraries.size();
 }
 
-void LibrariesModel::moveLibrary(const int libraryFromIndex, const int libraryToIndex)
+void LibrariesModel::moveLibrary(const std::size_t libraryFromIndex, const std::size_t libraryToIndex)
 {
 	if (isValidIndex(libraryFromIndex) and
 		(isValidIndex(libraryToIndex) or libraryToIndex == count()) and
@@ -180,15 +162,17 @@
 	{
 		Q_EMIT layoutAboutToBeChanged();
 		const Library library = this->library(libraryFromIndex);
-		if (libraryToIndex > libraryFromIndex)
+		const auto from = this->libraries.begin() + signed_cast(libraryFromIndex);
+		const auto to = this->libraries.begin() + signed_cast(libraryToIndex);
+		if (to > from)
 		{
-			this->libraries.insert(libraryToIndex, library);
-			this->libraries.removeAt(libraryFromIndex);
+			this->libraries.insert(to, library);
+			this->libraries.erase(from);
 		}
 		else if (libraryToIndex < libraryFromIndex)
 		{
-			this->libraries.removeAt(libraryFromIndex);
-			this->libraries.insert(libraryToIndex, library);
+			this->libraries.erase(from);
+			this->libraries.insert(to, library);
 		}
 		Q_EMIT layoutChanged();
 	}
@@ -199,7 +183,7 @@
  * @param libraryIndex Index to check
  * @returns whether or not it is valid
  */
-bool LibrariesModel::isValidIndex(const int libraryIndex) const
+bool LibrariesModel::isValidIndex(const std::size_t libraryIndex) const
 {
 	return libraryIndex >= 0 && libraryIndex < this->libraries.size();
 }
@@ -275,7 +259,7 @@
 	{
 		const int row = index.row();
 		const Column column = static_cast<Column>(index.column());
-		const Library& library = this->library(row);
+		const Library& library = this->library(static_cast<std::size_t>(row));
 		switch (column)
 		{
 		case RoleColumn:
@@ -320,7 +304,7 @@
  */
 int LibrariesModel::rowCount(const QModelIndex&) const
 {
-	return this->count();
+	return static_cast<int>(this->count());
 }
 
 /**
@@ -337,11 +321,11 @@
  * to update the table widget know when libraries are changed.
  * @param libraryIndex Index of the library.
  */
-void LibrariesModel::signalLibraryChange(int libraryIndex)
+void LibrariesModel::signalLibraryChange(std::size_t libraryIndex)
 {
 	Q_ASSERT(isValidIndex(libraryIndex));
-	const QModelIndex topLeft = this->index(libraryIndex, 0);
-	const QModelIndex bottomRight = this->index(libraryIndex, columnCount({}) - 1);
+	const QModelIndex topLeft = this->index(static_cast<int>(libraryIndex), 0);
+	const QModelIndex bottomRight = this->index(static_cast<int>(libraryIndex), columnCount({}) - 1);
 	Q_EMIT dataChanged(topLeft, bottomRight);
 }
 
@@ -378,3 +362,26 @@
 {
 	return one.role == other.role and one.path == other.path;
 }
+
+/*
+QDataStream &operator<<(QDataStream& stream, const Libraries& libs)
+{
+	const auto size = static_cast<std::uint32_t>(libs.size());
+	stream << size;
+	for (std::uint32_t i = 0; i < size; ++i) {
+		stream << libs[i];
+	}
+	return stream;
+}
+
+QDataStream &operator>>(QDataStream& stream, Libraries& libs)
+{
+	std::uint32_t size;
+	stream >> size;
+	libs.resize(size);
+	for (std::uint32_t i = 0; i < size; ++i) {
+		stream >> libs[i];
+	}
+	return stream;
+}
+*/
--- a/src/libraries.h	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/libraries.h	Sun Jun 26 19:44:45 2022 +0300
@@ -45,8 +45,10 @@
 QDataStream &operator<<(QDataStream&, const Library&);
 QDataStream &operator>>(QDataStream&, Library&);
 
-using Libraries = QVector<Library>;
-Q_DECLARE_METATYPE(Libraries)
+using Libraries = QList<Library>;
+//QDataStream &operator<<(QDataStream&, const Libraries&);
+//QDataStream &operator>>(QDataStream&, Libraries&);
+//Q_DECLARE_METATYPE(Libraries)
 
 class Configuration;
 
@@ -55,18 +57,18 @@
 	Q_OBJECT
 public:
 	LibrariesModel(QObject* parent = nullptr);
-	QVector<Library>::const_iterator begin() const;
-	QVector<Library>::const_iterator end() const;
+	auto begin() const { return this->libraries.begin(); }
+	auto end() const { return this->libraries.end(); }
 	QString findFile(QString fileName) const;
 	void addLibrary(const Library& library);
-	void removeLibrary(const int libraryIndex);
-	const Library& library(int libraryIndex) const;
-	void setLibraryPath(int libraryIndex, const QDir& path);
-	void setLibraryRole(int libraryIndex, const Library::Role role);
+	void removeLibrary(const std::size_t libraryIndex);
+	const Library& library(std::size_t libraryIndex) const;
+	void setLibraryPath(std::size_t libraryIndex, const QDir& path);
+	void setLibraryRole(std::size_t libraryIndex, const Library::Role role);
 	void restoreFromSettings();
 	void storeToSettings();
-	int count() const;
-	void moveLibrary(const int libraryFromIndex, const int libraryToIndex);
+	std::size_t count() const;
+	void moveLibrary(const std::size_t libraryFromIndex, const std::size_t libraryToIndex);
 	// Definitions for QAbstractTableModel
 	Qt::ItemFlags flags(const QModelIndex& index) const override;
 	QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
@@ -76,7 +78,7 @@
 		int role = Qt::DisplayRole) const override;
 	int rowCount(const QModelIndex&) const override;
 	int columnCount(const QModelIndex&) const override;
-	bool isValidIndex(const int libraryIndex) const;
+	bool isValidIndex(const std::size_t libraryIndex) const;
 	ColorTable loadColorTable(QTextStream& errors) const;
 private:
 	enum Column
@@ -84,6 +86,6 @@
 		RoleColumn,
 		PathColumn
 	};
-	void signalLibraryChange(int library);
+	void signalLibraryChange(std::size_t library);
 	Libraries libraries;
 };
--- a/src/main.cpp	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/main.cpp	Sun Jun 26 19:44:45 2022 +0300
@@ -72,10 +72,16 @@
 	QCoreApplication::setOrganizationName("hecknology.net");
 	QCoreApplication::setOrganizationDomain("hecknology.net");
 	qRegisterMetaType<Message>();
+	qRegisterMetaType<Library>();
+	qRegisterMetaType<QList<Library>>();
+	qRegisterMetaType<QMdiArea::ViewMode>();
+	qRegisterMetaType<gl::RenderStyle>();
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
 	qRegisterMetaTypeStreamOperators<Library>("Library");
 	qRegisterMetaTypeStreamOperators<Libraries>("Libraries");
 	qRegisterMetaTypeStreamOperators<gl::RenderStyle>();
 	qRegisterMetaTypeStreamOperators<QMdiArea::ViewMode>();
+#endif
 }
 
 template<typename BaseType, typename MemberType, typename DataType>
@@ -153,7 +159,7 @@
 {
 	if (not locale.isEmpty()) {
 		const QString localeCode = ::localeCode(locale);
-		QLocale::setDefault({localeCode});
+		QLocale::setDefault(QLocale{localeCode});
 		qApp->removeTranslator(translator);
 		const QString path = LOCALE_DIR.filePath(localeCode + ".qm");
 		const bool loadSuccessful = translator->load(path);
--- a/src/mainwindow.h	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/mainwindow.h	Sun Jun 26 19:44:45 2022 +0300
@@ -21,7 +21,6 @@
 #include <QTranslator>
 #include <QSettings>
 #include <QKeySequence>
-#include "configuration.h"
 #include "documentmanager.h"
 #include "libraries.h"
 #include "uiutilities.h"
--- a/src/model.h	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/model.h	Sun Jun 26 19:44:45 2022 +0300
@@ -198,7 +198,7 @@
 	constexpr auto operator<=>(const ModelId& other) const = default;
 };
 
-constexpr unsigned int qHash(ModelId id)
+constexpr auto qHash(ModelId id)
 {
 	return qHash(id.value);
 }
--- a/src/parser.cpp	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/parser.cpp	Sun Jun 26 19:44:45 2022 +0300
@@ -16,6 +16,8 @@
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <QRegExp>
+#include <QIODevice>
 #include "model.h"
 #include "parser.h"
 #include "ldrawalgorithm.h"
@@ -201,7 +203,7 @@
 	line = line.trimmed();
 	try
 	{
-		const QStringList tokens = line.split(QRegExp{R"(\s+)"});
+		const QStringList tokens = line.simplified().split(" ");
 		if (tokens.empty() or tokens == QStringList{{""}})
 		{
 			return Empty{};
--- a/src/settings.h	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/settings.h	Sun Jun 26 19:44:45 2022 +0300
@@ -42,7 +42,7 @@
 SETTING(LogOpenGLDebugMessages, false)
 
 // File management options
-SETTING(Libraries, QVector<Library>{})
+SETTING(Libraries, Libraries{})
 
 // End of setting definitions
 // -----------------------------------------------------------------------------
@@ -74,7 +74,7 @@
 template<class X>
 inline void setSetting(const SettingType_t<X>& value)
 {
-	if (value == settingDefaultValue<X>()) {
+	if (false/*value == settingDefaultValue<X>()*/) {
 		QSettings{}.remove(settingName<X>);
 	}
 	else {
--- a/src/settingseditor/keyboardshortcutseditor.cpp	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/settingseditor/keyboardshortcutseditor.cpp	Sun Jun 26 19:44:45 2022 +0300
@@ -10,7 +10,7 @@
 
 int KeyboardShortcutsEditor::rowCount(const QModelIndex&) const
 {
-	return this->actions.size();
+	return static_cast<int>(this->actions.size());
 }
 
 int KeyboardShortcutsEditor::columnCount(const QModelIndex&) const
@@ -22,7 +22,7 @@
 	const QModelIndex& index,
 	int role) const
 {
-	QAction* const action = this->actions[index.row()];
+	QAction* const action = this->actions[static_cast<std::size_t>(index.row())];
 	const Column column = static_cast<Column>(index.column());
 	switch(role)
 	{
--- a/src/settingseditor/keyboardshortcutseditor.h	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/settingseditor/keyboardshortcutseditor.h	Sun Jun 26 19:44:45 2022 +0300
@@ -17,5 +17,5 @@
 	QVariant data(const QModelIndex& index, int role) const override;
 	QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
 private:
-	const QVector<QAction*> actions;
+	const std::vector<QAction*> actions;
 };
--- a/src/settingseditor/librarieseditor.cpp	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/settingseditor/librarieseditor.cpp	Sun Jun 26 19:44:45 2022 +0300
@@ -6,7 +6,6 @@
 
 LibrariesEditor::LibrariesEditor(QWidget* parent) :
 	QWidget{parent},
-	libraries{this},
 	ui{*new Ui_LibrariesEditor}
 {
 	this->ui.setupUi(this);
@@ -20,13 +19,13 @@
 		&QPushButton::clicked,
 		this,
 		&LibrariesEditor::addNewLibrary);
-	this->ui.librariesTable->setModel(&this->libraries);
 	this->ui.librariesTable->setContextMenuPolicy(Qt::CustomContextMenu);
 	connect(
 		this->ui.librariesTable,
 		&QWidget::customContextMenuRequested,
 		this,
 		&LibrariesEditor::showContextMenu);
+	this->setEnabled(false);
 }
 
 LibrariesEditor::~LibrariesEditor()
@@ -45,33 +44,36 @@
 
 void LibrariesEditor::addNewLibrary()
 {
-	const QDir dir{this->ui.newLibraryPath->text()};
-	if (not dir.exists())
-	{
-		QMessageBox::critical(
+	if (LibrariesModel* model = this->currentModel()) {
+		const QDir dir{this->ui.newLibraryPath->text()};
+		if (not dir.exists())
+		{
+			QMessageBox::critical(
 			this,
 			tr("Library does not exist"),
 			tr("The directory %1 does not exist.").arg(quoted(dir.path()))
-		);
-	}
-	else
-	{
-		if (not dir.isReadable())
+			);
+		}
+		else
 		{
-			QMessageBox::warning(this,
+			if (not dir.isReadable())
+			{
+				QMessageBox::warning(this,
 				tr("Unreadable library"),
 				tr("The directory %1 cannot be read.").arg(quoted(dir.path()))
-			);
+				);
+			}
+			model->addLibrary({Library::OfficialLibrary, dir});
+			this->ui.newLibraryPath->clear();
 		}
-		this->libraries.addLibrary({Library::OfficialLibrary, dir});
-		this->ui.newLibraryPath->clear();
 	}
 }
 
 void LibrariesEditor::showContextMenu(const QPoint position)
 {
-	const int libraryIndex = this->currentLibraryIndex();
-	if (this->libraries.isValidIndex(libraryIndex))
+	const std::size_t libraryIndex = this->currentLibraryIndex();
+	LibrariesModel* model = this->currentModel();
+	if (model != nullptr and model->isValidIndex(libraryIndex))
 	{
 		QMenu* contextMenu = new QMenu{this};
 		QAction* removeAction = new QAction{tr("Remove library")};
@@ -115,36 +117,58 @@
 
 void LibrariesEditor::setCurrentLibraryRole()
 {
-	const int libraryIndex = currentLibraryIndex();
-	QObject* senderObject = sender();
-	QAction* senderAction = qobject_cast<QAction*>(senderObject);
-	const Library::Role role = senderAction->data().value<Library::Role>();
-	this->libraries.setLibraryRole(libraryIndex, role);
+	if (LibrariesModel* model = this->currentModel()) {
+		const std::size_t libraryIndex = currentLibraryIndex();
+		QObject* senderObject = sender();
+		QAction* senderAction = qobject_cast<QAction*>(senderObject);
+		const Library::Role role = senderAction->data().value<Library::Role>();
+		model->setLibraryRole(libraryIndex, role);
+	}
 }
 
 void LibrariesEditor::removeCurrentLibrary()
 {
-	this->libraries.removeLibrary(currentLibraryIndex());
+	if (LibrariesModel* model = this->currentModel()) {
+		model->removeLibrary(currentLibraryIndex());
+	}
 }
 
 void LibrariesEditor::moveCurrentLibraryUp()
 {
-	const int libraryIndex = this->currentLibraryIndex();
-	this->libraries.moveLibrary(libraryIndex, libraryIndex - 1);
+	if (LibrariesModel* model = this->currentModel()) {
+		const std::size_t libraryIndex = this->currentLibraryIndex();
+		model->moveLibrary(libraryIndex, libraryIndex - 1);
+	}
 }
 
 void LibrariesEditor::moveCurrentLibraryDown()
 {
-	const int libraryIndex = this->currentLibraryIndex();
-	this->libraries.moveLibrary(libraryIndex + 1, libraryIndex);
+	if (LibrariesModel* model = this->currentModel()) {
+		const std::size_t libraryIndex = this->currentLibraryIndex();
+		model->moveLibrary(libraryIndex + 1, libraryIndex);
+	}
 }
 
-int LibrariesEditor::currentLibraryIndex() const
+LibrariesModel *LibrariesEditor::currentModel()
 {
-	return this->ui.librariesTable->selectionModel()->currentIndex().row();
+	return qobject_cast<LibrariesModel*>(this->ui.librariesTable->model());
+}
+
+std::size_t LibrariesEditor::currentLibraryIndex() const
+{
+	const int row = this->ui.librariesTable->selectionModel()->currentIndex().row();
+	return static_cast<std::size_t>(row);
 }
 
 void LibrariesEditor::saveSettings()
 {
-	this->libraries.storeToSettings();
+	if (LibrariesModel* model = this->currentModel()) {
+		model->storeToSettings();
+	}
 }
+
+void LibrariesEditor::setModel(LibrariesModel *model)
+{
+	this->ui.librariesTable->setModel(model);
+	this->setEnabled(model != nullptr);
+}
--- a/src/settingseditor/librarieseditor.h	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/settingseditor/librarieseditor.h	Sun Jun 26 19:44:45 2022 +0300
@@ -10,6 +10,7 @@
 	LibrariesEditor(QWidget* parent = nullptr);
 	~LibrariesEditor();
 	void saveSettings();
+	void setModel(LibrariesModel *model);
 private Q_SLOTS:
 	void searchPathForNewLibrary();
 	void addNewLibrary();
@@ -24,7 +25,7 @@
 		RoleColumn,
 		PathColumn
 	};
-	LibrariesModel libraries;
 	class Ui_LibrariesEditor& ui;
-	int currentLibraryIndex() const;
+	LibrariesModel* currentModel();
+	std::size_t currentLibraryIndex() const;
 };
--- a/src/settingseditor/settingseditor.cpp	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/settingseditor/settingseditor.cpp	Sun Jun 26 19:44:45 2022 +0300
@@ -22,6 +22,7 @@
 	this->ui.viewModeButtonGroup->setId(this->ui.viewModeSubWindows, int{QMdiArea::SubWindowView});
 	this->loadLocales();
 	this->setDefaults();
+	this->librariesEditor.setModel(&libraries);
 	QVBoxLayout* layout = new QVBoxLayout{this};
 	layout->addWidget(&librariesEditor);
 	this->ui.tabLdrawLibraries->setLayout(layout);
@@ -77,6 +78,7 @@
 
 void SettingsEditor::setDefaults()
 {
+	this->libraries.restoreFromSettings();
 	this->setCurrentLanguage(setting<Setting::Locale>());
 	this->ui.mainColorButton->setColor(setting<Setting::MainColor>());
 	this->ui.backgroundColorButton->setColor(setting<Setting::BackgroundColor>());
--- a/src/settingseditor/settingseditor.h	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/settingseditor/settingseditor.h	Sun Jun 26 19:44:45 2022 +0300
@@ -4,7 +4,6 @@
 #include "librarieseditor.h"
 #include "libraries.h"
 #include "uiutilities.h"
-#include "configuration.h"
 
 class SettingsEditor : public QDialog
 {
--- a/src/uiutilities.cpp	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/uiutilities.cpp	Sun Jun 26 19:44:45 2022 +0300
@@ -17,11 +17,12 @@
  */
 
 #include <QStyleFactory>
+#include <QWidget>
 #include "uiutilities.h"
 
-QVector<QAction*> uiutilities::collectActions(QObject* subject)
+std::vector<QAction*> uiutilities::collectActions(QObject* subject)
 {
-	QVector<QAction*> actions;
+	std::vector<QAction*> actions;
 	for (QAction* action : subject->findChildren<QAction*>())
 	{
 		if (not action->text().isEmpty()
@@ -34,7 +35,7 @@
 	return actions;
 }
 
-uiutilities::KeySequenceMap uiutilities::makeKeySequenceMap(const QVector<QAction*>& actions)
+uiutilities::KeySequenceMap uiutilities::makeKeySequenceMap(const std::vector<QAction*>& actions)
 {
 	KeySequenceMap result;
 	for (QAction* action : actions)
@@ -51,4 +52,4 @@
 	widget->setAutoFillBackground(true);
 	widget->setStyle(QStyleFactory::create("Fusion"));
 	widget->update();
-}
\ No newline at end of file
+}
--- a/src/uiutilities.h	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/uiutilities.h	Sun Jun 26 19:44:45 2022 +0300
@@ -22,7 +22,7 @@
 namespace uiutilities
 {
 	using KeySequenceMap = QMap<QString, QKeySequence>;
-	QVector<QAction*> collectActions(QObject* subject);
-	KeySequenceMap makeKeySequenceMap(const QVector<QAction*>& actions);
+	std::vector<QAction *> collectActions(QObject* subject);
+	KeySequenceMap makeKeySequenceMap(const std::vector<QAction*>& actions);
 	void colorizeWidget(QWidget* widget, const QColor& color);
 }
--- a/src/vertexmap.cpp	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/vertexmap.cpp	Sun Jun 26 19:44:45 2022 +0300
@@ -1,7 +1,7 @@
 #include "vertexmap.h"
 #include "gl/common.h"
 
-unsigned int hashVertex(const glm::vec3& vec)
+hash_t hashVertex(const glm::vec3& vec)
 {
 	return qHash(glm::ivec3{
 		int(vec.x * 10000),
@@ -130,7 +130,7 @@
 				return glm::mat4{{a, 0}, {-c, 0}, {d, 0}, {}};
 			});
 		points(element, [&](const glm::vec3 point) {
-			const unsigned int hash = hashVertex(point);
+			const hash_t hash = hashVertex(point);
 			VertexInfo& info = this->map[hash];
 			info.point = point;
 			info.objects.insert(this->model->idAt(i));
--- a/src/vertexmap.h	Wed Jun 22 23:51:06 2022 +0300
+++ b/src/vertexmap.h	Sun Jun 26 19:44:45 2022 +0300
@@ -26,9 +26,9 @@
 	Q_SIGNAL void verticesChanged();
 private:
 	const Model* const model;
-	QSet<unsigned int> vertexHashes;
+	QSet<hash_t> vertexHashes;
 	std::vector<glm::vec3> vertices;
-	std::map<unsigned int, VertexInfo> map;
+	std::map<hash_t, VertexInfo> map;
 };
 
 #endif // VERTEXMAP_H
--- a/widgets/CMakeLists.txt	Wed Jun 22 23:51:06 2022 +0300
+++ b/widgets/CMakeLists.txt	Sun Jun 26 19:44:45 2022 +0300
@@ -1,5 +1,4 @@
-find_package(Qt5 REQUIRED COMPONENTS UiPlugin)
-qt5_wrap_ui(LDFORGEWIDGETS_FORMS
+qt_wrap_ui(LDFORGEWIDGETS_FORMS
 	vec3editor.ui
 	multiplyfactordialog.ui
 	matrixeditor.ui
@@ -21,14 +20,14 @@
 	${LDFORGEWIDGETS_FORMS}
 )
 
-get_target_property(Qt5UiPlugin_INCLUDES Qt5::UiPlugin INTERFACE_INCLUDE_DIRECTORIES)
-target_include_directories(ldforgewidgets PUBLIC ${Qt5UiPlugin_INCLUDES})
+get_target_property(UIPLUGIN_INCLUDES QtUiPlugin INTERFACE_INCLUDE_DIRECTORIES)
+target_include_directories(ldforgewidgets PUBLIC "${UIPLUGIN_INCLUDES}")
 target_include_directories(ldforgewidgets PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
 target_include_directories(ldforgewidgets PUBLIC "${CMAKE_CURRENT_BINARY_DIR}")
-target_link_libraries(ldforgewidgets Qt5::Widgets)
+target_link_libraries(ldforgewidgets Qt::Widgets)
 set_target_properties(ldforgewidgets PROPERTIES AUTOMOC 1)
 
-get_target_property(QT_QMAKE_EXECUTABLE Qt5::qmake LOCATION)
+get_target_property(QT_QMAKE_EXECUTABLE Qt::qmake LOCATION)
 execute_process(COMMAND ${QT_QMAKE_EXECUTABLE} -query QT_INSTALL_PLUGINS
 	OUTPUT_VARIABLE QT_INSTALL_PLUGINS OUTPUT_STRIP_TRAILING_WHITESPACE
 )
--- a/widgets/doublespinbox.cpp	Wed Jun 22 23:51:06 2022 +0300
+++ b/widgets/doublespinbox.cpp	Sun Jun 26 19:44:45 2022 +0300
@@ -24,7 +24,7 @@
 DoubleSpinBox::DoubleSpinBox(QWidget* parent) :
 	QDoubleSpinBox {parent}
 {
-	this->setLocale({"C"});
+	this->setLocale(QLocale{"C"});
 	this->setRange(-1e6, 1e6);
 	this->setDecimals(4);
 }

mercurial