Refactoring update.

Tue, 07 Jul 2015 21:35:20 +0300

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Tue, 07 Jul 2015 21:35:20 +0300
changeset 941
f895379d7fab
parent 940
edc716c1d8e1
child 951
54d90af8542d

Refactoring update.
Removed all asserts.

CMakeLists.txt file | annotate | diff | comparison | revisions
codegen.py file | annotate | diff | comparison | revisions
src/actions.cpp file | annotate | diff | comparison | revisions
src/actionsEdit.cpp file | annotate | diff | comparison | revisions
src/addObjectDialog.cpp file | annotate | diff | comparison | revisions
src/addObjectDialog.h file | annotate | diff | comparison | revisions
src/basics.cpp file | annotate | diff | comparison | revisions
src/basics.h file | annotate | diff | comparison | revisions
src/boundingbox.cpp file | annotate | diff | comparison | revisions
src/boundingbox.h file | annotate | diff | comparison | revisions
src/colorSelector.cpp file | annotate | diff | comparison | revisions
src/colorSelector.h file | annotate | diff | comparison | revisions
src/colors.cpp file | annotate | diff | comparison | revisions
src/configDialog.cpp file | annotate | diff | comparison | revisions
src/configDialog.h file | annotate | diff | comparison | revisions
src/configuration.cpp file | annotate | diff | comparison | revisions
src/configuration.h file | annotate | diff | comparison | revisions
src/crashCatcher.cpp file | annotate | diff | comparison | revisions
src/crashCatcher.h file | annotate | diff | comparison | revisions
src/dialogs.cpp file | annotate | diff | comparison | revisions
src/dialogs.h file | annotate | diff | comparison | revisions
src/documentation.cpp file | annotate | diff | comparison | revisions
src/editmodes/abstractEditMode.cpp file | annotate | diff | comparison | revisions
src/editmodes/circleMode.cpp file | annotate | diff | comparison | revisions
src/editmodes/linePathMode.cpp file | annotate | diff | comparison | revisions
src/editmodes/magicWandMode.cpp file | annotate | diff | comparison | revisions
src/editmodes/selectMode.cpp file | annotate | diff | comparison | revisions
src/extPrograms.cpp file | annotate | diff | comparison | revisions
src/glCompiler.cpp file | annotate | diff | comparison | revisions
src/glRenderer.cpp file | annotate | diff | comparison | revisions
src/glRenderer.h file | annotate | diff | comparison | revisions
src/ldConfig.cpp file | annotate | diff | comparison | revisions
src/ldDocument.cpp file | annotate | diff | comparison | revisions
src/ldDocument.h file | annotate | diff | comparison | revisions
src/ldObject.cpp file | annotate | diff | comparison | revisions
src/ldObject.h file | annotate | diff | comparison | revisions
src/ldObjectMath.cpp file | annotate | diff | comparison | revisions
src/ldObjectMath.h file | annotate | diff | comparison | revisions
src/macros.h file | annotate | diff | comparison | revisions
src/main.cpp 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/messageLog.cpp file | annotate | diff | comparison | revisions
src/messageLog.h file | annotate | diff | comparison | revisions
src/miscallenous.cpp file | annotate | diff | comparison | revisions
src/miscallenous.h file | annotate | diff | comparison | revisions
src/partDownloader.cpp file | annotate | diff | comparison | revisions
src/partDownloader.h file | annotate | diff | comparison | revisions
src/primitives.cpp file | annotate | diff | comparison | revisions
src/primitives.h file | annotate | diff | comparison | revisions
src/radioGroup.cpp file | annotate | diff | comparison | revisions
src/radioGroup.h file | annotate | diff | comparison | revisions
src/ringFinder.cpp file | annotate | diff | comparison | revisions
src/vertex.cpp file | annotate | diff | comparison | revisions
src/vertex.h file | annotate | diff | comparison | revisions
--- a/CMakeLists.txt	Sun Apr 12 23:02:26 2015 +0300
+++ b/CMakeLists.txt	Tue Jul 07 21:35:20 2015 +0300
@@ -30,6 +30,7 @@
 	src/actionsEdit.cpp
 	src/addObjectDialog.cpp
 	src/basics.cpp
+	src/boundingbox.cpp
 	src/colors.cpp
 	src/colorSelector.cpp
 	src/configuration.cpp
@@ -54,6 +55,7 @@
 	src/radioGroup.cpp
 	src/ringFinder.cpp
 	src/version.cpp
+	src/vertex.cpp
 	src/editmodes/abstractEditMode.cpp
 	src/editmodes/circleMode.cpp
 	src/editmodes/drawMode.cpp
@@ -90,6 +92,8 @@
 	src/mainWindow.h
 	src/editHistory.h
 	src/format.h
+	src/boundingbox.h
+	src/vertex.h
 	src/editmodes/abstractEditMode.h
 	src/editmodes/circleMode.h
 	src/editmodes/drawMode.h
@@ -155,19 +159,19 @@
 endif()
 
 if (USE_QT5)
-	qt5_generate_moc (LDFORGE_MOC ${LDFORGE_HEADERS})
 	qt5_add_resources (LDFORGE_QRC ${LDFORGE_RESOURCES})
 	qt5_wrap_ui (LDFORGE_FORMS_HEADERS ${LDFORGE_FORMS})
-	add_executable (${PROJECT_NAME} WIN32 ${LDFORGE_SOURCES} ${LDFORGE_MOC}
-		${LDFORGE_QRC} ${LDFORGE_FORMS_HEADERS})
+	add_executable (${PROJECT_NAME} WIN32 ${LDFORGE_SOURCES}
+		${LDFORGE_QRC} ${LDFORGE_FORMS_HEADERS} ${LDFORGE_HEADERS})
 else()
-	qt4_wrap_cpp (LDFORGE_MOC ${LDFORGE_HEADERS})
 	qt4_wrap_ui (LDFORGE_FORMS_HEADERS ${LDFORGE_FORMS})
 	qt4_add_resources (LDFORGE_RCC ${LDFORGE_RESOURCES})
-	add_executable (${PROJECT_NAME} WIN32 ${LDFORGE_SOURCES} ${LDFORGE_RCC}
-		${LDFORGE_FORMS_HEADERS} ${LDFORGE_MOC})
+	add_executable (${PROJECT_NAME} WIN32 ${LDFORGE_SOURCES}
+		${LDFORGE_FORMS_HEADERS} ${LDFORGE_MOC} ${LDFORGE_HEADERS})
 endif()
 
+set_target_properties (${PROJECT_NAME} PROPERTIES AUTOMOC 1)
+
 if (USE_QT5)
 	target_link_libraries (${PROJECT_NAME} Qt5::Widgets Qt5::Network Qt5::OpenGL ${OPENGL_LIBRARIES})
 else()
--- a/codegen.py	Sun Apr 12 23:02:26 2015 +0300
+++ b/codegen.py	Tue Jul 07 21:35:20 2015 +0300
@@ -140,10 +140,7 @@
 	progname = sys.argv[1]
 	sys.argv[0] = '%s %s' % (sys.argv[0], sys.argv[1])
 	sys.argv.pop (1)
-
-	impl = globals().copy()
-	impl.update (locals())
-	method = impl.get ('prog_' + progname)
+	method = globals().get ('prog_' + progname)
 
 	if method:
 		method()
--- a/src/actions.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/actions.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -158,7 +158,19 @@
 //
 void MainWindow::actionSettings()
 {
-	(new ConfigDialog)->exec();
+	ConfigDialog* dialog = new ConfigDialog (this);
+	connect (dialog, SIGNAL (settingsApplied()), this, SLOT (settingsApplied()));
+	dialog->exec();
+}
+
+// =============================================================================
+//
+void MainWindow::settingsApplied()
+{
+	m_quickColors = LoadQuickColorList();
+	R()->setBackground();
+	doFullRefresh();
+	updateDocumentList();
 }
 
 // =============================================================================
@@ -278,7 +290,7 @@
 			colors << obj->color();
 	}
 
-	RemoveDuplicates (colors);
+	removeDuplicates (colors);
 	CurrentDocument()->clearSelection();
 
 	for (LDObjectPtr obj : CurrentDocument()->objects())
@@ -306,8 +318,8 @@
 			subfilenames << obj.staticCast<LDSubfile>()->fileInfo()->name();
 	}
 
-	RemoveDuplicates (types);
-	RemoveDuplicates (subfilenames);
+	removeDuplicates (types);
+	removeDuplicates (subfilenames);
 	CurrentDocument()->clearSelection();
 
 	for (LDObjectPtr obj : CurrentDocument()->objects())
@@ -371,7 +383,7 @@
 		return;
 	}
 
-	LDObjectList objs = LoadFileContents (&f, null);
+	LDObjectList objs = LoadFileContents (&f, nullptr);
 
 	CurrentDocument()->clearSelection();
 
@@ -688,10 +700,10 @@
 	if (Selection().size() == 1)
 		defval = Selection()[0]->lineNumber();
 
-	int idx = QInputDialog::getInt (null, "Go to line", "Go to line:", defval,
+	int idx = QInputDialog::getInt (nullptr, "Go to line", "Go to line:", defval,
 		1, CurrentDocument()->getObjectCount(), 1, &ok);
 
-	if (not ok or (obj = CurrentDocument()->getObject (idx - 1)) == null)
+	if (not ok or (obj = CurrentDocument()->getObject (idx - 1)) == nullptr)
 		return;
 
 	CurrentDocument()->clearSelection();
@@ -733,7 +745,7 @@
 	int				refidx (Selection()[0]->lineNumber());
 
 	// Determine title of subfile
-	if (titleobj != null)
+	if (titleobj != nullptr)
 		subtitle = "~" + titleobj->text();
 	else
 		subtitle = "~subfile";
@@ -791,7 +803,7 @@
 				digits.prepend ("0");
 
 			fullsubname = subdirname + "/" + Basename (parentpath) + "s" + digits + ".dat";
-		} while (FindDocument ("s\\" + Basename (fullsubname)) != null or QFile (fullsubname).exists());
+		} while (FindDocument ("s\\" + Basename (fullsubname)) != nullptr or QFile (fullsubname).exists());
 	}
 
 	// Determine the BFC winding type used in the main document - it is to
@@ -882,7 +894,7 @@
 	{
 		LDSubfilePtr ref = obj.dynamicCast<LDSubfile>();
 
-		if (ref == null or not ref->fileInfo()->isImplicit())
+		if (ref == nullptr or not ref->fileInfo()->isImplicit())
 			continue;
 
 		ref->fileInfo()->setImplicit (false);
--- a/src/actionsEdit.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/actionsEdit.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -128,7 +128,9 @@
 		// inlined contents.
 		long idx = ref->lineNumber();
 
-		assert (idx != -1);
+		if (idx == -1)
+			idx = 0;
+
 		LDObjectList objs = ref->inlineContents (deep, false);
 
 		// Merge in the inlined objects
@@ -277,7 +279,7 @@
 
 		for (int i = 0; i < countof (lines); ++i)
 		{
-			if (lines[i] == null)
+			if (lines[i] == nullptr)
 				continue;
 
 			long idx = obj->lineNumber() + i + 1;
@@ -388,27 +390,27 @@
 
 void MainWindow::actionRotateXPos()
 {
-	RotateObjects (1, 0, 0, GetRotateActionAngle(), Selection());
+	rotateObjects (1, 0, 0, GetRotateActionAngle(), Selection());
 }
 void MainWindow::actionRotateYPos()
 {
-	RotateObjects (0, 1, 0, GetRotateActionAngle(), Selection());
+	rotateObjects (0, 1, 0, GetRotateActionAngle(), Selection());
 }
 void MainWindow::actionRotateZPos()
 {
-	RotateObjects (0, 0, 1, GetRotateActionAngle(), Selection());
+	rotateObjects (0, 0, 1, GetRotateActionAngle(), Selection());
 }
 void MainWindow::actionRotateXNeg()
 {
-	RotateObjects (-1, 0, 0, GetRotateActionAngle(), Selection());
+	rotateObjects (-1, 0, 0, GetRotateActionAngle(), Selection());
 }
 void MainWindow::actionRotateYNeg()
 {
-	RotateObjects (0, -1, 0, GetRotateActionAngle(), Selection());
+	rotateObjects (0, -1, 0, GetRotateActionAngle(), Selection());
 }
 void MainWindow::actionRotateZNeg()
 {
-	RotateObjects (0, 0, -1, GetRotateActionAngle(), Selection());
+	rotateObjects (0, 0, -1, GetRotateActionAngle(), Selection());
 }
 
 void MainWindow::actionRotationPoint()
@@ -427,14 +429,14 @@
 	{
 		LDMatrixObjectPtr mo = obj.dynamicCast<LDMatrixObject>();
 
-		if (mo != null)
+		if (mo != nullptr)
 		{
 			Vertex v = mo->position();
 			Matrix t = mo->transform();
 
 			// Note: matrix values are to be rounded to 4 decimals.
-			v.apply ([](Axis, double& a) { RoundToDecimals (a, cfg::RoundPosition); });
-			ApplyToMatrix (t, [](int, double& a) { RoundToDecimals (a, cfg::RoundMatrix); });
+			v.apply ([](Axis, double& a) { roundToDecimals (a, cfg::RoundPosition); });
+			applyToMatrix (t, [](int, double& a) { roundToDecimals (a, cfg::RoundMatrix); });
 
 			mo->setPosition (v);
 			mo->setTransform (t);
@@ -445,7 +447,7 @@
 			for (int i = 0; i < obj->numVertices(); ++i)
 			{
 				Vertex v = obj->vertex (i);
-				v.apply ([](Axis, double& a) { RoundToDecimals (a, cfg::RoundPosition); });
+				v.apply ([](Axis, double& a) { roundToDecimals (a, cfg::RoundPosition); });
 				obj->setVertex (i, v);
 				num += 3;
 			}
@@ -602,7 +604,7 @@
 
 	for (colnum = 0;
 		 colnum < CountLDConfigColors() and
-			((color = LDColor::fromIndex (colnum)) == null or
+			((color = LDColor::fromIndex (colnum)) == nullptr or
 			IsColorUsed (color));
 		colnum++) {}
 
@@ -652,12 +654,12 @@
 
 	// Find a spot to place the new comment
 	for (obj = CurrentDocument()->getObject (0);
-		obj != null and obj->next() != null and not obj->next()->isScemantic();
+		obj != nullptr and obj->next() != nullptr and not obj->next()->isScemantic();
 		obj = obj->next())
 	{
 		LDCommentPtr comm = obj.dynamicCast<LDComment>();
 
-		if (comm != null and comm->text().startsWith ("!HISTORY "))
+		if (comm != nullptr and comm->text().startsWith ("!HISTORY "))
 			ishistory = true;
 
 		if (prevIsHistory and not ishistory)
--- a/src/addObjectDialog.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/addObjectDialog.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -95,7 +95,7 @@
 			coordCount = 3;
 			tw_subfileList = new QTreeWidget();
 			tw_subfileList->setHeaderLabel (tr ("Primitives"));
-			PopulatePrimitives (tw_subfileList, (obj != null ? obj.staticCast<LDSubfile>()->fileInfo()->name() : ""));
+			PopulatePrimitives (tw_subfileList, (obj != nullptr ? obj.staticCast<LDSubfile>()->fileInfo()->name() : ""));
 
 			connect (tw_subfileList, SIGNAL (itemSelectionChanged()), this, SLOT (slot_subfileTypeChanged()));
 			lb_subfileName = new QLabel ("File:");
@@ -116,7 +116,7 @@
 	}
 
 	QPixmap icon = GetIcon (format ("add-%1", typeName));
-	LDObjectPtr defaults = LDObject::getDefault (type);
+	LDObjectPtr defaults = LDObject::spawnByType (type);
 
 	lb_typeIcon = new QLabel;
 	lb_typeIcon->setPixmap (icon);
@@ -124,7 +124,7 @@
 	// Show a color edit dialog for the types that actually use the color
 	if (defaults->isColored())
 	{
-		if (obj != null)
+		if (obj != nullptr)
 			m_color = obj->color();
 		else
 			m_color = (type == OBJ_CondLine or type == OBJ_Line) ? EdgeColor() : MainColor();
@@ -152,7 +152,7 @@
 		case OBJ_Triangle:
 		case OBJ_Quad:
 			// Apply coordinates
-			if (obj != null)
+			if (obj != nullptr)
 			{
 				for (int i = 0; i < coordCount / 3; ++i)
 				{
@@ -190,7 +190,7 @@
 		// le_matrix->setValidator (new QDoubleValidator);
 		Matrix defaultMatrix = IdentityMatrix;
 
-		if (mo != null)
+		if (mo != nullptr)
 		{
 			mo->position().apply ([&](Axis ax, double value)
 			{
@@ -234,7 +234,7 @@
 	button->setIcon (GetIcon ("palette"));
 	button->setAutoFillBackground (true);
 
-	if (color != null)
+	if (color != nullptr)
 		button->setStyleSheet (format ("background-color: %1", color.hexcode()));
 }
 
@@ -244,7 +244,7 @@
 {
 	SubfileListItem* item = static_cast<SubfileListItem*> (tw_subfileList->currentItem());
 
-	if (item->primitive() == null)
+	if (item->primitive() == nullptr)
 		return ""; // selected a heading
 
 	return item->primitive()->name;
@@ -273,7 +273,7 @@
 template<typename T>
 static QSharedPointer<T> InitObject (LDObjectPtr& obj)
 {
-	if (obj == null)
+	if (obj == nullptr)
 		obj = LDSpawn<T>();
 
 	return obj.staticCast<T>();
@@ -285,19 +285,17 @@
 {
 	setlocale (LC_ALL, "C");
 
-	// FIXME: Redirect to Edit Raw
-	if (obj and obj->type() == OBJ_Error)
+	// FIXME: Redirect errors to Edit Raw
+	if (obj and (obj->type() == OBJ_Error or obj->type() != type))
 		return;
 
 	if (type == OBJ_Empty)
 		return; // Nothing to edit with empties
 
-	const bool newObject = (obj == null);
+	const bool newObject = (obj == nullptr);
 	Matrix transform = IdentityMatrix;
 	AddObjectDialog dlg (type, obj);
 
-	assert (obj == null or obj->type() == type);
-
 	if (dlg.exec() == QDialog::Rejected)
 		return;
 
@@ -319,42 +317,43 @@
 
 	switch (type)
 	{
-		case OBJ_Comment:
+	case OBJ_Comment:
 		{
 			LDCommentPtr comm = InitObject<LDComment> (obj);
 			comm->setText (dlg.le_comment->text());
 		}
 		break;
 
-		case OBJ_Line:
-		case OBJ_Triangle:
-		case OBJ_Quad:
-		case OBJ_CondLine:
+	case OBJ_Line:
+	case OBJ_Triangle:
+	case OBJ_Quad:
+	case OBJ_CondLine:
+		if (not obj)
+			obj = LDObject::spawnByType (type);
+
+		for (int i = 0; i < obj->numVertices(); ++i)
 		{
-			if (not obj)
-				obj = LDObject::getDefault (type);
+			Vertex v;
 
-			for (int i = 0; i < obj->numVertices(); ++i)
+			v.apply ([&](Axis ax, double& value)
 			{
-				Vertex v;
+				value = dlg.dsb_coords[(i * 3) + ax]->value();
+			});
 
-				v.apply ([&](Axis ax, double& value)
-				{
-					value = dlg.dsb_coords[(i * 3) + ax]->value();
-				});
+			obj->setVertex (i, v);
+		}
+		break;
 
-				obj->setVertex (i, v);
-			}
-		} break;
-
-		case OBJ_BFC:
+	case OBJ_BFC:
 		{
 			LDBFCPtr bfc = InitObject<LDBFC> (obj);
-			assert (IsWithin (dlg.rb_bfcType->value(), 0, int (BFCStatement::NumValues) - 1));
-			bfc->setStatement (BFCStatement (dlg.rb_bfcType->value()));
-		} break;
 
-		case OBJ_Subfile:
+			if (isInRange (dlg.rb_bfcType->value(), 0, int (BFCStatement::NumValues) - 1))
+				bfc->setStatement (BFCStatement (dlg.rb_bfcType->value()));
+		}
+		break;
+
+	case OBJ_Subfile:
 		{
 			QString name = dlg.le_subfileName->text();
 
@@ -370,17 +369,17 @@
 			}
 
 			LDSubfilePtr ref = InitObject<LDSubfile> (obj);
-			assert (ref);
 
 			for_axes (ax)
 				ref->setCoordinate (ax, dlg.dsb_coords[ax]->value());
 
 			ref->setTransform (transform);
 			ref->setFileInfo (file);
-		} break;
+		}
+		break;
 
-		default:
-			break;
+	default:
+		break;
 	}
 
 	if (obj->isColored())
--- a/src/addObjectDialog.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/addObjectDialog.h	Tue Jul 07 21:35:20 2015 +0300
@@ -34,7 +34,7 @@
 	Q_OBJECT
 
 public:
-	AddObjectDialog (const LDObjectType type, LDObjectPtr obj, QWidget* parent = null);
+	AddObjectDialog (const LDObjectType type, LDObjectPtr obj, QWidget* parent = nullptr);
 	static void staticDialog (const LDObjectType type, LDObjectPtr obj);
 
 	QLabel* lb_typeIcon;
--- a/src/basics.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/basics.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -20,88 +20,12 @@
 #include <QStringList>
 #include <QTextStream>
 #include <QFile>
-#include <assert.h>
 #include "main.h"
 #include "basics.h"
 #include "miscallenous.h"
 #include "ldObject.h"
 #include "ldDocument.h"
 
-Vertex::Vertex() :
-	QVector3D() {}
-
-Vertex::Vertex (const QVector3D& a) :
-	QVector3D (a) {}
-
-Vertex::Vertex (qreal xpos, qreal ypos, qreal zpos) :
-	QVector3D(xpos, ypos, zpos) {}
-
-
-void Vertex::transform (const Matrix& matr, const Vertex& pos)
-{
-	double x2 = (matr[0] * x()) + (matr[1] * y()) + (matr[2] * z()) + pos.x();
-	double y2 = (matr[3] * x()) + (matr[4] * y()) + (matr[5] * z()) + pos.y();
-	double z2 = (matr[6] * x()) + (matr[7] * y()) + (matr[8] * z()) + pos.z();
-	setX (x2);
-	setY (y2);
-	setZ (z2);
-}
-
-void Vertex::apply (ApplyFunction func)
-{
-	double newX = x(), newY = y(), newZ = z();
-	func (X, newX);
-	func (Y, newY);
-	func (Z, newZ);
-	*this = Vertex (newX, newY, newZ);
-}
-
-void Vertex::apply (ApplyConstFunction func) const
-{
-	func (X, x());
-	func (Y, y());
-	func (Z, z());
-}
-
-double Vertex::operator[] (Axis ax) const
-{
-	switch (ax)
-	{
-		case X: return x();
-		case Y: return y();
-		case Z: return z();
-	}
-
-	assert (false);
-	return 0.0;
-}
-
-void Vertex::setCoordinate (Axis ax, qreal value)
-{
-	switch (ax)
-	{
-		case X: setX (value); break;
-		case Y: setY (value); break;
-		case Z: setZ (value); break;
-	}
-}
-
-QString Vertex::toString (bool mangled) const
-{
-	if (mangled)
-		return format ("(%1, %2, %3)", x(), y(), z());
-
-	return format ("%1 %2 %3", x(), y(), z());
-}
-
-bool Vertex::operator< (const Vertex& other) const
-{
-	if (x() != other.x()) return x() < other.x();
-	if (y() != other.y()) return y() < other.y();
-	if (z() != other.z()) return z() < other.z();
-	return false;
-}
-
 // =============================================================================
 //
 Matrix::Matrix (double vals[])
@@ -122,8 +46,8 @@
 //
 Matrix::Matrix (const std::initializer_list<double>& vals)
 {
-	assert (vals.size() == 9);
-	memcpy (&m_vals[0], vals.begin(), sizeof m_vals);
+	if (vals.size() == 9)
+		memcpy (&m_vals[0], vals.begin(), sizeof m_vals);
 }
 
 // =============================================================================
@@ -209,128 +133,4 @@
 	}
 
 	return true;
-}
-
-// =============================================================================
-//
-LDBoundingBox::LDBoundingBox()
-{
-	reset();
-}
-
-// =============================================================================
-//
-void LDBoundingBox::calculateFromCurrentDocument()
-{
-	reset();
-
-	if (CurrentDocument() == null)
-		return;
-
-	for (LDObjectPtr obj : CurrentDocument()->objects())
-		calcObject (obj);
-}
-
-// =============================================================================
-//
-void LDBoundingBox::calcObject (LDObjectPtr obj)
-{
-	switch (obj->type())
-	{
-		case OBJ_Line:
-		case OBJ_Triangle:
-		case OBJ_Quad:
-		case OBJ_CondLine:
-		{
-			for (int i = 0; i < obj->numVertices(); ++i)
-				calcVertex (obj->vertex (i));
-		} break;
-
-		case OBJ_Subfile:
-		{
-			LDSubfilePtr ref = obj.staticCast<LDSubfile>();
-			LDObjectList objs = ref->inlineContents (true, false);
-
-			for (LDObjectPtr obj : objs)
-			{
-				calcObject (obj);
-				obj->destroy();
-			}
-		}
-		break;
-
-		default:
-			break;
-	}
-}
-
-// =============================================================================
-//
-LDBoundingBox& LDBoundingBox::operator<< (const Vertex& v)
-{
-	calcVertex (v);
-	return *this;
-}
-
-// =============================================================================
-//
-LDBoundingBox& LDBoundingBox::operator<< (LDObjectPtr obj)
-{
-	calcObject (obj);
-	return *this;
-}
-
-// =============================================================================
-//
-void LDBoundingBox::calcVertex (const Vertex& vertex)
-{
-	m_vertex0.setX (Min (vertex.x(), m_vertex0.x()));
-	m_vertex0.setY (Min (vertex.y(), m_vertex0.y()));
-	m_vertex0.setZ (Min (vertex.z(), m_vertex0.z()));
-	m_vertex1.setX (Max (vertex.x(), m_vertex1.x()));
-	m_vertex1.setY (Max (vertex.y(), m_vertex1.y()));
-	m_vertex1.setZ (Max (vertex.z(), m_vertex1.z()));
-	setEmpty (false);
-}
-
-// =============================================================================
-//
-void LDBoundingBox::reset()
-{
-	m_vertex0 = Vertex (10000.0, 10000.0, 10000.0);
-	m_vertex1 = Vertex (-10000.0, -10000.0, -10000.0);
-	setEmpty (true);
-}
-
-// =============================================================================
-//
-double LDBoundingBox::longestMeasurement() const
-{
-	double xscale = (m_vertex0.x() - m_vertex1.x());
-	double yscale = (m_vertex0.y() - m_vertex1.y());
-	double zscale = (m_vertex0.z() - m_vertex1.z());
-	double size = zscale;
-
-	if (xscale > yscale)
-	{
-		if (xscale > zscale)
-			size = xscale;
-	}
-	elif (yscale > zscale)
-		size = yscale;
-
-	if (Abs (size) >= 2.0)
-		return Abs (size / 2);
-
-	return 1.0;
-}
-
-// =============================================================================
-//
-Vertex LDBoundingBox::center() const
-{
-	return Vertex (
-		(m_vertex0.x() + m_vertex1.x()) / 2,
-		(m_vertex0.y() + m_vertex1.y()) / 2,
-		(m_vertex0.z() + m_vertex1.z()) / 2);
-}
+}
\ No newline at end of file
--- a/src/basics.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/basics.h	Tue Jul 07 21:35:20 2015 +0300
@@ -21,9 +21,9 @@
 #include <QObject>
 #include <QStringList>
 #include <QMetaType>
+#include <QVector>
 #include <QVector3D>
 #include <QSharedPointer>
-#include <functional>
 #include "macros.h"
 
 class LDObject;
@@ -46,42 +46,11 @@
 using LDObjectWeakList = QList<LDObjectWeakPtr>;
 using LDDocumentPtr = QSharedPointer<LDDocument>;
 using LDDocumentWeakPtr = QWeakPointer<LDDocument>;
+using real = double;
 
 template<typename T, typename R>
 using Pair = std::pair<T, R>;
 
-enum Axis
-{
-	X,
-	Y,
-	Z
-};
-
-//
-// Derivative of QVector3D: this class is used for the vertices.
-//
-class Vertex : public QVector3D
-{
-public:
-	using ApplyFunction = std::function<void (Axis, double&)>;
-	using ApplyConstFunction = std::function<void (Axis, double)>;
-
-	Vertex();
-	Vertex (const QVector3D& a);
-	Vertex (qreal xpos, qreal ypos, qreal zpos);
-
-	void	apply (ApplyFunction func);
-	void	apply (ApplyConstFunction func) const;
-	QString	toString (bool mangled = false) const;
-	void	transform (const Matrix& matr, const Vertex& pos);
-	void	setCoordinate (Axis ax, qreal value);
-
-	bool	operator< (const Vertex& other) const;
-	double	operator[] (Axis ax) const;
-};
-
-Q_DECLARE_METATYPE (Vertex)
-
 //
 // A mathematical 3 x 3 matrix
 //
@@ -154,130 +123,65 @@
 	double m_vals[9];
 };
 
-//
-// Defines a bounding box that encompasses a given set of objects.
-// vertex0 is the minimum vertex, vertex1 is the maximum vertex.
-//
-class LDBoundingBox
-{
-	PROPERTY (private,	bool,		isEmpty,	setEmpty,		STOCK_WRITE)
-	PROPERTY (private,	Vertex,		vertex0,	setVertex0,		STOCK_WRITE)
-	PROPERTY (private,	Vertex,		vertex1,	setVertex1,		STOCK_WRITE)
-
-public:
-	// Constructs an empty bounding box.
-	LDBoundingBox();
-
-	// Clears the bounding box
-	void reset();
-
-	// Calculates the bounding box's values from the objects in the current
-	// document.
-	void calculateFromCurrentDocument();
-
-	// Returns the length of the bounding box on the longest measure.
-	double longestMeasurement() const;
-
-	// Calculates the given \c obj to the bounding box, adjusting
-	// extremas if necessary.
-	void calcObject (LDObjectPtr obj);
-
-	// Calculates the given \c vertex to the bounding box, adjusting
-	// extremas if necessary.
-	void calcVertex (const Vertex& vertex);
-
-	// Yields the center of the bounding box.
-	Vertex center() const;
-
-	// An operator overload for calcObject()
-	LDBoundingBox& operator<< (LDObjectPtr obj);
-
-	// An operator overload for calcVertex()
-	LDBoundingBox& operator<< (const Vertex& v);
-};
-
-extern const Vertex Origin;
 extern const Matrix IdentityMatrix;
 
 static const double Pi = 3.14159265358979323846;
 
-
-// =============================================================================
-// Plural expression
 template<typename T>
-static inline const char* Plural (T n)
-{
-	return (n != 1) ? "s" : "";
-}
-
-// =============================================================================
-// Templated clamp
-template<typename T>
-static inline T Clamp (T a, T min, T max)
+T clamp (T a, T min, T max)
 {
 	return (a > max) ? max : (a < min) ? min : a;
 }
 
-// Templated minimum
 template<typename T>
-static inline T Min (T a, T b)
+T min (T a, T b)
 {
 	return (a < b) ? a : b;
 }
 
-// Templated maximum
 template<typename T>
-static inline T Max (T a, T b)
+T max (T a, T b)
 {
 	return (a > b) ? a : b;
 }
 
-// Templated absolute value
 template<typename T>
-static inline T Abs (T a)
+T abs (T a)
 {
 	return (a >= 0) ? a : -a;
 }
 
 template<typename T>
-inline bool IsZero (T a)
+bool isZero (T a)
 {
-	return Abs<T> (a) < 0.00001;
+	return abs<T> (a) < 0.00001;
 }
 
 template<typename T>
-inline bool IsIntegral (T a)
+const char* plural (T n)
 {
-	return (Abs (a - floor(a)) < 0.00001) or (Abs (a - ceil(a)) < 0.00001);
+	return (not isZero (n - 1)) ? "s" : "";
 }
 
 template<typename T>
-inline bool IsWithin (T a, T b, T c)
+bool isInteger (T a)
+{
+	return (abs (a - floor(a)) < 0.00001) or (abs (a - ceil(a)) < 0.00001);
+}
+
+template<typename T>
+bool isInRange (T a, T b, T c)
 {
 	return a >= b and a <= c;
 }
 
 template<typename T>
-void RemoveDuplicates (T& a)
+void removeDuplicates (T& a)
 {
 	std::sort (a.begin(), a.end());
 	a.erase (std::unique (a.begin(), a.end()), a.end());
 }
 
-inline QString UTF16 (const char16_t* a)
-{
-	if (Q_LIKELY (sizeof(char16_t) == sizeof(unsigned short)))
-		return QString::fromUtf16 (reinterpret_cast<const unsigned short*> (a));
-
-	QVector<unsigned short> data;
-
-	for (const char16_t* ap = &a[0]; *ap != '\u0000'; ++ap)
-		data << *ap;
-
-	data << '\u0000';
-	return QString::fromUtf16 (data.constData());
-}
-
 //
 // Returns true if first arg is equal to any of the other args
 //
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/boundingbox.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -0,0 +1,144 @@
+/*
+ *  LDForge: LDraw parts authoring CAD
+ *  Copyright (C) 2013 - 2015 Teemu Piippo
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "boundingbox.h"
+#include "ldDocument.h"
+
+// =============================================================================
+//
+BoundingBox::BoundingBox()
+{
+	reset();
+}
+
+// =============================================================================
+//
+void BoundingBox::calculateFromCurrentDocument()
+{
+	reset();
+
+	if (CurrentDocument() == nullptr)
+		return;
+
+	for (LDObjectPtr obj : CurrentDocument()->objects())
+		calcObject (obj);
+}
+
+// =============================================================================
+//
+void BoundingBox::calcObject (LDObjectPtr obj)
+{
+	switch (obj->type())
+	{
+		case OBJ_Line:
+		case OBJ_Triangle:
+		case OBJ_Quad:
+		case OBJ_CondLine:
+		{
+			for (int i = 0; i < obj->numVertices(); ++i)
+				calcVertex (obj->vertex (i));
+		} break;
+
+		case OBJ_Subfile:
+		{
+			LDSubfilePtr ref = obj.staticCast<LDSubfile>();
+			LDObjectList objs = ref->inlineContents (true, false);
+
+			for (LDObjectPtr obj : objs)
+			{
+				calcObject (obj);
+				obj->destroy();
+			}
+		}
+		break;
+
+		default:
+			break;
+	}
+}
+
+// =============================================================================
+//
+BoundingBox& BoundingBox::operator<< (const Vertex& v)
+{
+	calcVertex (v);
+	return *this;
+}
+
+// =============================================================================
+//
+BoundingBox& BoundingBox::operator<< (LDObjectPtr obj)
+{
+	calcObject (obj);
+	return *this;
+}
+
+// =============================================================================
+//
+void BoundingBox::calcVertex (const Vertex& vertex)
+{
+	m_vertex0.setX (min (vertex.x(), m_vertex0.x()));
+	m_vertex0.setY (min (vertex.y(), m_vertex0.y()));
+	m_vertex0.setZ (min (vertex.z(), m_vertex0.z()));
+	m_vertex1.setX (max (vertex.x(), m_vertex1.x()));
+	m_vertex1.setY (max (vertex.y(), m_vertex1.y()));
+	m_vertex1.setZ (max (vertex.z(), m_vertex1.z()));
+	setEmpty (false);
+}
+
+// =============================================================================
+//
+void BoundingBox::reset()
+{
+	m_vertex0 = Vertex (10000.0, 10000.0, 10000.0);
+	m_vertex1 = Vertex (-10000.0, -10000.0, -10000.0);
+	setEmpty (true);
+}
+
+// =============================================================================
+//
+double BoundingBox::longestMeasurement() const
+{
+	double xscale = (m_vertex0.x() - m_vertex1.x());
+	double yscale = (m_vertex0.y() - m_vertex1.y());
+	double zscale = (m_vertex0.z() - m_vertex1.z());
+	double size = zscale;
+
+	if (xscale > yscale)
+	{
+		if (xscale > zscale)
+			size = xscale;
+	}
+	else if (yscale > zscale)
+		size = yscale;
+
+	if (abs (size) >= 2.0)
+		return abs (size / 2);
+
+	return 1.0;
+}
+
+// =============================================================================
+//
+Vertex BoundingBox::center() const
+{
+	return Vertex (
+		(m_vertex0.x() + m_vertex1.x()) / 2,
+		(m_vertex0.y() + m_vertex1.y()) / 2,
+		(m_vertex0.z() + m_vertex1.z()) / 2);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/boundingbox.h	Tue Jul 07 21:35:20 2015 +0300
@@ -0,0 +1,62 @@
+/*
+ *  LDForge: LDraw parts authoring CAD
+ *  Copyright (C) 2013 - 2015 Teemu Piippo
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+#include "main.h"
+
+//
+// Defines a bounding box that encompasses a given set of objects.
+// vertex0 is the minimum vertex, vertex1 is the maximum vertex.
+//
+class BoundingBox
+{
+	PROPERTY (private,	bool,		isEmpty,	setEmpty,		STOCK_WRITE)
+	PROPERTY (private,	Vertex,		vertex0,	setVertex0,		STOCK_WRITE)
+	PROPERTY (private,	Vertex,		vertex1,	setVertex1,		STOCK_WRITE)
+
+public:
+	// Constructs an empty bounding box.
+	BoundingBox();
+
+	// Clears the bounding box
+	void reset();
+
+	// Calculates the bounding box's values from the objects in the current
+	// document.
+	void calculateFromCurrentDocument();
+
+	// Returns the length of the bounding box on the longest measure.
+	double longestMeasurement() const;
+
+	// Calculates the given obj to the bounding box, adjusting
+	// extremas if necessary.
+	void calcObject (LDObjectPtr obj);
+
+	// Calculates the given vertex to the bounding box, adjusting
+	// extremas if necessary.
+	void calcVertex (const Vertex& vertex);
+
+	// Yields the center of the bounding box.
+	Vertex center() const;
+
+	// An operator overload for calcObject()
+	BoundingBox& operator<< (LDObjectPtr obj);
+
+	// An operator overload for calcVertex()
+	BoundingBox& operator<< (const Vertex& v);
+};
\ No newline at end of file
--- a/src/colorSelector.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/colorSelector.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -57,7 +57,7 @@
 		button->setMinimumSize (QSize (32, 32));
 		button->setMaximumSize (button->minimumSize());
 
-		if (ldcolor != null)
+		if (ldcolor != nullptr)
 		{
 			QString colorname;
 			QColor color (ldcolor.faceColor());
@@ -121,14 +121,14 @@
 	auto it = m_buttonsReversed.find (button);
 	LDColor color;
 
-	if (Q_UNLIKELY (button == null or it == m_buttonsReversed.end()
-		or (color = LDColor::fromIndex (*it)) == null))
+	if (Q_UNLIKELY (button == nullptr or it == m_buttonsReversed.end()
+		or (color = LDColor::fromIndex (*it)) == nullptr))
 	{
 		print ("colorButtonClicked() called with invalid sender");
 		return;
 	}
 
-	if (selection() != null)
+	if (selection() != nullptr)
 	{
 		auto it2 = m_buttons.find (selection().index());
 
@@ -145,7 +145,7 @@
 //
 void ColorSelector::drawColorInfo()
 {
-	if (selection() == null)
+	if (selection() == nullptr)
 	{
 		ui->colorLabel->setText ("---");
 		ui->iconLabel->setPixmap (QPixmap());
@@ -180,7 +180,7 @@
 //
 void ColorSelector::chooseDirectColor()
 {
-	QColor defcolor = selection() != null ? selection().faceColor() : Qt::white;
+	QColor defcolor = selection() != nullptr ? selection().faceColor() : Qt::white;
 	QColor newcolor = QColorDialog::getColor (defcolor);
 
 	if (not newcolor.isValid())
@@ -193,7 +193,7 @@
 //
 void ColorSelector::transparentCheckboxClicked()
 {
-	if (selection() == null or not selection().isDirect())
+	if (selection() == nullptr or not selection().isDirect())
 		return;
 
 	selectDirectColor (selection().faceColor());
@@ -205,7 +205,7 @@
 {
 	ColorSelector dlg (defval, parent);
 
-	if (dlg.exec() and dlg.selection() != null)
+	if (dlg.exec() and dlg.selection() != nullptr)
 	{
 		val = dlg.selection();
 		return true;
--- a/src/colorSelector.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/colorSelector.h	Tue Jul 07 21:35:20 2015 +0300
@@ -30,9 +30,9 @@
 	PROPERTY (private,	LDColor,	selection,	setSelection,	STOCK_WRITE)
 
 public:
-	explicit ColorSelector (LDColor defaultvalue = null, QWidget* parent = null);
+	explicit ColorSelector (LDColor defaultvalue = nullptr, QWidget* parent = nullptr);
 	virtual ~ColorSelector();
-	static bool selectColor (LDColor& val, LDColor defval = null, QWidget* parent = null);
+	static bool selectColor (LDColor& val, LDColor defval = nullptr, QWidget* parent = nullptr);
 
 private:
 	Ui_ColorSelUI*	ui;
--- a/src/colors.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/colors.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -59,13 +59,13 @@
 
 void LDColor::addLDConfigColor (qint32 index, LDColor color)
 {
-	assert (index >= 0 and index < countof (g_LDConfigColors));
-	g_LDConfigColors[index] = color;
+	if (index >= 0 and index < countof (g_LDConfigColors))
+		g_LDConfigColors[index] = color;
 }
 
 LDColor LDColor::fromIndex (qint32 index)
 {
-	if (index < countof (g_LDConfigColors) and g_LDConfigColors[index] != null)
+	if (index < countof (g_LDConfigColors) and g_LDConfigColors[index] != nullptr)
 		return g_LDConfigColors[index];
 
 	if (index >= 0x2000000)
@@ -88,7 +88,7 @@
 		return LDColor (color);
 	}
 
-	return null;
+	return nullptr;
 }
 
 QString LDColor::indexString() const
--- a/src/configDialog.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/configDialog.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -14,10 +14,6 @@
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *  =====================================================================
- *
- *  configDialog.cxx: Settings dialog and everything related to it.
- *  Actual configuration core is in config.cxx.
  */
 
 #include <QGridLayout>
@@ -59,25 +55,38 @@
 #endif
 	"All files (*.*)(*.*)";
 
-//
-//
-static struct LDExtProgInfo
+struct ExternalProgram
 {
+	ExternalProgram (const QString& name, const QString& iconName, QString* pathCfg,
+		bool* winePointer) :
+		name (name),
+		iconname (iconName),
+		path (pathCfg),
+		winePtr (winePointer),
+		inputField (nullptr),
+		pathSetButton (nullptr),
+		wineCheckbox (nullptr) {}
+
 	QString const	name;
 	QString const	iconname;
 	QString* const	path;
-	QLineEdit*		input;
-	QPushButton*	setPathButton;
-	bool* const		wine;
-	QCheckBox*		wineBox;
-} g_LDExtProgInfo[] =
+	bool* const		winePtr;
+	QLineEdit*		inputField;
+	QPushButton*	pathSetButton;
+	QCheckBox*		wineCheckbox;
+};
+
+#ifndef Q_OS_WIN32
+# define EXTPROG_WINE(NAME) (&cfg::NAME::#UsesWine)
+#else
+# define EXTPROG_WINE(NAME) nullptr
+#endif
+
+#define EXTPROG(NAME, LOWNAME) ExternalProgram (#NAME, #LOWNAME, \
+	&cfg::NAME##Path, EXTPROG_WINE (NAME)),
+
+static ExternalProgram ExternalProgramInfo[] =
 {
-#ifndef _WIN32
-# define EXTPROG(NAME, LOWNAME) { #NAME, #LOWNAME, &cfg::NAME##Path, null, null, \
-	&cfg::NAME##UsesWine, null },
-#else
-# define EXTPROG(NAME, LOWNAME) { #NAME, #LOWNAME, &cfg::NAME##Path, null, null, null, null },
-#endif
 	EXTPROG (Ytruder, ytruder)
 	EXTPROG (Rectifier, rectifier)
 	EXTPROG (Intersector, intersector)
@@ -87,98 +96,89 @@
 #undef EXTPROG
 };
 
-//
-//
+ConfigDialog::ConfigDialog (QWidget* parent, Qt::WindowFlags f) :
+	ConfigDialog (Tab (0), parent, f) {}
+
 ConfigDialog::ConfigDialog (ConfigDialog::Tab deftab, QWidget* parent, Qt::WindowFlags f) :
-	QDialog (parent, f)
+	QDialog (parent, f),
+	ui (*new Ui_ConfigUI)
 {
-	assert (g_win != null);
-	ui = new Ui_ConfigUI;
-	ui->setupUi (this);
+	ui.setupUi (this);
 
 	// Set defaults
-	m_applyToWidgetOptions ([&](QWidget* wdg, AbstractConfigEntry* conf)
+	applyToWidgetOptions ([&](QWidget* widget, AbstractConfigEntry* configEntry)
 	{
-		QVariant value (conf->toVariant());
-		QLineEdit* le;
-		QSpinBox* spinbox;
-		QDoubleSpinBox* doublespinbox;
-		QSlider* slider;
-		QCheckBox* checkbox;
-		QPushButton* button;
+		QVariant value = configEntry->toVariant();
 
-		if ((le = qobject_cast<QLineEdit*> (wdg)) != null)
+		if (qobject_cast<QLineEdit*> (widget))
 		{
-			le->setText (value.toString());
+			static_cast<QLineEdit*> (widget)->setText (value.toString());
 		}
-		elif ((spinbox = qobject_cast<QSpinBox*> (wdg)) != null)
+		else if (qobject_cast<QSpinBox*> (widget))
+		{
+			static_cast<QSpinBox*> (widget)->setValue (value.toInt());
+		}
+		else if (qobject_cast<QDoubleSpinBox*> (widget))
 		{
-			spinbox->setValue (value.toInt());
+			static_cast<QDoubleSpinBox*> (widget)->setValue (value.toDouble());
 		}
-		elif ((doublespinbox = qobject_cast<QDoubleSpinBox*> (wdg)) != null)
-		{
-			doublespinbox->setValue (value.toDouble());
-		}
-		elif ((slider = qobject_cast<QSlider*> (wdg)) != null)
+		else if (qobject_cast<QSlider*> (widget))
 		{
-			slider->setValue (value.toInt());
+			static_cast<QSlider*> (widget)->setValue (value.toInt());
 		}
-		elif ((checkbox = qobject_cast<QCheckBox*> (wdg)) != null)
+		else if (qobject_cast<QCheckBox*> (widget))
 		{
-			checkbox->setChecked (value.toBool());
+			static_cast<QCheckBox*> (widget)->setChecked (value.toBool());
 		}
-		elif ((button = qobject_cast<QPushButton*> (wdg)) != null)
+		else if (qobject_cast<QPushButton*> (widget))
 		{
-			setButtonBackground (button, value.toString());
-			connect (button, SIGNAL (clicked()), this, SLOT (setButtonColor()));
+			setButtonBackground (static_cast<QPushButton*> (widget), value.toString());
+			connect (widget, SIGNAL (clicked()), this, SLOT (setButtonColor()));
 		}
 		else
 		{
-			print ("Unknown widget of type %1\n", wdg->metaObject()->className());
+			print ("Unknown widget of type %1\n", widget->metaObject()->className());
 		}
 	});
 
-	g_win->applyToActions ([&](QAction* act)
+	if (parent)
 	{
-		addShortcut (act);
-	});
+		for (QAction* act : parent->findChildren<QAction*>())
+			addShortcut (act);
+	}
 
-	ui->shortcutsList->setSortingEnabled (true);
-	ui->shortcutsList->sortItems();
-	quickColors = LoadQuickColorList();
+	ui.shortcutsList->setSortingEnabled (true);
+	ui.shortcutsList->sortItems();
+	m_colorToolbarEntries = LoadQuickColorList();
 	updateQuickColorList();
 	initExtProgs();
 	selectPage (deftab);
-	connect (ui->shortcut_set, SIGNAL (clicked()), this, SLOT (slot_setShortcut()));
-	connect (ui->shortcut_reset, SIGNAL (clicked()), this, SLOT (slot_resetShortcut()));
-	connect (ui->shortcut_clear, SIGNAL (clicked()), this, SLOT (slot_clearShortcut()));
-	connect (ui->quickColor_add, SIGNAL (clicked()), this, SLOT (slot_setColor()));
-	connect (ui->quickColor_remove, SIGNAL (clicked()), this, SLOT (slot_delColor()));
-	connect (ui->quickColor_edit, SIGNAL (clicked()), this, SLOT (slot_setColor()));
-	connect (ui->quickColor_addSep, SIGNAL (clicked()), this, SLOT (slot_addColorSeparator()));
-	connect (ui->quickColor_moveUp, SIGNAL (clicked()), this, SLOT (slot_moveColor()));
-	connect (ui->quickColor_moveDown, SIGNAL (clicked()), this, SLOT (slot_moveColor()));
-	connect (ui->quickColor_clear, SIGNAL (clicked()), this, SLOT (slot_clearColors()));
-	connect (ui->findDownloadPath, SIGNAL (clicked (bool)), this, SLOT (slot_findDownloadFolder()));
-	connect (ui->buttonBox, SIGNAL (clicked (QAbstractButton*)),
+	connect (ui.shortcut_set, SIGNAL (clicked()), this, SLOT (slot_setShortcut()));
+	connect (ui.shortcut_reset, SIGNAL (clicked()), this, SLOT (slot_resetShortcut()));
+	connect (ui.shortcut_clear, SIGNAL (clicked()), this, SLOT (slot_clearShortcut()));
+	connect (ui.quickColor_add, SIGNAL (clicked()), this, SLOT (slot_setColor()));
+	connect (ui.quickColor_remove, SIGNAL (clicked()), this, SLOT (slot_delColor()));
+	connect (ui.quickColor_edit, SIGNAL (clicked()), this, SLOT (slot_setColor()));
+	connect (ui.quickColor_addSep, SIGNAL (clicked()), this, SLOT (slot_addColorSeparator()));
+	connect (ui.quickColor_moveUp, SIGNAL (clicked()), this, SLOT (slot_moveColor()));
+	connect (ui.quickColor_moveDown, SIGNAL (clicked()), this, SLOT (slot_moveColor()));
+	connect (ui.quickColor_clear, SIGNAL (clicked()), this, SLOT (slot_clearColors()));
+	connect (ui.findDownloadPath, SIGNAL (clicked()), this, SLOT (slot_findDownloadFolder()));
+	connect (ui.buttonBox, SIGNAL (clicked (QAbstractButton*)),
 		this, SLOT (buttonClicked (QAbstractButton*)));
-	connect (ui->m_pages, SIGNAL (currentChanged (int)), this, SLOT (selectPage (int)));
-	connect (ui->m_pagelist, SIGNAL (currentRowChanged (int)), this, SLOT (selectPage (int)));
+	connect (ui.m_pages, SIGNAL (currentChanged (int)), this, SLOT (selectPage (int)));
+	connect (ui.m_pagelist, SIGNAL (currentRowChanged (int)), this, SLOT (selectPage (int)));
 }
 
-//
-//
 ConfigDialog::~ConfigDialog()
 {
-	delete ui;
+	delete &ui;
 }
 
-//
-//
 void ConfigDialog::selectPage (int row)
 {
-	ui->m_pagelist->setCurrentRow (row);
-	ui->m_pages->setCurrentIndex (row);
+	ui.m_pagelist->setCurrentRow (row);
+	ui.m_pages->setCurrentIndex (row);
 }
 
 //
@@ -186,10 +186,12 @@
 //
 void ConfigDialog::addShortcut (QAction* act)
 {
-	ShortcutListItem* item = new ShortcutListItem;
+	QListWidgetItem* item = new QListWidgetItem;
 	item->setIcon (act->icon());
-	item->setAction (act);
-	item->setSequence (act->shortcut());
+
+	ShortcutInfo& info = m_shortcutInfo[item];
+	info.action = act;
+	info.sequence = act->shortcut();
 	setShortcutText (item);
 
 	// If the action doesn't have a valid icon, use an empty one
@@ -197,7 +199,7 @@
 	if (act->icon().isNull())
 		item->setIcon (GetIcon ("empty"));
 
-	ui->shortcutsList->insertItem (ui->shortcutsList->count(), item);
+	ui.shortcutsList->insertItem (ui.shortcutsList->count(), item);
 }
 
 //
@@ -208,7 +210,7 @@
 	QGridLayout* pathsLayout = new QGridLayout;
 	int row = 0;
 
-	for (LDExtProgInfo& info : g_LDExtProgInfo)
+	for (ExternalProgram& info : ExternalProgramInfo)
 	{
 		QLabel* icon = new QLabel,
 		*progLabel = new QLabel (info.name);
@@ -218,8 +220,8 @@
 		icon->setPixmap (GetIcon (info.iconname));
 		input->setText (*info.path);
 		setPathButton->setIcon (GetIcon ("folder"));
-		info.input = input;
-		info.setPathButton = setPathButton;
+		info.inputField = input;
+		info.pathSetButton = setPathButton;
 
 		connect (setPathButton, SIGNAL (clicked()), this, SLOT (slot_setExtProgPath()));
 
@@ -228,23 +230,22 @@
 		pathsLayout->addWidget (input, row, 2);
 		pathsLayout->addWidget (setPathButton, row, 3);
 
-		if (info.wine != null)
+		if (info.winePtr != nullptr)
 		{
 			QCheckBox* wineBox = new QCheckBox ("Wine");
-			wineBox->setChecked (*info.wine);
-			info.wineBox = wineBox;
+			wineBox->setChecked (*info.winePtr);
+			info.wineCheckbox = wineBox;
 			pathsLayout->addWidget (wineBox, row, 4);
 		}
 
 		++row;
 	}
 
-	ui->extProgs->setLayout (pathsLayout);
+	ui.extProgs->setLayout (pathsLayout);
 }
 
-void ConfigDialog::m_applyToWidgetOptions (std::function<void (QWidget*, AbstractConfigEntry*)> func)
+void ConfigDialog::applyToWidgetOptions (std::function<void (QWidget*, AbstractConfigEntry*)> func)
 {
-	// Apply configuration
 	for (QWidget* widget : findChildren<QWidget*>())
 	{
 		if (not widget->objectName().startsWith ("config"))
@@ -253,7 +254,7 @@
 		QString confname (widget->objectName().mid (strlen ("config")));
 		AbstractConfigEntry* conf (Config::FindByName (confname));
 
-		if (conf == null)
+		if (conf == nullptr)
 		{
 			print ("Couldn't find configuration entry named %1", confname);
 			continue;
@@ -268,60 +269,51 @@
 //
 void ConfigDialog::applySettings()
 {
-	m_applyToWidgetOptions ([&](QWidget* widget, AbstractConfigEntry* conf)
+	applyToWidgetOptions ([&](QWidget* widget, AbstractConfigEntry* conf)
 	{
 		QVariant value (conf->toVariant());
-		QLineEdit* le;
-		QSpinBox* spinbox;
-		QDoubleSpinBox* doublespinbox;
-		QSlider* slider;
-		QCheckBox* checkbox;
-		QPushButton* button;
 
-		if ((le = qobject_cast<QLineEdit*> (widget)) != null)
-			value = le->text();
-		elif ((spinbox = qobject_cast<QSpinBox*> (widget)) != null)
-			value = spinbox->value();
-		elif ((doublespinbox = qobject_cast<QDoubleSpinBox*> (widget)) != null)
-			value = doublespinbox->value();
-		elif ((slider = qobject_cast<QSlider*> (widget)) != null)
-			value = slider->value();
-		elif ((checkbox = qobject_cast<QCheckBox*> (widget)) != null)
-			value = checkbox->isChecked();
-		elif ((button = qobject_cast<QPushButton*> (widget)) != null)
-			value = m_buttonColors[button];
+		if (qobject_cast<QLineEdit*> (widget))
+			value = static_cast<QLineEdit*> (widget)->text();
+		else if (qobject_cast<QSpinBox*> (widget))
+			value = static_cast<QSpinBox*> (widget)->value();
+		else if (qobject_cast<QDoubleSpinBox*> (widget))
+			value = static_cast<QDoubleSpinBox*> (widget)->value();
+		else if (qobject_cast<QSlider*> (widget))
+			value = static_cast<QSlider*> (widget)->value();
+		else if (qobject_cast<QCheckBox*> (widget))
+			value = static_cast<QCheckBox*> (widget)->isChecked();
+		else if (qobject_cast<QPushButton*> (widget))
+			value = m_buttonColors[static_cast<QPushButton*> (widget)];
 		else
 			print ("Unknown widget of type %1\n", widget->metaObject()->className());
 
 		conf->loadFromVariant (value);
 	});
 
-	// Rebuild the quick color toolbar
-	g_win->setQuickColors (quickColors);
 	cfg::QuickColorToolbar = quickColorString();
 
-	// Ext program settings
-	for (const LDExtProgInfo& info : g_LDExtProgInfo)
+	// External program settings
+	for (const ExternalProgram& info : ExternalProgramInfo)
 	{
-		*info.path = info.input->text();
+		*info.path = info.inputField->text();
 
-		if (info.wine != null)
-			*info.wine = info.wineBox->isChecked();
+		if (info.winePtr != nullptr)
+			*info.winePtr = info.wineCheckbox->isChecked();
 	}
 
 	// Apply shortcuts
-	for (int i = 0; i < ui->shortcutsList->count(); ++i)
+	for (int i = 0; i < ui.shortcutsList->count(); ++i)
 	{
-		auto item = static_cast<ShortcutListItem*> (ui->shortcutsList->item (i));
-		item->action()->setShortcut (item->sequence());
+		QListWidgetItem* item = ui.shortcutsList->item (i);
+		ShortcutInfo& info = m_shortcutInfo[item];
+		info.action->setShortcut (info.sequence);
 	}
 
 	Config::Save();
 	LDDocument::current()->reloadAllSubfiles();
 	LoadLogoStuds();
-	g_win->R()->setBackground();
-	g_win->doFullRefresh();
-	g_win->updateDocumentList();
+	emit settingsApplied();
 }
 
 //
@@ -329,18 +321,18 @@
 //
 void ConfigDialog::buttonClicked (QAbstractButton* button)
 {
-	QDialogButtonBox* dbb = ui->buttonBox;
+	QDialogButtonBox* dbb = ui.buttonBox;
 
 	if (button == dbb->button (QDialogButtonBox::Ok))
 	{
 		applySettings();
 		accept();
 	}
-	elif (button == dbb->button (QDialogButtonBox::Apply))
+	else if (button == dbb->button (QDialogButtonBox::Apply))
 	{
 		applySettings();
 	}
-	elif (button == dbb->button (QDialogButtonBox::Cancel))
+	else if (button == dbb->button (QDialogButtonBox::Cancel))
 	{
 		reject();
 	}
@@ -349,15 +341,15 @@
 //
 // Update the list of color toolbar items in the quick color tab.
 //
-void ConfigDialog::updateQuickColorList (LDQuickColor* sel)
+void ConfigDialog::updateQuickColorList (ColorToolbarEntry* selected)
 {
-	for (QListWidgetItem * item : quickColorItems)
+	for (QListWidgetItem* item : m_colorToolbarItems)
 		delete item;
 
-	quickColorItems.clear();
+	m_colorToolbarItems.clear();
 
 	// Init table items
-	for (LDQuickColor& entry : quickColors)
+	for (ColorToolbarEntry& entry : m_colorToolbarEntries)
 	{
 		QListWidgetItem* item = new QListWidgetItem;
 
@@ -370,7 +362,7 @@
 		{
 			LDColor col (entry.color());
 
-			if (col == null)
+			if (col == nullptr)
 			{
 				item->setText ("[[unknown color]]");
 				item->setIcon (GetIcon ("error"));
@@ -382,13 +374,13 @@
 			}
 		}
 
-		ui->quickColorList->addItem (item);
-		quickColorItems << item;
+		ui.quickColorList->addItem (item);
+		m_colorToolbarItems << item;
 
-		if (sel and &entry == sel)
+		if (&entry == selected)
 		{
-			ui->quickColorList->setCurrentItem (item);
-			ui->quickColorList->scrollToItem (item);
+			ui.quickColorList->setCurrentItem (item);
+			ui.quickColorList->scrollToItem (item);
 		}
 	}
 }
@@ -398,9 +390,9 @@
 //
 void ConfigDialog::slot_setColor()
 {
-	LDQuickColor* entry = null;
-	QListWidgetItem* item = null;
-	const bool isNew = static_cast<QPushButton*> (sender()) == ui->quickColor_add;
+	ColorToolbarEntry* entry = nullptr;
+	QListWidgetItem* item = nullptr;
+	const bool isNew = static_cast<QPushButton*> (sender()) == ui.quickColor_add;
 
 	if (not isNew)
 	{
@@ -409,30 +401,30 @@
 		if (not item)
 			return;
 
-		int i = getItemRow (item, quickColorItems);
-		entry = &quickColors[i];
+		int i = getItemRow (item, m_colorToolbarItems);
+		entry = &m_colorToolbarEntries[i];
 
 		if (entry->isSeparator() == true)
 			return; // don't color separators
 	}
 
-	LDColor defval = entry ? entry->color() : null;
+	LDColor defval = entry ? entry->color() : nullptr;
 	LDColor val;
 
 	if (not ColorSelector::selectColor (val, defval, this))
 		return;
 
-	if (entry != null)
+	if (entry != nullptr)
 	{
 		entry->setColor (val);
 	}
 	else
 	{
-		LDQuickColor entry (val, null);
+		ColorToolbarEntry entry (val, nullptr);
 		item = getSelectedQuickColor();
-		int idx = (item) ? getItemRow (item, quickColorItems) + 1 : quickColorItems.size();
-		quickColors.insert (idx, entry);
-		entry = quickColors[idx];
+		int idx = (item) ? getItemRow (item, m_colorToolbarItems) + 1 : m_colorToolbarItems.size();
+		m_colorToolbarEntries.insert (idx, entry);
+		entry = m_colorToolbarEntries[idx];
 	}
 
 	updateQuickColorList (entry);
@@ -443,11 +435,11 @@
 //
 void ConfigDialog::slot_delColor()
 {
-	if (ui->quickColorList->selectedItems().isEmpty())
+	if (ui.quickColorList->selectedItems().isEmpty())
 		return;
 
-	QListWidgetItem* item = ui->quickColorList->selectedItems() [0];
-	quickColors.removeAt (getItemRow (item, quickColorItems));
+	QListWidgetItem* item = ui.quickColorList->selectedItems() [0];
+	m_colorToolbarEntries.removeAt (getItemRow (item, m_colorToolbarItems));
 	updateQuickColorList();
 }
 
@@ -456,20 +448,20 @@
 //
 void ConfigDialog::slot_moveColor()
 {
-	const bool up = (static_cast<QPushButton*> (sender()) == ui->quickColor_moveUp);
+	const bool up = (static_cast<QPushButton*> (sender()) == ui.quickColor_moveUp);
 
-	if (ui->quickColorList->selectedItems().isEmpty())
+	if (ui.quickColorList->selectedItems().isEmpty())
 		return;
 
-	QListWidgetItem* item = ui->quickColorList->selectedItems() [0];
-	int idx = getItemRow (item, quickColorItems);
+	QListWidgetItem* item = ui.quickColorList->selectedItems() [0];
+	int idx = getItemRow (item, m_colorToolbarItems);
 	int dest = up ? (idx - 1) : (idx + 1);
 
-	if (dest < 0 or dest >= quickColorItems.size())
+	if (dest < 0 or dest >= m_colorToolbarItems.size())
 		return; // destination out of bounds
 
-	qSwap (quickColors[dest], quickColors[idx]);
-	updateQuickColorList (&quickColors[dest]);
+	qSwap (m_colorToolbarEntries[dest], m_colorToolbarEntries[idx]);
+	updateQuickColorList (&m_colorToolbarEntries[dest]);
 }
 
 //
@@ -478,8 +470,8 @@
 //
 void ConfigDialog::slot_addColorSeparator()
 {
-	quickColors << LDQuickColor::getSeparator();
-	updateQuickColorList (&quickColors[quickColors.size() - 1]);
+	m_colorToolbarEntries << ColorToolbarEntry::getSeparator();
+	updateQuickColorList (&m_colorToolbarEntries[m_colorToolbarEntries.size() - 1]);
 }
 
 //
@@ -488,7 +480,7 @@
 //
 void ConfigDialog::slot_clearColors()
 {
-	quickColors.clear();
+	m_colorToolbarEntries.clear();
 	updateQuickColorList();
 }
 
@@ -498,7 +490,7 @@
 {
 	QPushButton* button = qobject_cast<QPushButton*> (sender());
 
-	if (button == null)
+	if (button == nullptr)
 	{
 		print ("setButtonColor: null sender!\n");
 		return;
@@ -548,21 +540,21 @@
 //
 QListWidgetItem* ConfigDialog::getSelectedQuickColor()
 {
-	if (ui->quickColorList->selectedItems().isEmpty())
-		return null;
+	if (ui.quickColorList->selectedItems().isEmpty())
+		return nullptr;
 
-	return ui->quickColorList->selectedItems() [0];
+	return ui.quickColorList->selectedItems() [0];
 }
 
 //
 // Get the list of shortcuts selected
 //
-QList<ShortcutListItem*> ConfigDialog::getShortcutSelection()
+QList<QListWidgetItem*> ConfigDialog::getShortcutSelection()
 {
-	QList<ShortcutListItem*> out;
+	QList<QListWidgetItem*> out;
 
-	for (QListWidgetItem* entry : ui->shortcutsList->selectedItems())
-		out << static_cast<ShortcutListItem*> (entry);
+	for (QListWidgetItem* entry : ui.shortcutsList->selectedItems())
+		out << entry;
 
 	return out;
 }
@@ -572,15 +564,20 @@
 //
 void ConfigDialog::slot_setShortcut()
 {
-	QList<ShortcutListItem*> sel = getShortcutSelection();
+	QList<QListWidgetItem*> sel = getShortcutSelection();
 
 	if (sel.size() < 1)
 		return;
 
-	ShortcutListItem* item = sel[0];
+	QListWidgetItem* item = sel[0];
+	ShortcutInfo& info = m_shortcutInfo[item];
+	KeySequenceDialog dlg (info.sequence, this);
 
-	if (KeySequenceDialog::staticDialog (item, this))
+	if (dlg.exec() == QDialog::Accepted)
+	{
+		info.sequence = dlg.keySequence();
 		setShortcutText (item);
+	}
 }
 
 //
@@ -588,11 +585,12 @@
 //
 void ConfigDialog::slot_resetShortcut()
 {
-	QList<ShortcutListItem*> sel = getShortcutSelection();
+	QList<QListWidgetItem*> selection = getShortcutSelection();
 
-	for (ShortcutListItem* item : sel)
+	for (QListWidgetItem* item : selection)
 	{
-		item->setSequence (MainWindow::defaultShortcut (item->action()));
+		ShortcutInfo& info = m_shortcutInfo[item];
+		info.sequence = (MainWindow::defaultShortcut (info.action));
 		setShortcutText (item);
 	}
 }
@@ -602,11 +600,11 @@
 //
 void ConfigDialog::slot_clearShortcut()
 {
-	QList<ShortcutListItem*> sel = getShortcutSelection();
+	QList<QListWidgetItem*> sel = getShortcutSelection();
 
-	for (ShortcutListItem* item : sel)
+	for (QListWidgetItem* item : sel)
 	{
-		item->setSequence (QKeySequence());
+		m_shortcutInfo[item].sequence = QKeySequence();
 		setShortcutText (item);
 	}
 }
@@ -616,24 +614,19 @@
 //
 void ConfigDialog::slot_setExtProgPath()
 {
-	const LDExtProgInfo* info = null;
-
-	for (const LDExtProgInfo& it : g_LDExtProgInfo)
+	for (const ExternalProgram& info : ExternalProgramInfo)
 	{
-		if (it.setPathButton == sender())
-		{
-			info = &it;
-			break;
-		}
-	}
+		if (info.pathSetButton != sender())
+			continue;
+
+		QString filePath = QFileDialog::getOpenFileName (this, format ("Path to %1", info.name),
+			*info.path, g_extProgPathFilter);
 
-	assert (info != null);
-	QString fpath = QFileDialog::getOpenFileName (this, format ("Path to %1", info->name), *info->path, g_extProgPathFilter);
+		if (filePath.isEmpty())
+			return;
 
-	if (fpath.isEmpty())
-		return;
-
-	info->input->setText (fpath);
+		info.inputField->setText (filePath);
+	}
 }
 
 //
@@ -641,22 +634,27 @@
 //
 void ConfigDialog::slot_findDownloadFolder()
 {
-	QString dpath = QFileDialog::getExistingDirectory();
+	QString dirPath = QFileDialog::getExistingDirectory();
 
-	if (not dpath.isEmpty())
-		ui->configDownloadFilePath->setText (dpath);
+	if (not dirPath.isEmpty())
+		ui.configDownloadFilePath->setText (dirPath);
 }
 
 //
 //
 // Updates the text string for a given shortcut list item
 //
-void ConfigDialog::setShortcutText (ShortcutListItem* item)
+void ConfigDialog::setShortcutText (QListWidgetItem* item)
 {
-	QAction* act = item->action();
-	QString label = act->iconText();
-	QString keybind = item->sequence().toString();
-	item->setText (format ("%1 (%2)", label, keybind));
+	ShortcutInfoMap::iterator it = m_shortcutInfo.find (item);
+
+	if (it != m_shortcutInfo.end())
+	{
+		QAction* action = it->action;
+		QString label = action->iconText();
+		QString keybind = it->sequence.toString();
+		item->setText (format ("%1 (%2)", label, keybind));
+	}
 }
 
 //
@@ -664,72 +662,61 @@
 //
 QString ConfigDialog::quickColorString()
 {
-	QString val;
+	QString result;
 
-	for (const LDQuickColor& entry : quickColors)
+	for (const ColorToolbarEntry& entry : m_colorToolbarEntries)
 	{
-		if (val.length() > 0)
-			val += ':';
+		if (not result.isEmpty())
+			result += ':';
 
 		if (entry.isSeparator())
-			val += '|';
+			result += '|';
 		else
-			val += format ("%1", entry.color().index());
+			result += format ("%1", entry.color().index());
 	}
 
-	return val;
+	return result;
 }
 
 //
 //
 KeySequenceDialog::KeySequenceDialog (QKeySequence seq, QWidget* parent, Qt::WindowFlags f) :
-	QDialog (parent, f), seq (seq)
+	QDialog (parent, f), m_keySequence (seq)
 {
-	lb_output = new QLabel;
-	IMPLEMENT_DIALOG_BUTTONS
-
-	setWhatsThis (tr ("Into this dialog you can input a key sequence for use as a "
-		"shortcut in LDForge. Use OK to confirm the new shortcut and Cancel to "
-		"dismiss."));
+	m_outputLabel = new QLabel;
+	m_buttonBox = new QDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+	connect (m_buttonBox, SIGNAL (accepted()), this, SLOT (accept()));
+	connect (m_buttonBox, SIGNAL (rejected()), this, SLOT (reject()));
 
 	QVBoxLayout* layout = new QVBoxLayout;
-	layout->addWidget (lb_output);
-	layout->addWidget (bbx_buttons);
+	layout->addWidget (m_outputLabel);
+	layout->addWidget (m_buttonBox);
 	setLayout (layout);
-
 	updateOutput();
 }
 
 //
 //
-bool KeySequenceDialog::staticDialog (ShortcutListItem* item, QWidget* parent)
-{
-	KeySequenceDialog dlg (item->sequence(), parent);
-
-	if (dlg.exec() == QDialog::Rejected)
-		return false;
-
-	item->setSequence (dlg.seq);
-	return true;
-}
-
-//
-//
 void KeySequenceDialog::updateOutput()
 {
-	QString shortcut = seq.toString();
+	QString shortcut = m_keySequence.toString();
 
-	if (seq == QKeySequence())
+	if (m_keySequence.isEmpty())
 		shortcut = "&lt;empty&gt;";
 
 	QString text = format ("<center><b>%1</b></center>", shortcut);
-	lb_output->setText (text);
+	m_outputLabel->setText (text);
 }
 
 //
 //
 void KeySequenceDialog::keyPressEvent (QKeyEvent* ev)
 {
-	seq = ev->key() + ev->modifiers();
+	m_keySequence = ev->key() | ev->modifiers();
 	updateOutput();
 }
+
+QKeySequence KeySequenceDialog::keySequence() const
+{
+	return m_keySequence;
+}
--- a/src/configDialog.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/configDialog.h	Tue Jul 07 21:35:20 2015 +0300
@@ -20,21 +20,6 @@
 #include "mainWindow.h"
 #include <QDialog>
 
-class Ui_ConfigUI;
-class QLabel;
-class QDoubleSpinBox;
-
-// =============================================================================
-class ShortcutListItem : public QListWidgetItem
-{
-	PROPERTY (public,	QAction*,		action,		setAction,		STOCK_WRITE)
-	PROPERTY (public,	QKeySequence,	sequence,	setSequence,	STOCK_WRITE)
-
-public:
-	explicit ShortcutListItem (QListWidget* view = null, int type = Type) :
-		QListWidgetItem (view, type) {}
-};
-
 // =============================================================================
 class ConfigDialog : public QDialog
 {
@@ -53,27 +38,40 @@
 		DownloadTab
 	};
 
-	explicit ConfigDialog (Tab deftab = InterfaceTab, QWidget* parent = null, Qt::WindowFlags f = 0);
+	struct ShortcutInfo
+	{
+		QAction* action;
+		QKeySequence sequence;
+	};
+
+	using ShortcutInfoMap = QMap<QListWidgetItem*, ShortcutInfo>;
+
+	ConfigDialog (QWidget* parent = nullptr, Qt::WindowFlags f = 0);
+	ConfigDialog (Tab deftab, QWidget* parent = nullptr, Qt::WindowFlags f = 0);
 	virtual ~ConfigDialog();
 
-	QList<LDQuickColor> quickColors;
-
 private:
-	Ui_ConfigUI* ui;
-	QList<QListWidgetItem*> quickColorItems;
+	class Ui_ConfigUI& ui;
+	QList<QListWidgetItem*> m_colorToolbarItems;
+	QList<ColorToolbarEntry> m_colorToolbarEntries;
 	QMap<QPushButton*, QColor> m_buttonColors;
+	ShortcutInfoMap m_shortcutInfo;
+	bool m_hasValidMainWindow;
 
 	void applySettings();
 	void addShortcut (QAction* act);
 	void setButtonBackground (QPushButton* button, QString value);
-	void updateQuickColorList (LDQuickColor* sel = null);
-	void setShortcutText (ShortcutListItem* item);
+	void updateQuickColorList (ColorToolbarEntry* selected = nullptr);
+	void setShortcutText (QListWidgetItem* item);
 	int getItemRow (QListWidgetItem* item, QList<QListWidgetItem*>& haystack);
 	QString quickColorString();
 	QListWidgetItem* getSelectedQuickColor();
-	QList<ShortcutListItem*> getShortcutSelection();
+	QList<QListWidgetItem*> getShortcutSelection();
 	void initExtProgs();
-	void m_applyToWidgetOptions (std::function<void (QWidget*, AbstractConfigEntry*)> func);
+	void applyToWidgetOptions (std::function<void (QWidget*, AbstractConfigEntry*)> func);
+
+signals:
+	void settingsApplied();
 
 private slots:
 	void setButtonColor();
@@ -98,16 +96,16 @@
 	Q_OBJECT
 
 public:
-	explicit KeySequenceDialog (QKeySequence seq, QWidget* parent = null, Qt::WindowFlags f = 0);
-	static bool staticDialog (ShortcutListItem* item, QWidget* parent = null);
-
-	QLabel* lb_output;
-	QDialogButtonBox* bbx_buttons;
-	QKeySequence seq;
+	explicit KeySequenceDialog (QKeySequence keySequence, QWidget* parent = nullptr, Qt::WindowFlags f = 0);
+	QKeySequence keySequence() const;
 
 private:
 	void updateOutput();
 
+	class QLabel* m_outputLabel;
+	QDialogButtonBox* m_buttonBox;
+	QKeySequence m_keySequence;
+
 private slots:
 	virtual void keyPressEvent (QKeyEvent* ev) override;
 };
--- a/src/configuration.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/configuration.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -40,8 +40,6 @@
 # define EXTENSION ".cfg"
 #endif // _WIN32
 
-#define MAX_CONFIG 512
-
 static QMap<QString, AbstractConfigEntry*>	EntriesByName;
 static QList<AbstractConfigEntry*>			ConfigurationEntries;
 
@@ -50,7 +48,7 @@
 
 void Config::Initialize()
 {
-	SetupConfigurationLists();
+	setupConfigurationLists();
 	print ("Configuration initialized with %1 entries\n", ConfigurationEntries.size());
 }
 
@@ -70,14 +68,14 @@
 
 	for (AbstractConfigEntry* cfg : ConfigurationEntries)
 	{
-		if (cfg == null)
+		if (cfg == nullptr)
 			break;
 
 		QVariant val = settings->value (cfg->name(), cfg->getDefaultAsVariant());
 		cfg->loadFromVariant (val);
 	}
 
-	if (g_win != null)
+	if (g_win != nullptr)
 		g_win->loadShortcuts (settings);
 
 	delete settings;
@@ -99,7 +97,7 @@
 			settings->remove (cfg->name());
 	}
 
-	if (g_win != null)
+	if (g_win != nullptr)
 		g_win->saveShortcuts (settings);
 
 	settings->sync();
@@ -156,7 +154,7 @@
 AbstractConfigEntry* Config::FindByName (QString const& name)
 {
 	auto it = EntriesByName.find (name);
-	return (it != EntriesByName.end()) ? *it : null;
+	return (it != EntriesByName.end()) ? *it : nullptr;
 }
 
 template<typename T>
@@ -165,7 +163,7 @@
 	auto it = EntriesByName.find (name);
 
 	if (it == EntriesByName.end())
-		return null;
+		return nullptr;
 
 	AbstractConfigEntry* cfg = it.value();
 
--- a/src/configuration.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/configuration.h	Tue Jul 07 21:35:20 2015 +0300
@@ -22,6 +22,7 @@
 #include <QKeySequence>
 #include "macros.h"
 #include "basics.h"
+#include "vertex.h"
 
 class QSettings;
 class AbstractConfigEntry;
--- a/src/crashCatcher.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/crashCatcher.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -16,14 +16,14 @@
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <QProcess>
-#include <QTemporaryFile>
-#include <unistd.h>
-#include <signal.h>
-#include "crashCatcher.h"
-#include "dialogs.h"
- 
 #ifdef __unix__
+# include <QProcess>
+# include <QTemporaryFile>
+# include <unistd.h>
+# include <signal.h>
+# include "crashCatcher.h"
+# include "dialogs.h"
+
 # ifdef Q_OS_LINUX
 #  include <sys/prctl.h>
 # endif
@@ -31,9 +31,6 @@
 // Is the crash catcher active now?
 static bool IsCrashCatcherActive = false;
 
-// If an assertion failed, what was it?
-static QString AssertionFailureText;
-
 // List of signals to catch and crash on
 static QList<int> SignalsToCatch ({
 	SIGSEGV, // segmentation fault
@@ -87,9 +84,9 @@
 	// Linux doesn't allow ptrace to be used on anything but direct child processes
 	// so we need to use prctl to register an exception to this to allow GDB attach to us.
 	// We need to do this now and no earlier because only now we actually know GDB's PID.
-#ifdef Q_OS_LINUX
+# ifdef Q_OS_LINUX
 	prctl (PR_SET_PTRACER, proc.pid(), 0, 0, 0);
-#endif
+# endif
 
 	proc.waitForFinished (1000);
 	QString output (proc.readAllStandardOutput());
@@ -98,16 +95,11 @@
 
 	if (f.open (QIODevice::WriteOnly))
 	{
-		fprint (f, format ("=== Program crashed with signal %1 ===\n\n%2"
-			"GDB stdout:\n%3\nGDB stderr:\n%4\n", sig,
-			(not AssertionFailureText.isEmpty()) ? AssertionFailureText + "\n\n" : "",
-			output, err));
+		fprint (f, format ("=== Program crashed with signal %1 ===\n\n"
+			"GDB stdout:\n%3\nGDB stderr:\n%4\n", sig, output, err));
 		f.close();
 	}
 
-	if (not AssertionFailureText.isEmpty())
-		printf ("Assertion failed: \"%s\".\n", qPrintable (AssertionFailureText));
-
 	printf ("Backtrace written to " UNIXNAME "-crash.log. Aborting.\n");
 	FinalAbort();
 }
@@ -134,28 +126,4 @@
 
 	print ("Crash catcher hooked to signals: %1\n", SignalsToCatch);
 }
-
-#endif // #ifdef __unix__
-
-// -------------------------------------------------------------------------------------------------
-//
-// This function catches an assertion failure. It must be readily available in both Windows and
-// Linux. We display the bomb box straight in Windows while in Linux we let abort() trigger
-// the signal handler, which will cause the usual bomb box with GDB diagnostics. Said prompt will
-// embed the assertion failure information.
-//
-void HandleAssertFailure (const char* file, int line, const char* funcname, const char* expr)
-{
-#ifdef __unix__
-	AssertionFailureText = format ("%1:%2: %3: %4", file, line, funcname, expr);
-#else
-	DisplayBombBox (format (
-		"<p><b>File</b>: <tt>%1</tt><br />"
-		"<b>Line</b>: <tt>%2</tt><br />"
-		"<b>Function:</b> <tt>%3</tt></p>"
-		"<p>Assertion <b><tt>`%4'</tt></b> failed.</p>",
-		file, line, funcname, expr));
-#endif
-
-	abort();
-}
\ No newline at end of file
+#endif // #ifdef __unix__
\ No newline at end of file
--- a/src/crashCatcher.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/crashCatcher.h	Tue Jul 07 21:35:20 2015 +0300
@@ -22,5 +22,5 @@
 #ifdef __unix__
 void InitCrashCatcher();
 #else // ifdef __unix__
-# define InitCrashCatcher()
+inline void InitCrashCatcher() {}
 #endif // ifdef __unix__
--- a/src/dialogs.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/dialogs.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -92,7 +92,7 @@
 	LDGLOverlay& info = g_win->R()->getOverlay (newcam);
 	RadioDefault<int> (newcam, m_cameraArgs);
 
-	if (info.img != null)
+	if (info.img != nullptr)
 	{
 		ui->filename->setText (info.fname);
 		ui->originX->setValue (info.ox);
@@ -144,7 +144,7 @@
 
 void OverlayDialog::slot_fpath()
 {
-	ui->filename->setText (QFileDialog::getOpenFileName (null, "Overlay image"));
+	ui->filename->setText (QFileDialog::getOpenFileName (nullptr, "Overlay image"));
 }
 
 void OverlayDialog::slot_help()
@@ -326,7 +326,7 @@
 // =============================================================================
 void ExtProgPathPrompt::findPath()
 {
-	QString path = QFileDialog::getOpenFileName (null, "", "", g_extProgPathFilter);
+	QString path = QFileDialog::getOpenFileName (nullptr, "", "", g_extProgPathFilter);
 
 	if (not path.isEmpty())
 		ui->m_path->setText (path);
--- a/src/dialogs.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/dialogs.h	Tue Jul 07 21:35:20 2015 +0300
@@ -43,7 +43,7 @@
 	Q_OBJECT
 
 public:
-	explicit OverlayDialog (QWidget* parent = null, Qt::WindowFlags f = 0);
+	explicit OverlayDialog (QWidget* parent = nullptr, Qt::WindowFlags f = 0);
 	virtual ~OverlayDialog();
 
 	QString         fpath() const;
@@ -70,7 +70,7 @@
 	Q_OBJECT
 
 public:
-	explicit LDrawPathDialog (const bool validDefault, QWidget* parent = null, Qt::WindowFlags f = 0);
+	explicit LDrawPathDialog (const bool validDefault, QWidget* parent = nullptr, Qt::WindowFlags f = 0);
 	virtual ~LDrawPathDialog();
 	QString filename() const;
 	void setPath (QString path);
@@ -97,7 +97,7 @@
 	PROPERTY (public,	int, numLines,	setNumLines,	CUSTOM_WRITE)
 
 public:
-	explicit OpenProgressDialog (QWidget* parent = null, Qt::WindowFlags f = 0);
+	explicit OpenProgressDialog (QWidget* parent = nullptr, Qt::WindowFlags f = 0);
 	virtual ~OpenProgressDialog();
 
 public slots:
@@ -132,7 +132,7 @@
 	Q_OBJECT
 
 public:
-	AboutDialog (QWidget* parent = null, Qt::WindowFlags f = 0);
+	AboutDialog (QWidget* parent = nullptr, Qt::WindowFlags f = 0);
 
 private slots:
 	void slot_mail();
--- a/src/documentation.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/documentation.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -28,7 +28,7 @@
 class DocumentViewer : public QDialog
 {
 	public:
-		explicit DocumentViewer (QWidget* parent = null, Qt::WindowFlags f = 0) : QDialog (parent, f)
+		explicit DocumentViewer (QWidget* parent = nullptr, Qt::WindowFlags f = 0) : QDialog (parent, f)
 		{
 			te_text = new QTextEdit (this);
 			te_text->setMinimumSize (QSize (400, 300));
--- a/src/editmodes/abstractEditMode.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/editmodes/abstractEditMode.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -100,7 +100,7 @@
 	{
 		// Find the closest vertex to our cursor
 		double			minimumDistance = 1024.0;
-		const Vertex*	closest = null;
+		const Vertex*	closest = nullptr;
 		Vertex			cursorPosition = renderer()->coordconv2_3 (data.ev->pos(), false);
 		QPoint			cursorPosition2D (data.ev->pos());
 		const Axis		relZ = renderer()->getRelativeZ();
@@ -142,7 +142,7 @@
 			}
 		}
 
-		if (closest != null)
+		if (closest != nullptr)
 			addDrawnVertex (*closest);
 
 		return true;
--- a/src/editmodes/circleMode.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/editmodes/circleMode.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -37,14 +37,18 @@
 
 double CircleMode::getCircleDrawDist (int pos) const
 {
-	assert (m_drawedVerts.size() >= pos + 1);
-	Vertex v1 = (m_drawedVerts.size() >= pos + 2) ? m_drawedVerts[pos + 1] :
-		renderer()->coordconv2_3 (renderer()->mousePosition(), false);
-	Axis localx, localy;
-	renderer()->getRelativeAxes (localx, localy);
-	double dx = m_drawedVerts[0][localx] - v1[localx];
-	double dy = m_drawedVerts[0][localy] - v1[localy];
-	return Grid::Snap (sqrt ((dx * dx) + (dy * dy)), Grid::Coordinate);
+	if (m_drawedVerts.size() >= pos + 1)
+	{
+		Vertex v1 = (m_drawedVerts.size() >= pos + 2) ? m_drawedVerts[pos + 1] :
+			renderer()->coordconv2_3 (renderer()->mousePosition(), false);
+		Axis localx, localy;
+		renderer()->getRelativeAxes (localx, localy);
+		double dx = m_drawedVerts[0][localx] - v1[localx];
+		double dy = m_drawedVerts[0][localy] - v1[localy];
+		return Grid::Snap (sqrt ((dx * dx) + (dy * dy)), Grid::Coordinate);
+	}
+
+	return 0.0;
 }
 
 Matrix CircleMode::getCircleDrawMatrix (double scale)
@@ -63,7 +67,7 @@
 	{
 		if (transform[i] == 2)
 			transform[i] = scale;
-		elif (transform[i] == 1 and renderer()->camera() >= 3)
+		else if (transform[i] == 1 and renderer()->camera() >= 3)
 			transform[i] = -1;
 	}
 
@@ -91,14 +95,14 @@
 		transform = getCircleDrawMatrix (dist0);
 		circleOrDisc = true;
 	}
-	elif (dist0 == 0 or dist1 == 0)
+	else if (dist0 == 0 or dist1 == 0)
 	{
 		// If either radii is 0, use a disc.
 		refFile = GetPrimitive (::Disc, segments, divisions, 0);
 		transform = getCircleDrawMatrix ((dist0 != 0) ? dist0 : dist1);
 		circleOrDisc = true;
 	}
-	elif (g_RingFinder.findRings (dist0, dist1))
+	else if (g_RingFinder.findRings (dist0, dist1))
 	{
 		// The ring finder found a solution, use that. Add the component rings to the file.
 		for (const RingFinder::Component& cmp : g_RingFinder.bestSolution()->getComponents())
@@ -155,7 +159,7 @@
 		}
 	}
 
-	if (circleOrDisc and refFile != null)
+	if (circleOrDisc and refFile != nullptr)
 	{
 		LDSubfilePtr ref = LDSpawn<LDSubfile>();
 		ref->setFileInfo (refFile);
@@ -165,13 +169,13 @@
 		objs << ref;
 	}
 
-	unless (objs.isEmpty())
+	if (not objs.isEmpty())
 	{
 		Axis relZ = renderer()->getRelativeZ();;
 		const int l (relZ == X ? 1 : 0);
 		const int m (relZ == Y ? 1 : 0);
 		const int n (relZ == Z ? 1 : 0);
-		RotateObjects (l, m, n, -m_angleOffset, objs);
+		rotateObjects (l, m, n, -m_angleOffset, objs);
 	}
 
 	finishDraw (objs);
--- a/src/editmodes/linePathMode.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/editmodes/linePathMode.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -16,7 +16,6 @@
 		points << renderer()->coordconv3_2 (vrt);
 
 	painter.setPen (renderer()->textPen());
-	assert (points.size() == points3d.size());
 
 	for (int i = 0; i < points.size() - 1; ++i)
 	{
--- a/src/editmodes/magicWandMode.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/editmodes/magicWandMode.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -73,7 +73,7 @@
 
 void MagicWandMode::doMagic (LDObjectPtr obj, MagicWandMode::MagicType type)
 {
-	if (obj == null)
+	if (obj == nullptr)
 	{
 		if (type == Set)
 		{
@@ -117,7 +117,7 @@
 	for (int i = 0; i < obj->numVertices(); ++i)
 		candidates += m_vertices[obj->vertex (i)];
 
-	RemoveDuplicates (candidates);
+	removeDuplicates (candidates);
 
 	// If we're dealing with surfaces, get a list of boundaries.
 	if (matchesneeded > 1)
@@ -209,7 +209,7 @@
 
 		if (data.keymods & Qt::ShiftModifier)
 			wandtype = MagicWandMode::Additive;
-		elif (data.keymods & Qt::ControlModifier)
+		else if (data.keymods & Qt::ControlModifier)
 			wandtype = MagicWandMode::Subtractive;
 
 		doMagic (renderer()->pickOneObject (data.ev->x(), data.ev->y()), wandtype);
--- a/src/editmodes/selectMode.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/editmodes/selectMode.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -76,10 +76,10 @@
 			}
 			else
 			{
-				int const x = Min (m_rangeStart.x(), mx);
-				int const y = Min (m_rangeStart.y(), my);
-				int const width = Abs (m_rangeStart.x() - mx);
-				int const height = Abs (m_rangeStart.y() - my);
+				int const x = min (m_rangeStart.x(), mx);
+				int const y = min (m_rangeStart.y(), my);
+				int const width = abs (m_rangeStart.x() - mx);
+				int const height = abs (m_rangeStart.y() - my);
 				area = QRect (x, y, width, height);
 			}
 
@@ -120,7 +120,7 @@
 		renderer()->document()->clearSelection();
 		LDObjectPtr obj = renderer()->pickOneObject (ev->x(), ev->y());
 
-		if (obj != null)
+		if (obj != nullptr)
 		{
 			AddObjectDialog::staticDialog (obj->type(), obj);
 			g_win->endAction();
--- a/src/extPrograms.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/extPrograms.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -319,7 +319,7 @@
 		return;
 	}
 
-	LDObjectList objs = LoadFileContents (&f, null);
+	LDObjectList objs = LoadFileContents (&f, nullptr);
 
 	// If we replace the objects, delete the selection now.
 	if (replace)
--- a/src/glCompiler.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/glCompiler.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -27,13 +27,13 @@
 #include "glRenderer.h"
 #include "dialogs.h"
 
-struct GLErrorInfo
+struct GlErrorInfo
 {
 	GLenum	value;
 	QString	text;
 };
 
-static const GLErrorInfo g_GLErrors[] =
+static const GlErrorInfo GlErrorMessages[] =
 {
 	{ GL_NO_ERROR,						"No error" },
 	{ GL_INVALID_ENUM,					"Unacceptable enumerator passed" },
@@ -65,7 +65,7 @@
 	if (errnum == GL_NO_ERROR)
 		return;
 
-	for (const GLErrorInfo& err : g_GLErrors)
+	for (const GlErrorInfo& err : GlErrorMessages)
 	{
 		if (err.value == errnum)
 		{
@@ -102,8 +102,8 @@
 	glDeleteBuffers (g_numVBOs, &m_vbo[0]);
 	CHECK_GL_ERROR();
 
-	if (m_renderer != null)
-		m_renderer->setCompiler (null);
+	if (m_renderer != nullptr)
+		m_renderer->setCompiler (nullptr);
 }
 
 // =============================================================================
@@ -166,7 +166,7 @@
 				else
 					qcol = topobj->color().faceColor();
 			}
-			elif (poly.color == EdgeColorIndex)
+			else if (poly.color == EdgeColorIndex)
 			{
 				qcol = Luma (QColor (cfg::BackgroundColor)) > 40 ? Qt::black : Qt::white;
 			}
@@ -203,7 +203,7 @@
 
 	if (topobj->isSelected())
 		blendAlpha = 1.0;
-	elif (topobj == m_renderer->objectAtCursor())
+	else if (topobj == m_renderer->objectAtCursor())
 		blendAlpha = 0.5;
 
 	if (blendAlpha != 0.0)
@@ -249,7 +249,7 @@
 //
 void GLCompiler::compileDocument (LDDocumentPtr doc)
 {
-	if (doc == null)
+	if (doc == nullptr)
 		return;
 
 	for (LDObjectPtr obj : doc->objects())
@@ -260,11 +260,11 @@
 //
 void GLCompiler::compileStaged()
 {
-	RemoveDuplicates (m_staged);
+	removeDuplicates (m_staged);
 
 	for (auto it = m_staged.begin(); it != m_staged.end(); ++it)
 	{
-		if (*it == null)
+		if (*it == nullptr)
 			continue;
 
 		compileObject (*it);
@@ -287,7 +287,7 @@
 
 	for (auto it = m_objectInfo.begin(); it != m_objectInfo.end();)
 	{
-		if (it.key() == null)
+		if (it.key() == nullptr)
 		{
 			it = m_objectInfo.erase (it);
 			continue;
@@ -331,7 +331,7 @@
 {
 //	print ("Compile %1\n", g_objectOrigins[obj]);
 
-	if (obj == null or obj->document() == null or obj->document().toStrongRef()->isImplicit())
+	if (obj == nullptr or obj->document() == nullptr or obj->document().toStrongRef()->isImplicit())
 		return;
 
 	ObjectVBOInfo info;
--- a/src/glRenderer.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/glRenderer.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -108,7 +108,7 @@
 	m_panning = false;
 	m_compiler = new GLCompiler (this);
 	setDrawOnly (false);
-	setMessageLog (null);
+	setMessageLog (nullptr);
 	m_width = m_height = -1;
 	m_position3D = Origin;
 	m_toolTipTimer = new QTimer (this);
@@ -142,9 +142,9 @@
 		delete info.img;
 
 	if (messageLog())
-		messageLog()->setRenderer (null);
+		messageLog()->setRenderer (nullptr);
 
-	m_compiler->setRenderer (null);
+	m_compiler->setRenderer (nullptr);
 	delete m_compiler;
 	delete m_editmode;
 
@@ -209,7 +209,7 @@
 //
 void GLRenderer::needZoomToFit()
 {
-	if (document() != null)
+	if (document() != nullptr)
 		currentDocumentData().needZoomToFit = true;
 }
 
@@ -365,7 +365,7 @@
 //
 void GLRenderer::drawGLScene()
 {
-	if (document() == null)
+	if (document() == nullptr)
 		return;
 
 	if (currentDocumentData().needZoomToFit)
@@ -502,10 +502,10 @@
 	if (count > 0)
 	{
 		glBindBuffer (GL_ARRAY_BUFFER, surfacevbo);
-		glVertexPointer (3, GL_FLOAT, 0, null);
+		glVertexPointer (3, GL_FLOAT, 0, nullptr);
 		CHECK_GL_ERROR();
 		glBindBuffer (GL_ARRAY_BUFFER, colorvbo);
-		glColorPointer (4, GL_FLOAT, 0, null);
+		glColorPointer (4, GL_FLOAT, 0, nullptr);
 		CHECK_GL_ERROR();
 		glDrawArrays (type, 0, count);
 		CHECK_GL_ERROR();
@@ -518,7 +518,8 @@
 //
 Vertex GLRenderer::coordconv2_3 (const QPoint& pos2d, bool snap) const
 {
-	assert (camera() != EFreeCamera);
+	if (camera() == EFreeCamera)
+		return Origin;
 
 	Vertex pos3d;
 	const LDFixedCamera* cam = &g_FixedCameras[camera()];
@@ -540,8 +541,8 @@
 	cx *= negXFac;
 	cy *= negYFac;
 
-	RoundToDecimals (cx, 4);
-	RoundToDecimals (cy, 4);
+	roundToDecimals (cx, 4);
+	roundToDecimals (cy, 4);
 
 	// Create the vertex from the coordinates
 	pos3d.setCoordinate (axisX, cx);
@@ -629,12 +630,12 @@
 		// Paint the overlay image if we have one
 		const LDGLOverlay& overlay = currentDocumentData().overlays[camera()];
 
-		if (overlay.img != null)
+		if (overlay.img != nullptr)
 		{
 			QPoint v0 = coordconv3_2 (currentDocumentData().overlays[camera()].v0),
 					   v1 = coordconv3_2 (currentDocumentData().overlays[camera()].v1);
 
-			QRect targRect (v0.x(), v0.y(), Abs (v1.x() - v0.x()), Abs (v1.y() - v0.y())),
+			QRect targRect (v0.x(), v0.y(), abs (v1.x() - v0.x()), abs (v1.y() - v0.y())),
 				  srcRect (0, 0, overlay.img->width(), overlay.img->height());
 			paint.drawImage (targRect, *overlay.img, srcRect);
 		}
@@ -794,7 +795,7 @@
 {
 	int dx = ev->x() - m_mousePosition.x();
 	int dy = ev->y() - m_mousePosition.y();
-	m_totalmove += Abs (dx) + Abs (dy);
+	m_totalmove += abs (dx) + abs (dy);
 	setCameraMoving (false);
 
 	if (not m_editmode->mouseMoved (ev))
@@ -810,7 +811,7 @@
 			m_panning = true;
 			setCameraMoving (true);
 		}
-		elif (left and camera() == EFreeCamera)
+		else if (left and camera() == EFreeCamera)
 		{
 			rot (X) = rot (X) + dy;
 			rot (Y) = rot (Y) + dx;
@@ -866,7 +867,7 @@
 	doMakeCurrent();
 
 	zoomNotch (ev->delta() > 0);
-	zoom() = Clamp (zoom(), 0.01, 10000.0);
+	zoom() = clamp (zoom(), 0.01, 10000.0);
 	setCameraMoving (true);
 	update();
 	ev->accept();
@@ -935,10 +936,10 @@
 	int y1 = y0 + range.height();
 
 	// Clamp the values to ensure they're within bounds
-	x0 = Max (0, x0);
-	y0 = Max (0, y0);
-	x1 = Min (x1, m_width);
-	y1 = Min (y1, m_height);
+	x0 = max (0, x0);
+	y0 = max (0, y0);
+	x1 = min (x1, m_width);
+	y1 = min (y1, m_height);
 	const int areawidth = (x1 - x0);
 	const int areaheight = (y1 - y0);
 	const qint32 numpixels = areawidth * areaheight;
@@ -967,12 +968,14 @@
 			indices << idx;
 	}
 
-	RemoveDuplicates (indices);
+	removeDuplicates (indices);
 
 	for (qint32 idx : indices)
 	{
 		LDObjectPtr obj = LDObject::fromID (idx);
-		assert (obj != null);
+
+		if (obj == nullptr)
+			continue;
 
 		// If this is an additive single pick and the object is currently selected,
 		// we remove it from selection instead.
@@ -1025,7 +1028,7 @@
 //
 void GLRenderer::setEditMode (EditModeType a)
 {
-	if (m_editmode != null and m_editmode->type() == a)
+	if (m_editmode != nullptr and m_editmode->type() == a)
 		return;
 
 	delete m_editmode;
@@ -1052,7 +1055,7 @@
 {
 	m_document = a;
 
-	if (a != null)
+	if (a != nullptr)
 	{
 		initOverlaysFromObjects();
 
@@ -1078,7 +1081,7 @@
 		glDisable (GL_DITHER);
 
 		// Use particularly thick lines while picking ease up selecting lines.
-		glLineWidth (Max<double> (cfg::LineThickness, 6.5));
+		glLineWidth (max<double> (cfg::LineThickness, 6.5));
 	}
 	else
 	{
@@ -1117,7 +1120,7 @@
 		for (int i = 0; i < obj->numVertices(); ++i)
 			verts << obj->vertex (i);
 	}
-	elif (obj->type() == OBJ_Subfile)
+	else if (obj->type() == OBJ_Subfile)
 	{
 		LDSubfilePtr ref = obj.staticCast<LDSubfile>();
 		LDObjectList objs = ref->inlineContents (true, false);
@@ -1143,7 +1146,7 @@
 //
 void GLRenderer::forgetObject (LDObjectPtr obj)
 {
-	if (compiler() != null)
+	if (compiler() != nullptr)
 		compiler()->dropObject (obj);
 }
 
@@ -1222,7 +1225,7 @@
 
 	if (info.lw == 0)
 		info.lw = (info.lh * img->width()) / img->height();
-	elif (info.lh == 0)
+	else if (info.lh == 0)
 		info.lh = (info.lw * img->height()) / img->width();
 
 	const Axis x2d = getCameraAxis (false, cam),
@@ -1257,7 +1260,7 @@
 
 	LDGLOverlay& info = currentDocumentData().overlays[camera()];
 	delete info.img;
-	info.img = null;
+	info.img = nullptr;
 
 	updateOverlayObjects();
 }
@@ -1266,16 +1269,18 @@
 //
 void GLRenderer::setDepthValue (double depth)
 {
-	assert (camera() < EFreeCamera);
-	currentDocumentData().depthValues[camera()] = depth;
+	if (camera() < EFreeCamera)
+		currentDocumentData().depthValues[camera()] = depth;
 }
 
 // =============================================================================
 //
 double GLRenderer::getDepthValue() const
 {
-	assert (camera() < EFreeCamera);
-	return currentDocumentData().depthValues[camera()];
+	if (camera() < EFreeCamera)
+		return currentDocumentData().depthValues[camera()];
+	else
+		return 0.0;
 }
 
 // =============================================================================
@@ -1305,7 +1310,7 @@
 {
 	zoom() = 30.0f;
 
-	if (document() == null or m_width == -1 or m_height == -1)
+	if (document() == nullptr or m_width == -1 or m_height == -1)
 		return;
 
 	bool lastfilled = false;
@@ -1412,7 +1417,7 @@
 	{
 		LDOverlayPtr ovlobj = obj.dynamicCast<LDOverlay>();
 
-		if (ovlobj != null and obj.staticCast<LDOverlay>()->camera() == cam)
+		if (ovlobj != nullptr and obj.staticCast<LDOverlay>()->camera() == cam)
 			return ovlobj;
 	}
 
@@ -1433,13 +1438,13 @@
 		LDGLOverlay& meta = currentDocumentData().overlays[cam];
 		LDOverlayPtr ovlobj = findOverlayObject (cam);
 
-		if (ovlobj == null and meta.img != null)
+		if (ovlobj == nullptr and meta.img != nullptr)
 		{
 			delete meta.img;
-			meta.img = null;
+			meta.img = nullptr;
 		}
-		elif (ovlobj != null and
-			(meta.img == null or meta.fname != ovlobj->fileName()) and
+		else if (ovlobj != nullptr and
+			(meta.img == nullptr or meta.fname != ovlobj->fileName()) and
 			not meta.invalid)
 		{
 			setupOverlay (cam, ovlobj->fileName(), ovlobj->x(),
@@ -1460,7 +1465,7 @@
 		LDGLOverlay& meta = currentDocumentData().overlays[cam];
 		LDOverlayPtr ovlobj = findOverlayObject (cam);
 
-		if (meta.img == null and ovlobj != null)
+		if (meta.img == nullptr and ovlobj != nullptr)
 		{
 			// If this is the last overlay image, we need to remove the empty space after it as well.
 			LDObjectPtr nextobj = ovlobj->next();
@@ -1472,7 +1477,7 @@
 			// not, remove the object.
 			ovlobj->destroy();
 		}
-		elif (meta.img != null and ovlobj == null)
+		else if (meta.img != nullptr and ovlobj == nullptr)
 		{
 			// Inverse case: image is there but the overlay object is
 			// not, thus create the object.
@@ -1512,7 +1517,7 @@
 			}
 		}
 
-		if (meta.img != null and ovlobj != null)
+		if (meta.img != nullptr and ovlobj != nullptr)
 		{
 			ovlobj->setCamera (cam);
 			ovlobj->setFileName (meta.fname);
@@ -1531,7 +1536,7 @@
 //
 void GLRenderer::highlightCursorObject()
 {
-	if (not cfg::HighlightObjectBelowCursor and objectAtCursor() == null)
+	if (not cfg::HighlightObjectBelowCursor and objectAtCursor() == nullptr)
 		return;
 
 	LDObjectWeakPtr newObject;
@@ -1553,17 +1558,17 @@
 		newIndex = pixel[0] * 0x10000 | pixel[1] * 0x100 | pixel[2];
 	}
 
-	if (newIndex != (oldObject != null ? oldObject.toStrongRef()->id() : 0))
+	if (newIndex != (oldObject != nullptr ? oldObject.toStrongRef()->id() : 0))
 	{
 		if (newIndex != 0)
 			newObject = LDObject::fromID (newIndex);
 
 		setObjectAtCursor (newObject);
 
-		if (oldObject != null)
+		if (oldObject != nullptr)
 			compileObject (oldObject);
 
-		if (newObject != null)
+		if (newObject != nullptr)
 			compileObject (newObject);
 	}
 
@@ -1572,13 +1577,17 @@
 
 void GLRenderer::dragEnterEvent (QDragEnterEvent* ev)
 {
-	if (g_win != null and ev->source() == g_win->getPrimitivesTree() and g_win->getPrimitivesTree()->currentItem() != null)
+	if (g_win != nullptr
+		and ev->source() == g_win->getPrimitivesTree()
+		and g_win->getPrimitivesTree()->currentItem() != nullptr)
+	{
 		ev->acceptProposedAction();
+	}
 }
 
 void GLRenderer::dropEvent (QDropEvent* ev)
 {
-	if (g_win != null and ev->source() == g_win->getPrimitivesTree())
+	if (g_win != nullptr and ev->source() == g_win->getPrimitivesTree())
 	{
 		QString primName = static_cast<SubfileListItem*> (g_win->getPrimitivesTree()->currentItem())->primitive()->name;
 		LDSubfilePtr ref = LDSpawn<LDSubfile>();
@@ -1634,9 +1643,3 @@
 {
 	return m_keymods;
 }
-
-LDFixedCamera const& GetFixedCamera (ECamera cam)
-{
-	assert (cam != EFreeCamera);
-	return g_FixedCameras[cam];
-}
--- a/src/glRenderer.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/glRenderer.h	Tue Jul 07 21:35:20 2015 +0300
@@ -88,7 +88,7 @@
 		{
 			if (i < 6)
 			{
-				overlays[i].img = null;
+				overlays[i].img = nullptr;
 				overlays[i].invalid = false;
 				depthValues[i] = 0.0f;
 			}
@@ -148,7 +148,7 @@
 	PROPERTY (private,	bool,				isCameraMoving,	setCameraMoving,	STOCK_WRITE)
 
 public:
-	GLRenderer (QWidget* parent = null);
+	GLRenderer (QWidget* parent = nullptr);
 	~GLRenderer();
 
 	inline ECamera			camera() const;
@@ -299,6 +299,4 @@
 	return currentDocumentData().zoom[camera()];
 }
 
-LDFixedCamera const& GetFixedCamera (ECamera cam);
-
-extern const char* g_CameraNames[7];
+extern const char* g_CameraNames[7];
\ No newline at end of file
--- a/src/ldConfig.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/ldConfig.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -45,7 +45,7 @@
 {
 	QFile* fp = OpenLDrawFile ("LDConfig.ldr", false);
 
-	if (fp == null)
+	if (fp == nullptr)
 	{
 		Critical (QObject::tr ("Unable to open LDConfig.ldr for parsing."));
 		return;
@@ -103,7 +103,7 @@
 
 		// Parse alpha if given.
 		if (ParseLDConfigTag (pars, "ALPHA", valuestr))
-			alpha = Clamp (valuestr.toInt(), 0, 255);
+			alpha = clamp (valuestr.toInt(), 0, 255);
 
 		LDColorData* col = new LDColorData;
 		col->m_name = name;
--- a/src/ldDocument.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/ldDocument.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -181,7 +181,7 @@
 
 			// Implicit files are not compiled by the GL renderer. Now that this
 			// part is no longer implicit, it needs to be compiled.
-			if (g_win != null)
+			if (g_win != nullptr)
 				g_win->R()->compiler()->compileDocument (self());
 		}
 		else
@@ -190,7 +190,7 @@
 			print ("Closed %1", name());
 		}
 
-		if (g_win != null)
+		if (g_win != nullptr)
 			g_win->updateDocumentList();
 
 		// If the current document just became implicit (e.g. it was 'closed'),
@@ -218,7 +218,7 @@
 {
 	for (LDDocumentWeakPtr weakfile : g_allDocuments)
 	{
-		if (weakfile == null)
+		if (weakfile == nullptr)
 			continue;
 
 		LDDocumentPtr file (weakfile.toStrongRef());
@@ -278,7 +278,7 @@
 
 	for (LDDocumentWeakPtr doc : g_allDocuments)
 	{
-		if (doc == null)
+		if (doc == nullptr)
 			continue;
 
 		QString partpath = format ("%1/%2", Dirname (doc.toStrongRef()->fullPath()), relpath);
@@ -341,11 +341,11 @@
 	print ("Opening %1...\n", relpath);
 	QString path = FindDocumentPath (relpath, subdirs);
 
-	if (pathpointer != null)
+	if (pathpointer != nullptr)
 		*pathpointer = path;
 
 	if (path.isEmpty())
-		return null;
+		return nullptr;
 
 	QFile* fp = new QFile (path);
 
@@ -353,7 +353,7 @@
 		return fp;
 
 	fp->deleteLater();
-	return null;
+	return nullptr;
 }
 
 // =============================================================================
@@ -382,7 +382,7 @@
 		connect (dlg, SIGNAL (rejected()), this, SLOT (abort()));
 	}
 	else
-		dlg = null;
+		dlg = nullptr;
 
 	// Begin working
 	work (0);
@@ -424,7 +424,7 @@
 			print ("Couldn't parse line #%1: %2",
 				progress() + 1, obj.staticCast<LDError>()->reason());
 
-			if (warnings() != null)
+			if (warnings() != nullptr)
 				(*warnings())++;
 		}
 
@@ -539,7 +539,7 @@
 	if (not fp)
 		return LDDocumentPtr();
 
-	LDDocumentPtr load = (fileToOverride != null ? fileToOverride : LDDocument::createNew());
+	LDDocumentPtr load = (fileToOverride != nullptr ? fileToOverride : LDDocument::createNew());
 	load->setImplicit (implicit);
 	load->setFullPath (fullpath);
 	load->setName (LDDocument::shortenName (load->fullPath()));
@@ -690,7 +690,7 @@
 
 	for (LDDocumentWeakPtr doc : g_allDocuments)
 	{
-		if (doc != null and doc.toStrongRef()->name() == shortName)
+		if (doc != nullptr and doc.toStrongRef()->name() == shortName)
 		{
 			documentToReplace = doc;
 			break;
@@ -699,14 +699,14 @@
 
 	// We cannot open this file if the document this would replace is not
 	// safe to close.
-	if (documentToReplace != null and not documentToReplace->isSafeToClose())
+	if (documentToReplace != nullptr and not documentToReplace->isSafeToClose())
 		return;
 
 	g_loadingMainFile = true;
 
 	// If we're replacing an existing document, clear the document and
 	// make it ready for being loaded to.
-	if (documentToReplace != null)
+	if (documentToReplace != nullptr)
 	{
 		file = documentToReplace;
 		file->clear();
@@ -714,7 +714,7 @@
 
 	file = OpenDocument (path, false, false, file);
 
-	if (file == null)
+	if (file == nullptr)
 	{
 		if (not g_aborted)
 		{
@@ -785,7 +785,7 @@
 	// If the second object in the list holds the file name, update that now.
 	LDObjectPtr nameObject = getObject (1);
 
-	if (nameObject != null and nameObject->type() == OBJ_Comment)
+	if (nameObject != nullptr and nameObject->type() == OBJ_Comment)
 	{
 		LDCommentPtr nameComment = nameObject.staticCast<LDComment>();
 
@@ -799,7 +799,7 @@
 
 	QByteArray data;
 
-	if (sizeptr != null)
+	if (sizeptr != nullptr)
 		*sizeptr = 0;
 
 	// File is open, now save the model to it. Note that LDraw requires files to
@@ -809,7 +809,7 @@
 		QByteArray subdata ((obj->asText() + "\r\n").toUtf8());
 		data.append (subdata);
 
-		if (sizeptr != null)
+		if (sizeptr != nullptr)
 			*sizeptr += subdata.size();
 	}
 
@@ -889,7 +889,7 @@
 	return v;
 }
 
-static int32 StringToNumber (QString a, bool* ok = null)
+static int32 StringToNumber (QString a, bool* ok = nullptr)
 {
 	int base = 10;
 
@@ -949,9 +949,9 @@
 					// need to handle MLCAD-style invertnext, clip and noclip separately.
 					if (commentTextSimplified == "BFC CERTIFY INVERTNEXT")
 						return LDSpawn<LDBFC> (BFCStatement::InvertNext);
-					elif (commentTextSimplified == "BFC CERTIFY CLIP")
+					else if (commentTextSimplified == "BFC CERTIFY CLIP")
 						return LDSpawn<LDBFC> (BFCStatement::Clip);
-					elif (commentTextSimplified == "BFC CERTIFY NOCLIP")
+					else if (commentTextSimplified == "BFC CERTIFY NOCLIP")
 						return LDSpawn<LDBFC> (BFCStatement::NoClip);
 				}
 
@@ -1107,7 +1107,7 @@
 			LDSubfilePtr ref = obj.staticCast<LDSubfile>();
 			LDDocumentPtr fileInfo = GetDocument (ref->fileInfo()->name());
 
-			if (fileInfo != null)
+			if (fileInfo != nullptr)
 			{
 				ref->setFileInfo (fileInfo);
 			}
@@ -1148,7 +1148,7 @@
 {
 	for (LDObjectPtr obj : objs)
 	{
-		if (obj != null)
+		if (obj != nullptr)
 			addObject (obj);
 	}
 }
@@ -1190,7 +1190,6 @@
 {
 	int idx = obj->lineNumber();
 	obj->deselect();
-	assert (m_objects[idx] == obj);
 
 	if (not isImplicit() and not (flags() & DOCF_IsBeingDestroyed))
 	{
@@ -1219,24 +1218,25 @@
 //
 void LDDocument::setObject (int idx, LDObjectPtr obj)
 {
-	assert (idx >= 0 and idx < m_objects.size());
+	if (idx >= 0 and idx < m_objects.size())
+	{
+		// Mark this change to history
+		if (not m_history->isIgnoring())
+		{
+			QString oldcode = getObject (idx)->asText();
+			QString newcode = obj->asText();
+			*m_history << new EditHistory (idx, oldcode, newcode);
+		}
 
-	// Mark this change to history
-	if (not m_history->isIgnoring())
-	{
-		QString oldcode = getObject (idx)->asText();
-		QString newcode = obj->asText();
-		*m_history << new EditHistory (idx, oldcode, newcode);
+		m_objectVertices.remove (m_objects[idx]);
+		m_objects[idx]->deselect();
+		m_objects[idx]->setDocument (LDDocumentPtr());
+		obj->setDocument (self());
+		addKnownVertices (obj);
+		g_win->R()->compileObject (obj);
+		m_objects[idx] = obj;
+		needVertexMerge();
 	}
-
-	m_objectVertices.remove (m_objects[idx]);
-	m_objects[idx]->deselect();
-	m_objects[idx]->setDocument (LDDocumentPtr());
-	obj->setDocument (self());
-	addKnownVertices (obj);
-	g_win->R()->compileObject (obj);
-	m_objects[idx] = obj;
-	needVertexMerge();
 }
 
 // =============================================================================
@@ -1296,7 +1296,7 @@
 
 			LDPolygon* data = obj->getPolygon();
 
-			if (data != null)
+			if (data != nullptr)
 			{
 				m_polygonData << *data;
 				delete data;
@@ -1330,7 +1330,7 @@
 	for (QVector<Vertex> const& verts : m_objectVertices)
 		m_vertices << verts;
 
-	RemoveDuplicates (m_vertices);
+	removeDuplicates (m_vertices);
 	m_needVertexMerge = false;
 }
 
@@ -1354,9 +1354,9 @@
 		// Ensure logoed studs are loaded first
 		LoadLogoStuds();
 
-		if (name() == "stud.dat" and g_logoedStud != null)
+		if (name() == "stud.dat" and g_logoedStud != nullptr)
 			return g_logoedStud->inlineContents (deep, renderinline);
-		elif (name() == "stud2.dat" and g_logoedStud2 != null)
+		else if (name() == "stud2.dat" and g_logoedStud2 != nullptr)
 			return g_logoedStud2->inlineContents (deep, renderinline);
 	}
 
@@ -1399,7 +1399,7 @@
 {
 	// Implicit files were loaded for caching purposes and must never be set
 	// current.
-	if (f != null and f->isImplicit())
+	if (f != nullptr and f->isImplicit())
 		return;
 
 	g_currentDocument = f;
@@ -1457,26 +1457,24 @@
 //
 void LDDocument::addToSelection (LDObjectPtr obj) // [protected]
 {
-	if (obj->isSelected())
-		return;
-
-	assert (obj->document() == self());
-	m_sel << obj;
-	g_win->R()->compileObject (obj);
-	obj->setSelected (true);
+	if (not obj->isSelected() and obj->document() == self())
+	{
+		m_sel << obj;
+		g_win->R()->compileObject (obj);
+		obj->setSelected (true);
+	}
 }
 
 // =============================================================================
 //
 void LDDocument::removeFromSelection (LDObjectPtr obj) // [protected]
 {
-	if (not obj->isSelected())
-		return;
-
-	assert (obj->document() == self());
-	m_sel.removeOne (obj);
-	g_win->R()->compileObject (obj);
-	obj->setSelected (false);
+	if (obj->isSelected() and obj->document() == self())
+	{
+		m_sel.removeOne (obj);
+		g_win->R()->compileObject (obj);
+		obj->setSelected (false);
+	}
 }
 
 // =============================================================================
@@ -1485,8 +1483,6 @@
 {
 	for (LDObjectPtr obj : m_sel)
 		removeFromSelection (obj);
-
-	assert (m_sel.isEmpty());
 }
 
 // =============================================================================
@@ -1502,10 +1498,13 @@
 {
 	int a = m_objects.indexOf (one);
 	int b = m_objects.indexOf (other);
-	assert (a != b and a != -1 and b != -1);
-	m_objects[b] = one;
-	m_objects[a] = other;
-	addToHistory (new SwapHistory (one->id(), other->id()));
+
+	if (a != b and a != -1 and b != -1)
+	{
+		m_objects[b] = one;
+		m_objects[a] = other;
+		addToHistory (new SwapHistory (one->id(), other->id()));
+	}
 }
 
 // =============================================================================
--- a/src/ldDocument.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/ldDocument.h	Tue Jul 07 21:35:20 2015 +0300
@@ -97,7 +97,7 @@
 	void insertObj (int pos, LDObjectPtr obj);
 	int getObjectCount() const;
 	LDObjectPtr getObject (int pos) const;
-	bool save (QString path = "", int64* sizeptr = null); // Saves this file to disk.
+	bool save (QString path = "", int64* sizeptr = nullptr); // Saves this file to disk.
 	void swapObjects (LDObjectPtr one, LDObjectPtr other);
 	bool isSafeToClose(); // Perform safety checks. Do this before closing any files!
 	void setObject (int idx, LDObjectPtr obj);
@@ -197,7 +197,7 @@
 LDDocumentPtr OpenDocument (QString path, bool search, bool implicit, LDDocumentPtr fileToOverride = LDDocumentPtr());
 
 // Opens the given file and returns a pointer to it, potentially looking in /parts and /p
-QFile* OpenLDrawFile (QString relpath, bool subdirs, QString* pathpointer = null);
+QFile* OpenLDrawFile (QString relpath, bool subdirs, QString* pathpointer = nullptr);
 
 // Close all open files, whether user-opened or subfile caches.
 void CloseAllDocuments();
@@ -212,7 +212,7 @@
 // Is it safe to close all files?
 bool IsSafeToCloseAll();
 
-LDObjectList LoadFileContents (QFile* f, int* numWarnings, bool* ok = null);
+LDObjectList LoadFileContents (QFile* f, int* numWarnings, bool* ok = nullptr);
 
 inline const LDObjectList& Selection()
 {
--- a/src/ldObject.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/ldObject.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -47,7 +47,7 @@
 	m_isHidden (false),
 	m_isSelected (false),
 	m_isDestructed (false),
-	qObjListEntry (null)
+	qObjListEntry (nullptr)
 {
 	*selfptr = LDObjectPtr (this, [](LDObject* obj){ obj->finalDelete(); });
 	memset (m_coords, 0, sizeof m_coords);
@@ -227,21 +227,23 @@
 void LDObject::replace (LDObjectPtr other)
 {
 	long idx = lineNumber();
-	assert (idx != -1);
 
-	// Replace the instance of the old object with the new object
-	document().toStrongRef()->setObject (idx, other);
+	if (idx != -1)
+	{
+		// Replace the instance of the old object with the new object
+		document().toStrongRef()->setObject (idx, other);
 
-	// Remove the old object
-	destroy();
+		// Remove the old object
+		destroy();
+	}
 }
 
 // =============================================================================
 //
 void LDObject::swap (LDObjectPtr other)
 {
-	assert (document() == other->document());
-	document().toStrongRef()->swapObjects (self(), other);
+	if (document() == other->document())
+		document().toStrongRef()->swapObjects (self(), other);
 }
 
 // =============================================================================
@@ -300,15 +302,15 @@
 		return;
 
 	// If this object was selected, unselect it now
-	if (isSelected() and document() != null)
+	if (isSelected() and document() != nullptr)
 		deselect();
 
 	// If this object was associated to a file, remove it off it now
-	if (document() != null)
+	if (document() != nullptr)
 		document().toStrongRef()->forgetObject (self());
 
 	// Delete the GL lists
-	if (g_win != null)
+	if (g_win != nullptr)
 		g_win->R()->forgetObject (self());
 
 	// Remove this object from the list of LDObjects
@@ -333,7 +335,7 @@
 {
 	m_document = a;
 
-	if (a == null)
+	if (a == nullptr)
 		setSelected (false);
 }
 
@@ -384,7 +386,6 @@
 	// Transform the objects
 	for (LDObjectPtr obj : objs)
 	{
-		// assert (obj->type() != OBJ_Subfile);
 		// Set the parent now so we know what inlined the object.
 		obj->setParent (self());
 		TransformObject (obj, transform(), position(), color());
@@ -405,7 +406,7 @@
 			: 0;
 
 	if (num == 0)
-		return null;
+		return nullptr;
 
 	LDPolygon* data = new LDPolygon;
 	data->id = id();
@@ -437,12 +438,13 @@
 // -----------------------------------------------------------------------------
 long LDObject::lineNumber() const
 {
-	assert (document() != null);
-
-	for (int i = 0; i < document().toStrongRef()->getObjectCount(); ++i)
+	if (document() != nullptr)
 	{
-		if (document().toStrongRef()->getObject (i) == this)
-			return i;
+		for (int i = 0; i < document().toStrongRef()->getObjectCount(); ++i)
+		{
+			if (document().toStrongRef()->getObject (i) == this)
+				return i;
+		}
 	}
 
 	return -1;
@@ -456,25 +458,23 @@
 		return;
 
 	// If we move down, we need to iterate the array in reverse order.
-	long const start = up ? 0 : (objs.size() - 1);
-	long const end = up ? objs.size() : -1;
-	long const incr = up ? 1 : -1;
+	const int start = up ? 0 : (objs.size() - 1);
+	const int end = up ? objs.size() : -1;
+	const int increment = up ? 1 : -1;
 	LDObjectList objsToCompile;
 	LDDocumentPtr file = objs[0]->document();
 
-	for (long i = start; i != end; i += incr)
+	for (long i = start; i != end; i += increment)
 	{
 		LDObjectPtr obj = objs[i];
+		const int idx = obj->lineNumber();
+		const int target = idx + (up ? -1 : 1);
 
-		long const idx = obj->lineNumber();
-		long const target = idx + (up ? -1 : 1);
-
-		if ((up and idx == 0) or (not up and idx == (long) file->objects().size() - 1l))
+		if ((up and idx == 0) or (not up and idx == (long) file->objects().size() - 1))
 		{
 			// One of the objects hit the extrema. If this happens, this should be the first
 			// object to be iterated on. Thus, nothing has changed yet and it's safe to just
 			// abort the entire operation.
-			assert (i == start);
 			return;
 		}
 
@@ -484,7 +484,7 @@
 		obj->swap (file->getObject (target));
 	}
 
-	RemoveDuplicates (objsToCompile);
+	removeDuplicates (objsToCompile);
 
 	// The objects need to be recompiled, otherwise their pick lists are left with
 	// the wrong index colors which messes up selection.
@@ -496,7 +496,7 @@
 //
 QString LDObject::typeName (LDObjectType type)
 {
-	return LDObject::getDefault (type)->typeName();
+	return LDObject::spawnByType (type)->typeName();
 }
 
 // =============================================================================
@@ -524,7 +524,7 @@
 		if (not text.isEmpty())
 			text += ", ";
 
-		QString noun = format ("%1%2", typeName (objType), Plural (count));
+		QString noun = format ("%1%2", typeName (objType), plural (count));
 		text += format ("%1 %2", count, noun);
 	}
 
@@ -535,12 +535,12 @@
 //
 LDObjectPtr LDObject::topLevelParent()
 {
-	if (parent() == null)
+	if (parent() == nullptr)
 		return self();
 
 	LDObjectWeakPtr it (self());
 
-	while (it.toStrongRef()->parent() != null)
+	while (it.toStrongRef()->parent() != nullptr)
 		it = it.toStrongRef()->parent();
 
 	return it.toStrongRef();
@@ -551,12 +551,16 @@
 LDObjectPtr LDObject::next() const
 {
 	long idx = lineNumber();
-	assert (idx != -1);
 
-	if (idx == (long) document().toStrongRef()->getObjectCount() - 1)
-		return LDObjectPtr();
+	if (idx != -1)
+	{
+		if (idx == (long) document().toStrongRef()->getObjectCount() - 1)
+			return LDObjectPtr();
 
-	return document().toStrongRef()->getObject (idx + 1);
+		return document().toStrongRef()->getObject (idx + 1);
+	}
+
+	return LDObjectPtr();
 }
 
 // =============================================================================
@@ -564,9 +568,8 @@
 LDObjectPtr LDObject::previous() const
 {
 	long idx = lineNumber();
-	assert (idx != -1);
 
-	if (idx == 0)
+	if (idx <= 0)
 		return LDObjectPtr();
 
 	return document().toStrongRef()->getObject (idx - 1);
@@ -578,7 +581,7 @@
 {
 	LDObjectPtr prev (previous());
 
-	if (prev != null and prev->type() == OBJ_BFC and
+	if (prev != nullptr and prev->type() == OBJ_BFC and
 		prev.staticCast<LDBFC>()->statement() == BFCStatement::InvertNext)
 	{
 		ptr = prev.staticCast<LDBFC>();
@@ -606,22 +609,23 @@
 
 // =============================================================================
 //
-LDObjectPtr LDObject::getDefault (const LDObjectType type)
+LDObjectPtr LDObject::spawnByType (const LDObjectType type)
 {
 	switch (type)
 	{
-		case OBJ_Comment:		return LDSpawn<LDComment>();
-		case OBJ_BFC:			return LDSpawn<LDBFC>();
-		case OBJ_Line:			return LDSpawn<LDLine>();
-		case OBJ_CondLine:		return LDSpawn<LDCondLine>();
-		case OBJ_Subfile:		return LDSpawn<LDSubfile>();
-		case OBJ_Triangle:		return LDSpawn<LDTriangle>();
-		case OBJ_Quad:			return LDSpawn<LDQuad>();
-		case OBJ_Empty:			return LDSpawn<LDEmpty>();
-		case OBJ_Error:			return LDSpawn<LDError>();
-		case OBJ_Overlay:		return LDSpawn<LDOverlay>();
-		case OBJ_NumTypes:		assert (false);
+	case OBJ_Comment:		return LDSpawn<LDComment>();
+	case OBJ_BFC:			return LDSpawn<LDBFC>();
+	case OBJ_Line:			return LDSpawn<LDLine>();
+	case OBJ_CondLine:		return LDSpawn<LDCondLine>();
+	case OBJ_Subfile:		return LDSpawn<LDSubfile>();
+	case OBJ_Triangle:		return LDSpawn<LDTriangle>();
+	case OBJ_Quad:			return LDSpawn<LDQuad>();
+	case OBJ_Empty:			return LDSpawn<LDEmpty>();
+	case OBJ_Error:			return LDSpawn<LDError>();
+	case OBJ_Overlay:		return LDSpawn<LDOverlay>();
+	case OBJ_NumTypes:		break;
 	}
+
 	return LDObjectPtr();
 }
 
@@ -662,7 +666,7 @@
 //
 void LDSubfile::invert()
 {
-	if (document() == null)
+	if (document() == nullptr)
 		return;
 
 	// Check whether subfile is flat
@@ -799,7 +803,7 @@
 	if (*ptr == val)
 		return;
 
-	if (obj->document() != null and (idx = obj->lineNumber()) != -1)
+	if (obj->document() != nullptr and (idx = obj->lineNumber()) != -1)
 	{
 		QString before = obj->asText();
 		*ptr = val;
@@ -855,30 +859,24 @@
 //
 void LDObject::select()
 {
-	assert (document() != null);
-	document().toStrongRef()->addToSelection (self());
-
-	// If this object is inverted with INVERTNEXT, pick the INVERTNEXT as well.
-	/*
-	LDBFCPtr invertnext;
-
-	if (previousIsInvertnext (invertnext))
-		invertnext->select();
-	*/
+	if (document() != nullptr)
+		document().toStrongRef()->addToSelection (self());
 }
 
 // =============================================================================
 //
 void LDObject::deselect()
 {
-	assert (document() != null);
-	document().toStrongRef()->removeFromSelection (self());
+	if (document() != nullptr)
+	{
+		document().toStrongRef()->removeFromSelection (self());
 
-	// If this object is inverted with INVERTNEXT, deselect the INVERTNEXT as well.
-	LDBFCPtr invertnext;
+		// If this object is inverted with INVERTNEXT, deselect the INVERTNEXT as well.
+		LDBFCPtr invertnext;
 
-	if (previousIsInvertnext (invertnext))
-		invertnext->deselect();
+		if (previousIsInvertnext (invertnext))
+			invertnext->deselect();
+	}
 }
 
 // =============================================================================
@@ -905,7 +903,7 @@
 	// If it's an immediate subfile reference (i.e. this subfile belongs in an
 	// explicit file), we need to pre-compile the GL polygons for the document
 	// if they don't exist already.
-	if (a != null and
+	if (a != nullptr and
 		a->isImplicit() == false and
 		a->polygonData().isEmpty())
 	{
--- a/src/ldObject.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/ldObject.h	Tue Jul 07 21:35:20 2015 +0300
@@ -181,7 +181,7 @@
 	static QString typeName (LDObjectType type);
 
 	// Returns a default-constructed LDObject by the given type
-	static LDObjectPtr getDefault (const LDObjectType type);
+	static LDObjectPtr spawnByType (const LDObjectType type);
 
 	// TODO: move this to LDDocument?
 	static void moveObjects (LDObjectList objs, const bool up);
--- a/src/ldObjectMath.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/ldObjectMath.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -22,7 +22,7 @@
 
 // =============================================================================
 //
-static void RotateVertex (Vertex& v, const Vertex& rotpoint, const Matrix& transformer)
+static void rotateVertex (Vertex& v, const Vertex& rotpoint, const Matrix& transformer)
 {
 	v -= rotpoint;
 	v.transform (transformer, Origin);
@@ -31,27 +31,26 @@
 
 // =============================================================================
 //
-void RotateObjects (const int l, const int m, const int n, double angle, LDObjectList const& objects)
+void rotateObjects (const int l, const int m, const int n, double angle, const LDObjectList& objects)
 {
-	QList<Vertex*> queue;
 	const Vertex rotpoint = GetRotationPoint (objects);
-	const double cosangle = cos (angle),
-				 sinangle = sin (angle);
+	const real cosangle = cos (angle);
+	const real sinangle = sin (angle);
 
 	// ref: http://en.wikipedia.org/wiki/Transformation_matrix#Rotation_2
 	Matrix transform (
 	{
-		(l* l * (1 - cosangle)) + cosangle,
-		(m* l * (1 - cosangle)) - (n* sinangle),
-		(n* l * (1 - cosangle)) + (m* sinangle),
+		(l * l * (1 - cosangle)) + cosangle,
+		(m * l * (1 - cosangle)) - (n* sinangle),
+		(n * l * (1 - cosangle)) + (m* sinangle),
 
-		(l* m * (1 - cosangle)) + (n* sinangle),
-		(m* m * (1 - cosangle)) + cosangle,
-		(n* m * (1 - cosangle)) - (l* sinangle),
+		(l * m * (1 - cosangle)) + (n* sinangle),
+		(m * m * (1 - cosangle)) + cosangle,
+		(n * m * (1 - cosangle)) - (l* sinangle),
 
-		(l* n * (1 - cosangle)) - (m* sinangle),
-		(m* n * (1 - cosangle)) + (l* sinangle),
-		(n* n * (1 - cosangle)) + cosangle
+		(l * n * (1 - cosangle)) - (m* sinangle),
+		(m * n * (1 - cosangle)) + (l* sinangle),
+		(n * n * (1 - cosangle)) + cosangle
 	});
 
 	// Apply the above matrix to everything
@@ -62,17 +61,17 @@
 			for (int i = 0; i < obj->numVertices(); ++i)
 			{
 				Vertex v = obj->vertex (i);
-				RotateVertex (v, rotpoint, transform);
+				rotateVertex (v, rotpoint, transform);
 				obj->setVertex (i, v);
 			}
 		}
-		elif (obj->hasMatrix())
+		else if (obj->hasMatrix())
 		{
 			LDMatrixObjectPtr mo = obj.dynamicCast<LDMatrixObject>();
 
 			// Transform the position
 			Vertex v = mo->position();
-			RotateVertex (v, rotpoint, transform);
+			rotateVertex (v, rotpoint, transform);
 			mo->setPosition (v);
 
 			// Transform the matrix
--- a/src/ldObjectMath.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/ldObjectMath.h	Tue Jul 07 21:35:20 2015 +0300
@@ -19,5 +19,5 @@
 #pragma once
 #include "main.h"
 
-void RotateObjects (const int l, const int m, const int n,
+void rotateObjects (const int l, const int m, const int n,
 	double angle, LDObjectList const& objects);
--- a/src/macros.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/macros.h	Tue Jul 07 21:35:20 2015 +0300
@@ -70,12 +70,6 @@
 
 // =============================================================================
 //
-#define elif(A) else if (A)
-#define unless(A) if (not (A))
-#define until(A) while (not (A))
-
-// =============================================================================
-//
 #ifdef WIN32
 # define DIRSLASH "\\"
 # define DIRSLASH_CHAR '\\'
@@ -95,20 +89,6 @@
 // =============================================================================
 //
 #define dvalof(A) dprint ("value of '%1' = %2\n", #A, A)
-
-// =============================================================================
-//
-// Replace assert with a version that shows a GUI dialog if possible.
-// On Windows I just can't get the actual error messages otherwise.
-//
-#undef assert
-
-#ifdef DEBUG
-# define assert(N) { ((N) ? (void) 0 : HandleAssertFailure (__FILE__, __LINE__, FUNCNAME, #N)); }
-#else
-# define assert(N) {}
-#endif // DEBUG
-
 #define for_axes(AX) for (const Axis AX : std::initializer_list<const Axis> ({X, Y, Z}))
 
 #define NUMERIC_ENUM_OPERATORS(T) \
--- a/src/main.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/main.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -34,7 +34,7 @@
 #include "dialogs.h"
 #include "crashCatcher.h"
 
-MainWindow* g_win = null;
+MainWindow* g_win = nullptr;
 static QString g_versionString, g_fullVersionString;
 static bool g_IsExiting (false);
 
--- a/src/main.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/main.h	Tue Jul 07 21:35:20 2015 +0300
@@ -29,12 +29,11 @@
 #include <QTextFormat>
 #include "macros.h"
 #include "version.h"
+#include "vertex.h"
+#include "basics.h"
 #include "configuration.h"
 #include "format.h"
 
-// Null pointer
-static const std::nullptr_t null = nullptr;
-
 void HandleAssertFailure (const char* file, int line, const char* funcname, const char* expr);
 bool IsExiting();
 void Exit();
--- a/src/mainWindow.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/mainWindow.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -94,7 +94,7 @@
 	connect (m_tabBar, SIGNAL (currentChanged(int)), this, SLOT (changeCurrentFile()));
 	connect (m_tabBar, SIGNAL (tabCloseRequested (int)), this, SLOT (closeTab (int)));
 
-	if (ActivePrimitiveScanner() != null)
+	if (ActivePrimitiveScanner() != nullptr)
 		connect (ActivePrimitiveScanner(), SIGNAL (workDone()), this, SLOT (updatePrimitives()));
 	else
 		updatePrimitives();
@@ -131,14 +131,14 @@
 	{
 		QToolBar* toolbar = findChild<QToolBar*> (toolbarname.toString());
 
-		if (toolbar != null)
+		if (toolbar != nullptr)
 			toolbar->hide();
 	}
 }
 
 MainWindow::~MainWindow()
 {
-	g_win = null;
+	g_win = nullptr;
 }
 
 // =============================================================================
@@ -180,7 +180,7 @@
 
 	m_recentFiles.clear();
 
-	QAction* first = null;
+	QAction* first = nullptr;
 
 	for (const QVariant& it : cfg::RecentFiles)
 	{
@@ -196,20 +196,20 @@
 
 // =============================================================================
 //
-QList<LDQuickColor> LoadQuickColorList()
+QList<ColorToolbarEntry> LoadQuickColorList()
 {
-	QList<LDQuickColor> colors;
+	QList<ColorToolbarEntry> colors;
 
 	for (QString colorname : cfg::QuickColorToolbar.split (":"))
 	{
 		if (colorname == "|")
-			colors << LDQuickColor::getSeparator();
+			colors << ColorToolbarEntry::getSeparator();
 		else
 		{
 			LDColor col = LDColor::fromIndex (colorname.toLong());
 
-			if (col != null)
-				colors << LDQuickColor (col, null);
+			if (col != nullptr)
+				colors << ColorToolbarEntry (col, nullptr);
 		}
 	}
 
@@ -225,7 +225,7 @@
 	ui->toolBarColors->addAction (ui->actionUncolor);
 	ui->toolBarColors->addSeparator();
 
-	for (LDQuickColor& entry : m_quickColors)
+	for (ColorToolbarEntry& entry : m_quickColors)
 	{
 		if (entry.isSeparator())
 		{
@@ -422,8 +422,8 @@
 			item->setBackground (QColor ("#AA0000"));
 			item->setForeground (QColor ("#FFAA00"));
 		}
-		elif (cfg::ColorizeObjectsList and obj->isColored() and
-			obj->color() != null and obj->color() != MainColor() and obj->color() != EdgeColor())
+		else if (cfg::ColorizeObjectsList and obj->isColored() and
+			obj->color() != nullptr and obj->color() != MainColor() and obj->color() != EdgeColor())
 		{
 			// If the object isn't in the main or edge color, draw this
 			// list entry in said color.
@@ -454,7 +454,7 @@
 //
 void MainWindow::slot_selectionChanged()
 {
-	if (g_isSelectionLocked == true or CurrentDocument() == null)
+	if (g_isSelectionLocked == true or CurrentDocument() == nullptr)
 		return;
 
 	LDObjectList priorSelection = Selection();
@@ -481,7 +481,7 @@
 
 	// Update the GL renderer
 	LDObjectList compound = priorSelection + Selection();
-	RemoveDuplicates (compound);
+	removeDuplicates (compound);
 
 	for (LDObjectPtr obj : compound)
 		R()->compileObject (obj);
@@ -502,9 +502,9 @@
 void MainWindow::slot_quickColor()
 {
 	QToolButton* button = static_cast<QToolButton*> (sender());
-	LDColor col = null;
+	LDColor col = nullptr;
 
-	for (const LDQuickColor& entry : m_quickColors)
+	for (const ColorToolbarEntry& entry : m_quickColors)
 	{
 		if (entry.toolButton() == button)
 		{
@@ -513,7 +513,7 @@
 		}
 	}
 
-	if (col == null)
+	if (col == nullptr)
 		return;
 
 	for (LDObjectPtr obj : Selection())
@@ -568,7 +568,7 @@
 
 	for (LDObjectPtr obj : Selection())
 	{
-		if (obj->qObjListEntry == null)
+		if (obj->qObjListEntry == nullptr)
 			continue;
 
 		int row = ui->objectList->row (obj->qObjListEntry);
@@ -611,10 +611,10 @@
 		if (not obj->isColored())
 			continue; // doesn't use color
 
-		if (result != null and obj->color() != result)
-			return null; // No consensus in object color
+		if (result != nullptr and obj->color() != result)
+			return nullptr; // No consensus in object color
 
-		if (result == null)
+		if (result == nullptr)
 			result = obj->color();
 	}
 
@@ -770,7 +770,7 @@
 
 		if (not doc->fullPath().isEmpty()) 
 			name = doc->fullPath();
-		elif (not doc->name().isEmpty())
+		else if (not doc->name().isEmpty())
 			name = doc->name();
 
 		name.replace ("\\", "/");
@@ -789,7 +789,7 @@
 		if (doc == CurrentDocument())
 			updateTitle();
 
-		print ("Saved to %1 (%2)", path, MakePrettyFileSize (savesize));
+		print ("Saved to %1 (%2)", path, makePrettyFileSize (savesize));
 
 		// Add it to recent files
 		AddRecentFile (path);
@@ -890,7 +890,7 @@
 
 	for (LDObjectPtr obj : CurrentDocument()->objects())
 	{
-		if (not obj->isColored() or obj->color() == null)
+		if (not obj->isColored() or obj->color() == nullptr)
 			continue;
 
 		if (counts.find (obj->color()) == counts.end())
@@ -906,7 +906,7 @@
 	{
 		QIcon ico = MakeColorIcon (pair.first, 16);
 		box->addItem (ico, format ("[%1] %2 (%3 object%4)",
-			pair.first, pair.first.name(), pair.second, Plural (pair.second)));
+			pair.first, pair.first.name(), pair.second, plural (pair.second)));
 		box->setItemData (row, pair.first.index());
 
 		++row;
@@ -986,7 +986,7 @@
 
 	// If we picked the same file we're currently on, we don't need to do
 	// anything.
-	if (f == null or f == CurrentDocument())
+	if (f == nullptr or f == CurrentDocument())
 		return;
 
 	LDDocument::setCurrent (f);
@@ -1012,7 +1012,7 @@
 //
 void MainWindow::updateActions()
 {
-	if (CurrentDocument() != null and CurrentDocument()->history() != null)
+	if (CurrentDocument() != nullptr and CurrentDocument()->history() != nullptr)
 	{
 		History* his = CurrentDocument()->history();
 		int pos = his->position();
@@ -1043,7 +1043,7 @@
 {
 	LDDocumentPtr doc = FindDocument (m_tabBar->tabData (tabindex).toString());
 
-	if (doc == null)
+	if (doc == nullptr)
 		return;
 
 	doc->dismiss();
@@ -1143,22 +1143,22 @@
 
 // =============================================================================
 //
-LDQuickColor::LDQuickColor (LDColor color, QToolButton* toolButton) :
+ColorToolbarEntry::ColorToolbarEntry (LDColor color, QToolButton* toolButton) :
 	m_color (color),
 	m_toolButton (toolButton) {}
 
 // =============================================================================
 //
-LDQuickColor LDQuickColor::getSeparator()
+ColorToolbarEntry ColorToolbarEntry::getSeparator()
 {
-	return LDQuickColor (null, null);
+	return ColorToolbarEntry (nullptr, nullptr);
 }
 
 // =============================================================================
 //
-bool LDQuickColor::isSeparator() const
+bool ColorToolbarEntry::isSeparator() const
 {
-	return color() == null;
+	return color() == nullptr;
 }
 
 void PopulatePrimitives (QTreeWidget* tw, QString const& selectByDefault)
@@ -1167,7 +1167,7 @@
 
 	for (PrimitiveCategory* cat : g_PrimitiveCategories)
 	{
-		SubfileListItem* parentItem = new SubfileListItem (tw, null);
+		SubfileListItem* parentItem = new SubfileListItem (tw, nullptr);
 		parentItem->setText (0, cat->name());
 		QList<QTreeWidgetItem*> subfileItems;
 
--- a/src/mainWindow.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/mainWindow.h	Tue Jul 07 21:35:20 2015 +0300
@@ -38,22 +38,16 @@
 class Ui_LDForgeUI;
 class Primitive;
 
-// Stuff for dialogs
-#define IMPLEMENT_DIALOG_BUTTONS \
-	bbx_buttons = new QDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel); \
-	connect (bbx_buttons, SIGNAL (accepted()), this, SLOT (accept())); \
-	connect (bbx_buttons, SIGNAL (rejected()), this, SLOT (reject())); \
-
-class LDQuickColor
+class ColorToolbarEntry
 {
 	PROPERTY (public,	LDColor,		color,		setColor,		STOCK_WRITE)
 	PROPERTY (public,	QToolButton*,	toolButton,	setToolButton,	STOCK_WRITE)
 
-	public:
-		LDQuickColor (LDColor color, QToolButton* toolButton);
-		bool isSeparator() const;
+public:
+	ColorToolbarEntry (LDColor color, QToolButton* toolButton);
+	bool isSeparator() const;
 
-		static LDQuickColor getSeparator();
+	static ColorToolbarEntry getSeparator();
 };
 
 //
@@ -75,7 +69,7 @@
 	Q_OBJECT
 
 public:
-	explicit MainWindow (QWidget* parent = null, Qt::WindowFlags flags = 0);
+	explicit MainWindow (QWidget* parent = nullptr, Qt::WindowFlags flags = 0);
 	~MainWindow();
 
 	// Rebuilds the object list.
@@ -148,7 +142,7 @@
 	}
 
 	// Sets the quick color list to the given list of colors.
-	inline void setQuickColors (const QList<LDQuickColor>& colors)
+	inline void setQuickColors (const QList<ColorToolbarEntry>& colors)
 	{
 		m_quickColors = colors;
 		updateColorToolbar();
@@ -181,6 +175,7 @@
 	void closeTab (int tabindex);
 	void ringToolHiResClicked (bool clicked);
 	void circleToolSegmentsChanged();
+	void settingsApplied();
 	void actionTriggered();
 	void actionNew();
 	void actionNewFile();
@@ -290,7 +285,7 @@
 private:
 	GLRenderer*			m_renderer;
 	LDObjectList		m_selection;
-	QList<LDQuickColor>	m_quickColors;
+	QList<ColorToolbarEntry>	m_quickColors;
 	QList<QToolButton*>	m_colorButtons;
 	QList<QAction*>		m_recentFiles;
 	MessageManager*		m_messageLog;
@@ -313,7 +308,7 @@
 QPixmap GetIcon (QString iconName);
 
 //! \returns a list of quick colors based on the configuration entry.
-QList<LDQuickColor> LoadQuickColorList();
+QList<ColorToolbarEntry> LoadQuickColorList();
 
 //! Asks the user a yes/no question with the given \c message and the given
 //! window \c title.
--- a/src/messageLog.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/messageLog.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -127,7 +127,7 @@
 {
 	for (QString& a : msg.split ("\n", QString::SkipEmptyParts))
 	{
-		if (g_win != null)
+		if (g_win != nullptr)
 			g_win->addMessage (a);
 
 		// Also print it to stdout
--- a/src/messageLog.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/messageLog.h	Tue Jul 07 21:35:20 2015 +0300
@@ -63,7 +63,7 @@
 	};
 
 	// Constructs the message manager.
-	explicit MessageManager (QObject* parent = null);
+	explicit MessageManager (QObject* parent = nullptr);
 
 	// Adds a line with the given \c text to the message manager.
 	void addLine (QString line);
--- a/src/miscallenous.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/miscallenous.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -25,6 +25,7 @@
 #include "dialogs.h"
 #include "ldDocument.h"
 #include "ui_rotpoint.h"
+#include "boundingbox.h"
 
 // Prime number table.
 static const int PrimeNumbers[] =
@@ -123,10 +124,10 @@
 double Grid::Snap (double value, const Grid::Config type)
 {
 	double snapvalue = (type == Coordinate) ? *CurrentGrid().coordinateSnap : *CurrentGrid().angleSnap;
-	double mult = floor (Abs<double> (value / snapvalue));
+	double mult = floor (abs<double> (value / snapvalue));
 	double out = mult * snapvalue;
 
-	if (Abs (value) - (mult * snapvalue) > snapvalue / 2)
+	if (abs (value) - (mult * snapvalue) > snapvalue / 2)
 		out += snapvalue;
 
 	if (value < 0)
@@ -171,7 +172,7 @@
 	{
 		case RotationPoint::ObjectOrigin:
 		{
-			LDBoundingBox box;
+			BoundingBox box;
 
 			// Calculate center vertex
 			for (LDObjectPtr obj : objs)
@@ -253,15 +254,15 @@
 
 // =============================================================================
 //
-void RoundToDecimals (double& a, int decimals)
+void roundToDecimals (double& a, int decimals)
 {
-	assert (decimals >= 0 and decimals < countof (E10));
-	a = round (a * E10[decimals]) / E10[decimals];
+	if (decimals >= 0 and decimals < countof (E10))
+		a = round (a * E10[decimals]) / E10[decimals];
 }
 
 // =============================================================================
 //
-void ApplyToMatrix (Matrix& a, ApplyToMatrixFunction func)
+void applyToMatrix (Matrix& a, ApplyToMatrixFunction func)
 {
 	for (int i = 0; i < 9; ++i)
 		func (i, a[i]);
@@ -269,7 +270,7 @@
 
 // =============================================================================
 //
-void ApplyToMatrix (const Matrix& a, ApplyToMatrixConstFunction func)
+void applyToMatrix (const Matrix& a, ApplyToMatrixConstFunction func)
 {
 	for (int i = 0; i < 9; ++i)
 		func (i, a[i]);
@@ -277,23 +278,21 @@
 
 // =============================================================================
 //
-double GetCoordinateOf (const Vertex& a, Axis ax)
+double getCoordinateOf (const Vertex& a, Axis ax)
 {
 	switch (ax)
 	{
-		case X: return a.x();
-		case Y: return a.y();
-		case Z: return a.z();
+	case X: return a.x();
+	case Y: return a.y();
+	case Z: return a.z();
 	}
 
-	assert (false);
 	return 0.0;
 }
 
-
 // =============================================================================
 //
-QString MakePrettyFileSize (qint64 size)
+QString makePrettyFileSize (qint64 size)
 {
 	if (size < 1024LL)
 		return QString::number (size) + " bytes";
--- a/src/miscallenous.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/miscallenous.h	Tue Jul 07 21:35:20 2015 +0300
@@ -33,12 +33,12 @@
 using ApplyToMatrixFunction = std::function<void (int, double&)>;
 using ApplyToMatrixConstFunction = std::function<void (int, double)>;
 
-void RoundToDecimals (double& a, int decimals);
-void ApplyToMatrix (Matrix& a, ApplyToMatrixFunction func);
-void ApplyToMatrix (const Matrix& a, ApplyToMatrixConstFunction func);
+void roundToDecimals (double& a, int decimals);
+void applyToMatrix (Matrix& a, ApplyToMatrixFunction func);
+void applyToMatrix (const Matrix& a, ApplyToMatrixConstFunction func);
 
-double GetCoordinateOf (const Vertex& a, Axis ax);
-QString MakePrettyFileSize (qint64 size);
+double getCoordinateOf (const Vertex& a, Axis ax);
+QString makePrettyFileSize (qint64 size);
 
 QString Join (QList<StringFormatArg> vals, QString delim = " ");
 
--- a/src/partDownloader.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/partDownloader.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -167,7 +167,7 @@
 		dest.remove (0, 2);
 		dest.prepend ("parts/s/");
 	}
-	elif (Eq (dest.left (3), "48\\", "48/"))
+	else if (Eq (dest.left (3), "48\\", "48/"))
 	{
 		dest.remove (0, 3);
 		dest.prepend ("p/48/");
@@ -194,9 +194,9 @@
 
 	if (QRegExp (subpartRegex).exactMatch (dest))
 		dest.prepend ("parts/s/");
-	elif (QRegExp (partRegex).exactMatch (dest))
+	else if (QRegExp (partRegex).exactMatch (dest))
 		dest.prepend ("parts/");
-	elif (not dest.startsWith ("parts/") and not dest.startsWith ("p/"))
+	else if (not dest.startsWith ("parts/") and not dest.startsWith ("p/"))
 		dest.prepend ("p/");
 }
 
@@ -235,14 +235,14 @@
 	{
 		reject();
 	}
-	elif (btn == getButton (Abort))
+	else if (btn == getButton (Abort))
 	{
 		setAborted (true);
 
 		for (PartDownloadRequest* req : requests())
 			req->abort();
 	}
-	elif (btn == getButton (Download))
+	else if (btn == getButton (Download))
 	{
 		QString dest = form()->fname->text();
 		setPrimaryFile (LDDocumentPtr());
@@ -311,7 +311,7 @@
 		if (not req->isFinished())
 			return;
 
-        if (req->state() == PartDownloadRequest::State::Failed)
+		if (req->state() == PartDownloadRequest::State::Failed)
 			failed = true;
 	}
 
@@ -321,7 +321,7 @@
 	m_requests.clear();
 
 	// Update everything now
-	if (primaryFile() != null)
+	if (primaryFile() != nullptr)
 	{
 		LDDocument::setCurrent (primaryFile());
 		g_win->doFullRefresh();
@@ -360,14 +360,14 @@
 			return qobject_cast<QPushButton*> (form()->buttonBox->button (QDialogButtonBox::Close));
 	}
 
-	return null;
+	return nullptr;
 }
 
 // =============================================================================
 //
 PartDownloadRequest::PartDownloadRequest (QString url, QString dest, bool primary, PartDownloader* parent) :
 	QObject (parent),
-    m_state (State::Requesting),
+	m_state (State::Requesting),
 	m_prompt (parent),
 	m_url (url),
 	m_destinaton (dest),
@@ -375,7 +375,7 @@
 	m_networkManager (new QNetworkAccessManager),
 	m_isFirstUpdate (true),
 	m_isPrimary (primary),
-	m_filePointer (null)
+	m_filePointer (nullptr)
 {
 	// Make sure that we have a valid destination.
 	QString dirpath = Dirname (filePath());
@@ -412,8 +412,8 @@
 
 	switch (state())
 	{
-        case State::Requesting:
-        case State::Downloading:
+		case State::Requesting:
+		case State::Downloading:
 		{
 			prog = qobject_cast<QProgressBar*> (table->cellWidget (tableRow(), progcol));
 
@@ -427,10 +427,10 @@
 			prog->setValue (numBytesRead());
 		} break;
 
-        case State::Finished:
-        case State::Failed:
+		case State::Finished:
+		case State::Failed:
 		{
-            const QString text = (state() == State::Finished)
+			const QString text = (state() == State::Finished)
 				? "<b><span style=\"color: #080\">FINISHED</span></b>"
 				: "<b><span style=\"color: #800\">FAILED</span></b>";
 
@@ -465,11 +465,11 @@
 			Critical (networkReply()->errorString());
 
 		print ("Unable to download %1: %2\n", m_destinaton, networkReply()->errorString());
-        setState (State::Failed);
+		setState (State::Failed);
 	}
-    elif (state() != State::Failed)
+	else if (state() != State::Failed)
 	{
-        setState (State::Finished);
+		setState (State::Finished);
 	}
 
 	setNumBytesRead (numBytesTotal());
@@ -479,13 +479,13 @@
 	{
 		filePointer()->close();
 		delete filePointer();
-		setFilePointer (null);
+		setFilePointer (nullptr);
 
-        if (state() == State::Failed)
+		if (state() == State::Failed)
 			QFile::remove (filePath());
 	}
 
-    if (state() != State::Finished)
+	if (state() != State::Finished)
 	{
 		prompt()->checkIfFinished();
 		return;
@@ -494,7 +494,7 @@
 	// Try to load this file now.
 	LDDocumentPtr f = OpenDocument (filePath(), false, not isPrimary());
 
-	if (f == null)
+	if (f == nullptr)
 		return;
 
 	// Iterate through this file and check for errors. If there's any that stems
@@ -505,7 +505,7 @@
 	{
 		LDErrorPtr err = obj.dynamicCast<LDError>();
 
-		if ((err == null) or (err->fileReferenced().isEmpty()))
+		if ((err == nullptr) or (err->fileReferenced().isEmpty()))
 			continue;
 
 		QString dest = err->fileReferenced();
@@ -536,7 +536,7 @@
 {
 	setNumBytesRead (recv);
 	setNumBytesTotal (total);
-    setState (State::Downloading);
+	setState (State::Downloading);
 	updateToTable();
 }
 
@@ -544,10 +544,10 @@
 //
 void PartDownloadRequest::readyRead()
 {
-    if (state() == State::Failed)
+	if (state() == State::Failed)
 		return;
 
-	if (filePointer() == null)
+	if (filePointer() == nullptr)
 	{
 		m_filePath.replace ("\\", "/");
 
@@ -558,7 +558,7 @@
 		if (not filePointer()->open (QIODevice::WriteOnly))
 		{
 			Critical (format (tr ("Couldn't open %1 for writing: %2"), filePath(), strerror (errno)));
-            setState (State::Failed);
+			setState (State::Failed);
 			networkReply()->abort();
 			updateToTable();
 			prompt()->checkIfFinished();
@@ -573,7 +573,7 @@
 //
 bool PartDownloadRequest::isFinished() const
 {
-    return Eq (state(), State::Finished, State::Failed);
+	return Eq (state(), State::Finished, State::Failed);
 }
 
 // =============================================================================
--- a/src/partDownloader.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/partDownloader.h	Tue Jul 07 21:35:20 2015 +0300
@@ -66,7 +66,7 @@
 	PROPERTY (private,	QPushButton*,		downloadButton,		setDownloadButton,	STOCK_WRITE)
 
 public:
-	explicit		PartDownloader (QWidget* parent = null);
+	explicit		PartDownloader (QWidget* parent = nullptr);
 	virtual			~PartDownloader();
 
 	void			addFile (LDDocumentPtr f);
--- a/src/primitives.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/primitives.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -28,8 +28,8 @@
 
 QList<PrimitiveCategory*> g_PrimitiveCategories;
 QList<Primitive> g_primitives;
-static PrimitiveScanner* g_activeScanner = null;
-PrimitiveCategory* g_unmatched = null;
+static PrimitiveScanner* g_activeScanner = nullptr;
+PrimitiveCategory* g_unmatched = nullptr;
 
 EXTERN_CFGENTRY (String, DefaultName)
 EXTERN_CFGENTRY (String, DefaultUser)
@@ -113,7 +113,6 @@
 {
 	g_activeScanner = this;
 	QDir dir (LDPaths::prims());
-	assert (dir.exists());
 	m_baselen = dir.absolutePath().length();
 	GetRecursiveFilenames (dir, m_files);
 	emit starting (m_files.size());
@@ -124,14 +123,14 @@
 //
 PrimitiveScanner::~PrimitiveScanner()
 {
-	g_activeScanner = null;
+	g_activeScanner = nullptr;
 }
 
 // =============================================================================
 //
 void PrimitiveScanner::work()
 {
-	int j = Min (m_i + 100, m_files.size());
+	int j = min (m_i + 100, m_files.size());
 
 	for (; m_i < j; ++m_i)
 	{
@@ -144,7 +143,7 @@
 		Primitive info;
 		info.name = fname.mid (m_baselen + 1);  // make full path relative
 		info.name.replace ('/', '\\');  // use DOS backslashes, they're expected
-		info.category = null;
+		info.category = nullptr;
 		QByteArray titledata = f.readLine();
 
 		if (titledata != QByteArray())
@@ -181,7 +180,7 @@
 		g_primitives = m_prims;
 		PrimitiveCategory::populateCategories();
 		print ("%1 primitives scanned", g_primitives.size());
-		g_activeScanner = null;
+		g_activeScanner = nullptr;
 		emit workDone();
 		deleteLater();
 	}
@@ -223,7 +222,7 @@
 	for (Primitive& prim : g_primitives)
 	{
 		bool matched = false;
-		prim.category = null;
+		prim.category = nullptr;
 
 		// Go over the categories and their regexes, if and when there's a match,
 		// the primitive's category is set to the category the regex beloings to.
@@ -254,13 +253,13 @@
 			}
 
 			// Drop out if a category was decided on.
-			if (prim.category != null)
+			if (prim.category != nullptr)
 				break;
 		}
 
 		// If there was a match, add the primitive to the category.
 		// Otherwise, add it to the list of unmatched primitives.
-		if (prim.category != null)
+		if (prim.category != nullptr)
 			prim.category->prims << prim;
 		else
 			g_unmatched->prims << prim;
@@ -296,7 +295,7 @@
 		return;
 	}
 
-	PrimitiveCategory* cat = null;
+	PrimitiveCategory* cat = nullptr;
 
 	while (not f.atEnd())
 	{
@@ -316,14 +315,14 @@
 
 			cat = new PrimitiveCategory (line);
 		}
-		elif (cat != null)
+		else if (cat != nullptr)
 		{
 			QString cmd = line.left (colon);
 			RegexType type = EFilenameRegex;
 
 			if (cmd == "f")
 				type = EFilenameRegex;
-			elif (cmd == "t")
+			else if (cmd == "t")
 				type = ETitleRegex;
 			else
 			{
@@ -368,7 +367,7 @@
 //
 bool IsPrimitiveLoaderBusy()
 {
-	return g_activeScanner != null;
+	return g_activeScanner != nullptr;
 }
 
 // =============================================================================
@@ -524,7 +523,7 @@
 		{
 			v1 = Vertex (v0[X], 1.0f, v0[Z]);
 		}
-		elif (type == Cone)
+		else if (type == Cone)
 		{
 			v1 = Vertex (v0[X] * (num + 1), 0.0f, v0[Z] * (num + 1));
 			v0.setX (v0.x() * num);
@@ -582,7 +581,7 @@
 	// Truncate the root if necessary (7-16rin4.dat for instance).
 	// However, always keep the root at least 2 characters.
 	int extra = (frac.length() + numstr.length() + root.length()) - 8;
-	root.chop (Clamp (extra, 0, 2));
+	root.chop (clamp (extra, 0, 2));
 
 	// Stick them all together and return the result.
 	return prefix + frac + root + numstr + ".dat";
@@ -655,7 +654,7 @@
 	QString name = MakeRadialFileName (type, segs, divs, num);
 	LDDocumentPtr f = GetDocument (name);
 
-	if (f != null)
+	if (f != nullptr)
 		return f;
 
 	return GeneratePrimitive (type, segs, divs, num);
--- a/src/primitives.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/primitives.h	Tue Jul 07 21:35:20 2015 +0300
@@ -109,7 +109,7 @@
 	Q_OBJECT
 
 public:
-	explicit PrimitivePrompt (QWidget* parent = null, Qt::WindowFlags f = 0);
+	explicit PrimitivePrompt (QWidget* parent = nullptr, Qt::WindowFlags f = 0);
 	virtual ~PrimitivePrompt();
 	Ui_MakePrimUI* ui;
 
--- a/src/radioGroup.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/radioGroup.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -57,7 +57,7 @@
 
 	m_buttonGroup = new QButtonGroup;
 	m_oldId = m_curId = 0;
-	m_coreLayout = null;
+	m_coreLayout = nullptr;
 
 	m_coreLayout = new QBoxLayout ( (orient == Qt::Vertical) ? QBoxLayout::LeftToRight : QBoxLayout::TopToBottom);
 	setLayout (m_coreLayout);
--- a/src/radioGroup.h	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/radioGroup.h	Tue Jul 07 21:35:20 2015 +0300
@@ -44,14 +44,14 @@
 		init (Qt::Vertical);
 	}
 
-	explicit RadioGroup (QWidget* parent = null) : QGroupBox (parent)
+	explicit RadioGroup (QWidget* parent = nullptr) : QGroupBox (parent)
 	{
 		init (Qt::Vertical);
 	}
 
-	explicit RadioGroup (const QString& title, QWidget* parent = null);
+	explicit RadioGroup (const QString& title, QWidget* parent = nullptr);
 	explicit RadioGroup (const QString& title, QList<char const*> entries, int const defaultId,
-		const Qt::Orientation orient = Qt::Vertical, QWidget* parent = null);
+		const Qt::Orientation orient = Qt::Vertical, QWidget* parent = nullptr);
 
 	void            addButton	(const char* entry);
 	void            addButton	(QRadioButton* button);
--- a/src/ringFinder.cpp	Sun Apr 12 23:02:26 2015 +0300
+++ b/src/ringFinder.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -31,13 +31,15 @@
 	if (m_stack >= 5)
 		return false;
 
+	if (r1 >= r0)
+		return false;
+
 	// Find the scale and number of a ring between r1 and r0.
-	assert (r1 >= r0);
 	double scale = r1 - r0;
 	double num = r0 / scale;
 
 	// If the ring number is integral, we have found a fitting ring to r0 -> r1!
-	if (IsIntegral (num))
+	if (isInteger (num))
 	{
 		Component cmp;
 		cmp.scale = scale;
@@ -55,7 +57,7 @@
 	else
 	{
 		// Try find solutions by splitting the ring in various positions.
-		if (IsZero (r1 - r0))
+		if (isZero (r1 - r0))
 			return false;
 
 		double interval;
@@ -122,26 +124,23 @@
 	m_solutions.clear();
 	Solution sol;
 
-	// If we're dealing with fractional radii, try upscale them into integral
-	// ones. This should yield in more reliable and more optimized results.
+	// If we're dealing with fractional radii, try upscale them into integer
+	// ones. This should yield more reliable and more optimal results.
 	// For instance, using r0=1.5, r1=3.5 causes the algorithm to fail but
 	// r0=3, r1=7 (scaled up by 2) yields a 2-component solution. We can then
 	// downscale the radii back by dividing the scale fields of the solution
 	// components.
 	double scale = 1.0;
 
-	if (not IsZero (scale = r0 - floor (r0)) or not IsZero (scale = r1 - floor (r1)))
+	if (not isZero (scale = r0 - floor (r0)) or not isZero (scale = r1 - floor (r1)))
 	{
-		double r0f = r0 / scale;
-		double r1f = r1 / scale;
-
-		if (IsIntegral (r0f) and IsIntegral (r1f))
+		if (isInteger (r0 / scale) and isInteger (r1 / scale))
 		{
-			r0 = r0f;
-			r1 = r1f;
+			r0 = r0 / scale;
+			r1 = r1 / scale;
 		}
 		// If the numbers are both at most one-decimal fractions, we can use a scale of 10
-		elif (IsIntegral (r0 * 10) and IsIntegral (r1 * 10))
+		else if (isInteger (r0 * 10) and isInteger (r1 * 10))
 		{
 			scale = 0.1;
 			r0 *= 10;
@@ -165,15 +164,15 @@
 
 	// Compare the solutions and find the best one. The solution class has an operator>
 	// overload to compare two solutions.
-	m_bestSolution = null;
+	m_bestSolution = nullptr;
 
 	for (Solution const& sol : m_solutions)
 	{
-		if (m_bestSolution == null or sol.isSuperiorTo (m_bestSolution))
+		if (m_bestSolution == nullptr or sol.isSuperiorTo (m_bestSolution))
 			m_bestSolution = &sol;
 	}
 
-	return (m_bestSolution != null);
+	return (m_bestSolution != nullptr);
 }
 
 //
@@ -204,8 +203,8 @@
 
 	for (int i = 0; i < getComponents().size(); ++i)
 	{
-		maxA = Max (getComponents()[i].num, maxA);
-		maxB = Max (other->getComponents()[i].num, maxB);
+		maxA = max (getComponents()[i].num, maxA);
+		maxB = max (other->getComponents()[i].num, maxB);
 	}
 
 	if (maxA != maxB)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/vertex.cpp	Tue Jul 07 21:35:20 2015 +0300
@@ -0,0 +1,94 @@
+/*
+ *  LDForge: LDraw parts authoring CAD
+ *  Copyright (C) 2013 - 2015 Teemu Piippo
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "vertex.h"
+#include "format.h"
+
+Vertex::Vertex() :
+	QVector3D() {}
+
+Vertex::Vertex (const QVector3D& a) :
+	QVector3D (a) {}
+
+Vertex::Vertex (qreal xpos, qreal ypos, qreal zpos) :
+	QVector3D(xpos, ypos, zpos) {}
+
+
+void Vertex::transform (const Matrix& matr, const Vertex& pos)
+{
+	double x2 = (matr[0] * x()) + (matr[1] * y()) + (matr[2] * z()) + pos.x();
+	double y2 = (matr[3] * x()) + (matr[4] * y()) + (matr[5] * z()) + pos.y();
+	double z2 = (matr[6] * x()) + (matr[7] * y()) + (matr[8] * z()) + pos.z();
+	setX (x2);
+	setY (y2);
+	setZ (z2);
+}
+
+void Vertex::apply (ApplyFunction func)
+{
+	double newX = x(), newY = y(), newZ = z();
+	func (X, newX);
+	func (Y, newY);
+	func (Z, newZ);
+	*this = Vertex (newX, newY, newZ);
+}
+
+void Vertex::apply (ApplyConstFunction func) const
+{
+	func (X, x());
+	func (Y, y());
+	func (Z, z());
+}
+
+double Vertex::operator[] (Axis ax) const
+{
+	switch (ax)
+	{
+	case X: return x();
+	case Y: return y();
+	case Z: return z();
+	}
+
+	return 0.0;
+}
+
+void Vertex::setCoordinate (Axis ax, qreal value)
+{
+	switch (ax)
+	{
+	case X: setX (value); break;
+	case Y: setY (value); break;
+	case Z: setZ (value); break;
+	}
+}
+
+QString Vertex::toString (bool mangled) const
+{
+	if (mangled)
+		return format ("(%1, %2, %3)", x(), y(), z());
+
+	return format ("%1 %2 %3", x(), y(), z());
+}
+
+bool Vertex::operator< (const Vertex& other) const
+{
+	if (x() != other.x()) return x() < other.x();
+	if (y() != other.y()) return y() < other.y();
+	if (z() != other.z()) return z() < other.z();
+	return false;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/vertex.h	Tue Jul 07 21:35:20 2015 +0300
@@ -0,0 +1,57 @@
+/*
+ *  LDForge: LDraw parts authoring CAD
+ *  Copyright (C) 2013 - 2015 Teemu Piippo
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+#include <QVector3D>
+#include <functional>
+#include "basics.h"
+
+class Matrix;
+
+enum Axis
+{
+	X,
+	Y,
+	Z
+};
+
+//
+// Derivative of QVector3D: this class is used for the vertices.
+//
+class Vertex : public QVector3D
+{
+public:
+	using ApplyFunction = std::function<void (Axis, double&)>;
+	using ApplyConstFunction = std::function<void (Axis, double)>;
+
+	Vertex();
+	Vertex (const QVector3D& a);
+	Vertex (qreal xpos, qreal ypos, qreal zpos);
+
+	void	apply (ApplyFunction func);
+	void	apply (ApplyConstFunction func) const;
+	QString	toString (bool mangled = false) const;
+	void	transform (const Matrix& matr, const Vertex& pos);
+	void	setCoordinate (Axis ax, qreal value);
+
+	bool	operator< (const Vertex& other) const;
+	double	operator[] (Axis ax) const;
+};
+
+extern const Vertex Origin;
+Q_DECLARE_METATYPE (Vertex)
\ No newline at end of file

mercurial