src/cfg.cpp

changeset 20
a5457405cc9b
child 30
6b82f6a3ad53
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cfg.cpp	Sun Sep 08 16:14:58 2013 +0300
@@ -0,0 +1,153 @@
+/*
+ *  ZanDemo: Zandronum demo launcher
+ *  Copyright (C) 2013 Santeri 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 <cassert>
+#include <QDir>
+#include <QTextStream>
+#include <QSettings>
+#include "main.h"
+#include "config.h"
+
+#define MAX_CONFIG 512
+
+// =============================================================================
+// -----------------------------------------------------------------------------
+namespace cfg {
+	static struct {
+		void* ptr;
+		Type type;
+		const char* name;
+		QVariant def;
+	} g_configData[MAX_CONFIG];
+	
+	static int g_cfgDataCursor = 0;
+	
+#define CASE(T) case T##Type: return QVariant (*(reinterpret_cast<T*> (ptr)));
+	static QVariant getConfigValue (void* ptr, Type type) {
+		switch (type) {
+		CASE (Int)
+		CASE (String)
+		CASE (Float)
+		CASE (Bool)
+		CASE (List)
+		CASE (Map)
+		
+		case KeySeqType:
+			return QVariant (reinterpret_cast<KeySeq*> (ptr)->toString());
+		}
+		
+		assert (false);
+		return QVariant();
+	}
+#undef CASE
+	
+#define CASE(T, METHOD) case T##Type: (*(reinterpret_cast<T*> (ptr))) = val.METHOD(); return;
+	static void setConfigValue (void* ptr, Type type, const QVariant& val) {
+		switch (type) {
+		CASE (Int, toInt)
+		CASE (String, toString)
+		CASE (Float, toFloat)
+		CASE (Bool, toBool)
+		CASE (List, toList)
+		CASE (Map, toMap)
+		
+		case KeySeqType:
+			reinterpret_cast<KeySeq*> (ptr)->fromString (val.toString());
+			break;
+		}
+	}
+	
+	// =============================================================================
+	// Get the QSettings object.
+	// -----------------------------------------------------------------------------
+	static QSettings* getSettingsObject() {
+		return new QSettings;
+	}
+	
+	// =============================================================================
+	// Load the configuration from file
+	// -----------------------------------------------------------------------------
+	bool load() {
+		QSettings* settings = getSettingsObject();
+		print ("config::load: Loading configuration file from %1\n", settings->fileName());
+		
+		for (alias i : g_configData) {
+			if (i.name == null)
+				break;
+			
+			setConfigValue (i.ptr, i.type, settings->value (i.name, i.def));
+		}
+		
+		settings->deleteLater();
+		return true;
+	}
+	
+	// =============================================================================
+	// Save the configuration to disk
+	// -----------------------------------------------------------------------------
+	bool save() {
+		QSettings* settings = getSettingsObject();
+		settings->clear();
+		print ("Saving configuration to %1...\n", settings->fileName());
+		
+		for (alias i : g_configData) {
+			if (i.name == null)
+				break;
+			
+			QVariant val = getConfigValue (i.ptr, i.type);
+			
+			if (val == i.def)
+				continue;
+			
+			settings->setValue (i.name, val);
+		}
+		
+		settings->sync();
+		settings->deleteLater();
+		return true;
+	}
+	
+	// =============================================================================
+	// Reset configuration defaults.
+	// -----------------------------------------------------------------------------
+	void reset() {
+		for (alias i : g_configData) {
+			if (i.name == null)
+				break;
+			
+			setConfigValue (i.ptr, i.type, i.def);
+		}
+	}
+
+	// =============================================================================
+	// We cannot just add config objects to a list or vector because that would rely
+	// on the vector's c-tor being called before the configs' c-tors. With global
+	// variables we cannot assume that!! Therefore we need to use a C-style array here.
+	// -----------------------------------------------------------------------------
+	ConfigAdder::ConfigAdder (void* ptr, Type type, const char* name, QVariant def) {
+		if (g_cfgDataCursor == 0)
+			memset (g_configData, 0, sizeof g_configData);
+		
+		assert (g_cfgDataCursor < MAX_CONFIG);
+		alias i = g_configData[g_cfgDataCursor++];
+		i.ptr = ptr;
+		i.type = type;
+		i.name = name;
+		i.def = def;
+	}
+}
\ No newline at end of file

mercurial