Renamed ConfigurationValueBag to Configuration and added a pointer to it into HierarchyElement. This helps with the fight against global variables.

Sun, 14 Feb 2016 03:19:28 +0200

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Sun, 14 Feb 2016 03:19:28 +0200
changeset 1017
fc1c13db9618
parent 1016
3b279b5e57d3
child 1018
49358df9495b

Renamed ConfigurationValueBag to Configuration and added a pointer to it into HierarchyElement. This helps with the fight against global variables.
Added transform.h that may or may not prove useful sometime
Added linelength.py that was missing from a prior commit
Converted the various boolean members of LDDocument to flags

CMakeLists.txt file | annotate | diff | comparison | revisions
src/addObjectDialog.cpp file | annotate | diff | comparison | revisions
src/basics.h file | annotate | diff | comparison | revisions
src/dialogs/colorselector.cpp file | annotate | diff | comparison | revisions
src/dialogs/configdialog.cpp file | annotate | diff | comparison | revisions
src/dialogs/newpartdialog.cpp file | annotate | diff | comparison | revisions
src/documentmanager.cpp file | annotate | diff | comparison | revisions
src/editHistory.cpp file | annotate | diff | comparison | revisions
src/editmodes/abstractEditMode.cpp file | annotate | diff | comparison | revisions
src/glCompiler.cpp file | annotate | diff | comparison | revisions
src/glRenderer.cpp file | annotate | diff | comparison | revisions
src/guiutilities.cpp file | annotate | diff | comparison | revisions
src/guiutilities.h file | annotate | diff | comparison | revisions
src/hierarchyelement.cpp file | annotate | diff | comparison | revisions
src/hierarchyelement.h 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/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/partdownloader.cpp file | annotate | diff | comparison | revisions
src/toolsets/algorithmtoolset.cpp file | annotate | diff | comparison | revisions
src/toolsets/basictoolset.cpp file | annotate | diff | comparison | revisions
src/toolsets/filetoolset.cpp file | annotate | diff | comparison | revisions
src/toolsets/movetoolset.cpp file | annotate | diff | comparison | revisions
src/toolsets/viewtoolset.cpp file | annotate | diff | comparison | revisions
src/transform.h file | annotate | diff | comparison | revisions
tools/configcollector.py file | annotate | diff | comparison | revisions
tools/linelength.py file | annotate | diff | comparison | revisions
--- a/CMakeLists.txt	Sat Feb 13 04:14:43 2016 +0200
+++ b/CMakeLists.txt	Sun Feb 14 03:19:28 2016 +0200
@@ -29,7 +29,7 @@
 
 include_directories (${QT_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR})
 
-set_source_files_properties (${CMAKE_BINARY_DIR}/configurationvaluebag.cpp PROPERTIES GENERATED TRUE)
+set_source_files_properties (${CMAKE_BINARY_DIR}/configuration.cpp PROPERTIES GENERATED TRUE)
 
 set (LDFORGE_SOURCES
 	src/addObjectDialog.cpp
@@ -112,6 +112,7 @@
 	src/primitives.h
 	src/radioGroup.h
 	src/ringFinder.h
+	src/transform.h
 	src/dialogs/colorselector.h
 	src/dialogs/configdialog.h
 	src/dialogs/ldrawpathdialog.h
@@ -193,13 +194,13 @@
 	qt5_wrap_ui (LDFORGE_FORMS_HEADERS ${LDFORGE_FORMS})
 	add_executable (ldforge WIN32 ${LDFORGE_SOURCES} ${LDFORGE_HEADERS}
 		${LDFORGE_QRC} ${LDFORGE_FORMS_HEADERS}
-		${CMAKE_BINARY_DIR}/configurationvaluebag.cpp)
+		${CMAKE_BINARY_DIR}/configuration.cpp)
 else()
 	qt4_wrap_ui (LDFORGE_FORMS_HEADERS ${LDFORGE_FORMS})
 	qt4_add_resources (LDFORGE_RCC ${LDFORGE_RESOURCES})
 	add_executable (ldforge WIN32 ${LDFORGE_SOURCES} ${LDFORGE_RCC}
 		${LDFORGE_FORMS_HEADERS} ${LDFORGE_HEADERS}
-		${CMAKE_BINARY_DIR}/configurationvaluebag.cpp)
+		${CMAKE_BINARY_DIR}/configuration.cpp)
 endif()
 
 set_source_files_properties (${LDFORGE_HEADERS} PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -220,8 +221,8 @@
 add_custom_target (config_collection ALL
 	COMMAND python
 		"${CMAKE_SOURCE_DIR}/tools/configcollector.py"
-		--header ${CMAKE_BINARY_DIR}/configurationvaluebag.h
-		--source ${CMAKE_BINARY_DIR}/configurationvaluebag.cpp
+		--header ${CMAKE_BINARY_DIR}/configuration.h
+		--source ${CMAKE_BINARY_DIR}/configuration.cpp
 		--sourcedir ${CMAKE_SOURCE_DIR}/src
 		${LDFORGE_SOURCES}
 	WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
--- a/src/addObjectDialog.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/addObjectDialog.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -391,7 +391,7 @@
 	if (newObject)
 	{
 		int idx = g_win->suggestInsertPoint();
-		g_win->currentDocument()->insertObj (idx, obj);
+		g_win->currentDocument()->insertObject (idx, obj);
 	}
 
 	g_win->refresh();
--- a/src/basics.h	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/basics.h	Sun Feb 14 03:19:28 2016 +0200
@@ -24,6 +24,7 @@
 #include <QVector3D>
 #include <functional>
 #include "macros.h"
+#include "transform.h"
 
 class LDObject;
 class QFile;
--- a/src/dialogs/colorselector.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/dialogs/colorselector.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -55,8 +55,8 @@
 
 			if (ldcolor == MainColor)
 			{
-				color = QColor (Config->mainColor());
-				color.setAlphaF (Config->mainColorAlpha());
+				color = QColor (m_config->mainColor());
+				color.setAlphaF (m_config->mainColorAlpha());
 			}
 
 			QString color2name (luma (color) < 80 ? "white" : "black");
--- a/src/dialogs/configdialog.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/dialogs/configdialog.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -82,7 +82,7 @@
 	applyToWidgetOptions (
 	[&](QWidget* widget, QString confname)
 	{
-		QVariant value = m_settings->value (confname, Config->defaultValueByName (confname));
+		QVariant value = m_settings->value (confname, m_config->defaultValueByName (confname));
 		QLineEdit* le;
 		QSpinBox* spinbox;
 		QDoubleSpinBox* doublespinbox;
@@ -128,7 +128,7 @@
 
 	ui.shortcutsList->setSortingEnabled (true);
 	ui.shortcutsList->sortItems();
-	quickColors = LoadQuickColorList();
+	quickColors = guiUtilities()->loadQuickColorList();
 	updateQuickColorList();
 	initExtProgs();
 	selectPage (defaulttab);
@@ -232,7 +232,7 @@
 
 		QString optionname (widget->objectName().mid (strlen ("config")));
 
-		if (Config->existsEntry (optionname))
+		if (m_config->existsEntry (optionname))
 			func (widget, optionname);
 		else
 			print ("Couldn't find configuration entry named %1", optionname);
@@ -277,7 +277,7 @@
 
 	// Rebuild the quick color toolbar
 	m_window->setQuickColors (quickColors);
-	Config->setQuickColorToolbar (quickColorString());
+	m_config->setQuickColorToolbar (quickColorString());
 
 	// Ext program settings
 	for (int i = 0; i < NumExternalPrograms; ++i)
--- a/src/dialogs/newpartdialog.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/dialogs/newpartdialog.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -31,13 +31,13 @@
 {
 	ui.setupUi (this);
 
-	QString authortext = Config->defaultName();
+	QString authortext = m_config->defaultName();
 
-	if (not Config->defaultUser().isEmpty())
-		authortext.append (format (" [%1]", Config->defaultUser()));
+	if (not m_config->defaultUser().isEmpty())
+		authortext.append (format (" [%1]", m_config->defaultUser()));
 
 	ui.author->setText (authortext);
-	ui.useCaLicense->setChecked (Config->useCaLicense());
+	ui.useCaLicense->setChecked (m_config->useCaLicense());
 }
 
 BfcStatement NewPartDialog::getWinding() const
--- a/src/documentmanager.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/documentmanager.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -139,7 +139,7 @@
 		unknowns << static_cast<LDError*> (obj)->fileReferenced();
 	}
 
-	if (Config->tryDownloadMissingFiles() and not unknowns.isEmpty())
+	if (m_config->tryDownloadMissingFiles() and not unknowns.isEmpty())
 	{
 		PartDownloader dl (m_window);
 		dl.setSourceType (PartDownloader::PartsTracker);
@@ -225,7 +225,7 @@
 		return relativePath;
 
 	// Try with just the LDraw path first
-	QString fullPath = format ("%1" DIRSLASH "%2", Config->lDrawPath(), relativePath);
+	QString fullPath = format ("%1" DIRSLASH "%2", m_config->lDrawPath(), relativePath);
 
 	if (QFileInfo::exists (fullPath))
 		return fullPath;
@@ -234,7 +234,7 @@
 	{
 		// Look in sub-directories: parts and p. Also look in the download path, since that's where we download parts
 		// from the PT to.
-		QStringList dirs = { Config->lDrawPath(), Config->downloadFilePath() };
+		QStringList dirs = { m_config->lDrawPath(), m_config->downloadFilePath() };
 		for (const QString& topdir : dirs)
 		{
 			for (const QString& subdir : QStringList ({ "parts", "p" }))
@@ -363,7 +363,7 @@
 
 void DocumentManager::addRecentFile (QString path)
 {
-	QStringList recentFiles = Config->recentFiles();
+	QStringList recentFiles = m_config->recentFiles();
 	int idx = recentFiles.indexOf (path);
 
 	// If this file already is in the list, pop it out.
@@ -381,7 +381,7 @@
 
 	// Add the file
 	recentFiles << path;
-	Config->setRecentFiles (recentFiles);
+	m_config->setRecentFiles (recentFiles);
 	m_window->syncSettings();
 	m_window->updateRecentFilesMenu();
 }
@@ -416,7 +416,7 @@
 	// Possibly substitute with logoed studs:
 	// stud.dat -> stud-logo.dat
 	// stud2.dat -> stud-logo2.dat
-	if (Config->useLogoStuds() and renderinline)
+	if (m_config->useLogoStuds() and renderinline)
 	{
 		// Ensure logoed studs are loaded first
 		loadLogoedStuds();
--- a/src/editHistory.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/editHistory.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -170,7 +170,7 @@
 
 void AddHistoryEntry::redo() const
 {
-	parent()->document()->insertObj (m_index, ParseLine (m_code));
+	parent()->document()->insertObject (m_index, ParseLine (m_code));
 }
 
 //
--- a/src/editmodes/abstractEditMode.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/editmodes/abstractEditMode.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -175,7 +175,7 @@
 	{
 		for (LDObject* obj : objs)
 		{
-			renderer()->document()->insertObj (pos++, obj);
+			renderer()->document()->insertObject (pos++, obj);
 			renderer()->compileObject (obj);
 		}
 
@@ -189,7 +189,7 @@
 void AbstractDrawMode::drawLength (QPainter &painter, const Vertex &v0, const Vertex &v1,
 	const QPointF& v0p, const QPointF& v1p) const
 {
-	if (not Config->drawLineLengths())
+	if (not m_config->drawLineLengths())
 		return;
 
 	const QString label = QString::number ((v1 - v0).length());
@@ -231,7 +231,7 @@
 			if (withlengths)
 				drawLength (painter, poly3d[i], poly3d[j], poly[i], poly[j]);
 
-			if (withangles and Config->drawAngles())
+			if (withangles and m_config->drawAngles())
 			{
 				QLineF l0 (poly[h], poly[i]),
 					l1 (poly[i], poly[j]);
--- a/src/glCompiler.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/glCompiler.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -145,7 +145,7 @@
 		}
 		else if (poly.color == EdgeColor)
 		{
-			qcol = luma (QColor (Config->backgroundColor())) > 40 ? Qt::black : Qt::white;
+			qcol = luma (QColor (m_config->backgroundColor())) > 40 ? Qt::black : Qt::white;
 		}
 		else
 		{
@@ -186,7 +186,7 @@
 
 	if (blendAlpha != 0.0)
 	{
-		QColor selcolor (Config->selectColorBlend());
+		QColor selcolor (m_config->selectColorBlend());
 		double denom = blendAlpha + 1.0;
 		qcol.setRed ((qcol.red() + (selcolor.red() * blendAlpha)) / denom);
 		qcol.setGreen ((qcol.green() + (selcolor.green() * blendAlpha)) / denom);
--- a/src/glRenderer.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/glRenderer.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -78,7 +78,7 @@
 	m_initialized (false)
 {
 	m_isPicking = false;
-	m_camera = (ECamera) Config->camera();
+	m_camera = (ECamera) m_config->camera();
 	m_drawToolTip = false;
 	m_currentEditMode = AbstractEditMode::createByType (this, EditModeType::Select);
 	m_panning = false;
@@ -174,7 +174,7 @@
 	glShadeModel (GL_SMOOTH);
 	glEnable (GL_MULTISAMPLE);
 
-	if (Config->antiAliasedLines())
+	if (m_config->antiAliasedLines())
 	{
 		glEnable (GL_LINE_SMOOTH);
 		glEnable (GL_POLYGON_SMOOTH);
@@ -264,7 +264,7 @@
 	initializeOpenGLFunctions();
 #endif
 	setBackground();
-	glLineWidth (Config->lineThickness());
+	glLineWidth (m_config->lineThickness());
 	glLineStipple (1, 0x6666);
 	setAutoFillBackground (false);
 	setMouseTracking (true);
@@ -331,7 +331,7 @@
 		return;
 	}
 
-	QColor color = Config->backgroundColor();
+	QColor color = m_config->backgroundColor();
 
 	if (not color.isValid())
 		return;
@@ -392,7 +392,7 @@
 		zoomAllToFit();
 	}
 
-	if (Config->drawWireframe() and not isPicking())
+	if (m_config->drawWireframe() and not isPicking())
 		glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
 
 	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -446,7 +446,7 @@
 	}
 	else
 	{
-		if (Config->bfcRedGreenView())
+		if (m_config->bfcRedGreenView())
 		{
 			glEnable (GL_CULL_FACE);
 			glCullFace (GL_BACK);
@@ -461,7 +461,7 @@
 		{
 			ComplementVboType colors;
 
-			if (Config->randomColors())
+			if (m_config->randomColors())
 				colors = RandomColorsVboComplement;
 			else
 				colors = NormalColorsVboComplement;
@@ -475,7 +475,7 @@
 		drawVbos (ConditionalLinesVbo, NormalColorsVboComplement, GL_LINES);
 		glDisable (GL_LINE_STIPPLE);
 
-		if (Config->drawAxes())
+		if (m_config->drawAxes())
 		{
 			glBindBuffer (GL_ARRAY_BUFFER, m_axesVbo);
 			glVertexPointer (3, GL_FLOAT, 0, NULL);
@@ -501,9 +501,9 @@
 void GLRenderer::drawVbos (SurfaceVboType surface, ComplementVboType colors, GLenum type)
 {
 	// Filter this through some configuration options
-	if ((isOneOf (surface, QuadsVbo, TrianglesVbo) and Config->drawSurfaces() == false)
-		or (surface == LinesVbo and Config->drawEdgeLines() == false)
-		or (surface == ConditionalLinesVbo and Config->drawConditionalLines() == false))
+	if ((isOneOf (surface, QuadsVbo, TrianglesVbo) and m_config->drawSurfaces() == false)
+		or (surface == LinesVbo and m_config->drawEdgeLines() == false)
+		or (surface == ConditionalLinesVbo and m_config->drawConditionalLines() == false))
 	{
 		return;
 	}
@@ -920,7 +920,7 @@
 		return;
 
 	m_camera = cam;
-	Config->setCamera ((int) cam);
+	m_config->setCamera ((int) cam);
 	m_window->updateEditModeActions();
 }
 
@@ -1095,14 +1095,14 @@
 		glDisable (GL_DITHER);
 
 		// Use particularly thick lines while picking ease up selecting lines.
-		glLineWidth (qMax<double> (Config->lineThickness(), 6.5));
+		glLineWidth (qMax<double> (m_config->lineThickness(), 6.5));
 	}
 	else
 	{
 		glEnable (GL_DITHER);
 
 		// Restore line thickness
-		glLineWidth (Config->lineThickness());
+		glLineWidth (m_config->lineThickness());
 	}
 }
 
@@ -1510,13 +1510,13 @@
 			}
 
 			if (lastOverlay != -1)
-				document()->insertObj (lastOverlay + 1, ovlobj);
+				document()->insertObject (lastOverlay + 1, ovlobj);
 			else
 			{
-				document()->insertObj (i, ovlobj);
+				document()->insertObject (i, ovlobj);
 
 				if (found)
-					document()->insertObj (i + 1, LDSpawn<LDEmpty>());
+					document()->insertObject (i + 1, LDSpawn<LDEmpty>());
 			}
 		}
 
@@ -1539,14 +1539,14 @@
 //
 void GLRenderer::highlightCursorObject()
 {
-	if (not Config->highlightObjectBelowCursor() and objectAtCursor() == nullptr)
+	if (not m_config->highlightObjectBelowCursor() and objectAtCursor() == nullptr)
 		return;
 
 	LDObject* newObject = nullptr;
 	LDObject* oldObject = objectAtCursor();
 	qint32 newIndex;
 
-	if (m_isCameraMoving or not Config->highlightObjectBelowCursor())
+	if (m_isCameraMoving or not m_config->highlightObjectBelowCursor())
 	{
 		newIndex = 0;
 	}
@@ -1595,7 +1595,7 @@
 		ref->setFileInfo (m_documents->getDocumentByName (primitiveName));
 		ref->setPosition (Origin);
 		ref->setTransform (IdentityMatrix);
-		currentDocument()->insertObj (m_window->suggestInsertPoint(), ref);
+		currentDocument()->insertObject (m_window->suggestInsertPoint(), ref);
 		ref->select();
 		m_window->buildObjectList();
 		m_window->renderer()->refresh();
--- a/src/guiutilities.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/guiutilities.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -37,8 +37,8 @@
 	if (ldcolor == MainColor)
 	{
 		// Use the user preferences for main color here
-		color = Config->mainColor();
-		color.setAlphaF (Config->mainColorAlpha());
+		color = m_config->mainColor();
+		color.setAlphaF (m_config->mainColorAlpha());
 	}
 
 	// Paint the icon border
@@ -84,11 +84,34 @@
 
 QColor GuiUtilities::mainColorRepresentation()
 {
-	QColor col (Config->mainColor());
+	QColor col (m_config->mainColor());
 
 	if (not col.isValid())
 		return QColor (0, 0, 0);
 
-	col.setAlpha (Config->mainColorAlpha() * 255.f);
+	col.setAlpha (m_config->mainColorAlpha() * 255.f);
 	return col;
 }
+
+//
+// Returns a list of quick colors based on the configuration entry.
+//
+QList<ColorToolbarItem> GuiUtilities::loadQuickColorList()
+{
+	QList<ColorToolbarItem> colors;
+
+	for (QString colorname : m_config->quickColorToolbar().split (":"))
+	{
+		if (colorname == "|")
+			colors << ColorToolbarItem::makeSeparator();
+		else
+		{
+			LDColor color = colorname.toInt();
+
+			if (color.isValid())
+				colors << ColorToolbarItem (color, nullptr);
+		}
+	}
+
+	return colors;
+}
\ No newline at end of file
--- a/src/guiutilities.h	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/guiutilities.h	Sun Feb 14 03:19:28 2016 +0200
@@ -19,6 +19,7 @@
 #pragma once
 #include "hierarchyelement.h"
 #include "main.h"
+#include "mainwindow.h"
 
 class GuiUtilities : public QObject, public HierarchyElement
 {
@@ -29,4 +30,5 @@
 	QIcon makeColorIcon (LDColor ldcolor, int size);
 	void fillUsedColorsToComboBox (class QComboBox* box);
 	QColor mainColorRepresentation();
+	QList<ColorToolbarItem> loadQuickColorList();
 };
--- a/src/hierarchyelement.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/hierarchyelement.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -41,6 +41,7 @@
 	}
 
 	m_documents = m_window->documents();
+	m_config = m_window->config();
 }
 
 GuiUtilities* HierarchyElement::guiUtilities() const
--- a/src/hierarchyelement.h	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/hierarchyelement.h	Sun Feb 14 03:19:28 2016 +0200
@@ -19,9 +19,9 @@
 #pragma once
 #include <QObject>
 #include "main.h"
+#include "configuration.h"
 
 class MainWindow;
-class ConfigurationValueBag;
 class GuiUtilities;
 class LDDocument;
 class DocumentManager;
@@ -42,4 +42,5 @@
 protected:
 	MainWindow* m_window;
 	DocumentManager* m_documents;
+	Configuration* m_config;
 };
--- a/src/ldDocument.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/ldDocument.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -38,12 +38,7 @@
 	QObject (parent),
 	HierarchyElement (parent),
 	m_history (new EditHistory (this)),
-	m_isCache (true),
-	m_verticesOutdated (true),
-	m_needVertexMerge (true),
-	m_needsReCache(true),
-	m_beingDestroyed (false),
-	m_needRecount(false),
+	m_flags(IsCache | VerticesOutdated | NeedsVertexMerge | NeedsRecache),
 	m_savePosition(-1),
 	m_tabIndex(-1),
 	m_triangleCount(0),
@@ -52,7 +47,7 @@
 
 LDDocument::~LDDocument()
 {
-	m_beingDestroyed = true;
+	m_flags |= IsBeingDestroyed;
 
 	for (int i = 0; i < m_objects.size(); ++i)
 		m_objects[i]->destroy();
@@ -128,14 +123,14 @@
 
 int LDDocument::triangleCount()
 {
-	if (m_needRecount)
+	if (checkFlag(NeedsTriangleRecount))
 	{
 		m_triangleCount = 0;
 
 		for (LDObject* obj : m_objects)
 			m_triangleCount += obj->triangleCount();
 
-		m_needRecount = false;
+		unsetFlag(NeedsTriangleRecount);
 	}
 
 	return m_triangleCount;
@@ -143,9 +138,9 @@
 
 void LDDocument::openForEditing()
 {
-	if (m_isCache)
+	if (isCache())
 	{
-		m_isCache = false;
+		m_flags &= ~IsCache;
 		print ("Opened %1", name());
 
 		// Cache files are not compiled by the GL renderer. Now that this file is open for editing, it needs to be
@@ -157,7 +152,7 @@
 
 bool LDDocument::isCache() const
 {
-	return m_isCache;
+	return !!(m_flags & IsCache);
 }
 
 void LDDocument::addHistoryStep()
@@ -189,7 +184,7 @@
 {
 	if (not isCache())
 	{
-		m_isCache = true;
+		m_flags |= IsCache;
 		print ("Closed %1", name());
 		m_window->updateDocumentList();
 
@@ -600,7 +595,7 @@
 			obj->replace (ParseLine (static_cast<LDError*> (obj)->contents()));
 	}
 
-	m_needsReCache = true;
+	m_flags |= NeedsRecache;
 
 	if (this == m_window->currentDocument())
 		m_window->buildObjectList();
@@ -614,7 +609,7 @@
 	m_objects << obj;
 	addKnownVertices (obj);
 	obj->setDocument (this);
-	m_needRecount = true;
+	setFlag(NeedsTriangleRecount);
 	m_window->renderer()->compileObject (obj);
 	return getObjectCount() - 1;
 }
@@ -632,12 +627,12 @@
 
 // =============================================================================
 //
-void LDDocument::insertObj (int pos, LDObject* obj)
+void LDDocument::insertObject (int pos, LDObject* obj)
 {
 	history()->add (new AddHistoryEntry (pos, obj));
 	m_objects.insert (pos, obj);
 	obj->setDocument (this);
-	m_needRecount = true;
+	setFlag(NeedsTriangleRecount);
 	m_window->renderer()->compileObject (obj);
 	
 
@@ -672,21 +667,21 @@
 	{
 		obj->deselect();
 
-		if (not isCache() and not m_beingDestroyed)
+		if (not isCache() and not checkFlag(IsBeingDestroyed))
 		{
 			history()->add (new DelHistoryEntry (idx, obj));
 			m_objectVertices.remove (obj);
 		}
 
 		m_objects.removeAt (idx);
-		m_needRecount = true;
+		setFlag(NeedsTriangleRecount);
 		obj->setDocument (nullptr);
 	}
 }
 
 // =============================================================================
 //
-void LDDocument::setObject (int idx, LDObject* obj)
+void LDDocument::setObjectAt (int idx, LDObject* obj)
 {
 	if (idx < 0 or idx >= m_objects.size())
 		return;
@@ -750,7 +745,7 @@
 //
 void LDDocument::initializeCachedData()
 {
-	if (m_needsReCache)
+	if (checkFlag(NeedsRecache))
 	{
 		m_vertices.clear();
 
@@ -773,10 +768,10 @@
 			}
 		}
 
-		m_needsReCache = false;
+		unsetFlag(NeedsRecache);
 	}
 
-	if (m_verticesOutdated)
+	if (checkFlag(VerticesOutdated))
 	{
 		m_objectVertices.clear();
 
@@ -784,10 +779,10 @@
 			addKnownVertices (obj);
 
 		mergeVertices();
-		m_verticesOutdated = false;
+		unsetFlag(VerticesOutdated);
 	}
 
-	if (m_needVertexMerge)
+	if (checkFlag(NeedsVertexMerge))
 		mergeVertices();
 }
 
@@ -801,7 +796,7 @@
 		m_vertices << verts;
 
 	removeDuplicates (m_vertices);
-	m_needVertexMerge = false;
+	unsetFlag(NeedsVertexMerge);
 }
 
 // =============================================================================
@@ -921,15 +916,15 @@
 
 void LDDocument::redoVertices()
 {
-	m_verticesOutdated = true;
+	setFlag(VerticesOutdated);
 }
 
 void LDDocument::needVertexMerge()
 {
-	m_needVertexMerge = true;
+	setFlag(NeedsVertexMerge);
 }
 
-void LDDocument::needRecount()
+void LDDocument::recountTriangles()
 {
-	m_needRecount = true;
+	setFlag(NeedsTriangleRecount);
 }
--- a/src/ldDocument.h	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/ldDocument.h	Sun Feb 14 03:19:28 2016 +0200
@@ -44,11 +44,22 @@
 	Q_OBJECT
 
 public:
+	enum Flag
+	{
+		IsCache = (1 << 0),
+		VerticesOutdated = (1 << 1),
+		NeedsVertexMerge = (1 << 2),
+		IsBeingDestroyed = (1 << 3),
+		NeedsRecache = (1 << 4), // The next polygon inline of this document rebuilds stored polygon data.
+		NeedsTriangleRecount = (1 << 5),
+	};
+
+	Q_DECLARE_FLAGS(Flags, Flag)
+
 	LDDocument (DocumentManager* parent);
 	~LDDocument();
 
 	void addHistoryStep();
-	void addKnownVertices (LDObject* obj);
 	int addObject (LDObject* obj);
 	void addObjects (const LDObjectList& objs);
 	void addToHistory (AbstractHistoryEntry* entry);
@@ -71,16 +82,15 @@
 	LDObjectList inlineContents (bool deep, bool renderinline);
 	QList<LDPolygon> inlinePolygons();
 	const QVector<Vertex>& inlineVertices();
-	void insertObj (int pos, LDObject* obj);
+	void insertObject (int pos, LDObject* obj);
 	bool isCache() const;
 	bool isSafeToClose();
-	void mergeVertices();
 	QString name() const;
 	void needVertexMerge();
-	void needRecount();
 	const LDObjectList& objects() const;
 	void openForEditing();
 	const QList<LDPolygon>& polygonData() const;
+	void recountTriangles();
 	void redo();
 	void redoVertices();
 	void reloadAllSubfiles();
@@ -89,9 +99,8 @@
 	long savePosition() const;
 	void setDefaultName (QString value);
 	void setFullPath (QString value);
-	void setImplicit (bool value);
 	void setName (QString value);
-	void setObject (int idx, LDObject* obj);
+	void setObjectAt (int idx, LDObject* obj);
 	void setSavePosition (long value);
 	void setTabIndex (int value);
 	void swapObjects (LDObject* one, LDObject* other);
@@ -108,12 +117,7 @@
 	QString m_defaultName;
 	LDObjectList m_objects;
 	EditHistory* m_history;
-	bool m_isCache;
-	bool m_verticesOutdated;
-	bool m_needVertexMerge;
-	bool m_needsReCache; // If true, next polygon inline of this document rebuilds stored polygon data.
-	bool m_beingDestroyed;
-	bool m_needRecount;
+	Flags m_flags;
 	long m_savePosition;
 	int m_tabIndex;
 	int m_triangleCount;
@@ -123,7 +127,13 @@
 	LDObjectList m_sel;
 	LDGLData* m_gldata;
 	DocumentManager* m_manager;
+
+	DEFINE_FLAG_ACCESS_METHODS
+	void addKnownVertices (LDObject* obj);
+	void mergeVertices();
 };
 
+Q_DECLARE_OPERATORS_FOR_FLAGS(LDDocument::Flags)
+
 // Parses a string line containing an LDraw object and returns the object parsed.
 LDObject* ParseLine (QString line);
--- a/src/ldObject.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/ldObject.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -217,7 +217,7 @@
 	if (idx != -1)
 	{
 		// Replace the instance of the old object with the new object
-		document()->setObject (idx, other);
+		document()->setObjectAt (idx, other);
 
 		// Remove the old object
 		destroy();
@@ -231,9 +231,9 @@
 	if (idx != -1 and not others.isEmpty())
 	{
 		for (int i = 1; i < others.size(); ++i)
-			document()->insertObj (idx + i, others[i]);
+			document()->insertObject (idx + i, others[i]);
 
-		document()->setObject (idx, others[0]);
+		document()->setObjectAt (idx, others[0]);
 		destroy();
 	}
 }
@@ -773,7 +773,7 @@
 	}
 
 	// Not inverted, thus prefix it with a new invertnext.
-	document()->insertObj (idx, new LDBfc (BfcStatement::InvertNext));
+	document()->insertObject (idx, new LDBfc (BfcStatement::InvertNext));
 }
 
 // =============================================================================
@@ -1210,7 +1210,7 @@
 	changeProperty (this, &m_fileInfo, newReferee);
 
 	if (document())
-		document()->needRecount();
+		document()->recountTriangles();
 
 	// If it's an immediate subfile reference (i.e. this subfile is in an opened document), we need to pre-compile the
 	// GL polygons for the document if they don't exist already.
--- a/src/macros.h	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/macros.h	Sun Feb 14 03:19:28 2016 +0200
@@ -66,6 +66,11 @@
 
 #define ConfigOption(...)
 
+#define DEFINE_FLAG_ACCESS_METHODS \
+	bool checkFlag(Flag flag) const { return !!(m_flags & flag); } \
+	void setFlag(Flag flag) { m_flags |= flag; } \
+	void unsetFlag(Flag flag) { m_flags &= ~flag; }
+
 // once-statement
 struct OnceGuard
 {
--- a/src/main.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/main.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -35,7 +35,7 @@
 #include "documentmanager.h"
 
 MainWindow* g_win = nullptr;
-ConfigurationValueBag* Config = nullptr;
+Configuration* Config = nullptr;
 const Vertex Origin (0.0f, 0.0f, 0.0f);
 const Matrix IdentityMatrix ({1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f});
 
@@ -49,7 +49,7 @@
 	app.setOrganizationName (APPNAME);
 	app.setApplicationName (APPNAME);
 
-	static ConfigurationValueBag configObject;
+	static Configuration configObject;
 	Config = &configObject;
 
 	LDPaths* paths = new LDPaths;
@@ -58,7 +58,7 @@
 
 	initCrashCatcher();
 	initColors();
-	MainWindow* win = new MainWindow;
+	MainWindow* win = new MainWindow(configObject);
 	LoadPrimitives();
 	win->show();
 
--- a/src/main.h	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/main.h	Sun Feb 14 03:19:28 2016 +0200
@@ -31,6 +31,6 @@
 #include "version.h"
 #include "format.h"
 #include "hierarchyelement.h"
-#include "configurationvaluebag.h"
+#include "configuration.h"
 
-extern ConfigurationValueBag* Config;
\ No newline at end of file
+extern Configuration* Config;
\ No newline at end of file
--- a/src/mainwindow.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/mainwindow.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -64,8 +64,9 @@
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-MainWindow::MainWindow (QWidget* parent, Qt::WindowFlags flags) :
+MainWindow::MainWindow(class Configuration& config, QWidget* parent, Qt::WindowFlags flags) :
 	QMainWindow (parent, flags),
+	m_config(config),
 	m_guiUtilities (new GuiUtilities (this)),
 	ui (*new Ui_MainWindow),
 	m_externalPrograms (nullptr),
@@ -100,7 +101,7 @@
 	else
 		updatePrimitives();
 
-	m_quickColors = LoadQuickColorList();
+	m_quickColors = m_guiUtilities->loadQuickColorList();
 	setStatusBar (new QStatusBar);
 	updateActions();
 
@@ -160,7 +161,7 @@
 		}
 	}
 
-	for (QVariant const& toolbarname : Config->hiddenToolbars())
+	for (QVariant const& toolbarname : m_config.hiddenToolbars())
 	{
 		QToolBar* toolbar = findChild<QToolBar*> (toolbarname.toString());
 
@@ -170,11 +171,11 @@
 
 	// If this is the first start, get the user to configuration. Especially point
 	// them to the profile tab, it's the most important form to fill in.
-	if (Config->firstStart())
+	if (m_config.firstStart())
 	{
 		ConfigDialog* dialog = new ConfigDialog (this, ConfigDialog::ProfileTab);
 		dialog->show();
-		Config->setFirstStart (false);
+		m_config.setFirstStart (false);
 	}
 }
 
@@ -234,7 +235,7 @@
 
 	QAction* first = nullptr;
 
-	for (const QVariant& it : Config->recentFiles())
+	for (const QVariant& it : m_config.recentFiles())
 	{
 		QString file = it.toString();
 		QAction* recent = new QAction (GetIcon ("open-recent"), file, this);
@@ -248,28 +249,6 @@
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-QList<ColorToolbarItem> LoadQuickColorList()
-{
-	QList<ColorToolbarItem> colors;
-
-	for (QString colorname : Config->quickColorToolbar().split (":"))
-	{
-		if (colorname == "|")
-			colors << ColorToolbarItem::makeSeparator();
-		else
-		{
-			LDColor color = colorname.toInt();
-
-			if (color.isValid())
-				colors << ColorToolbarItem (color, nullptr);
-		}
-	}
-
-	return colors;
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
 void MainWindow::updateColorToolbar()
 {
 	m_colorButtons.clear();
@@ -306,7 +285,7 @@
 void MainWindow::updateGridToolBar()
 {
 	// Ensure that the current grid - and only the current grid - is selected.
-	int grid = Config->grid();
+	int grid = m_config.grid();
 	ui.actionGridCoarse->setChecked (grid == Grid::Coarse);
 	ui.actionGridMedium->setChecked (grid == Grid::Medium);
 	ui.actionGridFine->setChecked (grid == Grid::Fine);
@@ -481,7 +460,7 @@
 			item->setBackground (QColor ("#AA0000"));
 			item->setForeground (QColor ("#FFAA00"));
 		}
-		else if (Config->colorizeObjectsList()
+		else if (m_config.colorizeObjectsList()
 			and obj->isColored()
 			and obj->color().isValid()
 			and obj->color() != MainColor
@@ -714,7 +693,7 @@
 	}
 
 	// Save the configuration before leaving.
-	Config->setHiddenToolbars (hiddenToolbars);
+	m_config.setHiddenToolbars (hiddenToolbars);
 	syncSettings();
 	ev->accept();
 }
@@ -1040,14 +1019,14 @@
 		ui.actionRedo->setEnabled (pos < (long) his->size() - 1);
 	}
 
-	ui.actionWireframe->setChecked (Config->drawWireframe());
-	ui.actionAxes->setChecked (Config->drawAxes());
-	ui.actionBfcView->setChecked (Config->bfcRedGreenView());
-	ui.actionRandomColors->setChecked (Config->randomColors());
-	ui.actionDrawAngles->setChecked (Config->drawAngles());
-	ui.actionDrawSurfaces->setChecked (Config->drawSurfaces());
-	ui.actionDrawEdgeLines->setChecked (Config->drawEdgeLines());
-	ui.actionDrawConditionalLines->setChecked (Config->drawConditionalLines());
+	ui.actionWireframe->setChecked (m_config.drawWireframe());
+	ui.actionAxes->setChecked (m_config.drawAxes());
+	ui.actionBfcView->setChecked (m_config.bfcRedGreenView());
+	ui.actionRandomColors->setChecked (m_config.randomColors());
+	ui.actionDrawAngles->setChecked (m_config.drawAngles());
+	ui.actionDrawSurfaces->setChecked (m_config.drawSurfaces());
+	ui.actionDrawEdgeLines->setChecked (m_config.drawEdgeLines());
+	ui.actionDrawConditionalLines->setChecked (m_config.drawConditionalLines());
 }
 
 // ---------------------------------------------------------------------------------------------------------------------
@@ -1202,7 +1181,7 @@
 //
 QVariant MainWindow::getConfigValue (QString name)
 {
-	QVariant value = m_settings->value (name, Config->defaultValueByName (name));
+	QVariant value = m_settings->value (name, m_config.defaultValueByName (name));
 	return value;
 }
 
@@ -1322,6 +1301,11 @@
 	return m_guiUtilities;
 }
 
+Configuration* MainWindow::config()
+{
+	return &m_config;
+}
+
 // ---------------------------------------------------------------------------------------------------------------------
 //
 ColorToolbarItem::ColorToolbarItem (LDColor color, QToolButton* toolButton) :
--- a/src/mainwindow.h	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/mainwindow.h	Sun Feb 14 03:19:28 2016 +0200
@@ -37,6 +37,7 @@
 class QProgressBar;
 struct Primitive;
 class Toolset;
+class Configuration;
 
 class ColorToolbarItem
 {
@@ -70,7 +71,7 @@
 	Q_OBJECT
 
 public:
-	explicit MainWindow (QWidget* parent = nullptr, Qt::WindowFlags flags = 0);
+	explicit MainWindow(Configuration& config, QWidget* parent = nullptr, Qt::WindowFlags flags = 0);
 	~MainWindow();
 
 	void addMessage (QString msg);
@@ -78,6 +79,7 @@
 	void buildObjectList();
 	void changeDocument (LDDocument* f);
 	void closeInitialDocument();
+	Configuration* config();
 	void createBlankDocument();
 	LDDocument* currentDocument();
 	void currentDocumentClosed();
@@ -133,6 +135,7 @@
 private:
 	struct ToolInfo { QMetaMethod method; Toolset* object; };
 
+	Configuration& m_config;
 	class GuiUtilities* m_guiUtilities;
 	GLRenderer* m_renderer;
 	LDObjectList m_sel;
@@ -167,9 +170,6 @@
 // Get an icon by name from the resources directory.
 QPixmap GetIcon (QString iconName);
 
-// Returns a list of quick colors based on the configuration entry.
-QList<ColorToolbarItem> LoadQuickColorList();
-
 // Asks the user a yes/no question with the given message and the given window title.
 // Returns true if the user answered yes, false if no.
 bool Confirm (const QString& title, const QString& message); // Generic confirm prompt
--- a/src/partdownloader.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/partdownloader.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -74,7 +74,7 @@
 		if (path.isEmpty())
 			reject();
 		else
-			Config->setDownloadFilePath (path);
+			m_config->setDownloadFilePath (path);
 	}
 }
 
@@ -103,7 +103,7 @@
 	dest = dest.simplified();
 
 	// If the user doesn't want us to guess, stop right here.
-	if (not Config->guessDownloadPaths())
+	if (not m_config->guessDownloadPaths())
 		return;
 
 	// Ensure .dat extension
@@ -271,7 +271,7 @@
 	for (LDDocument* f : m_files)
 		f->reloadAllSubfiles();
 
-	if (Config->autoCloseDownloadDialog() and not failed)
+	if (m_config->autoCloseDownloadDialog() and not failed)
 	{
 		// Close automatically if desired.
 		accept();
@@ -323,7 +323,7 @@
 
 QString PartDownloader::downloadPath()
 {
-	QString path = Config->downloadFilePath();
+	QString path = m_config->downloadFilePath();
 
 	if (DIRSLASH[0] != '/')
 		path.replace (DIRSLASH, "/");
--- a/src/toolsets/algorithmtoolset.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/toolsets/algorithmtoolset.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -64,8 +64,8 @@
 
 		// Replace the quad with the first triangle and add the second triangle
 		// after the first one.
-		currentDocument()->setObject (index, triangles[0]);
-		currentDocument()->insertObj (index + 1, triangles[1]);
+		currentDocument()->setObjectAt (index, triangles[0]);
+		currentDocument()->insertObject (index + 1, triangles[1]);
 		num++;
 	}
 
@@ -137,7 +137,7 @@
 				continue;
 
 			long idx = obj->lineNumber() + i + 1;
-			currentDocument()->insertObj (idx, lines[i]);
+			currentDocument()->insertObject (idx, lines[i]);
 			++num;
 		}
 	}
@@ -161,12 +161,12 @@
 
 			v.apply ([&](Axis, double& a)
 			{
-				roundToDecimals (a, Config->roundPositionPrecision());
+				roundToDecimals (a, m_config->roundPositionPrecision());
 			});
 
 			applyToMatrix (t, [&](int, double& a)
 			{
-				roundToDecimals (a, Config->roundMatrixPrecision());
+				roundToDecimals (a, m_config->roundMatrixPrecision());
 			});
 
 			mo->setPosition (v);
@@ -180,7 +180,7 @@
 				Vertex v = obj->vertex (i);
 				v.apply ([&](Axis, double& a)
 				{
-					roundToDecimals (a, Config->roundPositionPrecision());
+					roundToDecimals (a, m_config->roundPositionPrecision());
 				});
 				obj->setVertex (i, v);
 				num += 3;
@@ -333,7 +333,7 @@
 	QDialog* dlg = new QDialog;
 	Ui_AddHistoryLine* ui = new Ui_AddHistoryLine;
 	ui->setupUi (dlg);
-	ui->m_username->setText (Config->defaultUser());
+	ui->m_username->setText (m_config->defaultUser());
 	ui->m_date->setDate (QDate::currentDate());
 	ui->m_comment->setFocus();
 
@@ -363,12 +363,12 @@
 	}
 
 	int idx = obj ? obj->lineNumber() : 0;
-	currentDocument()->insertObj (idx++, comment);
+	currentDocument()->insertObject (idx++, comment);
 
 	// If we're adding a history line right before a scemantic object, pad it
 	// an empty line
 	if (obj and obj->next() and obj->next()->isScemantic())
-		currentDocument()->insertObj (idx, new LDEmpty);
+		currentDocument()->insertObject (idx, new LDEmpty);
 
 	m_window->buildObjectList();
 	delete ui;
@@ -378,12 +378,12 @@
 {
 	bool ok;
 	int segments = QInputDialog::getInt (m_window, APPNAME, "Amount of segments:",
-		Config->splitLinesSegments(), 0, std::numeric_limits<int>::max(), 1, &ok);
+		m_config->splitLinesSegments(), 0, std::numeric_limits<int>::max(), 1, &ok);
 
 	if (not ok)
 		return;
 
-	Config->setSplitLinesSegments (segments);
+	m_config->setSplitLinesSegments (segments);
 
 	for (LDObject* obj : selectedObjects())
 	{
@@ -420,7 +420,7 @@
 		int ln = obj->lineNumber();
 
 		for (LDObject* seg : newsegs)
-			currentDocument()->insertObj (ln++, seg);
+			currentDocument()->insertObject (ln++, seg);
 
 		obj->destroy();
 	}
@@ -544,7 +544,7 @@
 	LDObjectList objs;
 	objs << LDSpawn<LDComment> (subtitle);
 	objs << LDSpawn<LDComment> ("Name: "); // This gets filled in when the subfile is saved
-	objs << LDSpawn<LDComment> (format ("Author: %1 [%2]", Config->defaultName(), Config->defaultUser()));
+	objs << LDSpawn<LDComment> (format ("Author: %1 [%2]", m_config->defaultName(), m_config->defaultUser()));
 	objs << LDSpawn<LDComment> ("!LDRAW_ORG Unofficial_Subpart");
 
 	if (not license.isEmpty())
@@ -577,7 +577,7 @@
 		ref->setFileInfo (doc);
 		ref->setPosition (Origin);
 		ref->setTransform (IdentityMatrix);
-		currentDocument()->insertObj (refidx, ref);
+		currentDocument()->insertObject (refidx, ref);
 
 		// Refresh stuff
 		m_window->updateDocumentList();
--- a/src/toolsets/basictoolset.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/toolsets/basictoolset.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -77,7 +77,7 @@
 	for (QString line : clipboardText.split ("\n"))
 	{
 		LDObject* pasted = ParseLine (line);
-		currentDocument()->insertObj (idx++, pasted);
+		currentDocument()->insertObject (idx++, pasted);
 		pasted->select();
 		++num;
 	}
@@ -111,7 +111,7 @@
 				QString line = inlineobj->asText();
 				inlineobj->destroy();
 				LDObject* newobj = ParseLine (line);
-				currentDocument()->insertObj (idx++, newobj);
+				currentDocument()->insertObject (idx++, newobj);
 				newobj->select();
 			}
 	
@@ -185,7 +185,7 @@
 	{
 		LDObject* obj = ParseLine (line);
 
-		currentDocument()->insertObj (idx, obj);
+		currentDocument()->insertObject (idx, obj);
 		obj->select();
 		idx++;
 	}
--- a/src/toolsets/filetoolset.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/toolsets/filetoolset.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -98,10 +98,10 @@
 
 void FileToolset::setLDrawPath()
 {
-	LDrawPathDialog* dialog = new LDrawPathDialog (Config->lDrawPath(), true);
+	LDrawPathDialog* dialog = new LDrawPathDialog (m_config->lDrawPath(), true);
 
 	if (dialog->exec())
-		Config->setLDrawPath (dialog->path());
+		m_config->setLDrawPath (dialog->path());
 }
 
 void FileToolset::exit()
@@ -132,7 +132,7 @@
 
 	for (LDObject* obj : objs)
 	{
-		currentDocument()->insertObj (idx, obj);
+		currentDocument()->insertObject (idx, obj);
 		obj->select();
 		m_window->renderer()->compileObject (obj);
 
--- a/src/toolsets/movetoolset.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/toolsets/movetoolset.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -44,19 +44,19 @@
 
 void MoveToolset::gridCoarse()
 {
-	Config->setGrid (Grid::Coarse);
+	m_config->setGrid (Grid::Coarse);
 	m_window->updateGridToolBar();
 }
 
 void MoveToolset::gridMedium()
 {
-	Config->setGrid (Grid::Medium);
+	m_config->setGrid (Grid::Medium);
 	m_window->updateGridToolBar();
 }
 
 void MoveToolset::gridFine()
 {
-	Config->setGrid (Grid::Fine);
+	m_config->setGrid (Grid::Fine);
 	m_window->updateGridToolBar();
 }
 
--- a/src/toolsets/viewtoolset.cpp	Sat Feb 13 04:14:43 2016 +0200
+++ b/src/toolsets/viewtoolset.cpp	Sun Feb 14 03:19:28 2016 +0200
@@ -129,7 +129,7 @@
 
 void ViewToolset::axes()
 {
-	Config->setDrawAxes (not Config->drawAxes());
+	m_config->toggleDrawAxes();
 	m_window->updateActions();
 	m_window->renderer()->update();
 }
@@ -154,7 +154,7 @@
 
 void ViewToolset::wireframe()
 {
-	Config->setDrawWireframe (not Config->drawWireframe());
+	m_config->toggleDrawWireframe();
 	m_window->renderer()->refresh();
 }
 
@@ -176,7 +176,7 @@
 
 void ViewToolset::drawAngles()
 {
-	Config->setDrawAngles (not Config->drawAngles());
+	m_config->toggleDrawAngles();
 	m_window->renderer()->refresh();
 }
 
@@ -245,10 +245,10 @@
 
 void ViewToolset::bfcView()
 {
-	Config->setBfcRedGreenView (not Config->bfcRedGreenView());
+	m_config->toggleBfcRedGreenView();
 
-	if (Config->bfcRedGreenView())
-		Config->setRandomColors (false);
+	if (m_config->bfcRedGreenView())
+		m_config->setRandomColors (false);
 
 	m_window->updateActions();
 	m_window->renderer()->refresh();
@@ -276,10 +276,10 @@
 
 void ViewToolset::randomColors()
 {
-	Config->setRandomColors (not Config->randomColors());
+	m_config->toggleRandomColors();
 
-	if (Config->randomColors())
-		Config->setBfcRedGreenView (false);
+	if (m_config->randomColors())
+		m_config->setBfcRedGreenView (false);
 
 	m_window->updateActions();
 	m_window->renderer()->refresh();
@@ -287,18 +287,18 @@
 
 void ViewToolset::drawSurfaces()
 {
-	Config->setDrawSurfaces (not Config->drawSurfaces());
+	m_config->toggleDrawSurfaces();
 	m_window->updateActions();
 }
 
 void ViewToolset::drawEdgeLines()
 {
-	Config->setDrawEdgeLines (not Config->drawEdgeLines());
+	m_config->toggleDrawEdgeLines();
 	m_window->updateActions();
 }
 
 void ViewToolset::drawConditionalLines()
 {
-	Config->setDrawConditionalLines (not Config->drawConditionalLines());
+	m_config->toggleDrawConditionalLines();
 	m_window->updateActions();
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/transform.h	Sun Feb 14 03:19:28 2016 +0200
@@ -0,0 +1,93 @@
+/*
+ *  LDForge: LDraw parts authoring CAD
+ *  Copyright (C) 2013 - 2016 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 <functional>
+
+//
+// TransformingIterator
+//
+// Transforming iterator, calls Fn on iterated values before returning them.
+//
+template<typename T, typename Res, typename Arg>
+struct TransformingIterator
+{
+	using Iterator = decltype(T().begin());
+	using Self = TransformingIterator<T, Res, Arg>;
+	Iterator it;
+	std::function<Res(Arg)> fn;
+
+	TransformingIterator(Iterator it, std::function<Res(Arg)> fn) :
+		it(it),
+		fn(fn) {}
+
+	Res operator*()
+	{
+		return fn(*it);
+	}
+
+	bool operator!= (const Self& other) const
+	{
+		return other.it != it;
+	}
+
+	void operator++()
+	{
+		++it;
+	}
+};
+
+//
+// TransformWrapper
+//
+// Transform object, only serves to produce transforming iterators
+//
+template<typename T, typename Res, typename Arg>
+struct TransformWrapper
+{
+	using Iterator = TransformingIterator<T, Res, Arg>;
+
+	TransformWrapper(T& iterable, std::function<Res(Arg)> fn) :
+		iterable(iterable),
+		function(fn) {}
+
+	Iterator begin()
+	{
+		return Iterator(iterable.begin(), function);
+	}
+
+	Iterator end()
+	{
+		return Iterator(iterable.end(), function);
+	}
+
+	T& iterable;
+	std::function<Res(Arg)> function;
+};
+
+template<typename T, typename Res, typename Arg>
+TransformWrapper<T, Res, Arg> transform(T& iterable, Res(*fn)(Arg))
+{
+	return TransformWrapper<T, Res, Arg>(iterable, fn);
+}
+
+template<typename T, typename Res, typename Arg>
+TransformWrapper<T, Res, Arg> transform(T& iterable, std::function<Res(Arg)> fn)
+{
+	return TransformWrapper<T, Res, Arg>(iterable, fn);
+}
--- a/tools/configcollector.py	Sat Feb 13 04:14:43 2016 +0200
+++ b/tools/configcollector.py	Sun Feb 14 03:19:28 2016 +0200
@@ -123,6 +123,7 @@
 			decl['getter'] = caseconversions.convert_case (decl['name'], style='java')
 			decl['varname'] = 'm_' + decl['getter']
 			decl['setter'] = 'set' + caseconversions.convert_case (decl['name'], style='camel')
+			decl['toggler'] = 'toggle' + caseconversions.convert_case (decl['name'], style='camel')
 			decl['typecref'] = 'const %s&' % decl['type'] if decl['type'] not in passbyvalue else decl['type']
 
 			try:
@@ -153,20 +154,24 @@
 		fp.write ('#include <QMap>\n')
 		for qttype in sorted (self.qttypes):
 			fp.write ('#include <%s>\n' % qttype)
+		fp.write ('\n')
 		formatargs = {}
 		write = lambda value: fp.write (value)
-		write ('class ConfigurationValueBag\n')
+		write ('class Configuration\n')
 		write ('{\n')
 		write ('public:\n')
-		write ('\tConfigurationValueBag();\n')
-		write ('\t~ConfigurationValueBag();\n')
+		write ('\tConfiguration();\n')
+		write ('\t~Configuration();\n')
 		write ('\tbool existsEntry (const QString& name);\n')
 		write ('\tQVariant defaultValueByName (const QString& name);\n')
 
 		for decl in self.decls:
 			write ('\t{type} {getter}() const;\n'.format (**decl))
 		for decl in self.decls:
-			write ('\tvoid {setter} ({typecref} value);\n'.format (**decl))
+			write ('\tvoid {setter}({typecref} value);\n'.format (**decl))
+
+		for decl in filter(lambda decl: decl['type'] == 'bool', self.decls):
+			write('\tvoid {toggler}();\n'.format(**decl))
 
 		write ('\n')
 		write ('private:\n')
@@ -184,7 +189,7 @@
 
 		fp.write (
 			'\n'
-			'ConfigurationValueBag::ConfigurationValueBag() :\n'
+			'Configuration::Configuration() :\n'
 			'\tm_settings (makeSettings (nullptr))\n'
 			'{\n')
 
@@ -193,14 +198,14 @@
 
 		fp.write ('}\n'
 			'\n'
-			'ConfigurationValueBag::~ConfigurationValueBag()\n'
+			'Configuration::~Configuration()\n'
 			'{\n'
 			'\tm_settings->deleteLater();\n'
 			'}\n'
 			'\n')
 
 		maptype = 'QMap<QString, QVariant>'
-		fp.write ('QVariant ConfigurationValueBag::defaultValueByName (const QString& name)\n')
+		fp.write ('QVariant Configuration::defaultValueByName (const QString& name)\n')
 		fp.write ('{\n')
 		fp.write ('\t%s::iterator it = m_defaults.find (name);\n' % maptype)
 		fp.write ('\tif (it != m_defaults.end())\n')
@@ -208,14 +213,14 @@
 		fp.write ('\treturn QVariant();\n')
 		fp.write ('}\n')
 		fp.write ('\n')
-		fp.write ('bool ConfigurationValueBag::existsEntry (const QString& name)\n')
+		fp.write ('bool Configuration::existsEntry (const QString& name)\n')
 		fp.write ('{\n')
 		fp.write ('\treturn m_defaults.find (name) != m_defaults.end();\n')
 		fp.write ('}\n')
 		fp.write ('\n')
 
 		for decl in self.decls:
-			fp.write ('{type} ConfigurationValueBag::{getter}() const\n'.format (**decl))
+			fp.write ('{type} Configuration::{getter}() const\n'.format (**decl))
 			fp.write ('{\n')
 			fp.write ('\tstatic const QVariant defaultvalue = QVariant::fromValue<{type}> ({default});\n'.format (**decl))
 			fp.write ('\treturn m_settings->value ("{name}", defaultvalue).{valuefunc}();\n'.format (**decl))
@@ -223,7 +228,7 @@
 			fp.write ('\n')
 
 		for decl in self.decls:
-			fp.write ('void ConfigurationValueBag::{setter} ({typecref} value)\n'.format (**decl))
+			fp.write ('void Configuration::{setter}({typecref} value)\n'.format (**decl))
 			fp.write ('{\n')
 			fp.write ('\tif (value != {default})\n'.format (**decl))
 			fp.write ('\t\tm_settings->setValue ("{name}", QVariant::fromValue<{type}> (value));\n'.format (**decl))
@@ -232,6 +237,13 @@
 			fp.write ('}\n')
 			fp.write ('\n')
 
+		for decl in filter(lambda decl: decl['type'] == 'bool', self.decls):
+			fp.write('void Configuration::{toggler}()\n'.format(**decl))
+			fp.write('{\n')
+			fp.write('\t{setter}(not {getter}());\n'.format(**decl))
+			fp.write('}\n')
+			fp.write('\n')
+
 def main():
 	parser = argparse.ArgumentParser (description='Collects a list of configuration objects')
 	parser.add_argument ('inputs', nargs='+')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/linelength.py	Sun Feb 14 03:19:28 2016 +0200
@@ -0,0 +1,13 @@
+#!/usr/bin/env python3
+from sys import argv, stderr
+from os.path import realpath
+
+for filename in argv[1:]:
+	with open(filename, 'r') as fp:
+		try:
+			exceeders = [(i + 1) for i, ln in enumerate(fp.read().splitlines()) if len(ln.replace('\t', '    ')) > 120]
+
+			for linenumber in exceeders:
+				stderr.write('%s:%d: warning: line length exceeds 120 characters\n' % (realpath(filename), linenumber))
+		except Exception as e:
+			stderr.write('%s: warning: %s: %s\n' % (realpath(filename), type(e).__name__, e))

mercurial